OpenJDK / lambda / lambda / langtools
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; }); } }