479 |
479 |
480 private static class BreakAttr extends RuntimeException { |
480 private static class BreakAttr extends RuntimeException { |
481 static final long serialVersionUID = -6924771130405446405L; |
481 static final long serialVersionUID = -6924771130405446405L; |
482 private Env<AttrContext> env; |
482 private Env<AttrContext> env; |
483 private BreakAttr(Env<AttrContext> env) { |
483 private BreakAttr(Env<AttrContext> env) { |
484 this.env = copyEnv(env); |
484 this.env = env; |
485 } |
|
486 |
|
487 private Env<AttrContext> copyEnv(Env<AttrContext> env) { |
|
488 Env<AttrContext> newEnv = |
|
489 env.dup(env.tree, env.info.dup(copyScope(env.info.scope))); |
|
490 if (newEnv.outer != null) { |
|
491 newEnv.outer = copyEnv(newEnv.outer); |
|
492 } |
|
493 return newEnv; |
|
494 } |
|
495 |
|
496 private Scope copyScope(Scope sc) { |
|
497 Scope newScope = new Scope(sc.owner); |
|
498 List<Symbol> elemsList = List.nil(); |
|
499 while (sc != null) { |
|
500 for (Scope.Entry e = sc.elems ; e != null ; e = e.sibling) { |
|
501 elemsList = elemsList.prepend(e.sym); |
|
502 } |
|
503 sc = sc.next; |
|
504 } |
|
505 for (Symbol s : elemsList) { |
|
506 newScope.enter(s); |
|
507 } |
|
508 return newScope; |
|
509 } |
485 } |
510 } |
486 } |
511 |
487 |
512 class ResultInfo { |
488 class ResultInfo { |
513 final int pkind; |
489 final int pkind; |
603 this.env = env; |
579 this.env = env; |
604 this.resultInfo = resultInfo; |
580 this.resultInfo = resultInfo; |
605 tree.accept(this); |
581 tree.accept(this); |
606 if (tree == breakTree && |
582 if (tree == breakTree && |
607 resultInfo.checkContext.deferredAttrContext().mode == AttrMode.CHECK) { |
583 resultInfo.checkContext.deferredAttrContext().mode == AttrMode.CHECK) { |
608 throw new BreakAttr(env); |
584 throw new BreakAttr(copyEnv(env)); |
609 } |
585 } |
610 return result; |
586 return result; |
611 } catch (CompletionFailure ex) { |
587 } catch (CompletionFailure ex) { |
612 tree.type = syms.errType; |
588 tree.type = syms.errType; |
613 return chk.completionError(tree.pos(), ex); |
589 return chk.completionError(tree.pos(), ex); |
614 } finally { |
590 } finally { |
615 this.env = prevEnv; |
591 this.env = prevEnv; |
616 this.resultInfo = prevResult; |
592 this.resultInfo = prevResult; |
617 } |
593 } |
|
594 } |
|
595 |
|
596 Env<AttrContext> copyEnv(Env<AttrContext> env) { |
|
597 Env<AttrContext> newEnv = |
|
598 env.dup(env.tree, env.info.dup(copyScope(env.info.scope))); |
|
599 if (newEnv.outer != null) { |
|
600 newEnv.outer = copyEnv(newEnv.outer); |
|
601 } |
|
602 return newEnv; |
|
603 } |
|
604 |
|
605 Scope copyScope(Scope sc) { |
|
606 Scope newScope = new Scope(sc.owner); |
|
607 List<Symbol> elemsList = List.nil(); |
|
608 while (sc != null) { |
|
609 for (Scope.Entry e = sc.elems ; e != null ; e = e.sibling) { |
|
610 elemsList = elemsList.prepend(e.sym); |
|
611 } |
|
612 sc = sc.next; |
|
613 } |
|
614 for (Symbol s : elemsList) { |
|
615 newScope.enter(s); |
|
616 } |
|
617 return newScope; |
618 } |
618 } |
619 |
619 |
620 /** Derived visitor method: attribute an expression tree. |
620 /** Derived visitor method: attribute an expression tree. |
621 */ |
621 */ |
622 public Type attribExpr(JCTree tree, Env<AttrContext> env, Type pt) { |
622 public Type attribExpr(JCTree tree, Env<AttrContext> env, Type pt) { |
2429 result = check(that, target, VAL, resultInfo); |
2429 result = check(that, target, VAL, resultInfo); |
2430 |
2430 |
2431 boolean isSpeculativeRound = |
2431 boolean isSpeculativeRound = |
2432 resultInfo.checkContext.deferredAttrContext().mode == DeferredAttr.AttrMode.SPECULATIVE; |
2432 resultInfo.checkContext.deferredAttrContext().mode == DeferredAttr.AttrMode.SPECULATIVE; |
2433 |
2433 |
2434 postAttr(that); |
2434 preFlow(that); |
2435 flow.analyzeLambda(env, that, make, isSpeculativeRound); |
2435 flow.analyzeLambda(env, that, make, isSpeculativeRound); |
2436 |
2436 |
2437 checkLambdaCompatible(that, lambdaType, resultInfo.checkContext, isSpeculativeRound); |
2437 checkLambdaCompatible(that, lambdaType, resultInfo.checkContext, isSpeculativeRound); |
2438 |
2438 |
2439 if (!isSpeculativeRound) { |
2439 if (!isSpeculativeRound) { |
2451 attribTree(that, env, recoveryInfo); |
2451 attribTree(that, env, recoveryInfo); |
2452 } |
2452 } |
2453 } |
2453 } |
2454 } |
2454 } |
2455 //where |
2455 //where |
|
2456 void preFlow(JCLambda tree) { |
|
2457 new PostAttrAnalyzer() { |
|
2458 @Override |
|
2459 public void scan(JCTree tree) { |
|
2460 if (tree == null || |
|
2461 (tree.type != null && |
|
2462 tree.type == Type.stuckType)) { |
|
2463 //don't touch stuck expressions! |
|
2464 return; |
|
2465 } |
|
2466 super.scan(tree); |
|
2467 } |
|
2468 }.scan(tree); |
|
2469 } |
|
2470 |
2456 Types.MapVisitor<DiagnosticPosition> targetChecker = new Types.MapVisitor<DiagnosticPosition>() { |
2471 Types.MapVisitor<DiagnosticPosition> targetChecker = new Types.MapVisitor<DiagnosticPosition>() { |
2457 |
2472 |
2458 @Override |
2473 @Override |
2459 public Type visitClassType(ClassType t, DiagnosticPosition pos) { |
2474 public Type visitClassType(ClassType t, DiagnosticPosition pos) { |
2460 return t.isCompound() ? |
2475 return t.isCompound() ? |