--- old/src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java 2017-11-28 16:55:10.141408676 +0530 +++ new/src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java 2017-11-28 16:55:10.081408675 +0530 @@ -2009,7 +2009,7 @@ Assert.error(skind.name()); throw new AssertionError(); } - if (ret != sym) { + if (ret != sym && skind.propagateAnnotations()) { ret.setDeclarationAttributes(sym.getRawAttributes()); ret.setTypeAttributes(sym.getRawTypeAttributes()); } @@ -2045,7 +2045,6 @@ if (m.containsKey(lambdaIdent.sym)) { Symbol tSym = m.get(lambdaIdent.sym); JCTree t = make.Ident(tSym).setType(lambdaIdent.type); - tSym.setTypeAttributes(lambdaIdent.sym.getRawTypeAttributes()); return t; } break; @@ -2054,7 +2053,6 @@ // Transform outer instance variable references anchoring them to the captured synthetic. Symbol tSym = m.get(lambdaIdent.sym.owner); JCExpression t = make.Ident(tSym).setType(lambdaIdent.sym.owner.type); - tSym.setTypeAttributes(lambdaIdent.sym.owner.getRawTypeAttributes()); t = make.Select(t, lambdaIdent.name); t.setType(lambdaIdent.type); TreeInfo.setSymbol(t, lambdaIdent.sym); @@ -2075,7 +2073,6 @@ if (m.containsKey(fieldAccess.sym.owner)) { Symbol tSym = m.get(fieldAccess.sym.owner); JCExpression t = make.Ident(tSym).setType(fieldAccess.sym.owner.type); - tSym.setTypeAttributes(fieldAccess.sym.owner.getRawTypeAttributes()); return t; } return null; @@ -2272,6 +2269,17 @@ CAPTURED_THIS, // class symbols to translated synthetic parameters (for captured member access) CAPTURED_OUTER_THIS, // used when `this' capture is illegal, but outer this capture is legit (JDK-8129740) TYPE_VAR; // original to translated lambda type variables + + boolean propagateAnnotations() { + switch (this) { + case CAPTURED_VAR: + case CAPTURED_THIS: + case CAPTURED_OUTER_THIS: + return false; + default: + return true; + } + } } /** --- /dev/null 2017-11-25 16:22:25.878821052 +0530 +++ new/test/tools/javac/annotations/typeAnnotations/classfile/TypeAnnotationPropagationTest.java 2017-11-28 16:55:10.313408681 +0530 @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2017, Google Inc. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8144185 8191969 + * @summary javac produces incorrect RuntimeInvisibleTypeAnnotations length attribute + */ + +import static java.lang.annotation.ElementType.TYPE_USE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import com.sun.tools.classfile.Attribute; +import com.sun.tools.classfile.ClassFile; +import com.sun.tools.classfile.Code_attribute; +import com.sun.tools.classfile.Method; +import com.sun.tools.classfile.RuntimeVisibleTypeAnnotations_attribute; +import com.sun.tools.classfile.TypeAnnotation; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; +import java.util.Arrays; +import java.util.Objects; + +public class TypeAnnotationPropagationTest extends ClassfileTestHelper { + public static void main(String[] args) throws Exception { + new TypeAnnotationPropagationTest().run(); + } + + public void run() throws Exception { + ClassFile cf = getClassFile("TypeAnnotationPropagationTest$Test.class"); + + Method f = null; + for (Method m : cf.methods) { + if (m.getName(cf.constant_pool).contains("f")) { + f = m; + break; + } + } + + int idx = f.attributes.getIndex(cf.constant_pool, Attribute.Code); + Code_attribute cattr = (Code_attribute) f.attributes.get(idx); + idx = cattr.attributes.getIndex(cf.constant_pool, Attribute.RuntimeVisibleTypeAnnotations); + RuntimeVisibleTypeAnnotations_attribute attr = + (RuntimeVisibleTypeAnnotations_attribute) cattr.attributes.get(idx); + + TypeAnnotation anno = attr.annotations[0]; + assertEquals(anno.position.lvarOffset, new int[] {3}, "start_pc"); + assertEquals(anno.position.lvarLength, new int[] {8}, "length"); + assertEquals(anno.position.lvarIndex, new int[] {1}, "index"); + } + + void assertEquals(int[] actual, int[] expected, String message) { + if (!Arrays.equals(actual, expected)) { + throw new AssertionError( + String.format( + "actual: %s, expected: %s, %s", + Arrays.toString(actual), Arrays.toString(expected), message)); + } + } + + /** ********************* Test class ************************ */ + static class Test { + void f() { + @A String s = ""; + Runnable r = + () -> { + Objects.requireNonNull(s); + Objects.requireNonNull(s); + Objects.requireNonNull(s); + Objects.requireNonNull(s); + Objects.requireNonNull(s); + Objects.requireNonNull(s); + }; + } + + @Retention(RUNTIME) + @Target(TYPE_USE) + @interface A {} + } +}