changeset 2019:10c9e12512a3

8013222: Javac issues spurious raw type warnings when lambda has implicit parameter types *) Add type-based calculation for metafactory bridging (reloaded) *) Fix perf issue in Resolve.resolveOperator
author mcimadamore
date Fri, 26 Apr 2013 16:33:15 +0100
parents 3015fd8397e9
children 816207d6a63c
files src/share/classes/com/sun/tools/javac/code/Types.java src/share/classes/com/sun/tools/javac/comp/Attr.java src/share/classes/com/sun/tools/javac/comp/Infer.java src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java src/share/classes/com/sun/tools/javac/comp/Resolve.java src/share/classes/com/sun/tools/javac/comp/TransTypes.java src/share/classes/com/sun/tools/javac/tree/JCTree.java test/tools/javac/lambda/NoWarnOnImplicitParams.java test/tools/javac/lambda/NoWarnOnImplicitParams.out
diffstat 9 files changed, 80 insertions(+), 70 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/com/sun/tools/javac/code/Types.java	Thu Apr 25 12:40:07 2013 +0100
+++ b/src/share/classes/com/sun/tools/javac/code/Types.java	Fri Apr 26 16:33:15 2013 +0100
@@ -616,10 +616,10 @@
      * main purposes: (i) checking well-formedness of a functional interface;
      * (ii) perform functional interface bridge calculation.
      */
-    public ClassSymbol makeFunctionalInterfaceClass(Env<AttrContext> env, Name name, Type funcExprType, long cflags) {
-        Assert.check(isFunctionalInterface(funcExprType));
-        Symbol descSym = findDescriptorSymbol(funcExprType.tsym);
-        Type descType = findDescriptorType(funcExprType);
+    public ClassSymbol makeFunctionalInterfaceClass(Env<AttrContext> env, Name name, List<Type> targets, long cflags) {
+        Assert.check(targets.nonEmpty() && isFunctionalInterface(targets.head));
+        Symbol descSym = findDescriptorSymbol(targets.head.tsym);
+        Type descType = findDescriptorType(targets.head);
         ClassSymbol csym = new ClassSymbol(cflags, name, env.enclClass.sym.outermostClass());
         csym.completer = null;
         csym.members_field = new Scope(csym);
@@ -627,7 +627,7 @@
         csym.members_field.enter(instDescSym);
         Type.ClassType ctype = new Type.ClassType(Type.noType, List.<Type>nil(), csym);
         ctype.supertype_field = syms.objectType;
-        ctype.interfaces_field = List.of(removeWildcards(funcExprType));
+        ctype.interfaces_field = targets;
         csym.type = ctype;
         csym.sourcefile = ((ClassSymbol)csym.owner).sourcefile;
         return csym;
--- a/src/share/classes/com/sun/tools/javac/comp/Attr.java	Thu Apr 25 12:40:07 2013 +0100
+++ b/src/share/classes/com/sun/tools/javac/comp/Attr.java	Fri Apr 26 16:33:15 2013 +0100
@@ -1056,7 +1056,10 @@
         Lint prevLint = chk.setLint(lint);
 
         // Check that the variable's declared type is well-formed.
-        chk.validate(tree.vartype, env);
+        boolean isImplicitLambdaParameter = env.tree.hasTag(LAMBDA) &&
+                ((JCLambda)env.tree).paramKind == JCLambda.ParameterKind.IMPLICIT &&
+                (tree.sym.flags() & PARAMETER) != 0;
+        chk.validate(tree.vartype, env, !isImplicitLambdaParameter);
         deferredLintHandler.flush(tree.pos());
 
         try {
@@ -2282,7 +2285,7 @@
                 lambdaType = fallbackDescriptorType(that);
             }
 
-            setFunctionalInfo(that, pt(), lambdaType, target, resultInfo.checkContext.inferenceContext());
+            setFunctionalInfo(localEnv, that, pt(), lambdaType, target, resultInfo.checkContext);
 
             if (lambdaType.hasTag(FORALL)) {
                 //lambda expression target desc cannot be a generic method
@@ -2308,7 +2311,7 @@
                     Type argType = arityMismatch ?
                             syms.errType :
                             actuals.head;
-                    params.head.vartype = make.Type(argType);
+                    params.head.vartype = make.at(params.head).Type(argType);
                     params.head.sym = null;
                     actuals = actuals.isEmpty() ?
                             actuals :
@@ -2384,7 +2387,6 @@
             
             if (!isSpeculativeRound && target != Type.recoveryType) {
                 checkAccessibleTypes(that, localEnv, resultInfo.checkContext.inferenceContext(), lambdaType, target);
-                checkFunctionalInterfaceClass(localEnv, resultInfo.checkContext.inferenceContext(), target);
             }
             result = check(that, target, VAL, resultInfo);
         } catch (Types.FunctionDescriptorLookupError ex) {
@@ -2486,22 +2488,6 @@
             }
         }
 
-        private void checkFunctionalInterfaceClass(final Env<AttrContext> env,
-                final InferenceContext inferenceContext, final Type funcExprType) {
-            if (inferenceContext.free(funcExprType)) {
-                inferenceContext.addFreeTypeListener(List.of(funcExprType), new FreeTypeListener() {
-                    @Override
-                    public void typesInferred(InferenceContext inferenceContext) {
-                        checkFunctionalInterfaceClass(env, inferenceContext, inferenceContext.asInstType(funcExprType));
-                    }
-                });
-            } else {
-                ClassSymbol csym =
-                        types.makeFunctionalInterfaceClass(env, names.empty, funcExprType, ABSTRACT);
-                chk.checkImplementations(env.tree, csym, csym);
-            }
-        }
-
         /**
          * Lambda/method reference have a special check context that ensures
          * that i.e. a lambda return type is compatible with the expected
@@ -2642,7 +2628,7 @@
                 desc = fallbackDescriptorType(that);
             }
 
-            setFunctionalInfo(that, pt(), desc, target, resultInfo.checkContext.inferenceContext());
+            setFunctionalInfo(localEnv, that, pt(), desc, target, resultInfo.checkContext);
             List<Type> argtypes = desc.getParameterTypes();
 
             Pair<Symbol, Resolve.ReferenceLookupHelper> refResult =
@@ -2782,7 +2768,6 @@
             checkReferenceCompatible(that, desc, refType, resultInfo.checkContext, isSpeculativeRound);
             if (!isSpeculativeRound && target != Type.recoveryType) {
                 checkAccessibleTypes(that, localEnv, resultInfo.checkContext.inferenceContext(), desc, target);
-                checkFunctionalInterfaceClass(localEnv, resultInfo.checkContext.inferenceContext(), target);
             }
             result = check(that, target, VAL, resultInfo);
         } catch (Types.FunctionDescriptorLookupError ex) {
@@ -2845,31 +2830,37 @@
      * might contain inference variables, we might need to register an hook in the
      * current inference context.
      */
-    private void setFunctionalInfo(final JCFunctionalExpression fExpr, final Type pt,
-            final Type descriptorType, final Type primaryTarget, InferenceContext inferenceContext) {
-        if (inferenceContext.free(descriptorType)) {
-            inferenceContext.addFreeTypeListener(List.of(pt, descriptorType), new FreeTypeListener() {
+    private void setFunctionalInfo(final Env<AttrContext> env, final JCFunctionalExpression fExpr,
+            final Type pt, final Type descriptorType, final Type primaryTarget, final CheckContext checkContext) {
+        if (checkContext.inferenceContext().free(descriptorType)) {
+            checkContext.inferenceContext().addFreeTypeListener(List.of(pt, descriptorType), new FreeTypeListener() {
                 public void typesInferred(InferenceContext inferenceContext) {
-                    setFunctionalInfo(fExpr, pt, inferenceContext.asInstType(descriptorType),
-                            inferenceContext.asInstType(primaryTarget), inferenceContext);
+                    setFunctionalInfo(env, fExpr, pt, inferenceContext.asInstType(descriptorType),
+                            inferenceContext.asInstType(primaryTarget), checkContext);
                 }
             });
         } else {
-            ListBuffer<TypeSymbol> targets = ListBuffer.lb();
+            ListBuffer<Type> targets = ListBuffer.lb();
             if (pt.hasTag(CLASS)) {
                 if (pt.isCompound()) {
-                    targets.append(primaryTarget.tsym); //this goes first
+                    targets.append(types.removeWildcards(primaryTarget)); //this goes first
                     for (Type t : ((IntersectionClassType)pt()).interfaces_field) {
                         if (t != primaryTarget) {
-                            targets.append(t.tsym);
+                            targets.append(types.removeWildcards(t));
                         }
                     }
                 } else {
-                    targets.append(pt.tsym);
+                    targets.append(types.removeWildcards(primaryTarget));
                 }
             }
             fExpr.targets = targets.toList();
-            fExpr.descriptorType = descriptorType;
+            if (checkContext.deferredAttrContext().mode == DeferredAttr.AttrMode.CHECK &&
+                    pt != Type.recoveryType) {
+                //check that functional interface class is well-formed
+                ClassSymbol csym = types.makeFunctionalInterfaceClass(env,
+                        names.empty, List.of(fExpr.targets.head), ABSTRACT);
+                chk.checkImplementations(env.tree, csym, csym);
+            }
         }
     }
 
@@ -4477,9 +4468,6 @@
         @Override
         public void visitLambda(JCLambda that) {
             super.visitLambda(that);
-            if (that.descriptorType == null) {
-                that.descriptorType = syms.unknownType;
-            }
             if (that.targets == null) {
                 that.targets = List.nil();
             }
@@ -4491,9 +4479,6 @@
             if (that.sym == null) {
                 that.sym = new MethodSymbol(0, names.empty, syms.unknownType, syms.noSymbol);
             }
-            if (that.descriptorType == null) {
-                that.descriptorType = syms.unknownType;
-            }
             if (that.targets == null) {
                 that.targets = List.nil();
             }
--- a/src/share/classes/com/sun/tools/javac/comp/Infer.java	Thu Apr 25 12:40:07 2013 +0100
+++ b/src/share/classes/com/sun/tools/javac/comp/Infer.java	Fri Apr 26 16:33:15 2013 +0100
@@ -1388,8 +1388,6 @@
         java.util.Map<FreeTypeListener, List<Type>> freeTypeListeners =
                 new java.util.HashMap<FreeTypeListener, List<Type>>();
 
-        List<FreeTypeListener> freetypeListeners = List.nil();
-
         public InferenceContext(List<Type> inferencevars) {
             this.undetvars = Type.map(inferencevars, fromTypeVarFun);
             this.inferencevars = inferencevars;
--- a/src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java	Thu Apr 25 12:40:07 2013 +0100
+++ b/src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java	Fri Apr 26 16:33:15 2013 +0100
@@ -879,7 +879,7 @@
     private JCExpression makeMetaFactoryIndyCall(JCFunctionalExpression tree, boolean needsAltMetafactory,
             boolean isSerializable, int refKind, Symbol refSym, List<JCExpression> indy_args) {
         //determine the static bsm args
-        Type mtype = types.erasure(tree.descriptorType);
+        Type mtype = types.erasure(tree.getDescriptorType(types));
         MethodSymbol samSym = (MethodSymbol) types.findDescriptorSymbol(tree.type.tsym);
         List<Object> staticArgs = List.<Object>of(
                 new Pool.MethodHandle(ClassFile.REF_invokeInterface,
@@ -907,9 +907,9 @@
 
         if (needsAltMetafactory) {
             ListBuffer<Object> markers = ListBuffer.lb();
-            for (Symbol t : tree.targets.tail) {
-                if (t != syms.serializableType.tsym) {
-                    markers.append(t);
+            for (Type t : tree.targets.tail) {
+                if (t.tsym != syms.serializableType.tsym) {
+                    markers.append(t.tsym);
                 }
             }
             int flags = isSerializable? FLAG_SERIALIZABLE : 0;
@@ -1576,8 +1576,8 @@
                 if (forceSerializableRepresentation) {
                     return true;
                 }
-                for (Symbol target : tree.targets) {
-                    if (types.asSuper(target.type, syms.serializableType.tsym) != null) {
+                for (Type target : tree.targets) {
+                    if (types.asSuper(target, syms.serializableType.tsym) != null) {
                         return true;
                     }
                 }
@@ -1748,7 +1748,7 @@
             }
 
             Type generatedLambdaSig() {
-                return types.erasure(tree.descriptorType);
+                return types.erasure(tree.getDescriptorType(types));
             }
         }
 
@@ -1819,7 +1819,7 @@
             }
 
             Type bridgedRefSig() {
-                return types.erasure(types.findDescriptorSymbol(tree.targets.head).type);
+                return types.erasure(types.findDescriptorSymbol(tree.targets.head.tsym).type);
             }
         }
     }
--- a/src/share/classes/com/sun/tools/javac/comp/Resolve.java	Thu Apr 25 12:40:07 2013 +0100
+++ b/src/share/classes/com/sun/tools/javac/comp/Resolve.java	Fri Apr 26 16:33:15 2013 +0100
@@ -2531,10 +2531,11 @@
             env.info.pendingResolutionPhase = currentResolutionContext.step = BASIC;
             Symbol sym = findMethod(env, syms.predefClass.type, name, argtypes,
                                     null, false, false, true);
-            if (boxingEnabled && sym.kind >= WRONG_MTHS)
+            if (boxingEnabled && sym.kind >= WRONG_MTHS) {
                 env.info.pendingResolutionPhase = currentResolutionContext.step = BOX;
                 sym = findMethod(env, syms.predefClass.type, name, argtypes,
                                  null, true, false, true);
+            }
             return accessMethod(sym, pos, env.enclClass.sym.type, name,
                           false, argtypes, null);
         }
@@ -3672,7 +3673,7 @@
                     List<Type> allThrown = chk.intersect(mt1.getThrownTypes(), mt2.getThrownTypes());
                     Type newSig = types.createMethodTypeWithThrown(mostSpecific.type, allThrown);
                     res = new MethodSymbol(
-                            mostSpecific.flags(),
+                            mostSpecific.flags() & ~DEFAULT,
                             mostSpecific.name,
                             newSig,
                             mostSpecific.owner);
--- a/src/share/classes/com/sun/tools/javac/comp/TransTypes.java	Thu Apr 25 12:40:07 2013 +0100
+++ b/src/share/classes/com/sun/tools/javac/comp/TransTypes.java	Fri Apr 26 16:33:15 2013 +0100
@@ -565,8 +565,8 @@
             currentMethod = null;
             tree.params = translate(tree.params);
             tree.body = translate(tree.body, null);
+            tree.type = erasure(tree.type);
             bridgeFunctionalInfoIfNeeded(tree);
-            tree.type = erasure(tree.type);
             result = tree;
         }
         finally {
@@ -582,14 +582,9 @@
      */
     private void bridgeFunctionalInfoIfNeeded(JCTree.JCFunctionalExpression funcExpr) {
         ClassSymbol csym = types.makeFunctionalInterfaceClass(env, syntheticBridgedInterfaceName(),
-                funcExpr.type, INTERFACE | ABSTRACT);
+                funcExpr.targets, INTERFACE | ABSTRACT);
         if (!allowInterfaceBridges ||
                 types.functionalInterfaceBridges(csym).length() <= 1) return;
-        //append extra targets
-        for (TypeSymbol target : funcExpr.targets.tail) {
-            ((Type.ClassType)csym.type).interfaces_field =
-                    ((Type.ClassType)csym.type).interfaces_field.prepend(target.erasure(types));
-        }
         //create an interface def
         JCClassDecl idecl = make.ClassDef(make.Modifiers(csym.flags()),
                 csym.name, List.<JCTypeParameter>nil(), null, make.Types(types.interfaces(csym.type)),
@@ -605,8 +600,7 @@
         env.enclClass.sym.outermostClass().members().enter(csym);
         bridgedFunctionalInterfaces = bridgedFunctionalInterfaces.prepend(idecl);
         //update functional info
-        funcExpr.descriptorType = types.findDescriptorType(csym.type);
-        funcExpr.targets = List.<TypeSymbol>of(csym);
+        funcExpr.targets = List.<Type>of(csym.type);
         funcExpr.type = csym.type;
     }
     //where
@@ -849,8 +843,8 @@
 
     public void visitReference(JCMemberReference tree) {
         tree.expr = translate(tree.expr, null);
+        tree.type = erasure(tree.type);
         bridgeFunctionalInfoIfNeeded(tree);
-        tree.type = erasure(tree.type);
         result = tree;
     }
 
--- a/src/share/classes/com/sun/tools/javac/tree/JCTree.java	Thu Apr 25 12:40:07 2013 +0100
+++ b/src/share/classes/com/sun/tools/javac/tree/JCTree.java	Fri Apr 26 16:33:15 2013 +0100
@@ -641,11 +641,13 @@
             //a functional expression is always a 'true' poly
             polyKind = PolyKind.POLY;
         }
-
-        /** target descriptor inferred for this functional expression. */
-        public Type descriptorType;
+        
         /** list of target types inferred for this functional expression. */
-        public List<TypeSymbol> targets;
+        public List<Type> targets;
+        
+        public Type getDescriptorType(Types types) {
+            return types.findDescriptorType(targets.head);
+        }
     }
 
     /**
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/lambda/NoWarnOnImplicitParams.java	Fri Apr 26 16:33:15 2013 +0100
@@ -0,0 +1,26 @@
+/*
+ * @test /nodynamiccopyright/
+ * @bug 8013222
+ * @summary Javac issues spurious raw type warnings when lambda has implicit parameter types
+ * @compile/fail/ref=NoWarnOnImplicitParams.out -Xlint:rawtypes -Werror -XDrawDiagnostics NoWarnOnImplicitParams.java
+ */
+import java.util.List;
+
+class NoWarnOnImplicitParams {
+
+    public void testRawMerge(List<String> ls) {
+        R12 r12_1 = l->"Foo";
+        R12 r12_2 = (List l)->"Foo";
+    }
+
+    interface R1 {
+        Object m(List<String> ls);
+    }
+
+    @SuppressWarnings("rawtypes")
+    interface R2 {
+        String m(List l);
+    }
+
+    interface R12 extends R1, R2 {}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/lambda/NoWarnOnImplicitParams.out	Fri Apr 26 16:33:15 2013 +0100
@@ -0,0 +1,4 @@
+NoWarnOnImplicitParams.java:13:22: compiler.warn.raw.class.use: java.util.List, java.util.List<E>
+- compiler.err.warnings.and.werror
+1 error
+1 warning