1.1 --- a/src/share/classes/com/sun/tools/javac/comp/DeferredAttr.java Mon Feb 04 18:08:53 2013 -0500 1.2 +++ b/src/share/classes/com/sun/tools/javac/comp/DeferredAttr.java Sun Feb 17 16:44:55 2013 -0500 1.3 @@ -234,7 +234,7 @@ 1.4 dt.speculativeCache.put(deferredAttrContext.msym, speculativeTree, deferredAttrContext.phase); 1.5 return speculativeTree.type; 1.6 case CHECK: 1.7 - Assert.check(dt.mode == AttrMode.SPECULATIVE); 1.8 + Assert.check(dt.mode != null); 1.9 return attr.attribTree(dt.tree, dt.env, resultInfo); 1.10 } 1.11 Assert.error(); 1.12 @@ -242,6 +242,13 @@ 1.13 } 1.14 }; 1.15 1.16 + DeferredTypeCompleter dummyCompleter = new DeferredTypeCompleter() { 1.17 + public Type complete(DeferredType dt, ResultInfo resultInfo, DeferredAttrContext deferredAttrContext) { 1.18 + Assert.check(deferredAttrContext.mode == AttrMode.CHECK); 1.19 + return dt.tree.type = Type.noType; 1.20 + } 1.21 + }; 1.22 + 1.23 /** 1.24 * The 'mode' in which the deferred type is to be type-checked 1.25 */ 1.26 @@ -332,13 +339,22 @@ 1.27 /** inference context */ 1.28 final InferenceContext inferenceContext; 1.29 1.30 + /** parent deferred context */ 1.31 + final DeferredAttrContext parent; 1.32 + 1.33 + /** Warner object to report warnings */ 1.34 + final Warner warn; 1.35 + 1.36 /** list of deferred attribution nodes to be processed */ 1.37 ArrayList<DeferredAttrNode> deferredAttrNodes = new ArrayList<DeferredAttrNode>(); 1.38 1.39 - DeferredAttrContext(AttrMode mode, Symbol msym, MethodResolutionPhase phase, InferenceContext inferenceContext) { 1.40 + DeferredAttrContext(AttrMode mode, Symbol msym, MethodResolutionPhase phase, 1.41 + InferenceContext inferenceContext, DeferredAttrContext parent, Warner warn) { 1.42 this.mode = mode; 1.43 this.msym = msym; 1.44 this.phase = phase; 1.45 + this.parent = parent; 1.46 + this.warn = warn; 1.47 this.inferenceContext = inferenceContext; 1.48 } 1.49 1.50 @@ -363,7 +379,7 @@ 1.51 //scan a defensive copy of the node list - this is because a deferred 1.52 //attribution round can add new nodes to the list 1.53 for (DeferredAttrNode deferredAttrNode : List.from(deferredAttrNodes)) { 1.54 - if (!deferredAttrNode.process()) { 1.55 + if (!deferredAttrNode.process(this)) { 1.56 stuckVars.addAll(deferredAttrNode.stuckVars); 1.57 } else { 1.58 deferredAttrNodes.remove(deferredAttrNode); 1.59 @@ -373,123 +389,133 @@ 1.60 if (!progress) { 1.61 //remove all variables that have already been instantiated 1.62 //from the list of stuck variables 1.63 - inferenceContext.solveAny(inferenceContext.freeVarsIn(List.from(stuckVars)), types, infer); 1.64 - inferenceContext.notifyChange(types); 1.65 + inferenceContext.solveAny(List.from(stuckVars), warn); 1.66 + inferenceContext.notifyChange(); 1.67 } 1.68 } 1.69 } 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 + */ 1.76 + class DeferredAttrNode implements Infer.FreeTypeListener { 1.77 + 1.78 + /** underlying deferred type */ 1.79 + DeferredType dt; 1.80 + 1.81 + /** underlying target type information */ 1.82 + ResultInfo resultInfo; 1.83 + 1.84 + /** list of uninferred inference variables causing this node to be stuck */ 1.85 + List<Type> stuckVars; 1.86 + 1.87 + DeferredAttrNode(DeferredType dt, ResultInfo resultInfo, List<Type> stuckVars) { 1.88 + this.dt = dt; 1.89 + this.resultInfo = resultInfo; 1.90 + this.stuckVars = stuckVars; 1.91 + if (!stuckVars.isEmpty()) { 1.92 + resultInfo.checkContext.inferenceContext().addFreeTypeListener(stuckVars, this); 1.93 + } 1.94 + } 1.95 + 1.96 + @Override 1.97 + public void typesInferred(InferenceContext inferenceContext) { 1.98 + stuckVars = List.nil(); 1.99 + resultInfo = resultInfo.dup(inferenceContext.asInstType(resultInfo.pt)); 1.100 + } 1.101 + 1.102 + /** 1.103 + * Process a deferred attribution node. 1.104 + * Invariant: a stuck node cannot be processed. 1.105 + */ 1.106 + @SuppressWarnings("fallthrough") 1.107 + boolean process(DeferredAttrContext deferredAttrContext) { 1.108 + switch (deferredAttrContext.mode) { 1.109 + case SPECULATIVE: 1.110 + dt.check(resultInfo, List.<Type>nil(), new StructuralStuckChecker()); 1.111 + return true; 1.112 + case CHECK: 1.113 + if (stuckVars.nonEmpty()) { 1.114 + //stuck expression - see if we can propagate 1.115 + if (deferredAttrContext.parent != emptyDeferredAttrContext && 1.116 + Type.containsAny(deferredAttrContext.parent.inferenceContext.inferencevars, List.from(stuckVars))) { 1.117 + deferredAttrContext.parent.deferredAttrNodes.add(this); 1.118 + dt.check(resultInfo, List.<Type>nil(), dummyCompleter); 1.119 + return true; 1.120 + } else { 1.121 + return false; 1.122 + } 1.123 + } else { 1.124 + dt.check(resultInfo, stuckVars, basicCompleter); 1.125 + return true; 1.126 + } 1.127 + default: 1.128 + throw new AssertionError("Bad mode"); 1.129 + } 1.130 + } 1.131 1.132 /** 1.133 - * Class representing a deferred attribution node. It keeps track of 1.134 - * a deferred type, along with the expected target type information. 1.135 + * Structural checker for stuck expressions 1.136 */ 1.137 - class DeferredAttrNode implements Infer.InferenceContext.FreeTypeListener { 1.138 + class StructuralStuckChecker extends TreeScanner implements DeferredTypeCompleter { 1.139 1.140 - /** underlying deferred type */ 1.141 - DeferredType dt; 1.142 + ResultInfo resultInfo; 1.143 + InferenceContext inferenceContext; 1.144 1.145 - /** underlying target type information */ 1.146 - ResultInfo resultInfo; 1.147 + public Type complete(DeferredType dt, ResultInfo resultInfo, DeferredAttrContext deferredAttrContext) { 1.148 + this.resultInfo = resultInfo; 1.149 + this.inferenceContext = deferredAttrContext.inferenceContext; 1.150 + dt.tree.accept(this); 1.151 + dt.speculativeCache.put(deferredAttrContext.msym, stuckTree, deferredAttrContext.phase); 1.152 + return Type.noType; 1.153 + } 1.154 1.155 - /** list of uninferred inference variables causing this node to be stuck */ 1.156 - List<Type> stuckVars; 1.157 - 1.158 - DeferredAttrNode(DeferredType dt, ResultInfo resultInfo, List<Type> stuckVars) { 1.159 - this.dt = dt; 1.160 - this.resultInfo = resultInfo; 1.161 - this.stuckVars = stuckVars; 1.162 - if (!stuckVars.isEmpty()) { 1.163 - resultInfo.checkContext.inferenceContext().addFreeTypeListener(stuckVars, this); 1.164 + @Override 1.165 + public void visitLambda(JCLambda tree) { 1.166 + Check.CheckContext checkContext = resultInfo.checkContext; 1.167 + Type pt = resultInfo.pt; 1.168 + if (inferenceContext.inferencevars.contains(pt)) { 1.169 + //ok 1.170 + return; 1.171 + } else { 1.172 + //must be a functional descriptor 1.173 + try { 1.174 + Type desc = types.findDescriptorType(pt); 1.175 + if (desc.getParameterTypes().length() != tree.params.length()) { 1.176 + checkContext.report(tree, diags.fragment("incompatible.arg.types.in.lambda")); 1.177 + } 1.178 + } catch (Types.FunctionDescriptorLookupError ex) { 1.179 + checkContext.report(null, ex.getDiagnostic()); 1.180 + } 1.181 } 1.182 } 1.183 1.184 @Override 1.185 - public void typesInferred(InferenceContext inferenceContext) { 1.186 - stuckVars = List.nil(); 1.187 - resultInfo = resultInfo.dup(inferenceContext.asInstType(resultInfo.pt, types)); 1.188 + public void visitNewClass(JCNewClass tree) { 1.189 + //do nothing 1.190 } 1.191 1.192 - /** 1.193 - * Process a deferred attribution node. 1.194 - * Invariant: a stuck node cannot be processed. 1.195 - */ 1.196 - @SuppressWarnings("fallthrough") 1.197 - boolean process() { 1.198 - switch (mode) { 1.199 - case SPECULATIVE: 1.200 - dt.check(resultInfo, List.<Type>nil(), new StructuralStuckChecker()); 1.201 - return true; 1.202 - case CHECK: 1.203 - if (stuckVars.nonEmpty()) { 1.204 - return false; 1.205 - } else { 1.206 - dt.check(resultInfo, stuckVars, basicCompleter); 1.207 - return true; 1.208 - } 1.209 - default: 1.210 - throw new AssertionError("Bad mode"); 1.211 - } 1.212 + @Override 1.213 + public void visitApply(JCMethodInvocation tree) { 1.214 + //do nothing 1.215 } 1.216 1.217 - /** 1.218 - * Structural checker for stuck expressions 1.219 - */ 1.220 - class StructuralStuckChecker extends TreeScanner implements DeferredTypeCompleter { 1.221 - 1.222 - ResultInfo resultInfo; 1.223 - 1.224 - public Type complete(DeferredType dt, ResultInfo resultInfo, DeferredAttrContext deferredAttrContext) { 1.225 - this.resultInfo = resultInfo; 1.226 - dt.tree.accept(this); 1.227 - dt.speculativeCache.put(msym, stuckTree, phase); 1.228 - return Type.noType; 1.229 - } 1.230 - 1.231 - @Override 1.232 - public void visitLambda(JCLambda tree) { 1.233 - Check.CheckContext checkContext = resultInfo.checkContext; 1.234 - Type pt = resultInfo.pt; 1.235 - if (inferenceContext.inferencevars.contains(pt)) { 1.236 - //ok 1.237 - return; 1.238 - } else { 1.239 - //must be a functional descriptor 1.240 - try { 1.241 - Type desc = types.findDescriptorType(pt); 1.242 - if (desc.getParameterTypes().length() != tree.params.length()) { 1.243 - checkContext.report(tree, diags.fragment("incompatible.arg.types.in.lambda")); 1.244 - } 1.245 - } catch (Types.FunctionDescriptorLookupError ex) { 1.246 - checkContext.report(null, ex.getDiagnostic()); 1.247 - } 1.248 - } 1.249 - } 1.250 - 1.251 - @Override 1.252 - public void visitNewClass(JCNewClass tree) { 1.253 - //do nothing 1.254 - } 1.255 - 1.256 - @Override 1.257 - public void visitApply(JCMethodInvocation tree) { 1.258 - //do nothing 1.259 - } 1.260 - 1.261 - @Override 1.262 - public void visitReference(JCMemberReference tree) { 1.263 - Check.CheckContext checkContext = resultInfo.checkContext; 1.264 - Type pt = resultInfo.pt; 1.265 - if (inferenceContext.inferencevars.contains(pt)) { 1.266 - //ok 1.267 - return; 1.268 - } else { 1.269 - try { 1.270 - //TODO: we should speculative determine if there's a match 1.271 - //based on arity - if yes, method is applicable. 1.272 - types.findDescriptorType(pt); 1.273 - } catch (Types.FunctionDescriptorLookupError ex) { 1.274 - checkContext.report(null, ex.getDiagnostic()); 1.275 - } 1.276 + @Override 1.277 + public void visitReference(JCMemberReference tree) { 1.278 + Check.CheckContext checkContext = resultInfo.checkContext; 1.279 + Type pt = resultInfo.pt; 1.280 + if (inferenceContext.inferencevars.contains(pt)) { 1.281 + //ok 1.282 + return; 1.283 + } else { 1.284 + try { 1.285 + //TODO: we should speculative determine if there's a match 1.286 + //based on arity - if yes, method is applicable. 1.287 + types.findDescriptorType(pt); 1.288 + } catch (Types.FunctionDescriptorLookupError ex) { 1.289 + checkContext.report(null, ex.getDiagnostic()); 1.290 } 1.291 } 1.292 } 1.293 @@ -498,7 +524,7 @@ 1.294 1.295 /** an empty deferred attribution context - all methods throw exceptions */ 1.296 final DeferredAttrContext emptyDeferredAttrContext = 1.297 - new DeferredAttrContext(AttrMode.CHECK, null, MethodResolutionPhase.BOX, null) { 1.298 + new DeferredAttrContext(AttrMode.CHECK, null, MethodResolutionPhase.BOX, null, null, null) { 1.299 @Override 1.300 void addDeferredAttrNode(DeferredType dt, ResultInfo ri, List<Type> stuckVars) { 1.301 Assert.error("Empty deferred context!"); 1.302 @@ -521,7 +547,8 @@ 1.303 1.304 protected DeferredTypeMap(AttrMode mode, Symbol msym, MethodResolutionPhase phase) { 1.305 super(String.format("deferredTypeMap[%s]", mode)); 1.306 - this.deferredAttrContext = new DeferredAttrContext(mode, msym, phase, infer.emptyContext); 1.307 + this.deferredAttrContext = new DeferredAttrContext(mode, msym, phase, 1.308 + infer.emptyContext, emptyDeferredAttrContext, types.noWarnings); 1.309 } 1.310 1.311 protected boolean validState(DeferredType dt) {