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

changeset 1348
573ceb23beeb
parent 1347
1408af4cd8b0
child 1357
c75be5bc5283
equal deleted inserted replaced
1347:1408af4cd8b0 1348:573ceb23beeb
495 * are mapped to themselves, in order to have a richer diagnostic 495 * are mapped to themselves, in order to have a richer diagnostic
496 * representation. Remaining deferred types are attributed using 496 * representation. Remaining deferred types are attributed using
497 * a default expected type (j.l.Object). 497 * a default expected type (j.l.Object).
498 */ 498 */
499 private Type recover(DeferredType dt) { 499 private Type recover(DeferredType dt) {
500 dt.check(new RecoveryInfo()); 500 dt.check(attr.new RecoveryInfo(deferredAttrContext));
501 switch (TreeInfo.skipParens(dt.tree).getTag()) { 501 switch (TreeInfo.skipParens(dt.tree).getTag()) {
502 case LAMBDA: 502 case LAMBDA:
503 case REFERENCE: 503 case REFERENCE:
504 case CONDEXPR: 504 case CONDEXPR:
505 //propagate those deferred types to the 505 //propagate those deferred types to the
507 return dt; 507 return dt;
508 default: 508 default:
509 return super.apply(dt); 509 return super.apply(dt);
510 } 510 }
511 } 511 }
512
513 class RecoveryInfo extends ResultInfo {
514
515 public RecoveryInfo() {
516 attr.super(Kinds.VAL, Type.recoveryType, new Check.NestedCheckContext(chk.basicHandler) {
517 @Override
518 public DeferredAttrContext deferredAttrContext() {
519 return deferredAttrContext;
520 }
521 @Override
522 public boolean compatible(Type found, Type req, Warner warn) {
523 return true;
524 }
525 @Override
526 public void report(DiagnosticPosition pos, JCDiagnostic details) {
527 //do nothing
528 }
529 });
530 }
531
532 @Override
533 protected Type check(DiagnosticPosition pos, Type found) {
534 return chk.checkNonVoid(pos, super.check(pos, found));
535 }
536 }
537 } 512 }
538 513
539 /** 514 /**
540 * Retrieves the list of inference variables that need to be inferred before 515 * Retrieves the list of inference variables that need to be inferred before
541 * an AST node can be type-checked 516 * an AST node can be type-checked
542 */ 517 */
543 @SuppressWarnings("fallthrough") 518 @SuppressWarnings("fallthrough")
544 List<Type> stuckVars(JCExpression tree, ResultInfo resultInfo) { 519 List<Type> stuckVars(JCTree tree, ResultInfo resultInfo) {
545 switch (tree.getTag()) { 520 if (resultInfo.pt.tag == NONE || resultInfo.pt.isErroneous()) {
546 case LAMBDA: 521 return List.nil();
547 case REFERENCE: 522 } else {
548 Assert.error("not supported yet"); 523 StuckChecker sc = new StuckChecker(resultInfo);
549 default: 524 sc.scan(tree);
550 return List.nil(); 525 return List.from(sc.stuckVars);
526 }
527 }
528
529 /**
530 * This visitor is used to check that structural expressions conform
531 * to their target - this step is required as inference could end up
532 * inferring types that make some of the nested expressions incompatible
533 * with their corresponding instantiated target
534 */
535 class StuckChecker extends TreeScanner {
536
537 Type pt;
538 Filter<JCTree> treeFilter;
539 Infer.InferenceContext inferenceContext;
540 Set<Type> stuckVars = new HashSet<Type>();
541
542 final Filter<JCTree> argsFilter = new Filter<JCTree>() {
543 public boolean accepts(JCTree t) {
544 switch (t.getTag()) {
545 case CONDEXPR:
546 case LAMBDA:
547 case PARENS:
548 case REFERENCE:
549 return true;
550 default:
551 return false;
552 }
553 }
554 };
555
556 final Filter<JCTree> lambdaBodyFilter = new Filter<JCTree>() {
557 public boolean accepts(JCTree t) {
558 switch (t.getTag()) {
559 case BLOCK: case CASE: case CATCH: case DOLOOP:
560 case FOREACHLOOP: case FORLOOP: case RETURN:
561 case SYNCHRONIZED: case SWITCH: case TRY: case WHILELOOP:
562 return true;
563 default:
564 return false;
565 }
566 }
567 };
568
569 StuckChecker(ResultInfo resultInfo) {
570 this.pt = resultInfo.pt;
571 this.inferenceContext = resultInfo.checkContext.inferenceContext();
572 this.treeFilter = argsFilter;
573 }
574
575 @Override
576 public void scan(JCTree tree) {
577 if (tree != null && treeFilter.accepts(tree)) {
578 super.scan(tree);
579 }
580 }
581
582 @Override
583 public void visitLambda(JCLambda tree) {
584 Type prevPt = pt;
585 Filter<JCTree> prevFilter = treeFilter;
586 try {
587 if (inferenceContext.inferenceVars().contains(pt)) {
588 stuckVars.add(pt);
589 }
590 if (!types.isFunctionalInterface(pt.tsym)) {
591 return;
592 }
593 Type descType = types.findDescriptorType(pt);
594 List<Type> freeArgVars = inferenceContext.freeVarsIn(descType.getParameterTypes());
595 if (!TreeInfo.isExplicitLambda(tree) &&
596 freeArgVars.nonEmpty()) {
597 stuckVars.addAll(freeArgVars);
598 }
599 pt = descType.getReturnType();
600 if (tree.getBodyKind() == JCTree.JCLambda.BodyKind.EXPRESSION) {
601 scan(tree.getBody());
602 } else {
603 treeFilter = lambdaBodyFilter;
604 super.visitLambda(tree);
605 }
606 } finally {
607 pt = prevPt;
608 treeFilter = prevFilter;
609 }
610 }
611
612 @Override
613 public void visitReference(JCMemberReference tree) {
614 scan(tree.expr);
615 if (inferenceContext.inferenceVars().contains(pt)) {
616 stuckVars.add(pt);
617 return;
618 }
619 if (!types.isFunctionalInterface(pt.tsym)) {
620 return;
621 }
622 Type descType = types.findDescriptorType(pt);
623 List<Type> freeArgVars = inferenceContext.freeVarsIn(descType.getParameterTypes());
624 stuckVars.addAll(freeArgVars);
625 }
626
627 @Override
628 public void visitReturn(JCReturn tree) {
629 Filter<JCTree> prevFilter = treeFilter;
630 try {
631 treeFilter = argsFilter;
632 if (tree.expr != null) {
633 scan(tree.expr);
634 }
635 } finally {
636 treeFilter = prevFilter;
637 }
551 } 638 }
552 } 639 }
553 } 640 }

mercurial