提交 66fc167d 编写于 作者: M mcimadamore

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
上级 cb22b5bc
......@@ -332,13 +332,22 @@ public class DeferredAttr extends JCTree.Visitor {
/** 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 @@ public class DeferredAttr extends JCTree.Visitor {
//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 @@ public class DeferredAttr extends JCTree.Visitor {
}
}
}
}
/**
* 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 {
/**
* 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 deferred type */
DeferredType dt;
/** underlying target type information */
ResultInfo resultInfo;
/** underlying target type information */
ResultInfo resultInfo;
/** list of uninferred inference variables causing this node to be stuck */
List<Type> stuckVars;
/** 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);
}
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));
}
@Override
public void typesInferred(InferenceContext inferenceContext) {
stuckVars = List.nil();
resultInfo = resultInfo.dup(inferenceContext.asInstType(resultInfo.pt));
}
/**
* 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());
/**
* Process a deferred attribution node.
* Invariant: a stuck node cannot be processed.
*/
@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;
case CHECK:
if (stuckVars.nonEmpty()) {
return false;
} else {
dt.check(resultInfo, stuckVars, basicCompleter);
return true;
}
default:
throw new AssertionError("Bad mode");
}
}
default:
throw new AssertionError("Bad mode");
}
}
/**
* Structural checker for stuck expressions
*/
class StructuralStuckChecker extends TreeScanner implements DeferredTypeCompleter {
/**
* Structural checker for stuck expressions
*/
class StructuralStuckChecker extends TreeScanner implements DeferredTypeCompleter {
ResultInfo resultInfo;
ResultInfo resultInfo;
InferenceContext inferenceContext;
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;
}
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;
}
@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 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 visitNewClass(JCNewClass tree) {
//do nothing
}
@Override
public void visitApply(JCMethodInvocation 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 @@ public class DeferredAttr extends JCTree.Visitor {
/** 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 @@ public class DeferredAttr extends JCTree.Visitor {
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) {
......
......@@ -269,7 +269,7 @@ public class Infer {
inferenceException.clear();
DeferredAttr.DeferredAttrContext deferredAttrContext =
resolveContext.deferredAttrContext(msym, inferenceContext);
resolveContext.deferredAttrContext(msym, inferenceContext, resultInfo, warn);
try {
methodCheck.argumentsAcceptable(env, deferredAttrContext, argtypes, mt.getParameterTypes(), warn);
......
......@@ -564,7 +564,7 @@ public class Resolve {
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 @@ public class Resolve {
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);
}
/**
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册