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

changeset 1510
7873d37f5b37
parent 1481
d07340b61e6a
child 1550
1df20330f6bd
equal deleted inserted replaced
1509:1985e35e97b2 1510:7873d37f5b37
63 protected static final Context.Key<DeferredAttr> deferredAttrKey = 63 protected static final Context.Key<DeferredAttr> deferredAttrKey =
64 new Context.Key<DeferredAttr>(); 64 new Context.Key<DeferredAttr>();
65 65
66 final Attr attr; 66 final Attr attr;
67 final Check chk; 67 final Check chk;
68 final JCDiagnostic.Factory diags;
68 final Enter enter; 69 final Enter enter;
69 final Infer infer; 70 final Infer infer;
70 final Log log; 71 final Log log;
71 final Symtab syms; 72 final Symtab syms;
72 final TreeMaker make; 73 final TreeMaker make;
81 82
82 protected DeferredAttr(Context context) { 83 protected DeferredAttr(Context context) {
83 context.put(deferredAttrKey, this); 84 context.put(deferredAttrKey, this);
84 attr = Attr.instance(context); 85 attr = Attr.instance(context);
85 chk = Check.instance(context); 86 chk = Check.instance(context);
87 diags = JCDiagnostic.Factory.instance(context);
86 enter = Enter.instance(context); 88 enter = Enter.instance(context);
87 infer = Infer.instance(context); 89 infer = Infer.instance(context);
88 log = Log.instance(context); 90 log = Log.instance(context);
89 syms = Symtab.instance(context); 91 syms = Symtab.instance(context);
90 make = TreeMaker.instance(context); 92 make = TreeMaker.instance(context);
91 types = Types.instance(context); 93 types = Types.instance(context);
92 } 94 Names names = Names.instance(context);
95 stuckTree = make.Ident(names.empty).setType(Type.noType);
96 }
97
98 /** shared tree for stuck expressions */
99 final JCTree stuckTree;
93 100
94 /** 101 /**
95 * This type represents a deferred type. A deferred type starts off with 102 * This type represents a deferred type. A deferred type starts off with
96 * no information on the underlying expression type. Such info needs to be 103 * no information on the underlying expression type. Such info needs to be
97 * discovered through type-checking the deferred type against a target-type. 104 * discovered through type-checking the deferred type against a target-type.
354 Set<Type> stuckVars = new LinkedHashSet<Type>(); 361 Set<Type> stuckVars = new LinkedHashSet<Type>();
355 boolean progress = false; 362 boolean progress = false;
356 //scan a defensive copy of the node list - this is because a deferred 363 //scan a defensive copy of the node list - this is because a deferred
357 //attribution round can add new nodes to the list 364 //attribution round can add new nodes to the list
358 for (DeferredAttrNode deferredAttrNode : List.from(deferredAttrNodes)) { 365 for (DeferredAttrNode deferredAttrNode : List.from(deferredAttrNodes)) {
359 if (!deferredAttrNode.isStuck()) { 366 if (!deferredAttrNode.process()) {
360 deferredAttrNode.process(); 367 stuckVars.addAll(deferredAttrNode.stuckVars);
368 } else {
361 deferredAttrNodes.remove(deferredAttrNode); 369 deferredAttrNodes.remove(deferredAttrNode);
362 progress = true; 370 progress = true;
363 } else {
364 stuckVars.addAll(deferredAttrNode.stuckVars);
365 } 371 }
366 } 372 }
367 if (!progress) { 373 if (!progress) {
368 //remove all variables that have already been instantiated 374 //remove all variables that have already been instantiated
369 //from the list of stuck variables 375 //from the list of stuck variables
402 stuckVars = List.nil(); 408 stuckVars = List.nil();
403 resultInfo = resultInfo.dup(inferenceContext.asInstType(resultInfo.pt, types)); 409 resultInfo = resultInfo.dup(inferenceContext.asInstType(resultInfo.pt, types));
404 } 410 }
405 411
406 /** 412 /**
407 * is this node stuck?
408 */
409 boolean isStuck() {
410 return stuckVars.nonEmpty();
411 }
412
413 /**
414 * Process a deferred attribution node. 413 * Process a deferred attribution node.
415 * Invariant: a stuck node cannot be processed. 414 * Invariant: a stuck node cannot be processed.
416 */ 415 */
417 void process() { 416 @SuppressWarnings("fallthrough")
418 if (isStuck()) { 417 boolean process() {
419 throw new IllegalStateException("Cannot process a stuck deferred node"); 418 switch (mode) {
420 } 419 case SPECULATIVE:
421 dt.check(resultInfo); 420 dt.check(resultInfo, List.<Type>nil(), new StructuralStuckChecker());
421 return true;
422 case CHECK:
423 if (stuckVars.nonEmpty()) {
424 return false;
425 } else {
426 dt.check(resultInfo, stuckVars, basicCompleter);
427 return true;
428 }
429 default:
430 throw new AssertionError("Bad mode");
431 }
432 }
433
434 /**
435 * Structural checker for stuck expressions
436 */
437 class StructuralStuckChecker extends TreeScanner implements DeferredTypeCompleter {
438
439 ResultInfo resultInfo;
440
441 public Type complete(DeferredType dt, ResultInfo resultInfo, DeferredAttrContext deferredAttrContext) {
442 this.resultInfo = resultInfo;
443 dt.tree.accept(this);
444 dt.speculativeCache.put(msym, stuckTree, phase);
445 return Type.noType;
446 }
447
448 @Override
449 public void visitLambda(JCLambda tree) {
450 Check.CheckContext checkContext = resultInfo.checkContext;
451 Type pt = resultInfo.pt;
452 if (inferenceContext.inferencevars.contains(pt)) {
453 //ok
454 return;
455 } else {
456 //must be a functional descriptor
457 try {
458 Type desc = types.findDescriptorType(pt);
459 if (desc.getParameterTypes().length() != tree.params.length()) {
460 checkContext.report(tree, diags.fragment("incompatible.arg.types.in.lambda"));
461 }
462 } catch (Types.FunctionDescriptorLookupError ex) {
463 checkContext.report(null, ex.getDiagnostic());
464 }
465 }
466 }
467
468 @Override
469 public void visitNewClass(JCNewClass tree) {
470 //do nothing
471 }
472
473 @Override
474 public void visitApply(JCMethodInvocation tree) {
475 //do nothing
476 }
477
478 @Override
479 public void visitReference(JCMemberReference tree) {
480 Check.CheckContext checkContext = resultInfo.checkContext;
481 Type pt = resultInfo.pt;
482 if (inferenceContext.inferencevars.contains(pt)) {
483 //ok
484 return;
485 } else {
486 try {
487 //TODO: we should speculative determine if there's a match
488 //based on arity - if yes, method is applicable.
489 types.findDescriptorType(pt);
490 } catch (Types.FunctionDescriptorLookupError ex) {
491 checkContext.report(null, ex.getDiagnostic());
492 }
493 }
494 }
422 } 495 }
423 } 496 }
424 } 497 }
425 498
426 /** an empty deferred attribution context - all methods throw exceptions */ 499 /** an empty deferred attribution context - all methods throw exceptions */
622 @Override 695 @Override
623 public void visitLambda(JCLambda tree) { 696 public void visitLambda(JCLambda tree) {
624 if (inferenceContext.inferenceVars().contains(pt)) { 697 if (inferenceContext.inferenceVars().contains(pt)) {
625 stuckVars.add(pt); 698 stuckVars.add(pt);
626 } 699 }
627 if (!types.isFunctionalInterface(pt.tsym)) { 700 if (!types.isFunctionalInterface(pt)) {
628 return; 701 return;
629 } 702 }
630 Type descType = types.findDescriptorType(pt); 703 Type descType = types.findDescriptorType(pt);
631 List<Type> freeArgVars = inferenceContext.freeVarsIn(descType.getParameterTypes()); 704 List<Type> freeArgVars = inferenceContext.freeVarsIn(descType.getParameterTypes());
632 if (!TreeInfo.isExplicitLambda(tree) && 705 if (tree.paramKind == JCLambda.ParameterKind.IMPLICIT &&
633 freeArgVars.nonEmpty()) { 706 freeArgVars.nonEmpty()) {
634 stuckVars.addAll(freeArgVars); 707 stuckVars.addAll(freeArgVars);
635 } 708 }
636 scanLambdaBody(tree, descType.getReturnType()); 709 scanLambdaBody(tree, descType.getReturnType());
637 } 710 }
641 scan(tree.expr); 714 scan(tree.expr);
642 if (inferenceContext.inferenceVars().contains(pt)) { 715 if (inferenceContext.inferenceVars().contains(pt)) {
643 stuckVars.add(pt); 716 stuckVars.add(pt);
644 return; 717 return;
645 } 718 }
646 if (!types.isFunctionalInterface(pt.tsym)) { 719 if (!types.isFunctionalInterface(pt)) {
647 return; 720 return;
648 } 721 }
649 722
650 Type descType = types.findDescriptorType(pt); 723 Type descType = types.findDescriptorType(pt);
651 List<Type> freeArgVars = inferenceContext.freeVarsIn(descType.getParameterTypes()); 724 List<Type> freeArgVars = inferenceContext.freeVarsIn(descType.getParameterTypes());

mercurial