--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java Wed Dec 17 12:48:04 2014 -0800
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java Thu Dec 18 13:21:44 2014 +0000
@@ -155,6 +155,8 @@
unknownTypeInfo = new ResultInfo(KindSelector.TYP, Type.noType);
unknownTypeExprInfo = new ResultInfo(KindSelector.VAL_TYP, Type.noType);
recoveryInfo = new RecoveryInfo(deferredAttr.emptyDeferredAttrContext);
+
+ noCheckTree = make.at(-1).Skip();
}
/** Switch: relax some constraints for retrofit mode.
@@ -214,31 +216,32 @@
final ResultInfo resultInfo) {
InferenceContext inferenceContext = resultInfo.checkContext.inferenceContext();
Type owntype;
- if (!found.hasTag(ERROR) && !resultInfo.pt.hasTag(METHOD) && !resultInfo.pt.hasTag(FORALL)) {
- if (!ownkind.subset(resultInfo.pkind)) {
- log.error(tree.pos(), "unexpected.type",
- resultInfo.pkind.kindNames(),
- ownkind.kindNames());
- owntype = types.createErrorType(found);
- } else if (allowPoly && inferenceContext.free(found)) {
- //delay the check if there are inference variables in the found type
- //this means we are dealing with a partially inferred poly expression
- owntype = resultInfo.pt;
- inferenceContext.addFreeTypeListener(List.of(found, resultInfo.pt), new FreeTypeListener() {
- @Override
- public void typesInferred(InferenceContext inferenceContext) {
+ boolean shouldCheck = !found.hasTag(ERROR) &&
+ !resultInfo.pt.hasTag(METHOD) &&
+ !resultInfo.pt.hasTag(FORALL);
+ if (shouldCheck && !ownkind.subset(resultInfo.pkind)) {
+ log.error(tree.pos(), "unexpected.type",
+ resultInfo.pkind.kindNames(),
+ ownkind.kindNames());
+ owntype = types.createErrorType(found);
+ } else if (allowPoly && inferenceContext.free(found)) {
+ //delay the check if there are inference variables in the found type
+ //this means we are dealing with a partially inferred poly expression
+ owntype = shouldCheck ? resultInfo.pt : found;
+ inferenceContext.addFreeTypeListener(List.of(found, resultInfo.pt),
+ instantiatedContext -> {
ResultInfo pendingResult =
resultInfo.dup(inferenceContext.asInstType(resultInfo.pt));
check(tree, inferenceContext.asInstType(found), ownkind, pendingResult);
- }
- });
- } else {
- owntype = resultInfo.check(tree, found);
- }
+ });
} else {
- owntype = found;
+ owntype = shouldCheck ?
+ resultInfo.check(tree, found) :
+ found;
}
- tree.type = owntype;
+ if (tree != noCheckTree) {
+ tree.type = owntype;
+ }
return owntype;
}
@@ -514,6 +517,10 @@
*/
Type result;
+ /** Synthetic tree to be used during 'fake' checks.
+ */
+ JCTree noCheckTree;
+
/** Visitor method: attribute a tree, catching any completion failure
* exceptions. Return the tree's type.
*
@@ -2007,7 +2014,7 @@
}
});
Type constructorType = tree.constructorType = types.createErrorType(clazztype);
- constructorType = checkId(tree, site,
+ constructorType = checkId(noCheckTree, site,
constructor,
diamondEnv,
diamondResult);
@@ -2033,7 +2040,7 @@
tree.constructor = rs.resolveConstructor(
tree.pos(), rsEnv, clazztype, argtypes, typeargtypes);
if (cdef == null) { //do not check twice!
- tree.constructorType = checkId(tree,
+ tree.constructorType = checkId(noCheckTree,
clazztype,
tree.constructor,
rsEnv,
@@ -2103,7 +2110,7 @@
tree.pos(), localEnv, clazztype, argtypes, typeargtypes);
Assert.check(!sym.kind.isOverloadError());
tree.constructor = sym;
- tree.constructorType = checkId(tree,
+ tree.constructorType = checkId(noCheckTree,
clazztype,
tree.constructor,
localEnv,
@@ -2114,6 +2121,14 @@
owntype = clazztype;
}
result = check(tree, owntype, KindSelector.VAL, resultInfo);
+ InferenceContext inferenceContext = resultInfo.checkContext.inferenceContext();
+ if (tree.constructorType != null && inferenceContext.free(tree.constructorType)) {
+ //we need to wait for inference to finish and then replace inference vars in the constructor type
+ inferenceContext.addFreeTypeListener(List.of(tree.constructorType),
+ instantiatedContext -> {
+ tree.constructorType = instantiatedContext.asInstType(tree.constructorType);
+ });
+ }
chk.validate(tree.typeargs, localEnv);
}
@@ -2290,6 +2305,7 @@
preFlow(that);
flow.analyzeLambda(env, that, make, isSpeculativeRound);
+ that.type = currentTarget; //avoids recovery at this stage
checkLambdaCompatible(that, lambdaType, resultInfo.checkContext);
if (!isSpeculativeRound) {
@@ -2730,7 +2746,7 @@
that.kind.isUnbound() ? argtypes.tail : argtypes, typeargtypes),
new FunctionalReturnContext(resultInfo.checkContext));
- Type refType = checkId(that, lookupHelper.site, refSym, localEnv, checkInfo);
+ Type refType = checkId(noCheckTree, lookupHelper.site, refSym, localEnv, checkInfo);
if (that.kind.isUnbound() &&
resultInfo.checkContext.inferenceContext().free(argtypes.head)) {
@@ -2752,6 +2768,8 @@
//is a no-op (as this has been taken care during method applicability)
boolean isSpeculativeRound =
resultInfo.checkContext.deferredAttrContext().mode == DeferredAttr.AttrMode.SPECULATIVE;
+
+ that.type = currentTarget; //avoids recovery at this stage
checkReferenceCompatible(that, desc, refType, resultInfo.checkContext, isSpeculativeRound);
if (!isSpeculativeRound) {
checkAccessibleTypes(that, localEnv, resultInfo.checkContext.inferenceContext(), desc, currentTarget);
@@ -3882,7 +3900,7 @@
all_multicatchTypes.append(ctype);
}
}
- Type t = check(tree, types.lub(multicatchTypes.toList()),
+ Type t = check(noCheckTree, types.lub(multicatchTypes.toList()),
KindSelector.TYP, resultInfo);
if (t.hasTag(CLASS)) {
List<Type> alternatives =