8073842: Invalid method reference when referencing a method on a wildcard type
authormcimadamore
Fri, 27 Feb 2015 18:20:33 +0000
changeset 29292 c10d63c667cd
parent 29291 076c277565f7
child 29293 1583c6dd6df7
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
langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java
langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java
langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/DeferredAttr.java
langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java
langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java
langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransTypes.java
langtools/test/tools/javac/lambda/8073842/T8073842.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)) {
--- 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, ...
--- 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);
--- 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);
--- 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);
             }
         }
 
--- 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).
--- /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);
+    }
+}