Wed, 06 Feb 2013 14:04:43 +0000
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
1.1 --- a/src/share/classes/com/sun/tools/javac/comp/DeferredAttr.java Wed Feb 06 14:03:39 2013 +0000 1.2 +++ b/src/share/classes/com/sun/tools/javac/comp/DeferredAttr.java Wed Feb 06 14:04:43 2013 +0000 1.3 @@ -332,13 +332,22 @@ 1.4 /** inference context */ 1.5 final InferenceContext inferenceContext; 1.6 1.7 + /** parent deferred context */ 1.8 + final DeferredAttrContext parent; 1.9 + 1.10 + /** Warner object to report warnings */ 1.11 + final Warner warn; 1.12 + 1.13 /** list of deferred attribution nodes to be processed */ 1.14 ArrayList<DeferredAttrNode> deferredAttrNodes = new ArrayList<DeferredAttrNode>(); 1.15 1.16 - DeferredAttrContext(AttrMode mode, Symbol msym, MethodResolutionPhase phase, InferenceContext inferenceContext) { 1.17 + DeferredAttrContext(AttrMode mode, Symbol msym, MethodResolutionPhase phase, 1.18 + InferenceContext inferenceContext, DeferredAttrContext parent, Warner warn) { 1.19 this.mode = mode; 1.20 this.msym = msym; 1.21 this.phase = phase; 1.22 + this.parent = parent; 1.23 + this.warn = warn; 1.24 this.inferenceContext = inferenceContext; 1.25 } 1.26 1.27 @@ -363,7 +372,7 @@ 1.28 //scan a defensive copy of the node list - this is because a deferred 1.29 //attribution round can add new nodes to the list 1.30 for (DeferredAttrNode deferredAttrNode : List.from(deferredAttrNodes)) { 1.31 - if (!deferredAttrNode.process()) { 1.32 + if (!deferredAttrNode.process(this)) { 1.33 stuckVars.addAll(deferredAttrNode.stuckVars); 1.34 } else { 1.35 deferredAttrNodes.remove(deferredAttrNode); 1.36 @@ -378,118 +387,120 @@ 1.37 } 1.38 } 1.39 } 1.40 + } 1.41 + 1.42 + /** 1.43 + * Class representing a deferred attribution node. It keeps track of 1.44 + * a deferred type, along with the expected target type information. 1.45 + */ 1.46 + class DeferredAttrNode implements Infer.FreeTypeListener { 1.47 + 1.48 + /** underlying deferred type */ 1.49 + DeferredType dt; 1.50 + 1.51 + /** underlying target type information */ 1.52 + ResultInfo resultInfo; 1.53 + 1.54 + /** list of uninferred inference variables causing this node to be stuck */ 1.55 + List<Type> stuckVars; 1.56 + 1.57 + DeferredAttrNode(DeferredType dt, ResultInfo resultInfo, List<Type> stuckVars) { 1.58 + this.dt = dt; 1.59 + this.resultInfo = resultInfo; 1.60 + this.stuckVars = stuckVars; 1.61 + if (!stuckVars.isEmpty()) { 1.62 + resultInfo.checkContext.inferenceContext().addFreeTypeListener(stuckVars, this); 1.63 + } 1.64 + } 1.65 + 1.66 + @Override 1.67 + public void typesInferred(InferenceContext inferenceContext) { 1.68 + stuckVars = List.nil(); 1.69 + resultInfo = resultInfo.dup(inferenceContext.asInstType(resultInfo.pt)); 1.70 + } 1.71 1.72 /** 1.73 - * Class representing a deferred attribution node. It keeps track of 1.74 - * a deferred type, along with the expected target type information. 1.75 + * Process a deferred attribution node. 1.76 + * Invariant: a stuck node cannot be processed. 1.77 */ 1.78 - class DeferredAttrNode implements Infer.FreeTypeListener { 1.79 + @SuppressWarnings("fallthrough") 1.80 + boolean process(DeferredAttrContext deferredAttrContext) { 1.81 + switch (deferredAttrContext.mode) { 1.82 + case SPECULATIVE: 1.83 + dt.check(resultInfo, List.<Type>nil(), new StructuralStuckChecker()); 1.84 + return true; 1.85 + case CHECK: 1.86 + if (stuckVars.nonEmpty()) { 1.87 + return false; 1.88 + } else { 1.89 + dt.check(resultInfo, stuckVars, basicCompleter); 1.90 + return true; 1.91 + } 1.92 + default: 1.93 + throw new AssertionError("Bad mode"); 1.94 + } 1.95 + } 1.96 1.97 - /** underlying deferred type */ 1.98 - DeferredType dt; 1.99 + /** 1.100 + * Structural checker for stuck expressions 1.101 + */ 1.102 + class StructuralStuckChecker extends TreeScanner implements DeferredTypeCompleter { 1.103 1.104 - /** underlying target type information */ 1.105 ResultInfo resultInfo; 1.106 + InferenceContext inferenceContext; 1.107 1.108 - /** list of uninferred inference variables causing this node to be stuck */ 1.109 - List<Type> stuckVars; 1.110 + public Type complete(DeferredType dt, ResultInfo resultInfo, DeferredAttrContext deferredAttrContext) { 1.111 + this.resultInfo = resultInfo; 1.112 + this.inferenceContext = deferredAttrContext.inferenceContext; 1.113 + dt.tree.accept(this); 1.114 + dt.speculativeCache.put(deferredAttrContext.msym, stuckTree, deferredAttrContext.phase); 1.115 + return Type.noType; 1.116 + } 1.117 1.118 - DeferredAttrNode(DeferredType dt, ResultInfo resultInfo, List<Type> stuckVars) { 1.119 - this.dt = dt; 1.120 - this.resultInfo = resultInfo; 1.121 - this.stuckVars = stuckVars; 1.122 - if (!stuckVars.isEmpty()) { 1.123 - resultInfo.checkContext.inferenceContext().addFreeTypeListener(stuckVars, this); 1.124 + @Override 1.125 + public void visitLambda(JCLambda tree) { 1.126 + Check.CheckContext checkContext = resultInfo.checkContext; 1.127 + Type pt = resultInfo.pt; 1.128 + if (inferenceContext.inferencevars.contains(pt)) { 1.129 + //ok 1.130 + return; 1.131 + } else { 1.132 + //must be a functional descriptor 1.133 + try { 1.134 + Type desc = types.findDescriptorType(pt); 1.135 + if (desc.getParameterTypes().length() != tree.params.length()) { 1.136 + checkContext.report(tree, diags.fragment("incompatible.arg.types.in.lambda")); 1.137 + } 1.138 + } catch (Types.FunctionDescriptorLookupError ex) { 1.139 + checkContext.report(null, ex.getDiagnostic()); 1.140 + } 1.141 } 1.142 } 1.143 1.144 @Override 1.145 - public void typesInferred(InferenceContext inferenceContext) { 1.146 - stuckVars = List.nil(); 1.147 - resultInfo = resultInfo.dup(inferenceContext.asInstType(resultInfo.pt)); 1.148 + public void visitNewClass(JCNewClass tree) { 1.149 + //do nothing 1.150 } 1.151 1.152 - /** 1.153 - * Process a deferred attribution node. 1.154 - * Invariant: a stuck node cannot be processed. 1.155 - */ 1.156 - @SuppressWarnings("fallthrough") 1.157 - boolean process() { 1.158 - switch (mode) { 1.159 - case SPECULATIVE: 1.160 - dt.check(resultInfo, List.<Type>nil(), new StructuralStuckChecker()); 1.161 - return true; 1.162 - case CHECK: 1.163 - if (stuckVars.nonEmpty()) { 1.164 - return false; 1.165 - } else { 1.166 - dt.check(resultInfo, stuckVars, basicCompleter); 1.167 - return true; 1.168 - } 1.169 - default: 1.170 - throw new AssertionError("Bad mode"); 1.171 - } 1.172 + @Override 1.173 + public void visitApply(JCMethodInvocation tree) { 1.174 + //do nothing 1.175 } 1.176 1.177 - /** 1.178 - * Structural checker for stuck expressions 1.179 - */ 1.180 - class StructuralStuckChecker extends TreeScanner implements DeferredTypeCompleter { 1.181 - 1.182 - ResultInfo resultInfo; 1.183 - 1.184 - public Type complete(DeferredType dt, ResultInfo resultInfo, DeferredAttrContext deferredAttrContext) { 1.185 - this.resultInfo = resultInfo; 1.186 - dt.tree.accept(this); 1.187 - dt.speculativeCache.put(msym, stuckTree, phase); 1.188 - return Type.noType; 1.189 - } 1.190 - 1.191 - @Override 1.192 - public void visitLambda(JCLambda tree) { 1.193 - Check.CheckContext checkContext = resultInfo.checkContext; 1.194 - Type pt = resultInfo.pt; 1.195 - if (inferenceContext.inferencevars.contains(pt)) { 1.196 - //ok 1.197 - return; 1.198 - } else { 1.199 - //must be a functional descriptor 1.200 - try { 1.201 - Type desc = types.findDescriptorType(pt); 1.202 - if (desc.getParameterTypes().length() != tree.params.length()) { 1.203 - checkContext.report(tree, diags.fragment("incompatible.arg.types.in.lambda")); 1.204 - } 1.205 - } catch (Types.FunctionDescriptorLookupError ex) { 1.206 - checkContext.report(null, ex.getDiagnostic()); 1.207 - } 1.208 - } 1.209 - } 1.210 - 1.211 - @Override 1.212 - public void visitNewClass(JCNewClass tree) { 1.213 - //do nothing 1.214 - } 1.215 - 1.216 - @Override 1.217 - public void visitApply(JCMethodInvocation tree) { 1.218 - //do nothing 1.219 - } 1.220 - 1.221 - @Override 1.222 - public void visitReference(JCMemberReference tree) { 1.223 - Check.CheckContext checkContext = resultInfo.checkContext; 1.224 - Type pt = resultInfo.pt; 1.225 - if (inferenceContext.inferencevars.contains(pt)) { 1.226 - //ok 1.227 - return; 1.228 - } else { 1.229 - try { 1.230 - //TODO: we should speculative determine if there's a match 1.231 - //based on arity - if yes, method is applicable. 1.232 - types.findDescriptorType(pt); 1.233 - } catch (Types.FunctionDescriptorLookupError ex) { 1.234 - checkContext.report(null, ex.getDiagnostic()); 1.235 - } 1.236 + @Override 1.237 + public void visitReference(JCMemberReference tree) { 1.238 + Check.CheckContext checkContext = resultInfo.checkContext; 1.239 + Type pt = resultInfo.pt; 1.240 + if (inferenceContext.inferencevars.contains(pt)) { 1.241 + //ok 1.242 + return; 1.243 + } else { 1.244 + try { 1.245 + //TODO: we should speculative determine if there's a match 1.246 + //based on arity - if yes, method is applicable. 1.247 + types.findDescriptorType(pt); 1.248 + } catch (Types.FunctionDescriptorLookupError ex) { 1.249 + checkContext.report(null, ex.getDiagnostic()); 1.250 } 1.251 } 1.252 } 1.253 @@ -498,7 +509,7 @@ 1.254 1.255 /** an empty deferred attribution context - all methods throw exceptions */ 1.256 final DeferredAttrContext emptyDeferredAttrContext = 1.257 - new DeferredAttrContext(AttrMode.CHECK, null, MethodResolutionPhase.BOX, null) { 1.258 + new DeferredAttrContext(AttrMode.CHECK, null, MethodResolutionPhase.BOX, null, null, null) { 1.259 @Override 1.260 void addDeferredAttrNode(DeferredType dt, ResultInfo ri, List<Type> stuckVars) { 1.261 Assert.error("Empty deferred context!"); 1.262 @@ -521,7 +532,8 @@ 1.263 1.264 protected DeferredTypeMap(AttrMode mode, Symbol msym, MethodResolutionPhase phase) { 1.265 super(String.format("deferredTypeMap[%s]", mode)); 1.266 - this.deferredAttrContext = new DeferredAttrContext(mode, msym, phase, infer.emptyContext); 1.267 + this.deferredAttrContext = new DeferredAttrContext(mode, msym, phase, 1.268 + infer.emptyContext, emptyDeferredAttrContext, types.noWarnings); 1.269 } 1.270 1.271 protected boolean validState(DeferredType dt) {
2.1 --- a/src/share/classes/com/sun/tools/javac/comp/Infer.java Wed Feb 06 14:03:39 2013 +0000 2.2 +++ b/src/share/classes/com/sun/tools/javac/comp/Infer.java Wed Feb 06 14:04:43 2013 +0000 2.3 @@ -269,7 +269,7 @@ 2.4 inferenceException.clear(); 2.5 2.6 DeferredAttr.DeferredAttrContext deferredAttrContext = 2.7 - resolveContext.deferredAttrContext(msym, inferenceContext); 2.8 + resolveContext.deferredAttrContext(msym, inferenceContext, resultInfo, warn); 2.9 2.10 try { 2.11 methodCheck.argumentsAcceptable(env, deferredAttrContext, argtypes, mt.getParameterTypes(), warn);
3.1 --- a/src/share/classes/com/sun/tools/javac/comp/Resolve.java Wed Feb 06 14:03:39 2013 +0000 3.2 +++ b/src/share/classes/com/sun/tools/javac/comp/Resolve.java Wed Feb 06 14:04:43 2013 +0000 3.3 @@ -564,7 +564,7 @@ 3.4 methodCheck, 3.5 warn); 3.6 3.7 - methodCheck.argumentsAcceptable(env, currentResolutionContext.deferredAttrContext(m, infer.emptyContext), 3.8 + methodCheck.argumentsAcceptable(env, currentResolutionContext.deferredAttrContext(m, infer.emptyContext, resultInfo, warn), 3.9 argtypes, mt.getParameterTypes(), warn); 3.10 return mt; 3.11 } 3.12 @@ -3589,8 +3589,8 @@ 3.13 candidates = candidates.append(c); 3.14 } 3.15 3.16 - DeferredAttrContext deferredAttrContext(Symbol sym, InferenceContext inferenceContext) { 3.17 - return deferredAttr.new DeferredAttrContext(attrMode, sym, step, inferenceContext); 3.18 + DeferredAttrContext deferredAttrContext(Symbol sym, InferenceContext inferenceContext, ResultInfo pendingResult, Warner warn) { 3.19 + return deferredAttr.new DeferredAttrContext(attrMode, sym, step, inferenceContext, pendingResult != null ? pendingResult.checkContext.deferredAttrContext() : deferredAttr.emptyDeferredAttrContext, warn); 3.20 } 3.21 3.22 /**