src/share/classes/com/sun/tools/javac/comp/DeferredAttr.java

changeset 1415
01c9d4161882
parent 1406
2901c7b5339e
child 1481
d07340b61e6a
equal deleted inserted replaced
1414:843d3b191773 1415:01c9d4161882
36 import com.sun.tools.javac.tree.JCTree.*; 36 import com.sun.tools.javac.tree.JCTree.*;
37 37
38 import javax.tools.JavaFileObject; 38 import javax.tools.JavaFileObject;
39 39
40 import java.util.ArrayList; 40 import java.util.ArrayList;
41 import java.util.HashSet; 41 import java.util.LinkedHashSet;
42 import java.util.Map; 42 import java.util.Map;
43 import java.util.Queue; 43 import java.util.Queue;
44 import java.util.Set; 44 import java.util.Set;
45 import java.util.WeakHashMap; 45 import java.util.WeakHashMap;
46 46
47 import static com.sun.tools.javac.code.TypeTag.DEFERRED; 47 import static com.sun.tools.javac.code.TypeTag.*;
48 import static com.sun.tools.javac.code.TypeTag.NONE;
49 import static com.sun.tools.javac.tree.JCTree.Tag.*; 48 import static com.sun.tools.javac.tree.JCTree.Tag.*;
50 49
51 /** 50 /**
52 * This is an helper class that is used to perform deferred type-analysis. 51 * This is an helper class that is used to perform deferred type-analysis.
53 * Each time a poly expression occurs in argument position, javac attributes it 52 * Each time a poly expression occurs in argument position, javac attributes it
135 return this.phase == phase; 134 return this.phase == phase;
136 } 135 }
137 } 136 }
138 137
139 /** 138 /**
140 * Clone a speculative cache entry as a fresh entry associated
141 * with a new method (this maybe required to fixup speculative cache
142 * misses after Resolve.access())
143 */
144 void dupAllTo(Symbol from, Symbol to) {
145 Assert.check(cache.get(to) == null);
146 List<Entry> entries = cache.get(from);
147 if (entries != null) {
148 cache.put(to, entries);
149 }
150 }
151
152 /**
153 * Retrieve a speculative cache entry corresponding to given symbol 139 * Retrieve a speculative cache entry corresponding to given symbol
154 * and resolution phase 140 * and resolution phase
155 */ 141 */
156 Entry get(Symbol msym, MethodResolutionPhase phase) { 142 Entry get(Symbol msym, MethodResolutionPhase phase) {
157 List<Entry> entries = cache.get(msym); 143 List<Entry> entries = cache.get(msym);
192 */ 178 */
193 Type check(ResultInfo resultInfo) { 179 Type check(ResultInfo resultInfo) {
194 DeferredAttrContext deferredAttrContext = 180 DeferredAttrContext deferredAttrContext =
195 resultInfo.checkContext.deferredAttrContext(); 181 resultInfo.checkContext.deferredAttrContext();
196 Assert.check(deferredAttrContext != emptyDeferredAttrContext); 182 Assert.check(deferredAttrContext != emptyDeferredAttrContext);
197 List<Type> stuckVars = stuckVars(tree, resultInfo); 183 List<Type> stuckVars = stuckVars(tree, env, resultInfo);
198 if (stuckVars.nonEmpty()) { 184 if (stuckVars.nonEmpty()) {
199 deferredAttrContext.addDeferredAttrNode(this, resultInfo, stuckVars); 185 deferredAttrContext.addDeferredAttrNode(this, resultInfo, stuckVars);
200 return Type.noType; 186 return Type.noType;
201 } else { 187 } else {
202 try { 188 try {
273 //where 259 //where
274 protected TreeScanner unenterScanner = new TreeScanner() { 260 protected TreeScanner unenterScanner = new TreeScanner() {
275 @Override 261 @Override
276 public void visitClassDef(JCClassDecl tree) { 262 public void visitClassDef(JCClassDecl tree) {
277 ClassSymbol csym = tree.sym; 263 ClassSymbol csym = tree.sym;
264 //if something went wrong during method applicability check
265 //it is possible that nested expressions inside argument expression
266 //are left unchecked - in such cases there's nothing to clean up.
267 if (csym == null) return;
278 enter.typeEnvs.remove(csym); 268 enter.typeEnvs.remove(csym);
279 chk.compiled.remove(csym.flatname); 269 chk.compiled.remove(csym.flatname);
280 syms.classes.remove(csym.flatname); 270 syms.classes.remove(csym.flatname);
281 super.visitClassDef(tree); 271 super.visitClassDef(tree);
282 } 272 }
331 * some inference variable might get eagerly instantiated so that all nodes 321 * some inference variable might get eagerly instantiated so that all nodes
332 * can be type-checked. 322 * can be type-checked.
333 */ 323 */
334 void complete() { 324 void complete() {
335 while (!deferredAttrNodes.isEmpty()) { 325 while (!deferredAttrNodes.isEmpty()) {
336 Set<Type> stuckVars = new HashSet<Type>(); 326 Set<Type> stuckVars = new LinkedHashSet<Type>();
337 boolean progress = false; 327 boolean progress = false;
338 //scan a defensive copy of the node list - this is because a deferred 328 //scan a defensive copy of the node list - this is because a deferred
339 //attribution round can add new nodes to the list 329 //attribution round can add new nodes to the list
340 for (DeferredAttrNode deferredAttrNode : List.from(deferredAttrNodes)) { 330 for (DeferredAttrNode deferredAttrNode : List.from(deferredAttrNodes)) {
341 if (!deferredAttrNode.isStuck()) { 331 if (!deferredAttrNode.isStuck()) {
405 } 395 }
406 } 396 }
407 397
408 /** an empty deferred attribution context - all methods throw exceptions */ 398 /** an empty deferred attribution context - all methods throw exceptions */
409 final DeferredAttrContext emptyDeferredAttrContext = 399 final DeferredAttrContext emptyDeferredAttrContext =
410 new DeferredAttrContext(null, null, null, null) { 400 new DeferredAttrContext(AttrMode.CHECK, null, MethodResolutionPhase.BOX, null) {
411 @Override 401 @Override
412 void addDeferredAttrNode(DeferredType dt, ResultInfo ri, List<Type> stuckVars) { 402 void addDeferredAttrNode(DeferredType dt, ResultInfo ri, List<Type> stuckVars) {
413 Assert.error("Empty deferred context!"); 403 Assert.error("Empty deferred context!");
414 } 404 }
415 @Override 405 @Override
469 * (the latter step is useful in a recovery scenario). 459 * (the latter step is useful in a recovery scenario).
470 */ 460 */
471 public class RecoveryDeferredTypeMap extends DeferredTypeMap { 461 public class RecoveryDeferredTypeMap extends DeferredTypeMap {
472 462
473 public RecoveryDeferredTypeMap(AttrMode mode, Symbol msym, MethodResolutionPhase phase) { 463 public RecoveryDeferredTypeMap(AttrMode mode, Symbol msym, MethodResolutionPhase phase) {
474 super(mode, msym, phase); 464 super(mode, msym, phase != null ? phase : MethodResolutionPhase.BOX);
475 } 465 }
476 466
477 @Override 467 @Override
478 protected Type typeOf(DeferredType dt) { 468 protected Type typeOf(DeferredType dt) {
479 Type owntype = super.typeOf(dt); 469 Type owntype = super.typeOf(dt);
480 return owntype.hasTag(NONE) ? 470 return owntype == Type.noType ?
481 recover(dt) : owntype; 471 recover(dt) : owntype;
482 } 472 }
483 473
484 @Override 474 @Override
485 protected boolean validState(DeferredType dt) { 475 protected boolean validState(DeferredType dt) {
493 * representation. Remaining deferred types are attributed using 483 * representation. Remaining deferred types are attributed using
494 * a default expected type (j.l.Object). 484 * a default expected type (j.l.Object).
495 */ 485 */
496 private Type recover(DeferredType dt) { 486 private Type recover(DeferredType dt) {
497 dt.check(attr.new RecoveryInfo(deferredAttrContext)); 487 dt.check(attr.new RecoveryInfo(deferredAttrContext));
498 switch (TreeInfo.skipParens(dt.tree).getTag()) { 488 return super.apply(dt);
499 case LAMBDA:
500 case REFERENCE:
501 case CONDEXPR:
502 //propagate those deferred types to the
503 //diagnostic formatter
504 return dt;
505 default:
506 return super.apply(dt);
507 }
508 } 489 }
509 } 490 }
510 491
511 /** 492 /**
512 * Retrieves the list of inference variables that need to be inferred before 493 * Retrieves the list of inference variables that need to be inferred before
513 * an AST node can be type-checked 494 * an AST node can be type-checked
514 */ 495 */
515 @SuppressWarnings("fallthrough") 496 @SuppressWarnings("fallthrough")
516 List<Type> stuckVars(JCTree tree, ResultInfo resultInfo) { 497 List<Type> stuckVars(JCTree tree, Env<AttrContext> env, ResultInfo resultInfo) {
517 if (resultInfo.pt.hasTag(NONE) || resultInfo.pt.isErroneous()) { 498 if (resultInfo.pt.hasTag(NONE) || resultInfo.pt.isErroneous()) {
518 return List.nil(); 499 return List.nil();
519 } else { 500 } else {
520 StuckChecker sc = new StuckChecker(resultInfo); 501 StuckChecker sc = new StuckChecker(resultInfo, env);
521 sc.scan(tree); 502 sc.scan(tree);
522 return List.from(sc.stuckVars); 503 return List.from(sc.stuckVars);
523 } 504 }
524 } 505 }
525 506
532 class StuckChecker extends TreeScanner { 513 class StuckChecker extends TreeScanner {
533 514
534 Type pt; 515 Type pt;
535 Filter<JCTree> treeFilter; 516 Filter<JCTree> treeFilter;
536 Infer.InferenceContext inferenceContext; 517 Infer.InferenceContext inferenceContext;
537 Set<Type> stuckVars = new HashSet<Type>(); 518 Set<Type> stuckVars = new LinkedHashSet<Type>();
519 Env<AttrContext> env;
538 520
539 final Filter<JCTree> argsFilter = new Filter<JCTree>() { 521 final Filter<JCTree> argsFilter = new Filter<JCTree>() {
540 public boolean accepts(JCTree t) { 522 public boolean accepts(JCTree t) {
541 switch (t.getTag()) { 523 switch (t.getTag()) {
542 case CONDEXPR: 524 case CONDEXPR:
561 return false; 543 return false;
562 } 544 }
563 } 545 }
564 }; 546 };
565 547
566 StuckChecker(ResultInfo resultInfo) { 548 StuckChecker(ResultInfo resultInfo, Env<AttrContext> env) {
567 this.pt = resultInfo.pt; 549 this.pt = resultInfo.pt;
568 this.inferenceContext = resultInfo.checkContext.inferenceContext(); 550 this.inferenceContext = resultInfo.checkContext.inferenceContext();
569 this.treeFilter = argsFilter; 551 this.treeFilter = argsFilter;
552 this.env = env;
570 } 553 }
571 554
572 @Override 555 @Override
573 public void scan(JCTree tree) { 556 public void scan(JCTree tree) {
574 if (tree != null && treeFilter.accepts(tree)) { 557 if (tree != null && treeFilter.accepts(tree)) {
614 return; 597 return;
615 } 598 }
616 if (!types.isFunctionalInterface(pt.tsym)) { 599 if (!types.isFunctionalInterface(pt.tsym)) {
617 return; 600 return;
618 } 601 }
602
619 Type descType = types.findDescriptorType(pt); 603 Type descType = types.findDescriptorType(pt);
620 List<Type> freeArgVars = inferenceContext.freeVarsIn(descType.getParameterTypes()); 604 List<Type> freeArgVars = inferenceContext.freeVarsIn(descType.getParameterTypes());
621 stuckVars.addAll(freeArgVars); 605 stuckVars.addAll(freeArgVars);
622 } 606 }
623 607

mercurial