langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java
changeset 33712 fd1ce6d7ac63
parent 33710 acb12d30a5ac
child 33916 9b8030e8e0d9
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java	Thu Nov 12 05:59:47 2015 +0530
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java	Thu Nov 12 06:13:14 2015 +0530
@@ -55,12 +55,16 @@
 import java.util.LinkedHashMap;
 import java.util.Map;
 import java.util.Set;
+import java.util.function.Consumer;
+import java.util.function.Supplier;
 
 import static com.sun.tools.javac.comp.LambdaToMethod.LambdaSymbolKind.*;
 import static com.sun.tools.javac.code.Flags.*;
 import static com.sun.tools.javac.code.Kinds.Kind.*;
 import static com.sun.tools.javac.code.TypeTag.*;
 import static com.sun.tools.javac.tree.JCTree.Tag.*;
+
+import javax.lang.model.element.ElementKind;
 import javax.lang.model.type.TypeKind;
 
 /**
@@ -268,21 +272,34 @@
         MethodSymbol sym = localContext.translatedSym;
         MethodType lambdaType = (MethodType) sym.type;
 
-        {
+        {   /* Type annotation management: Based on where the lambda features, type annotations that
+               are interior to it, may at this point be attached to the enclosing method, or the first
+               constructor in the class, or in the enclosing class symbol or in the field whose
+               initializer is the lambda. In any event, gather up the annotations that belong to the
+               lambda and attach it to the implementation method.
+            */
+
             Symbol owner = localContext.owner;
-            ListBuffer<Attribute.TypeCompound> ownerTypeAnnos = new ListBuffer<>();
-            ListBuffer<Attribute.TypeCompound> lambdaTypeAnnos = new ListBuffer<>();
+            apportionTypeAnnotations(tree,
+                    owner::getRawTypeAttributes,
+                    owner::setTypeAttributes,
+                    sym::setTypeAttributes);
+
 
-            for (Attribute.TypeCompound tc : owner.getRawTypeAttributes()) {
-                if (tc.position.onLambda == tree) {
-                    lambdaTypeAnnos.append(tc);
-                } else {
-                    ownerTypeAnnos.append(tc);
-                }
+            boolean init;
+            if ((init = (owner.name == names.init)) || owner.name == names.clinit) {
+                owner = owner.owner;
+                apportionTypeAnnotations(tree,
+                        init ? owner::getInitTypeAttributes : owner::getClassInitTypeAttributes,
+                        init ? owner::setInitTypeAttributes : owner::setClassInitTypeAttributes,
+                        sym::appendUniqueTypeAttributes);
             }
-            if (lambdaTypeAnnos.nonEmpty()) {
-                owner.setTypeAttributes(ownerTypeAnnos.toList());
-                sym.setTypeAttributes(lambdaTypeAnnos.toList());
+            if (localContext.self != null && localContext.self.getKind() == ElementKind.FIELD) {
+                owner = localContext.self;
+                apportionTypeAnnotations(tree,
+                        owner::getRawTypeAttributes,
+                        owner::setTypeAttributes,
+                        sym::appendUniqueTypeAttributes);
             }
         }
 
@@ -354,6 +371,29 @@
         result = makeMetafactoryIndyCall(context, refKind, sym, indy_args);
     }
 
+    // where
+        // Reassign type annotations from the source that should really belong to the lambda
+        private void apportionTypeAnnotations(JCLambda tree,
+                                              Supplier<List<Attribute.TypeCompound>> source,
+                                              Consumer<List<Attribute.TypeCompound>> owner,
+                                              Consumer<List<Attribute.TypeCompound>> lambda) {
+
+            ListBuffer<Attribute.TypeCompound> ownerTypeAnnos = new ListBuffer<>();
+            ListBuffer<Attribute.TypeCompound> lambdaTypeAnnos = new ListBuffer<>();
+
+            for (Attribute.TypeCompound tc : source.get()) {
+                if (tc.position.onLambda == tree) {
+                    lambdaTypeAnnos.append(tc);
+                } else {
+                    ownerTypeAnnos.append(tc);
+                }
+            }
+            if (lambdaTypeAnnos.nonEmpty()) {
+                owner.accept(ownerTypeAnnos.toList());
+                lambda.accept(lambdaTypeAnnos.toList());
+            }
+        }
+
     private JCIdent makeThis(Type type, Symbol owner) {
         VarSymbol _this = new VarSymbol(PARAMETER | FINAL | SYNTHETIC,
                 names._this,