langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java
changeset 14547 86d8d242b0c4
parent 14541 36f9d11fc9aa
child 14722 aaa39655aa2e
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java	Fri Nov 16 18:27:36 2012 +0000
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java	Sat Nov 17 19:01:03 2012 +0000
@@ -133,7 +133,7 @@
         allowCovariantReturns = source.allowCovariantReturns();
         allowAnonOuterThis = source.allowAnonOuterThis();
         allowStringsInSwitch = source.allowStringsInSwitch();
-        allowPoly = source.allowPoly() && options.isSet("allowPoly");
+        allowPoly = source.allowPoly();
         allowLambda = source.allowLambda();
         allowDefaultMethods = source.allowDefaultMethods();
         sourceName = source.name;
@@ -179,14 +179,14 @@
      */
     boolean allowCovariantReturns;
 
+    /** Switch: support lambda expressions ?
+     */
+    boolean allowLambda;
+
     /** Switch: support default methods ?
      */
     boolean allowDefaultMethods;
 
-    /** Switch: support lambda expressions ?
-     */
-    boolean allowLambda;
-
     /** Switch: allow references to surrounding object from anonymous
      * objects during constructor call?
      */
@@ -524,6 +524,10 @@
         protected ResultInfo dup(Type newPt) {
             return new ResultInfo(pkind, newPt, checkContext);
         }
+
+        protected ResultInfo dup(CheckContext newContext) {
+            return new ResultInfo(pkind, pt, newContext);
+        }
     }
 
     class RecoveryInfo extends ResultInfo {
@@ -540,7 +544,7 @@
                 }
                 @Override
                 public void report(DiagnosticPosition pos, JCDiagnostic details) {
-                    //do nothing
+                    chk.basicHandler.report(pos, details);
                 }
             });
         }
@@ -595,8 +599,10 @@
             this.env = env;
             this.resultInfo = resultInfo;
             tree.accept(this);
-            if (tree == breakTree)
+            if (tree == breakTree &&
+                    resultInfo.checkContext.deferredAttrContext().mode == AttrMode.CHECK) {
                 throw new BreakAttr(env);
+            }
             return result;
         } catch (CompletionFailure ex) {
             tree.type = syms.errType;
@@ -903,7 +909,7 @@
 
             localEnv.info.lint = lint;
 
-            if (isDefaultMethod && types.overridesObjectMethod(m)) {
+            if (isDefaultMethod && types.overridesObjectMethod(m.enclClass(), m)) {
                 log.error(tree, "default.overrides.object.member", m.name, Kinds.kindName(m.location()), m.location());
             }
 
@@ -1390,13 +1396,14 @@
 
         if (!standaloneConditional && resultInfo.pt.hasTag(VOID)) {
             //cannot get here (i.e. it means we are returning from void method - which is already an error)
+            resultInfo.checkContext.report(tree, diags.fragment("conditional.target.cant.be.void"));
             result = tree.type = types.createErrorType(resultInfo.pt);
             return;
         }
 
         ResultInfo condInfo = standaloneConditional ?
                 unknownExprInfo :
-                new ResultInfo(VAL, pt(), new Check.NestedCheckContext(resultInfo.checkContext) {
+                resultInfo.dup(new Check.NestedCheckContext(resultInfo.checkContext) {
                     //this will use enclosing check context to check compatibility of
                     //subexpression against target type; if we are in a method check context,
                     //depending on whether boxing is allowed, we could have incompatibilities
@@ -1419,11 +1426,11 @@
         result = check(tree, owntype, VAL, resultInfo);
     }
     //where
-        @SuppressWarnings("fallthrough")
         private boolean isBooleanOrNumeric(Env<AttrContext> env, JCExpression tree) {
             switch (tree.getTag()) {
                 case LITERAL: return ((JCLiteral)tree).typetag.isSubRangeOf(DOUBLE) ||
-                              ((JCLiteral)tree).typetag == BOOLEAN;
+                              ((JCLiteral)tree).typetag == BOOLEAN ||
+                              ((JCLiteral)tree).typetag == BOT;
                 case LAMBDA: case REFERENCE: return false;
                 case PARENS: return isBooleanOrNumeric(env, ((JCParens)tree).expr);
                 case CONDEXPR:
@@ -1612,19 +1619,23 @@
             // it conforms to result type of enclosing method.
             if (tree.expr != null) {
                 if (env.info.returnResult.pt.hasTag(VOID)) {
-                    log.error(tree.expr.pos(),
-                              "cant.ret.val.from.meth.decl.void");
+                    env.info.returnResult.checkContext.report(tree.expr.pos(),
+                              diags.fragment("unexpected.ret.val"));
                 }
                 attribTree(tree.expr, env, env.info.returnResult);
             } else if (!env.info.returnResult.pt.hasTag(VOID)) {
-                log.error(tree.pos(), "missing.ret.val");
+                env.info.returnResult.checkContext.report(tree.pos(),
+                              diags.fragment("missing.ret.val"));
             }
         }
         result = null;
     }
 
     public void visitThrow(JCThrow tree) {
-        attribExpr(tree.expr, env, syms.throwableType);
+        Type owntype = attribExpr(tree.expr, env, allowPoly ? Type.noType : syms.throwableType);
+        if (allowPoly) {
+            chk.checkType(tree, owntype, syms.throwableType);
+        }
         result = null;
     }
 
@@ -2068,7 +2079,7 @@
                             resultInfo.checkContext.inferenceContext().free(resultInfo.pt) ? Type.noType : pt());
                     Type inferred = deferredAttr.attribSpeculative(tree, env, findDiamondResult).type;
                     if (!inferred.isErroneous() &&
-                        types.isAssignable(inferred, pt().hasTag(NONE) ? syms.objectType : pt(), Warner.noWarnings)) {
+                        types.isAssignable(inferred, pt().hasTag(NONE) ? syms.objectType : pt(), types.noWarnings)) {
                         String key = types.isSameType(clazztype, inferred) ?
                             "diamond.redundant.args" :
                             "diamond.redundant.args.1";
@@ -2172,7 +2183,7 @@
         }
         //create an environment for attribution of the lambda expression
         final Env<AttrContext> localEnv = lambdaEnv(that, env);
-        boolean needsRecovery = resultInfo.checkContext.deferredAttrContext() == deferredAttr.emptyDeferredAttrContext ||
+        boolean needsRecovery =
                 resultInfo.checkContext.deferredAttrContext().mode == DeferredAttr.AttrMode.CHECK;
         try {
             List<Type> explicitParamTypes = null;
@@ -2182,10 +2193,16 @@
                 explicitParamTypes = TreeInfo.types(that.params);
             }
 
-            Type target = infer.instantiateFunctionalInterface(that, pt(), explicitParamTypes, resultInfo.checkContext);
-            Type lambdaType = (target == Type.recoveryType) ?
-                    fallbackDescriptorType(that) :
-                    types.findDescriptorType(target);
+            Type target;
+            Type lambdaType;
+            if (pt() != Type.recoveryType) {
+                target = infer.instantiateFunctionalInterface(that, pt(), explicitParamTypes, resultInfo.checkContext);
+                lambdaType = types.findDescriptorType(target);
+                chk.checkFunctionalInterface(that, target);
+            } else {
+                target = Type.recoveryType;
+                lambdaType = fallbackDescriptorType(that);
+            }
 
             if (!TreeInfo.isExplicitLambda(that)) {
                 //add param type info in the AST
@@ -2250,7 +2267,7 @@
             checkLambdaCompatible(that, lambdaType, resultInfo.checkContext, isSpeculativeRound);
 
             if (!isSpeculativeRound) {
-                checkAccessibleFunctionalDescriptor(that, localEnv, resultInfo.checkContext.inferenceContext(), lambdaType);
+                checkAccessibleTypes(that, localEnv, resultInfo.checkContext.inferenceContext(), lambdaType, target);
             }
             result = check(that, target, VAL, resultInfo);
         } catch (Types.FunctionDescriptorLookupError ex) {
@@ -2285,17 +2302,22 @@
             return null;
         }
 
-        private void checkAccessibleFunctionalDescriptor(final DiagnosticPosition pos,
-                final Env<AttrContext> env, final InferenceContext inferenceContext, final Type desc) {
-            if (inferenceContext.free(desc)) {
-                inferenceContext.addFreeTypeListener(List.of(desc), new FreeTypeListener() {
+        private void checkAccessibleTypes(final DiagnosticPosition pos, final Env<AttrContext> env, final InferenceContext inferenceContext, final Type... ts) {
+            checkAccessibleTypes(pos, env, inferenceContext, List.from(ts));
+        }
+
+        private void checkAccessibleTypes(final DiagnosticPosition pos, final Env<AttrContext> env, final InferenceContext inferenceContext, final List<Type> ts) {
+            if (inferenceContext.free(ts)) {
+                inferenceContext.addFreeTypeListener(ts, new FreeTypeListener() {
                     @Override
                     public void typesInferred(InferenceContext inferenceContext) {
-                        checkAccessibleFunctionalDescriptor(pos, env, inferenceContext, inferenceContext.asInstType(desc, types));
+                        checkAccessibleTypes(pos, env, inferenceContext, inferenceContext.asInstTypes(ts, types));
                     }
                 });
             } else {
-                chk.checkAccessibleFunctionalDescriptor(pos, env, desc);
+                for (Type t : ts) {
+                    rs.checkAccessibleType(env, t);
+                }
             }
         }
 
@@ -2411,15 +2433,20 @@
                 typeargtypes = attribTypes(that.typeargs, localEnv);
             }
 
-            Type target = infer.instantiateFunctionalInterface(that, pt(), null, resultInfo.checkContext);
-            Type desc = (target == Type.recoveryType) ?
-                    fallbackDescriptorType(that) :
-                    types.findDescriptorType(target);
+            Type target;
+            Type desc;
+            if (pt() != Type.recoveryType) {
+                target = infer.instantiateFunctionalInterface(that, pt(), null, resultInfo.checkContext);
+                desc = types.findDescriptorType(target);
+                chk.checkFunctionalInterface(that, target);
+            } else {
+                target = Type.recoveryType;
+                desc = fallbackDescriptorType(that);
+            }
 
             List<Type> argtypes = desc.getParameterTypes();
 
             boolean allowBoxing =
-                    resultInfo.checkContext.deferredAttrContext() == deferredAttr.emptyDeferredAttrContext ||
                     resultInfo.checkContext.deferredAttrContext().phase.isBoxingRequired();
             Pair<Symbol, Resolve.ReferenceLookupHelper> refResult = rs.resolveMemberReference(that.pos(), localEnv, that,
                     that.expr.type, that.name, argtypes, typeargtypes, allowBoxing);
@@ -2455,18 +2482,25 @@
                 JCDiagnostic diag = diags.create(diagKind, log.currentSource(), that,
                         "invalid.mref", Kinds.kindName(that.getMode()), detailsDiag);
 
-                if (targetError) {
-                    resultInfo.checkContext.report(that, diag);
+                if (targetError && target == Type.recoveryType) {
+                    //a target error doesn't make sense during recovery stage
+                    //as we don't know what actual parameter types are
+                    result = that.type = target;
+                    return;
                 } else {
-                    log.report(diag);
+                    if (targetError) {
+                        resultInfo.checkContext.report(that, diag);
+                    } else {
+                        log.report(diag);
+                    }
+                    result = that.type = types.createErrorType(target);
+                    return;
                 }
-                result = that.type = types.createErrorType(target);
-                return;
             }
 
             if (desc.getReturnType() == Type.recoveryType) {
                 // stop here
-                result = that.type = types.createErrorType(target);
+                result = that.type = target;
                 return;
             }
 
@@ -2492,7 +2526,7 @@
                     resultInfo.checkContext.deferredAttrContext().mode == DeferredAttr.AttrMode.SPECULATIVE;
             checkReferenceCompatible(that, desc, refType, resultInfo.checkContext, isSpeculativeRound);
             if (!isSpeculativeRound) {
-                checkAccessibleFunctionalDescriptor(that, localEnv, resultInfo.checkContext.inferenceContext(), desc);
+                checkAccessibleTypes(that, localEnv, resultInfo.checkContext.inferenceContext(), desc, target);
             }
             result = check(that, target, VAL, resultInfo);
         } catch (Types.FunctionDescriptorLookupError ex) {
@@ -2526,7 +2560,7 @@
 
         if (!returnType.hasTag(VOID) && !resType.hasTag(VOID)) {
             if (resType.isErroneous() ||
-                    new LambdaReturnContext(checkContext).compatible(resType, returnType, Warner.noWarnings)) {
+                    new LambdaReturnContext(checkContext).compatible(resType, returnType, types.noWarnings)) {
                 incompatibleReturnType = null;
             }
         }
@@ -3039,15 +3073,52 @@
                      Symbol sym,
                      Env<AttrContext> env,
                      ResultInfo resultInfo) {
-            Type pt = resultInfo.pt.hasTag(FORALL) || resultInfo.pt.hasTag(METHOD) ?
-                    resultInfo.pt.map(deferredAttr.new DeferredTypeMap(AttrMode.SPECULATIVE, sym, env.info.pendingResolutionPhase)) :
-                    resultInfo.pt;
-
-            DeferredAttr.DeferredTypeMap recoveryMap =
-                    deferredAttr.new RecoveryDeferredTypeMap(AttrMode.CHECK, sym, env.info.pendingResolutionPhase);
-
+            return (resultInfo.pt.hasTag(FORALL) || resultInfo.pt.hasTag(METHOD)) ?
+                    checkMethodId(tree, site, sym, env, resultInfo) :
+                    checkIdInternal(tree, site, sym, resultInfo.pt, env, resultInfo);
+        }
+
+        Type checkMethodId(JCTree tree,
+                     Type site,
+                     Symbol sym,
+                     Env<AttrContext> env,
+                     ResultInfo resultInfo) {
+            boolean isPolymorhicSignature =
+                sym.kind == MTH && ((MethodSymbol)sym.baseSymbol()).isSignaturePolymorphic(types);
+            return isPolymorhicSignature ?
+                    checkSigPolyMethodId(tree, site, sym, env, resultInfo) :
+                    checkMethodIdInternal(tree, site, sym, env, resultInfo);
+        }
+
+        Type checkSigPolyMethodId(JCTree tree,
+                     Type site,
+                     Symbol sym,
+                     Env<AttrContext> env,
+                     ResultInfo resultInfo) {
+            //recover original symbol for signature polymorphic methods
+            checkMethodIdInternal(tree, site, sym.baseSymbol(), env, resultInfo);
+            env.info.pendingResolutionPhase = Resolve.MethodResolutionPhase.BASIC;
+            return sym.type;
+        }
+
+        Type checkMethodIdInternal(JCTree tree,
+                     Type site,
+                     Symbol sym,
+                     Env<AttrContext> env,
+                     ResultInfo resultInfo) {
+            Type pt = resultInfo.pt.map(deferredAttr.new RecoveryDeferredTypeMap(AttrMode.SPECULATIVE, sym, env.info.pendingResolutionPhase));
+            Type owntype = checkIdInternal(tree, site, sym, pt, env, resultInfo);
+            resultInfo.pt.map(deferredAttr.new RecoveryDeferredTypeMap(AttrMode.CHECK, sym, env.info.pendingResolutionPhase));
+            return owntype;
+        }
+
+        Type checkIdInternal(JCTree tree,
+                     Type site,
+                     Symbol sym,
+                     Type pt,
+                     Env<AttrContext> env,
+                     ResultInfo resultInfo) {
             if (pt.isErroneous()) {
-                Type.map(resultInfo.pt.getParameterTypes(), recoveryMap);
                 return types.createErrorType(site);
             }
             Type owntype; // The computed type of this identifier occurrence.
@@ -3132,7 +3203,6 @@
                 break;
             }
             case PCK: case ERR:
-                Type.map(resultInfo.pt.getParameterTypes(), recoveryMap);
                 owntype = sym.type;
                 break;
             default:
@@ -3288,21 +3358,21 @@
             }
         }
 
-        if (env.info.defaultSuperCallSite != null &&
-                !types.interfaceCandidates(env.enclClass.type, (MethodSymbol)sym, true).contains(sym)) {
-            Symbol ovSym = null;
-            for (MethodSymbol msym : types.interfaceCandidates(env.enclClass.type, (MethodSymbol)sym, true)) {
-                if (msym.overrides(sym, msym.enclClass(), types, true)) {
-                    for (Type i : types.interfaces(env.enclClass.type)) {
-                        if (i.tsym.isSubClass(msym.owner, types)) {
-                            ovSym = i.tsym;
-                            break;
-                        }
-                    }
+        if (env.info.defaultSuperCallSite != null) {
+            for (Type sup : types.interfaces(env.enclClass.type).prepend(types.supertype((env.enclClass.type)))) {
+                if (!sup.tsym.isSubClass(sym.enclClass(), types) ||
+                        types.isSameType(sup, env.info.defaultSuperCallSite)) continue;
+                List<MethodSymbol> icand_sup =
+                        types.interfaceCandidates(sup, (MethodSymbol)sym);
+                if (icand_sup.nonEmpty() &&
+                        icand_sup.head != sym &&
+                        icand_sup.head.overrides(sym, icand_sup.head.enclClass(), types, true)) {
+                    log.error(env.tree.pos(), "illegal.default.super.call", env.info.defaultSuperCallSite,
+                        diags.fragment("overridden.default", sym, sup));
+                    break;
                 }
             }
-            log.error(env.tree.pos(), "illegal.default.super.call", env.info.defaultSuperCallSite,
-                    diags.fragment("overridden.default", sym, ovSym));
+            env.info.defaultSuperCallSite = null;
         }
 
         // Compute the identifier's instantiated type.