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

changeset 2222
8832b6048e65
parent 2210
a746587a1ff1
child 2253
afb6642d0603
equal deleted inserted replaced
2221:d80c3d6f4f05 2222:8832b6048e65
2588 if (!types.isSameTypes(argTypes, TreeInfo.types(tree.params))) { 2588 if (!types.isSameTypes(argTypes, TreeInfo.types(tree.params))) {
2589 checkContext.report(tree, diags.fragment("incompatible.arg.types.in.lambda")); 2589 checkContext.report(tree, diags.fragment("incompatible.arg.types.in.lambda"));
2590 } 2590 }
2591 } 2591 }
2592 2592
2593 /* Map to hold 'fake' clinit methods. If a lambda is used to initialize a
2594 * static field and that lambda has type annotations, these annotations will
2595 * also be stored at these fake clinit methods.
2596 *
2597 * LambdaToMethod also use fake clinit methods so they can be reused.
2598 * Also as LTM is a phase subsequent to attribution, the methods from
2599 * clinits can be safely removed by LTM to save memory.
2600 */
2601 private Map<ClassSymbol, MethodSymbol> clinits = new HashMap<>();
2602
2603 public MethodSymbol removeClinit(ClassSymbol sym) {
2604 return clinits.remove(sym);
2605 }
2606
2607 /* This method returns an environment to be used to attribute a lambda
2608 * expression.
2609 *
2610 * The owner of this environment is a method symbol. If the current owner
2611 * is not a method, for example if the lambda is used to initialize
2612 * a field, then if the field is:
2613 *
2614 * - an instance field, we use the first constructor.
2615 * - a static field, we create a fake clinit method.
2616 */
2593 private Env<AttrContext> lambdaEnv(JCLambda that, Env<AttrContext> env) { 2617 private Env<AttrContext> lambdaEnv(JCLambda that, Env<AttrContext> env) {
2594 Env<AttrContext> lambdaEnv; 2618 Env<AttrContext> lambdaEnv;
2595 Symbol owner = env.info.scope.owner; 2619 Symbol owner = env.info.scope.owner;
2596 if (owner.kind == VAR && owner.owner.kind == TYP) { 2620 if (owner.kind == VAR && owner.owner.kind == TYP) {
2597 //field initializer 2621 //field initializer
2598 lambdaEnv = env.dup(that, env.info.dup(env.info.scope.dupUnshared())); 2622 lambdaEnv = env.dup(that, env.info.dup(env.info.scope.dupUnshared()));
2599 lambdaEnv.info.scope.owner = 2623 ClassSymbol enclClass = owner.enclClass();
2600 new MethodSymbol((owner.flags() & STATIC) | BLOCK, names.empty, null, 2624 /* if the field isn't static, then we can get the first constructor
2601 env.info.scope.owner); 2625 * and use it as the owner of the environment. This is what
2626 * LTM code is doing to look for type annotations so we are fine.
2627 */
2628 if ((owner.flags() & STATIC) == 0) {
2629 for (Symbol s : enclClass.members_field.getElementsByName(names.init)) {
2630 lambdaEnv.info.scope.owner = s;
2631 break;
2632 }
2633 } else {
2634 /* if the field is static then we need to create a fake clinit
2635 * method, this method can later be reused by LTM.
2636 */
2637 MethodSymbol clinit = clinits.get(enclClass);
2638 if (clinit == null) {
2639 Type clinitType = new MethodType(List.<Type>nil(),
2640 syms.voidType, List.<Type>nil(), syms.methodClass);
2641 clinit = new MethodSymbol(STATIC | SYNTHETIC | PRIVATE,
2642 names.clinit, clinitType, enclClass);
2643 clinit.params = List.<VarSymbol>nil();
2644 clinits.put(enclClass, clinit);
2645 }
2646 lambdaEnv.info.scope.owner = clinit;
2647 }
2602 } else { 2648 } else {
2603 lambdaEnv = env.dup(that, env.info.dup(env.info.scope.dup())); 2649 lambdaEnv = env.dup(that, env.info.dup(env.info.scope.dup()));
2604 } 2650 }
2605 return lambdaEnv; 2651 return lambdaEnv;
2606 } 2652 }

mercurial