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 } |