Tue, 13 Jan 2015 10:25:24 +0100
8037546: javac -parameters does not emit parameter names for lambda expressions
Summary: MethodParameters attribute is missing for synthetic methods encoding lambda expressions.
Reviewed-by: rfield, mcimadamore
Contributed-by: srikanth.adayapalam@oracle.com
1.1 --- a/src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java Wed Apr 01 13:23:01 2015 -0700 1.2 +++ b/src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java Tue Jan 13 10:25:24 2015 +0100 1.3 @@ -265,7 +265,7 @@ 1.4 @Override 1.5 public void visitLambda(JCLambda tree) { 1.6 LambdaTranslationContext localContext = (LambdaTranslationContext)context; 1.7 - MethodSymbol sym = (MethodSymbol)localContext.translatedSym; 1.8 + MethodSymbol sym = localContext.translatedSym; 1.9 MethodType lambdaType = (MethodType) sym.type; 1.10 1.11 { 1.12 @@ -1755,7 +1755,7 @@ 1.13 Map<LambdaSymbolKind, Map<Symbol, Symbol>> translatedSymbols; 1.14 1.15 /** the synthetic symbol for the method hoisting the translated lambda */ 1.16 - Symbol translatedSym; 1.17 + MethodSymbol translatedSym; 1.18 1.19 List<JCVariableDecl> syntheticParams; 1.20 1.21 @@ -1997,6 +1997,7 @@ 1.22 1.23 //compute synthetic params 1.24 ListBuffer<JCVariableDecl> params = new ListBuffer<>(); 1.25 + ListBuffer<VarSymbol> parameterSymbols = new ListBuffer<>(); 1.26 1.27 // The signature of the method is augmented with the following 1.28 // synthetic parameters: 1.29 @@ -2005,19 +2006,16 @@ 1.30 // 2) enclosing locals captured by the lambda expression 1.31 for (Symbol thisSym : getSymbolMap(CAPTURED_VAR).values()) { 1.32 params.append(make.VarDef((VarSymbol) thisSym, null)); 1.33 - } 1.34 - if (methodReferenceReceiver != null) { 1.35 - params.append(make.VarDef( 1.36 - make.Modifiers(PARAMETER|FINAL), 1.37 - names.fromString("$rcvr$"), 1.38 - make.Type(methodReferenceReceiver.type), 1.39 - null)); 1.40 + parameterSymbols.append((VarSymbol) thisSym); 1.41 } 1.42 for (Symbol thisSym : getSymbolMap(PARAM).values()) { 1.43 params.append(make.VarDef((VarSymbol) thisSym, null)); 1.44 + parameterSymbols.append((VarSymbol) thisSym); 1.45 } 1.46 syntheticParams = params.toList(); 1.47 1.48 + translatedSym.params = parameterSymbols.toList(); 1.49 + 1.50 // Compute and set the lambda name 1.51 translatedSym.name = isSerializable() 1.52 ? serializedLambdaName()
2.1 --- a/test/tools/javac/MethodParameters/ClassFileVisitor.java Wed Apr 01 13:23:01 2015 -0700 2.2 +++ b/test/tools/javac/MethodParameters/ClassFileVisitor.java Tue Jan 13 10:25:24 2015 +0100 2.3 @@ -147,6 +147,7 @@ 2.4 public int mAttrs; 2.5 public int mNumParams; 2.6 public boolean mSynthetic; 2.7 + public boolean mIsLambda; 2.8 public boolean mIsConstructor; 2.9 public boolean mIsClinit; 2.10 public boolean mIsBridge; 2.11 @@ -165,6 +166,7 @@ 2.12 mIsClinit = mName.equals("<clinit>"); 2.13 prefix = cname + "." + mName + "() - "; 2.14 mIsBridge = method.access_flags.is(AccessFlags.ACC_BRIDGE); 2.15 + mIsLambda = mSynthetic && mName.startsWith("lambda$"); 2.16 2.17 if (mIsClinit) { 2.18 sb = new StringBuilder(); // Discard output 2.19 @@ -225,7 +227,7 @@ 2.20 2.21 // IMPL: Whether MethodParameters attributes will be generated 2.22 // for some synthetics is unresolved. For now, assume no. 2.23 - if (mSynthetic) { 2.24 + if (mSynthetic && !mIsLambda) { 2.25 warn(prefix + "synthetic has MethodParameter attribute"); 2.26 } 2.27 2.28 @@ -349,10 +351,12 @@ 2.29 } else if (isEnum && mNumParams == 1 && index == 0 && mName.equals("valueOf")) { 2.30 expect = "name"; 2.31 allowMandated = true; 2.32 - } else if (mIsBridge) { 2.33 + } else if (mIsBridge || mIsLambda) { 2.34 allowSynthetic = true; 2.35 /* you can't expect an special name for bridges' parameters. 2.36 - * The name of the original parameters are now copied. 2.37 + * The name of the original parameters are now copied. Likewise 2.38 + * for a method encoding the lambda expression, names are derived 2.39 + * from source lambda's parameters and captured enclosing locals. 2.40 */ 2.41 expect = null; 2.42 }
3.1 --- a/test/tools/javac/MethodParameters/LambdaTest.java Wed Apr 01 13:23:01 2015 -0700 3.2 +++ b/test/tools/javac/MethodParameters/LambdaTest.java Tue Jan 13 10:25:24 2015 +0100 3.3 @@ -1,5 +1,5 @@ 3.4 /* 3.5 - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. 3.6 + * Copyright (c) 2013, 2015 Oracle and/or its affiliates. All rights reserved. 3.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3.8 * 3.9 * This code is free software; you can redistribute it and/or modify it 3.10 @@ -23,7 +23,7 @@ 3.11 3.12 /* 3.13 * @test 3.14 - * @bug 8006582 3.15 + * @bug 8006582 8037546 3.16 * @summary javac should generate method parameters correctly. 3.17 * @build Tester 3.18 * @compile -parameters LambdaTest.java 3.19 @@ -31,8 +31,8 @@ 3.20 */ 3.21 3.22 /** 3.23 - * Parameter names are not recorded for lambdas. This test verifies 3.24 - * that there are no MethodParameters attribute for lambdas. 3.25 + * Post https://bugs.openjdk.java.net/browse/JDK-8037546, this test verifies 3.26 + * that MethodParameters attribute for lambdas are emitted properly. 3.27 */ 3.28 class LambdaTest { 3.29
4.1 --- a/test/tools/javac/MethodParameters/LambdaTest.out Wed Apr 01 13:23:01 2015 -0700 4.2 +++ b/test/tools/javac/MethodParameters/LambdaTest.out Tue Jan 13 10:25:24 2015 +0100 4.3 @@ -1,7 +1,7 @@ 4.4 class LambdaTest -- 4.5 LambdaTest.<init>() 4.6 LambdaTest.foo(i) 4.7 -LambdaTest.lambda$static$1(arg0)/*synthetic*/ 4.8 -LambdaTest.lambda$null$0(arg0, arg1)/*synthetic*/ 4.9 +LambdaTest.lambda$static$1(x1/*synthetic*/)/*synthetic*/ 4.10 +LambdaTest.lambda$null$0(final cap$0/*synthetic*/, x2/*synthetic*/)/*synthetic*/ 4.11 static interface LambdaTest$I -- inner 4.12 LambdaTest$I.m(x)
5.1 --- a/test/tools/javac/MethodParameters/ReflectionVisitor.java Wed Apr 01 13:23:01 2015 -0700 5.2 +++ b/test/tools/javac/MethodParameters/ReflectionVisitor.java Tue Jan 13 10:25:24 2015 +0100 5.3 @@ -277,7 +277,7 @@ 5.4 param = "final " + param; 5.5 } 5.6 sb.append(sep).append(param); 5.7 - if (!m.isBridge() && !expect.equals(param)) { 5.8 + if (!m.isBridge() && !m.getName().startsWith("lambda$") && !expect.equals(param)) { 5.9 error(prefix + "param[" + i + "]='" 5.10 + param + "' expected '" + expect + "'"); 5.11 break;