# HG changeset patch # User mcimadamore # Date 1425061233 0 # Node ID c10d63c667cd7e4e9eca730f74556e1b670e3b40 # Parent 076c277565f7fab27d3fd28c0125098c5dd70212 8073842: Invalid method reference when referencing a method on a wildcard type Summary: Method rteference lookup logic doesn't skip type-variables as required by javac. Reviewed-by: jlahoda diff -r 076c277565f7 -r c10d63c667cd langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java Fri Feb 27 11:51:53 2015 +0000 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java Fri Feb 27 18:20:33 2015 +0000 @@ -168,6 +168,18 @@ } else return t; } + + /** + * Recursively skip type-variables until a class/array type is found; capture conversion is then + * (optionally) applied to the resulting type. This is useful for i.e. computing a site that is + * suitable for a method lookup. + */ + public Type skipTypeVars(Type site, boolean capture) { + while (site.hasTag(TYPEVAR)) { + site = site.getUpperBound(); + } + return capture ? capture(site) : site; + } // </editor-fold> // <editor-fold defaultstate="collapsed" desc="isUnbounded"> @@ -1787,12 +1799,9 @@ } private Type relaxBound(Type t) { - if (t.hasTag(TYPEVAR)) { - while (t.hasTag(TYPEVAR)) - t = t.getUpperBound(); - t = rewriteQuantifiers(t, true, true); - } - return t; + return (t.hasTag(TYPEVAR)) ? + rewriteQuantifiers(skipTypeVars(t, false), true, true) : + t; } // </editor-fold> @@ -1872,10 +1881,7 @@ */ private Mapping elemTypeFun = new Mapping ("elemTypeFun") { public Type apply(Type t) { - while (t.hasTag(TYPEVAR)) { - t = t.getUpperBound(); - } - return elemtype(t); + return elemtype(skipTypeVars(t, false)); } }; @@ -2662,8 +2668,7 @@ private MethodSymbol implementationInternal(MethodSymbol ms, TypeSymbol origin, boolean checkResult, Filter<Symbol> implFilter) { for (Type t = origin.type; t.hasTag(CLASS) || t.hasTag(TYPEVAR); t = supertype(t)) { - while (t.hasTag(TYPEVAR)) - t = t.getUpperBound(); + t = skipTypeVars(t, false); TypeSymbol c = t.tsym; Symbol bestSoFar = null; for (Symbol sym : c.members().getSymbolsByName(ms.name, implFilter)) { diff -r 076c277565f7 -r c10d63c667cd langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java Fri Feb 27 11:51:53 2015 +0000 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java Fri Feb 27 18:20:33 2015 +0000 @@ -3176,8 +3176,7 @@ tree.sym = sym; if (site.hasTag(TYPEVAR) && !isType(sym) && sym.kind != ERR) { - while (site.hasTag(TYPEVAR)) site = site.getUpperBound(); - site = capture(site); + site = types.skipTypeVars(site, true); } // If that symbol is a variable, ... diff -r 076c277565f7 -r c10d63c667cd langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/DeferredAttr.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/DeferredAttr.java Fri Feb 27 11:51:53 2015 +0000 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/DeferredAttr.java Fri Feb 27 18:20:33 2015 +0000 @@ -28,7 +28,6 @@ import com.sun.source.tree.LambdaExpressionTree.BodyKind; import com.sun.tools.javac.code.*; import com.sun.tools.javac.comp.Resolve.ResolveError; -import com.sun.tools.javac.resources.CompilerProperties; import com.sun.tools.javac.resources.CompilerProperties.Fragments; import com.sun.tools.javac.tree.*; import com.sun.tools.javac.util.*; @@ -1372,11 +1371,7 @@ site = env.enclClass.sym.type; } - while (site.hasTag(TYPEVAR)) { - site = site.getUpperBound(); - } - - site = types.capture(site); + site = types.skipTypeVars(site, true); List<Type> args = rs.dummyArgs(tree.args.length()); Name name = TreeInfo.name(tree.meth); diff -r 076c277565f7 -r c10d63c667cd langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java Fri Feb 27 11:51:53 2015 +0000 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java Fri Feb 27 18:20:33 2015 +0000 @@ -3446,10 +3446,7 @@ syms.iterableType.tsym); if (iterableType.getTypeArguments().nonEmpty()) iteratorTarget = types.erasure(iterableType.getTypeArguments().head); - Type eType = tree.expr.type; - while (eType.hasTag(TYPEVAR)) { - eType = eType.getUpperBound(); - } + Type eType = types.skipTypeVars(tree.expr.type, false); tree.expr.type = types.erasure(eType); if (eType.isCompound()) tree.expr = make.TypeCast(types.erasure(iterableType), tree.expr); diff -r 076c277565f7 -r c10d63c667cd langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java Fri Feb 27 11:51:53 2015 +0000 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java Fri Feb 27 18:20:33 2015 +0000 @@ -1791,8 +1791,7 @@ !t.hasTag(TYPEVAR)) { return null; } - while (t.hasTag(TYPEVAR)) - t = t.getUpperBound(); + t = types.skipTypeVars(t, false); if (seen.contains(t.tsym)) { //degenerate case in which we have a circular //class hierarchy - because of ill-formed classfiles @@ -2656,11 +2655,9 @@ InferenceContext inferenceContext, ReferenceChooser referenceChooser) { - site = types.capture(site); + //step 1 - bound lookup ReferenceLookupHelper boundLookupHelper = makeReferenceLookupHelper( referenceTree, site, name, argtypes, typeargtypes, VARARITY); - - //step 1 - bound lookup Env<AttrContext> boundEnv = env.dup(env.tree, env.info.dup()); MethodResolutionContext boundSearchResolveContext = new MethodResolutionContext(); boundSearchResolveContext.methodCheck = methodCheck; @@ -3044,9 +3041,13 @@ */ class MethodReferenceLookupHelper extends ReferenceLookupHelper { + /** The original method reference lookup site. */ + Type originalSite; + MethodReferenceLookupHelper(JCMemberReference referenceTree, Name name, Type site, List<Type> argtypes, List<Type> typeargtypes, MethodResolutionPhase maxPhase) { - super(referenceTree, name, site, argtypes, typeargtypes, maxPhase); + super(referenceTree, name, types.skipTypeVars(site, true), argtypes, typeargtypes, maxPhase); + this.originalSite = site; } @Override @@ -3062,7 +3063,7 @@ (argtypes.head.hasTag(NONE) || types.isSubtypeUnchecked(inferenceContext.asUndetVar(argtypes.head), site))) { return new UnboundMethodReferenceLookupHelper(referenceTree, name, - site, argtypes, typeargtypes, maxPhase); + originalSite, argtypes, typeargtypes, maxPhase); } else { return new ReferenceLookupHelper(referenceTree, name, site, argtypes, typeargtypes, maxPhase) { @Override @@ -3114,7 +3115,7 @@ super(referenceTree, name, site, argtypes.tail, typeargtypes, maxPhase); if (site.isRaw() && !argtypes.head.hasTag(NONE)) { Type asSuperSite = types.asSuper(argtypes.head, site.tsym); - this.site = types.capture(asSuperSite); + this.site = types.skipTypeVars(asSuperSite, true); } } diff -r 076c277565f7 -r c10d63c667cd langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransTypes.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransTypes.java Fri Feb 27 11:51:53 2015 +0000 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransTypes.java Fri Feb 27 18:20:33 2015 +0000 @@ -818,9 +818,7 @@ } public void visitSelect(JCFieldAccess tree) { - Type t = tree.selected.type; - while (t.hasTag(TYPEVAR)) - t = t.getUpperBound(); + Type t = types.skipTypeVars(tree.selected.type, false); if (t.isCompound()) { if ((tree.sym.flags() & IPROXY) != 0) { tree.sym = ((MethodSymbol)tree.sym). diff -r 076c277565f7 -r c10d63c667cd langtools/test/tools/javac/lambda/8073842/T8073842.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/lambda/8073842/T8073842.java Fri Feb 27 18:20:33 2015 +0000 @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8073842 + * @summary Invalid method reference when referencing a method on a wildcard type + * @compile T8073842.java + */ + +import java.util.stream.Stream; + +class T8073842 { + + static class Chunck { + public void work() { } + } + + void test(Stream<? extends Chunck> s) { + Stream<Runnable> r = s.map(o -> o::work); + } +}