changeset 753:4335e2277cbd

Lexical scope fixes: *) wrong dispatching of Object members (e.g. toString()) inside a lambda in case Object member not overriden in enclosing class *) javac crash when compiling a lambda expression containing an Object.getClass() call *) NoSuchField error when executing a lambda expression containing 'this'
author mcimadamore
date Mon, 15 Nov 2010 17:07:07 +0000
parents 81019709553d
children 83c22f23d80c
files src/share/classes/com/sun/tools/javac/comp/Attr.java src/share/classes/com/sun/tools/javac/comp/Unlambda.java test/tools/javac/lambda/LambdaScope03.java
diffstat 3 files changed, 96 insertions(+), 5 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/com/sun/tools/javac/comp/Attr.java	Fri Nov 12 15:49:29 2010 +0000
+++ b/src/share/classes/com/sun/tools/javac/comp/Attr.java	Mon Nov 15 17:07:07 2010 +0000
@@ -1534,6 +1534,9 @@
                 Type qualifier = (tree.meth.getTag() == JCTree.SELECT)
                     ? ((JCFieldAccess) tree.meth).selected.type
                     : env.enclClass.sym.type;
+                while ((qualifier.tsym.flags() & LAMBDA) != 0) {
+                    qualifier = qualifier.getEnclosingType();
+                }
                 restype = new
                     ClassType(restype.getEnclosingType(),
                               List.<Type>of(new WildcardType(types.erasure(qualifier),
--- a/src/share/classes/com/sun/tools/javac/comp/Unlambda.java	Fri Nov 12 15:49:29 2010 +0000
+++ b/src/share/classes/com/sun/tools/javac/comp/Unlambda.java	Mon Nov 15 17:07:07 2010 +0000
@@ -108,11 +108,11 @@
         ClassSymbol samClassSym = (ClassSymbol)tree.sym.owner;
 
         //add this
-        VarSymbol thisSym = new VarSymbol(Flags.FINAL | Flags.HASINIT,
-                    names._this,
-                    samClassSym.type,
-                    samClassSym);
-        samClassSym.members().enter(thisSym);
+//        VarSymbol thisSym = new VarSymbol(Flags.FINAL | Flags.HASINIT,
+//                    names._this,
+//                    samClassSym.type,
+//                    samClassSym);
+//        samClassSym.members().enter(thisSym);
 
         Type superType = types.isFunctionType(tree.targetType) ?
             syms.methodHandleType :
@@ -226,6 +226,32 @@
     }
 
     @Override
+    public void visitIdent(JCIdent tree) {
+        if ((currentClass.sym.flags() & Flags.LAMBDA) != 0 &&
+                (tree.name == names._super ||
+                tree.name == names._this)) {
+            Type encl = tree.sym.owner.type;
+            result = make.Select(make.Type(types.erasure(encl)), tree.sym);
+        }
+        else if ((currentClass.sym.flags() & Flags.LAMBDA) != 0 &&
+                (tree.sym.kind == Kinds.VAR || tree.sym.kind == Kinds.MTH) &&
+                tree.sym.owner == syms.objectType.tsym) {
+            Type encl = currentClass.type.getEnclosingType();
+            while (encl != Type.noType && (encl.tsym.flags() & Flags.LAMBDA) != 0) {
+                encl = encl.getEnclosingType();
+            }
+            JCFieldAccess qualifiedThis =
+                    (JCFieldAccess)make.Select(make.Type(types.erasure(encl)),
+                                               names._this).setType(encl);
+            qualifiedThis.sym =  new VarSymbol(0, names._this, encl, encl.tsym);
+            result = make.Select(qualifiedThis, tree.sym);
+        }
+        else {
+            super.visitIdent(tree);
+        }
+    }
+
+    @Override
     public void visitVarDef(final JCVariableDecl tree) {
         if (tree.sym.owner.kind == Kinds.MTH &&
                 tree.init != null &&
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/lambda/LambdaScope03.java	Mon Nov 15 17:07:07 2010 +0000
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2010, 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
+ * 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
+ * @summary check that unqualified Object members are accessed as expected
+ * @author  Maurizio Cimadamore
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableMethodHandles LambdaScope03
+ */
+
+public class LambdaScope03 {
+
+    static int assertionCount = 0;
+
+    static void assertTrue(boolean cond) {
+        assertionCount++;
+        if (!cond)
+            throw new AssertionError();
+    }
+
+    interface SAM {
+        void m();
+    }
+
+    static void call(SAM s) { s.m(); }
+
+    void test() {
+        call(#{ assertTrue(LambdaScope03.this.getClass().equals(getClass())); });
+        call(#{ assertTrue(LambdaScope03.this.getClass().equals(this.getClass())); });
+        call(#{ assertTrue(LambdaScope03.this.hashCode() == hashCode()); });
+        call(#{ assertTrue(LambdaScope03.this.hashCode() == this.hashCode()); });
+        call(#{ assertTrue(LambdaScope03.this.toString().equals(toString())); });
+        call(#{ assertTrue(LambdaScope03.this.toString().equals(this.toString())); });
+        call(#{ assertTrue(LambdaScope03.this.equals(this)); });
+        call(#{ assertTrue(equals(LambdaScope03.this)); });
+    }
+
+    public static void main(String[] args) {
+        new LambdaScope03().test();
+        assertTrue(assertionCount == 8);
+    }
+}