8007479: Refactor DeferredAttrContext so that it points to parent context
Summary: Move DeferredAttrNode out of DeferredAttrContext; add support for nested deferred contexts
Reviewed-by: jjg
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/DeferredAttr.java Wed Feb 06 14:03:39 2013 +0000
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/DeferredAttr.java Wed Feb 06 14:04:43 2013 +0000
@@ -332,13 +332,22 @@
/** inference context */
final InferenceContext inferenceContext;
+ /** parent deferred context */
+ final DeferredAttrContext parent;
+
+ /** Warner object to report warnings */
+ final Warner warn;
+
/** list of deferred attribution nodes to be processed */
ArrayList<DeferredAttrNode> deferredAttrNodes = new ArrayList<DeferredAttrNode>();
- DeferredAttrContext(AttrMode mode, Symbol msym, MethodResolutionPhase phase, InferenceContext inferenceContext) {
+ DeferredAttrContext(AttrMode mode, Symbol msym, MethodResolutionPhase phase,
+ InferenceContext inferenceContext, DeferredAttrContext parent, Warner warn) {
this.mode = mode;
this.msym = msym;
this.phase = phase;
+ this.parent = parent;
+ this.warn = warn;
this.inferenceContext = inferenceContext;
}
@@ -363,7 +372,7 @@
//scan a defensive copy of the node list - this is because a deferred
//attribution round can add new nodes to the list
for (DeferredAttrNode deferredAttrNode : List.from(deferredAttrNodes)) {
- if (!deferredAttrNode.process()) {
+ if (!deferredAttrNode.process(this)) {
stuckVars.addAll(deferredAttrNode.stuckVars);
} else {
deferredAttrNodes.remove(deferredAttrNode);
@@ -378,118 +387,120 @@
}
}
}
+ }
+
+ /**
+ * Class representing a deferred attribution node. It keeps track of
+ * a deferred type, along with the expected target type information.
+ */
+ class DeferredAttrNode implements Infer.FreeTypeListener {
+
+ /** underlying deferred type */
+ DeferredType dt;
+
+ /** underlying target type information */
+ ResultInfo resultInfo;
+
+ /** list of uninferred inference variables causing this node to be stuck */
+ List<Type> stuckVars;
+
+ DeferredAttrNode(DeferredType dt, ResultInfo resultInfo, List<Type> stuckVars) {
+ this.dt = dt;
+ this.resultInfo = resultInfo;
+ this.stuckVars = stuckVars;
+ if (!stuckVars.isEmpty()) {
+ resultInfo.checkContext.inferenceContext().addFreeTypeListener(stuckVars, this);
+ }
+ }
+
+ @Override
+ public void typesInferred(InferenceContext inferenceContext) {
+ stuckVars = List.nil();
+ resultInfo = resultInfo.dup(inferenceContext.asInstType(resultInfo.pt));
+ }
/**
- * Class representing a deferred attribution node. It keeps track of
- * a deferred type, along with the expected target type information.
+ * Process a deferred attribution node.
+ * Invariant: a stuck node cannot be processed.
*/
- class DeferredAttrNode implements Infer.FreeTypeListener {
+ @SuppressWarnings("fallthrough")
+ boolean process(DeferredAttrContext deferredAttrContext) {
+ switch (deferredAttrContext.mode) {
+ case SPECULATIVE:
+ dt.check(resultInfo, List.<Type>nil(), new StructuralStuckChecker());
+ return true;
+ case CHECK:
+ if (stuckVars.nonEmpty()) {
+ return false;
+ } else {
+ dt.check(resultInfo, stuckVars, basicCompleter);
+ return true;
+ }
+ default:
+ throw new AssertionError("Bad mode");
+ }
+ }
- /** underlying deferred type */
- DeferredType dt;
+ /**
+ * Structural checker for stuck expressions
+ */
+ class StructuralStuckChecker extends TreeScanner implements DeferredTypeCompleter {
- /** underlying target type information */
ResultInfo resultInfo;
+ InferenceContext inferenceContext;
- /** list of uninferred inference variables causing this node to be stuck */
- List<Type> stuckVars;
+ public Type complete(DeferredType dt, ResultInfo resultInfo, DeferredAttrContext deferredAttrContext) {
+ this.resultInfo = resultInfo;
+ this.inferenceContext = deferredAttrContext.inferenceContext;
+ dt.tree.accept(this);
+ dt.speculativeCache.put(deferredAttrContext.msym, stuckTree, deferredAttrContext.phase);
+ return Type.noType;
+ }
- DeferredAttrNode(DeferredType dt, ResultInfo resultInfo, List<Type> stuckVars) {
- this.dt = dt;
- this.resultInfo = resultInfo;
- this.stuckVars = stuckVars;
- if (!stuckVars.isEmpty()) {
- resultInfo.checkContext.inferenceContext().addFreeTypeListener(stuckVars, this);
+ @Override
+ public void visitLambda(JCLambda tree) {
+ Check.CheckContext checkContext = resultInfo.checkContext;
+ Type pt = resultInfo.pt;
+ if (inferenceContext.inferencevars.contains(pt)) {
+ //ok
+ return;
+ } else {
+ //must be a functional descriptor
+ try {
+ Type desc = types.findDescriptorType(pt);
+ if (desc.getParameterTypes().length() != tree.params.length()) {
+ checkContext.report(tree, diags.fragment("incompatible.arg.types.in.lambda"));
+ }
+ } catch (Types.FunctionDescriptorLookupError ex) {
+ checkContext.report(null, ex.getDiagnostic());
+ }
}
}
@Override
- public void typesInferred(InferenceContext inferenceContext) {
- stuckVars = List.nil();
- resultInfo = resultInfo.dup(inferenceContext.asInstType(resultInfo.pt));
+ public void visitNewClass(JCNewClass tree) {
+ //do nothing
}
- /**
- * Process a deferred attribution node.
- * Invariant: a stuck node cannot be processed.
- */
- @SuppressWarnings("fallthrough")
- boolean process() {
- switch (mode) {
- case SPECULATIVE:
- dt.check(resultInfo, List.<Type>nil(), new StructuralStuckChecker());
- return true;
- case CHECK:
- if (stuckVars.nonEmpty()) {
- return false;
- } else {
- dt.check(resultInfo, stuckVars, basicCompleter);
- return true;
- }
- default:
- throw new AssertionError("Bad mode");
- }
+ @Override
+ public void visitApply(JCMethodInvocation tree) {
+ //do nothing
}
- /**
- * Structural checker for stuck expressions
- */
- class StructuralStuckChecker extends TreeScanner implements DeferredTypeCompleter {
-
- ResultInfo resultInfo;
-
- public Type complete(DeferredType dt, ResultInfo resultInfo, DeferredAttrContext deferredAttrContext) {
- this.resultInfo = resultInfo;
- dt.tree.accept(this);
- dt.speculativeCache.put(msym, stuckTree, phase);
- return Type.noType;
- }
-
- @Override
- public void visitLambda(JCLambda tree) {
- Check.CheckContext checkContext = resultInfo.checkContext;
- Type pt = resultInfo.pt;
- if (inferenceContext.inferencevars.contains(pt)) {
- //ok
- return;
- } else {
- //must be a functional descriptor
- try {
- Type desc = types.findDescriptorType(pt);
- if (desc.getParameterTypes().length() != tree.params.length()) {
- checkContext.report(tree, diags.fragment("incompatible.arg.types.in.lambda"));
- }
- } catch (Types.FunctionDescriptorLookupError ex) {
- checkContext.report(null, ex.getDiagnostic());
- }
- }
- }
-
- @Override
- public void visitNewClass(JCNewClass tree) {
- //do nothing
- }
-
- @Override
- public void visitApply(JCMethodInvocation tree) {
- //do nothing
- }
-
- @Override
- public void visitReference(JCMemberReference tree) {
- Check.CheckContext checkContext = resultInfo.checkContext;
- Type pt = resultInfo.pt;
- if (inferenceContext.inferencevars.contains(pt)) {
- //ok
- return;
- } else {
- try {
- //TODO: we should speculative determine if there's a match
- //based on arity - if yes, method is applicable.
- types.findDescriptorType(pt);
- } catch (Types.FunctionDescriptorLookupError ex) {
- checkContext.report(null, ex.getDiagnostic());
- }
+ @Override
+ public void visitReference(JCMemberReference tree) {
+ Check.CheckContext checkContext = resultInfo.checkContext;
+ Type pt = resultInfo.pt;
+ if (inferenceContext.inferencevars.contains(pt)) {
+ //ok
+ return;
+ } else {
+ try {
+ //TODO: we should speculative determine if there's a match
+ //based on arity - if yes, method is applicable.
+ types.findDescriptorType(pt);
+ } catch (Types.FunctionDescriptorLookupError ex) {
+ checkContext.report(null, ex.getDiagnostic());
}
}
}
@@ -498,7 +509,7 @@
/** an empty deferred attribution context - all methods throw exceptions */
final DeferredAttrContext emptyDeferredAttrContext =
- new DeferredAttrContext(AttrMode.CHECK, null, MethodResolutionPhase.BOX, null) {
+ new DeferredAttrContext(AttrMode.CHECK, null, MethodResolutionPhase.BOX, null, null, null) {
@Override
void addDeferredAttrNode(DeferredType dt, ResultInfo ri, List<Type> stuckVars) {
Assert.error("Empty deferred context!");
@@ -521,7 +532,8 @@
protected DeferredTypeMap(AttrMode mode, Symbol msym, MethodResolutionPhase phase) {
super(String.format("deferredTypeMap[%s]", mode));
- this.deferredAttrContext = new DeferredAttrContext(mode, msym, phase, infer.emptyContext);
+ this.deferredAttrContext = new DeferredAttrContext(mode, msym, phase,
+ infer.emptyContext, emptyDeferredAttrContext, types.noWarnings);
}
protected boolean validState(DeferredType dt) {
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Infer.java Wed Feb 06 14:03:39 2013 +0000
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Infer.java Wed Feb 06 14:04:43 2013 +0000
@@ -269,7 +269,7 @@
inferenceException.clear();
DeferredAttr.DeferredAttrContext deferredAttrContext =
- resolveContext.deferredAttrContext(msym, inferenceContext);
+ resolveContext.deferredAttrContext(msym, inferenceContext, resultInfo, warn);
try {
methodCheck.argumentsAcceptable(env, deferredAttrContext, argtypes, mt.getParameterTypes(), warn);
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java Wed Feb 06 14:03:39 2013 +0000
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java Wed Feb 06 14:04:43 2013 +0000
@@ -564,7 +564,7 @@
methodCheck,
warn);
- methodCheck.argumentsAcceptable(env, currentResolutionContext.deferredAttrContext(m, infer.emptyContext),
+ methodCheck.argumentsAcceptable(env, currentResolutionContext.deferredAttrContext(m, infer.emptyContext, resultInfo, warn),
argtypes, mt.getParameterTypes(), warn);
return mt;
}
@@ -3589,8 +3589,8 @@
candidates = candidates.append(c);
}
- DeferredAttrContext deferredAttrContext(Symbol sym, InferenceContext inferenceContext) {
- return deferredAttr.new DeferredAttrContext(attrMode, sym, step, inferenceContext);
+ DeferredAttrContext deferredAttrContext(Symbol sym, InferenceContext inferenceContext, ResultInfo pendingResult, Warner warn) {
+ return deferredAttr.new DeferredAttrContext(attrMode, sym, step, inferenceContext, pendingResult != null ? pendingResult.checkContext.deferredAttrContext() : deferredAttr.emptyDeferredAttrContext, warn);
}
/**