changeset 2787:441711fd360d

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
author jlahoda
date Tue, 13 Jan 2015 10:25:24 +0100
parents 143e819d5ddc
children 4359df35c893
files src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java test/tools/javac/MethodParameters/ClassFileVisitor.java test/tools/javac/MethodParameters/LambdaTest.java test/tools/javac/MethodParameters/LambdaTest.out test/tools/javac/MethodParameters/ReflectionVisitor.java
diffstat 5 files changed, 21 insertions(+), 19 deletions(-) [+]
line wrap: on
line diff
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java	Tue Jan 13 10:17:25 2015 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java	Tue Jan 13 10:25:24 2015 +0100
@@ -263,7 +263,7 @@
     @Override
     public void visitLambda(JCLambda tree) {
         LambdaTranslationContext localContext = (LambdaTranslationContext)context;
-        MethodSymbol sym = (MethodSymbol)localContext.translatedSym;
+        MethodSymbol sym = localContext.translatedSym;
         MethodType lambdaType = (MethodType) sym.type;
 
         {
@@ -1755,7 +1755,7 @@
             Map<LambdaSymbolKind, Map<Symbol, Symbol>> translatedSymbols;
 
             /** the synthetic symbol for the method hoisting the translated lambda */
-            Symbol translatedSym;
+            MethodSymbol translatedSym;
 
             List<JCVariableDecl> syntheticParams;
 
@@ -1997,6 +1997,7 @@
 
                 //compute synthetic params
                 ListBuffer<JCVariableDecl> params = new ListBuffer<>();
+                ListBuffer<VarSymbol> parameterSymbols = new ListBuffer<>();
 
                 // The signature of the method is augmented with the following
                 // synthetic parameters:
@@ -2005,19 +2006,16 @@
                 // 2) enclosing locals captured by the lambda expression
                 for (Symbol thisSym : getSymbolMap(CAPTURED_VAR).values()) {
                     params.append(make.VarDef((VarSymbol) thisSym, null));
-                }
-                if (methodReferenceReceiver != null) {
-                    params.append(make.VarDef(
-                            make.Modifiers(PARAMETER|FINAL),
-                            names.fromString("$rcvr$"),
-                            make.Type(methodReferenceReceiver.type),
-                            null));
+                    parameterSymbols.append((VarSymbol) thisSym);
                 }
                 for (Symbol thisSym : getSymbolMap(PARAM).values()) {
                     params.append(make.VarDef((VarSymbol) thisSym, null));
+                    parameterSymbols.append((VarSymbol) thisSym);
                 }
                 syntheticParams = params.toList();
 
+                translatedSym.params = parameterSymbols.toList();
+
                 // Compute and set the lambda name
                 translatedSym.name = isSerializable()
                         ? serializedLambdaName()
--- a/test/tools/javac/MethodParameters/ClassFileVisitor.java	Tue Jan 13 10:17:25 2015 +0100
+++ b/test/tools/javac/MethodParameters/ClassFileVisitor.java	Tue Jan 13 10:25:24 2015 +0100
@@ -147,6 +147,7 @@
         public int mAttrs;
         public int mNumParams;
         public boolean mSynthetic;
+        public boolean mIsLambda;
         public boolean mIsConstructor;
         public boolean mIsClinit;
         public boolean mIsBridge;
@@ -165,6 +166,7 @@
             mIsClinit = mName.equals("<clinit>");
             prefix = cname + "." + mName + "() - ";
             mIsBridge = method.access_flags.is(AccessFlags.ACC_BRIDGE);
+            mIsLambda = mSynthetic && mName.startsWith("lambda$");
 
             if (mIsClinit) {
                 sb = new StringBuilder(); // Discard output
@@ -225,7 +227,7 @@
 
             // IMPL: Whether MethodParameters attributes will be generated
             // for some synthetics is unresolved. For now, assume no.
-            if (mSynthetic) {
+            if (mSynthetic && !mIsLambda) {
                 warn(prefix + "synthetic has MethodParameter attribute");
             }
 
@@ -349,10 +351,12 @@
             } else if (isEnum && mNumParams == 1 && index == 0 && mName.equals("valueOf")) {
                 expect = "name";
                 allowMandated = true;
-            } else if (mIsBridge) {
+            } else if (mIsBridge || mIsLambda) {
                 allowSynthetic = true;
                 /*  you can't expect an special name for bridges' parameters.
-                 *  The name of the original parameters are now copied.
+                 *  The name of the original parameters are now copied. Likewise
+                 *  for a method encoding the lambda expression, names are derived
+                 *  from source lambda's parameters and captured enclosing locals.
                  */
                 expect = null;
             }
--- a/test/tools/javac/MethodParameters/LambdaTest.java	Tue Jan 13 10:17:25 2015 +0100
+++ b/test/tools/javac/MethodParameters/LambdaTest.java	Tue Jan 13 10:25:24 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2015 Oracle and/or its affiliates. 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
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug 8006582
+ * @bug 8006582 8037546
  * @summary javac should generate method parameters correctly.
  * @build Tester
  * @compile -parameters LambdaTest.java
@@ -31,8 +31,8 @@
  */
 
 /**
- * Parameter names are not recorded for lambdas. This test verifies
- * that there are no MethodParameters attribute for lambdas.
+ * Post https://bugs.openjdk.java.net/browse/JDK-8037546, this test verifies
+ * that MethodParameters attribute for lambdas are emitted properly.
  */
 class LambdaTest {
 
--- a/test/tools/javac/MethodParameters/LambdaTest.out	Tue Jan 13 10:17:25 2015 +0100
+++ b/test/tools/javac/MethodParameters/LambdaTest.out	Tue Jan 13 10:25:24 2015 +0100
@@ -1,7 +1,7 @@
 class LambdaTest -- 
 LambdaTest.<init>()
 LambdaTest.foo(i)
-LambdaTest.lambda$static$1(arg0)/*synthetic*/
-LambdaTest.lambda$null$0(arg0, arg1)/*synthetic*/
+LambdaTest.lambda$static$1(x1/*synthetic*/)/*synthetic*/
+LambdaTest.lambda$null$0(final cap$0/*synthetic*/, x2/*synthetic*/)/*synthetic*/
 static interface LambdaTest$I -- inner
 LambdaTest$I.m(x)
--- a/test/tools/javac/MethodParameters/ReflectionVisitor.java	Tue Jan 13 10:17:25 2015 +0100
+++ b/test/tools/javac/MethodParameters/ReflectionVisitor.java	Tue Jan 13 10:25:24 2015 +0100
@@ -277,7 +277,7 @@
                     param = "final " + param;
                 }
                 sb.append(sep).append(param);
-                if (!m.isBridge() && !expect.equals(param)) {
+                if (!m.isBridge() && !m.getName().startsWith("lambda$") && !expect.equals(param)) {
                     error(prefix + "param[" + i + "]='"
                           + param + "' expected '" + expect + "'");
                     break;