1.1 --- a/src/share/classes/com/sun/tools/javac/comp/Attr.java Tue Oct 27 10:35:14 2015 +0100 1.2 +++ b/src/share/classes/com/sun/tools/javac/comp/Attr.java Thu Nov 12 21:20:49 2015 +0000 1.3 @@ -156,6 +156,8 @@ 1.4 unknownTypeInfo = new ResultInfo(TYP, Type.noType); 1.5 unknownTypeExprInfo = new ResultInfo(Kinds.TYP | Kinds.VAL, Type.noType); 1.6 recoveryInfo = new RecoveryInfo(deferredAttr.emptyDeferredAttrContext); 1.7 + 1.8 + noCheckTree = make.at(-1).Skip(); 1.9 } 1.10 1.11 /** Switch: relax some constraints for retrofit mode. 1.12 @@ -253,31 +255,34 @@ 1.13 Type check(final JCTree tree, final Type found, final int ownkind, final ResultInfo resultInfo) { 1.14 InferenceContext inferenceContext = resultInfo.checkContext.inferenceContext(); 1.15 Type owntype; 1.16 - if (!found.hasTag(ERROR) && !resultInfo.pt.hasTag(METHOD) && !resultInfo.pt.hasTag(FORALL)) { 1.17 - if ((ownkind & ~resultInfo.pkind) != 0) { 1.18 - log.error(tree.pos(), "unexpected.type", 1.19 + boolean shouldCheck = !found.hasTag(ERROR) && 1.20 + !resultInfo.pt.hasTag(METHOD) && 1.21 + !resultInfo.pt.hasTag(FORALL); 1.22 + if (shouldCheck && (ownkind & ~resultInfo.pkind) != 0) { 1.23 + log.error(tree.pos(), "unexpected.type", 1.24 kindNames(resultInfo.pkind), 1.25 kindName(ownkind)); 1.26 - owntype = types.createErrorType(found); 1.27 - } else if (allowPoly && inferenceContext.free(found)) { 1.28 - //delay the check if there are inference variables in the found type 1.29 - //this means we are dealing with a partially inferred poly expression 1.30 - owntype = resultInfo.pt; 1.31 - inferenceContext.addFreeTypeListener(List.of(found, resultInfo.pt), new FreeTypeListener() { 1.32 + owntype = types.createErrorType(found); 1.33 + } else if (allowPoly && inferenceContext.free(found)) { 1.34 + //delay the check if there are inference variables in the found type 1.35 + //this means we are dealing with a partially inferred poly expression 1.36 + owntype = shouldCheck ? resultInfo.pt : found; 1.37 + inferenceContext.addFreeTypeListener(List.of(found, resultInfo.pt), new FreeTypeListener() { 1.38 @Override 1.39 public void typesInferred(InferenceContext inferenceContext) { 1.40 ResultInfo pendingResult = 1.41 resultInfo.dup(inferenceContext.asInstType(resultInfo.pt)); 1.42 check(tree, inferenceContext.asInstType(found), ownkind, pendingResult); 1.43 } 1.44 - }); 1.45 - } else { 1.46 - owntype = resultInfo.check(tree, found); 1.47 - } 1.48 + }); 1.49 } else { 1.50 - owntype = found; 1.51 + owntype = shouldCheck ? 1.52 + resultInfo.check(tree, found) : 1.53 + found; 1.54 } 1.55 - tree.type = owntype; 1.56 + if (tree != noCheckTree) { 1.57 + tree.type = owntype; 1.58 + } 1.59 return owntype; 1.60 } 1.61 1.62 @@ -550,6 +555,10 @@ 1.63 */ 1.64 Type result; 1.65 1.66 + /** Synthetic tree to be used during 'fake' checks. 1.67 + */ 1.68 + JCTree noCheckTree; 1.69 + 1.70 /** Visitor method: attribute a tree, catching any completion failure 1.71 * exceptions. Return the tree's type. 1.72 * 1.73 @@ -2043,7 +2052,7 @@ 1.74 } 1.75 }); 1.76 Type constructorType = tree.constructorType = types.createErrorType(clazztype); 1.77 - constructorType = checkId(tree, site, 1.78 + constructorType = checkId(noCheckTree, site, 1.79 constructor, 1.80 diamondEnv, 1.81 diamondResult); 1.82 @@ -2069,7 +2078,7 @@ 1.83 tree.constructor = rs.resolveConstructor( 1.84 tree.pos(), rsEnv, clazztype, argtypes, typeargtypes); 1.85 if (cdef == null) { //do not check twice! 1.86 - tree.constructorType = checkId(tree, 1.87 + tree.constructorType = checkId(noCheckTree, 1.88 clazztype, 1.89 tree.constructor, 1.90 rsEnv, 1.91 @@ -2150,7 +2159,7 @@ 1.92 tree.pos(), localEnv, clazztype, argtypes, typeargtypes); 1.93 Assert.check(sym.kind < AMBIGUOUS); 1.94 tree.constructor = sym; 1.95 - tree.constructorType = checkId(tree, 1.96 + tree.constructorType = checkId(noCheckTree, 1.97 clazztype, 1.98 tree.constructor, 1.99 localEnv, 1.100 @@ -2161,6 +2170,17 @@ 1.101 owntype = clazztype; 1.102 } 1.103 result = check(tree, owntype, VAL, resultInfo); 1.104 + InferenceContext inferenceContext = resultInfo.checkContext.inferenceContext(); 1.105 + if (tree.constructorType != null && inferenceContext.free(tree.constructorType)) { 1.106 + //we need to wait for inference to finish and then replace inference vars in the constructor type 1.107 + inferenceContext.addFreeTypeListener(List.of(tree.constructorType), 1.108 + new FreeTypeListener() { 1.109 + @Override 1.110 + public void typesInferred(InferenceContext instantiatedContext) { 1.111 + tree.constructorType = instantiatedContext.asInstType(tree.constructorType); 1.112 + } 1.113 + }); 1.114 + } 1.115 chk.validate(tree.typeargs, localEnv); 1.116 } 1.117 //where 1.118 @@ -2388,6 +2408,7 @@ 1.119 preFlow(that); 1.120 flow.analyzeLambda(env, that, make, isSpeculativeRound); 1.121 1.122 + that.type = currentTarget; //avoids recovery at this stage 1.123 checkLambdaCompatible(that, lambdaType, resultInfo.checkContext); 1.124 1.125 if (!isSpeculativeRound) { 1.126 @@ -2826,7 +2847,7 @@ 1.127 that.kind.isUnbound() ? argtypes.tail : argtypes, typeargtypes), 1.128 new FunctionalReturnContext(resultInfo.checkContext)); 1.129 1.130 - Type refType = checkId(that, lookupHelper.site, refSym, localEnv, checkInfo); 1.131 + Type refType = checkId(noCheckTree, lookupHelper.site, refSym, localEnv, checkInfo); 1.132 1.133 if (that.kind.isUnbound() && 1.134 resultInfo.checkContext.inferenceContext().free(argtypes.head)) { 1.135 @@ -2848,6 +2869,8 @@ 1.136 //is a no-op (as this has been taken care during method applicability) 1.137 boolean isSpeculativeRound = 1.138 resultInfo.checkContext.deferredAttrContext().mode == DeferredAttr.AttrMode.SPECULATIVE; 1.139 + 1.140 + that.type = currentTarget; //avoids recovery at this stage 1.141 checkReferenceCompatible(that, desc, refType, resultInfo.checkContext, isSpeculativeRound); 1.142 if (!isSpeculativeRound) { 1.143 checkAccessibleTypes(that, localEnv, resultInfo.checkContext.inferenceContext(), desc, currentTarget); 1.144 @@ -3968,7 +3991,7 @@ 1.145 all_multicatchTypes.append(ctype); 1.146 } 1.147 } 1.148 - Type t = check(tree, types.lub(multicatchTypes.toList()), TYP, resultInfo); 1.149 + Type t = check(noCheckTree, types.lub(multicatchTypes.toList()), TYP, resultInfo); 1.150 if (t.hasTag(CLASS)) { 1.151 List<Type> alternatives = 1.152 ((all_multicatchTypes == null) ? multicatchTypes : all_multicatchTypes).toList();