changeset 1461:3fc4791e07c2

Enhancements/cleanups: *) Improved support for recovery attribution: remove unnecessary recovery rounds on speculative trees *) Improved support for recovery attribution: suppress spurious errors on lambda parameters *) More method refence type-checking cleanup
author mcimadamore
date Thu, 13 Sep 2012 13:10:10 +0100
parents 0ea8d35cbe12
children e5310f5fd26b
files src/share/classes/com/sun/tools/javac/comp/Attr.java src/share/classes/com/sun/tools/javac/comp/Resolve.java test/tools/javac/lambda/TargetType43.java
diffstat 3 files changed, 146 insertions(+), 112 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/com/sun/tools/javac/comp/Attr.java	Wed Sep 12 16:16:13 2012 +0100
+++ b/src/share/classes/com/sun/tools/javac/comp/Attr.java	Thu Sep 13 13:10:10 2012 +0100
@@ -2285,7 +2285,8 @@
         }
         //create an environment for attribution of the lambda expression
         final Env<AttrContext> localEnv = lambdaEnv(that, env);
-        boolean bodyAttributed = false;
+        boolean needsRecovery = resultInfo.checkContext.deferredAttrContext() == deferredAttr.emptyDeferredAttrContext ||
+                resultInfo.checkContext.deferredAttrContext().mode == DeferredAttr.AttrMode.CHECK;
         try {
             List<Type> explicitParamTypes = null;
             if (TreeInfo.isExplicitLambda(that)) {
@@ -2333,8 +2334,23 @@
                 }
             }
 
-            bodyAttributed = true;
-            attribLambdaBody(localEnv, that, lambdaType, resultInfo.checkContext);
+            //from this point on, no recovery is needed; if we are in assignment context
+            //we will be able to attribute the whole lambda body, regardless of errors;
+            //if we are in a 'check' method context, and the lambda is not compatible
+            //with the target-type, it will be recovered anyway in Attr.checkId
+            needsRecovery = false;
+
+            ResultInfo bodyResultInfo = lambdaType.getReturnType() == Type.recoveryType ?
+                recoveryInfo :
+                new ResultInfo(VAL, lambdaType.getReturnType(), new LambdaReturnContext(resultInfo.checkContext));
+            localEnv.info.returnResult = bodyResultInfo;
+
+            if (that.getBodyKind() == JCLambda.BodyKind.EXPRESSION) {
+                attribTree(that.getBody(), localEnv, bodyResultInfo);
+            } else {
+                JCBlock body = (JCBlock)that.body;
+                attribStats(body.stats, localEnv);
+            }
             
             result = check(that, target, VAL, resultInfo);
             
@@ -2355,29 +2371,10 @@
             result = that.type = types.createErrorType(pt());
             return;
         } finally {
-            if (!bodyAttributed) {
-                Type prevResult = result;
-                try {
-                    attribLambdaBody(localEnv, that, fallbackDescriptorType(that), resultInfo.checkContext);
-                } finally {
-                    result = prevResult;
-                }
+            localEnv.info.scope.leave();
+            if (needsRecovery) {
+                attribTree(that, env, recoveryInfo);
             }
-            localEnv.info.scope.leave();
-        }
-    }
-    
-    void attribLambdaBody(Env<AttrContext> env, JCLambda that, Type desc, CheckContext checkContext) {
-        ResultInfo bodyResultInfo = desc.getReturnType() == Type.recoveryType ?
-                recoveryInfo :
-                new ResultInfo(VAL, desc.getReturnType(), new LambdaReturnContext(checkContext));
-        env.info.returnResult = bodyResultInfo;
-
-        if (that.getBodyKind() == JCLambda.BodyKind.EXPRESSION) {
-            attribTree(that.getBody(), env, bodyResultInfo);
-        } else {
-            JCBlock body = (JCBlock)that.body;
-            attribStats(body.stats, env);
         }
     }
     
@@ -2738,24 +2735,23 @@
             //attribute member reference qualifier - if this is a constructor
             //reference, the expected kind must be a type
             Type exprType = attribTree(that.expr,
-                  env,
-                  new ResultInfo(that.getMode() == ReferenceMode.INVOKE ? VAL | TYP : TYP, Type.noType));
+                    env, new ResultInfo(that.getMode() == ReferenceMode.INVOKE ? VAL | TYP : TYP, Type.noType));
             
             if (that.getMode() == JCMemberReference.ReferenceMode.NEW) {
                 exprType = chk.checkConstructorRefType(that.expr, exprType);
             }
 
             if (exprType.isErroneous()) {
-              //if the qualifier expression contains problems,
-              //give up atttribution of method reference
-              result = that.type = exprType;
-              return;
+                //if the qualifier expression contains problems,
+                //give up atttribution of method reference
+                result = that.type = exprType;
+                return;
             }
 
             if (TreeInfo.isStaticSelector(that.expr, names) &&
                     (that.getMode() != ReferenceMode.NEW || !that.expr.type.isRaw())) {
-              //if the qualifier is a type, validate it
-              chk.validate(that.expr, env);
+                //if the qualifier is a type, validate it
+                chk.validate(that.expr, env);
             }
             
             //attrib type-arguments
@@ -2774,11 +2770,11 @@
             boolean allowBoxing =
                     resultInfo.checkContext.deferredAttrContext() == deferredAttr.emptyDeferredAttrContext ||
                     resultInfo.checkContext.deferredAttrContext().phase.isBoxingRequired();
-            Pair<Type, Symbol> refResult = rs.resolveMemberReference(that.pos(), localEnv, that,
+            Pair<Symbol, Resolve.ReferenceLookupHelper> refResult = rs.resolveMemberReference(that.pos(), localEnv, that,
                     that.expr.type, that.name, argtypes, typeargtypes, allowBoxing);
             
-            Type refSite = refResult.fst;
-            Symbol refSym = refResult.snd;
+            Symbol refSym = refResult.fst;
+            Resolve.ReferenceLookupHelper lookupHelper = refResult.snd;
 
             if (refSym.kind != MTH) {
                 boolean targetError;
@@ -2824,21 +2820,20 @@
             }
             
             that.sym = refSym.baseSymbol();
-            
-            setReferenceKind(that, argtypes);
+            that.kind = lookupHelper.referenceKind(that.sym);
             
             ResultInfo checkInfo =
                     resultInfo.dup(newMethTemplate(
                         desc.getReturnType().tag == VOID ? Type.noType : desc.getReturnType(),
-                        that.kind.isUnbound() ? argtypes.tail : argtypes,
+                        lookupHelper.argtypes,
                         typeargtypes));
             
-            Type refType = checkId(that, refSite,
+            Type refType = checkId(that, lookupHelper.site,
                     refSym, localEnv, checkInfo, localEnv.info.lastResolveVarargs());
             
             if (!refType.isErroneous()) {
                 refType = types.createMethodTypeWithReturn(refType,
-                        adjustMethodReturnType(refSite, that.name, checkInfo.pt.getParameterTypes(), refType.getReturnType()));
+                        adjustMethodReturnType(lookupHelper.site, that.name, checkInfo.pt.getParameterTypes(), refType.getReturnType()));
             }
 
             //go ahead with standard SAM compatibility check - note that param check
@@ -2855,37 +2850,8 @@
             resultInfo.checkContext.report(that, cause);
             result = that.type = types.createErrorType(pt());
             return;
-        } 
+        }
     }
-        //where
-        private void setReferenceKind(JCMemberReference tree, List<Type> argtypes) {
-            if (tree.name == names.init) {
-                //Constructor reference
-                if (tree.sym.owner.type.getEnclosingType() == Type.noType) {
-                    tree.kind = ReferenceKind.TOPLEVEL;
-                } else if (!rs.hasEnclosingInstance(env, tree.sym.owner.type) ||
-                        tree.sym.type.getParameterTypes().length() < argtypes.length()) {
-                    tree.kind = ReferenceKind.UNBOUND_INNER;
-                } else {
-                    tree.kind = ReferenceKind.IMPLICIT_INNER;
-                }
-            } else if (TreeInfo.isStaticSelector(tree.getQualifierExpression(), names)) {
-                if (tree.sym.isStatic()) {
-                    tree.kind = ReferenceKind.STATIC;
-                } else {
-                    tree.kind = ReferenceKind.UNBOUND;
-                }
-            } else {
-                Name name = TreeInfo.name(tree.getQualifierExpression());
-                if (name != null && name == names._super) {
-                    tree.kind = ReferenceKind.SUPER;
-                } else if (tree.sym.isStatic()) {
-                    tree.kind = ReferenceKind.STATIC_EVAL;
-                } else {
-                    tree.kind = ReferenceKind.BOUND;
-                }
-            }
-        }
 
     /**
      * SAM compatibility. Check that given return types, thrown types, parameter types
--- a/src/share/classes/com/sun/tools/javac/comp/Resolve.java	Wed Sep 12 16:16:13 2012 +0100
+++ b/src/share/classes/com/sun/tools/javac/comp/Resolve.java	Thu Sep 13 13:10:10 2012 +0100
@@ -63,6 +63,7 @@
 import com.sun.tools.javac.comp.DeferredAttr.AttrMode;
 import com.sun.tools.javac.comp.DeferredAttr.DeferredAttrContext;
 import static com.sun.tools.javac.comp.Resolve.MethodResolutionPhase.*;
+import com.sun.tools.javac.tree.JCTree.JCMemberReference.ReferenceKind;
 import static com.sun.tools.javac.tree.JCTree.Tag.*;
 
 /** Helper class for name resolution, used mostly by the attribution phase.
@@ -2320,7 +2321,7 @@
      * the type T might be dynamically inferred (i.e. if constructor reference
      * has a raw qualifier).
      */
-    Pair<Type, Symbol> resolveMemberReference(DiagnosticPosition pos,
+    Pair<Symbol, ReferenceLookupHelper> resolveMemberReference(DiagnosticPosition pos,
                                   Env<AttrContext> env,
                                   JCMemberReference referenceTree,
                                   Type site,
@@ -2340,15 +2341,15 @@
         Symbol unboundSym = findMemberReference(unboundEnv, unboundLookupHelper);
         
         //merge results
-        Pair<Type, Symbol> res;
+        Pair<Symbol, ReferenceLookupHelper> res;
         if (unboundSym.kind != MTH) {
-            res = new Pair<Type, Symbol>(boundLookupHelper.site, boundSym);
+            res = new Pair<Symbol, ReferenceLookupHelper>(boundSym, boundLookupHelper);
             env.info.pendingResolutionPhase = boundEnv.info.pendingResolutionPhase;
         } else if (boundSym.kind == MTH) {
-            res = new Pair<Type, Symbol>(boundLookupHelper.site, ambiguityError(boundSym, unboundSym));
+            res = new Pair<Symbol, ReferenceLookupHelper>(ambiguityError(boundSym, unboundSym), boundLookupHelper);
             env.info.pendingResolutionPhase = boundEnv.info.pendingResolutionPhase;
         } else {
-            res = new Pair<Type, Symbol>(unboundLookupHelper.site, unboundSym);
+            res = new Pair<Symbol, ReferenceLookupHelper>(unboundSym, unboundLookupHelper);
             env.info.pendingResolutionPhase = unboundEnv.info.pendingResolutionPhase;
         }
         
@@ -2376,7 +2377,6 @@
     abstract class ReferenceLookupHelper extends LookupHelper {
     
         JCMemberReference referenceTree;
-        Symbol refSym;
         MethodResolutionPhase maxPhase;
 
         ReferenceLookupHelper(JCMemberReference referenceTree, Name name, Type site,
@@ -2386,8 +2386,6 @@
             this.maxPhase = boxingAllowed ? VARARITY : BASIC;
         }
         
-        boolean unbound() { return false; }
-        
         ReferenceLookupHelper unboundLookup() {
             //dummy loopkup helper that always return 'methodNotFound'
             return new ReferenceLookupHelper(referenceTree, name, site, argtypes, typeargtypes, maxPhase.isBoxingRequired()) {
@@ -2399,8 +2397,15 @@
                 Symbol lookupReference(Env<AttrContext> env, MethodResolutionPhase phase) {
                     return methodNotFound;
                 }
+                @Override
+                ReferenceKind referenceKind(Symbol sym) {
+                    Assert.error();
+                    return null;
+                }
             };
         }
+        
+        abstract JCMemberReference.ReferenceKind referenceKind(Symbol sym);
 
         @Override
         Symbol lookup(Env<AttrContext> env, MethodResolutionPhase phase) {
@@ -2429,14 +2434,21 @@
                 List<Type> argtypes, List<Type> typeargtypes, boolean boxingAllowed) {
             super(referenceTree, name, site, argtypes, typeargtypes, boxingAllowed);
         }
+        
+        protected Symbol lookupReferenceInternal(Env<AttrContext> env, MethodResolutionPhase phase) {
+            return findMethod(env, site, name, argtypes, typeargtypes,
+                    phase.isBoxingRequired(), phase.isVarargsRequired(), isOperator(name));
+        }
+        
+        protected Symbol adjustLookupResult(Env<AttrContext> env, Symbol sym) {
+            return !TreeInfo.isStaticSelector(referenceTree.expr, names) ||
+                        sym.kind != MTH ||
+                        sym.isStatic() ? sym : new StaticError(sym);
+        }
 
         @Override
-        Symbol lookupReference(Env<AttrContext> env, MethodResolutionPhase phase) {
-            Symbol sym = findMethod(env, site, name, argtypes, typeargtypes,
-                    phase.isBoxingRequired(), phase.isVarargsRequired(), isOperator(name));
-            return !TreeInfo.isStaticSelector(referenceTree.expr, names) ||
-                        sym.kind != MTH ||
-                        sym.isStatic() != unbound() ? sym : new StaticError(sym);
+        final Symbol lookupReference(Env<AttrContext> env, MethodResolutionPhase phase) {
+            return adjustLookupResult(env, lookupReferenceInternal(env, phase));            
         }
 
         @Override
@@ -2445,20 +2457,51 @@
                     argtypes.nonEmpty() &&
                     types.isSubtypeUnchecked(argtypes.head, site)) {
                 Type unboundSite = site.isRaw() ? types.asSuper(argtypes.head, site.tsym) : site;
-                return new MethodReferenceLookupHelper(referenceTree, name,
-                        unboundSite, argtypes.tail, typeargtypes, maxPhase.isBoxingRequired()) {
-                            @Override
-                            boolean unbound() {
-                                return true;
-                            }
-                        };
+                return new UnboundMethodReferenceLookupHelper(referenceTree, name,
+                        unboundSite, argtypes.tail, typeargtypes, maxPhase.isBoxingRequired());
             } else {
                 return super.unboundLookup();
             }
         }
+
+        @Override
+        ReferenceKind referenceKind(Symbol sym) {
+            if (sym.isStatic()) {
+                return TreeInfo.isStaticSelector(referenceTree.expr, names) ?
+                        ReferenceKind.STATIC : ReferenceKind.STATIC_EVAL;
+            } else {
+                Name selName = TreeInfo.name(referenceTree.getQualifierExpression());
+                return selName != null && selName == names._super ?
+                        ReferenceKind.SUPER :
+                        ReferenceKind.BOUND;
+            }
+        }
     }
     
-    class ConstructorReferenceLookupHelper extends ReferenceLookupHelper {
+    class UnboundMethodReferenceLookupHelper extends MethodReferenceLookupHelper {
+
+        UnboundMethodReferenceLookupHelper(JCMemberReference referenceTree, Name name, Type site,
+                List<Type> argtypes, List<Type> typeargtypes, boolean boxingAllowed) {
+            super(referenceTree, name, site, argtypes, typeargtypes, boxingAllowed);
+        }
+
+        @Override
+        protected Symbol adjustLookupResult(Env<AttrContext> env, Symbol sym) {
+            return sym.kind != MTH || !sym.isStatic() ? sym : new StaticError(sym);
+        }
+
+        @Override
+        ReferenceLookupHelper unboundLookup() {
+            return this;
+        }
+
+        @Override
+        ReferenceKind referenceKind(Symbol sym) {
+            return ReferenceKind.UNBOUND;
+        }
+    }
+    
+    class ConstructorReferenceLookupHelper extends MethodReferenceLookupHelper {
         
         boolean needsInference;
 
@@ -2473,32 +2516,27 @@
 
         @Override
         ReferenceLookupHelper unboundLookup() {
-            //TODO: this should be removed
             if (argtypes.nonEmpty() &&
                     site.getEnclosingType().tag != NONE &&
                     types.asEnclosingSuper(argtypes.head, site.getEnclosingType().tsym) != null) {
-                return new ConstructorReferenceLookupHelper(referenceTree, site, argtypes.tail,
-                        typeargtypes, maxPhase.isBoxingRequired()) {
-                            @Override
-                            boolean unbound() {
-                                return true;
-                            }
-                        };
+                return new UnboundConstructorReferenceLookupHelper(referenceTree, site, argtypes.tail,
+                        typeargtypes, maxPhase.isBoxingRequired());
             } else {
                 return super.unboundLookup();
             }
         }
+        
+        @Override
+        protected Symbol lookupReferenceInternal(Env<AttrContext> env, MethodResolutionPhase phase) {
+            return needsInference ?
+                findDiamond(env, site, argtypes, typeargtypes, phase.isBoxingRequired(), phase.isVarargsRequired()) :
+                findMethod(env, site, name, argtypes, typeargtypes,
+                        phase.isBoxingRequired(), phase.isVarargsRequired(), isOperator(name));
+        }
 
         @Override
-        Symbol lookupReference(Env<AttrContext> env, MethodResolutionPhase phase) {
-            Symbol sym;
-            if (needsInference) {
-                sym = findDiamond(env, site, argtypes, typeargtypes, phase.isBoxingRequired(), phase.isVarargsRequired());
-            } else {
-                sym = findMethod(env, site, name, argtypes, typeargtypes,
-                        phase.isBoxingRequired(), phase.isVarargsRequired(), isOperator(name));
-            }
-            return unbound() ||
+        protected Symbol adjustLookupResult(Env<AttrContext> env, Symbol sym) {
+            return sym.kind != MTH ||
                     site.getEnclosingType().tag == NONE ||
                     hasEnclosingInstance(env, site) ?
                     sym : new InvalidSymbolError(Kinds.MISSING_ENCL, sym, null) {
@@ -2509,6 +2547,36 @@
                         }
                     };
         }
+
+        @Override
+        ReferenceKind referenceKind(Symbol sym) {
+            return site.getEnclosingType().tag == NONE ?
+                    ReferenceKind.TOPLEVEL : ReferenceKind.IMPLICIT_INNER;
+        }
+    }
+    
+    //TODO: this should be removed
+    class UnboundConstructorReferenceLookupHelper extends ConstructorReferenceLookupHelper {
+
+        UnboundConstructorReferenceLookupHelper(JCMemberReference referenceTree, Type site,
+                List<Type> argtypes, List<Type> typeargtypes, boolean boxingAllowed) {
+            super(referenceTree, site, argtypes, typeargtypes, boxingAllowed);
+        }
+
+        @Override
+        ReferenceLookupHelper unboundLookup() {
+            return this;
+        }
+
+        @Override
+        protected Symbol adjustLookupResult(Env<AttrContext> env, Symbol sym) {
+            return sym;
+        }
+
+        @Override
+        ReferenceKind referenceKind(Symbol sym) {
+            return ReferenceKind.UNBOUND_INNER;
+        }
     }
 
     /**
--- a/test/tools/javac/lambda/TargetType43.java	Wed Sep 12 16:16:13 2012 +0100
+++ b/test/tools/javac/lambda/TargetType43.java	Thu Sep 13 13:10:10 2012 +0100
@@ -31,7 +31,7 @@
     void m(Object o) { }
 
     void test(Object obj) {
-        Object o = x-> { new NonExistentClass(); return 5; };
-        m(x-> { new NonExistentClass(); return 5; });
+        Object o = x-> { new NonExistentClass(x); return 5; };
+        m(x-> { new NonExistentClass(x); return 5; });
     }
 }