changeset 1431:68da3a8292fc lambda-b48

Miscellaneous fixes: *) On-demand symbol completion during speculative attribution round fails to report error messages *) Compiler crash when local inner class nested inside lambda captures local variables from enclosing scope
author mcimadamore
date Thu, 12 Jul 2012 15:39:53 +0100
parents d0cc56651ab1
children df7741e57447
files src/share/classes/com/sun/tools/javac/comp/Attr.java src/share/classes/com/sun/tools/javac/comp/DeferredAttr.java src/share/classes/com/sun/tools/javac/comp/Flow.java src/share/classes/com/sun/tools/javac/comp/LambdaToInnerClass.java src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java src/share/classes/com/sun/tools/javac/comp/LambdaTranslator.java src/share/classes/com/sun/tools/javac/main/JavaCompiler.java src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java src/share/classes/com/sun/tools/javac/util/Log.java test/tools/javac/lambda/LambdaCapture06.java test/tools/javac/lambda/speculative/A.java test/tools/javac/lambda/speculative/Main.java test/tools/javac/lambda/speculative/Main.out
diffstat 13 files changed, 189 insertions(+), 40 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/com/sun/tools/javac/comp/Attr.java	Wed Jul 11 16:37:26 2012 +0100
+++ b/src/share/classes/com/sun/tools/javac/comp/Attr.java	Thu Jul 12 15:39:53 2012 +0100
@@ -1274,10 +1274,10 @@
             types.asSuper(resource, syms.autoCloseableType.tsym) != null &&
             !types.isSameType(resource, syms.autoCloseableType)) { // Don't emit warning for AutoCloseable itself
             Symbol close = syms.noSymbol;
-            boolean prevDeferDiags = log.deferDiagnostics;
+            Filter<JCDiagnostic> prevDeferDiagsFilter = log.deferredDiagFilter;
             Queue<JCDiagnostic> prevDeferredDiags = log.deferredDiagnostics;
             try {
-                log.deferDiagnostics = true;
+                log.deferAll();
                 log.deferredDiagnostics = ListBuffer.lb();
                 close = rs.resolveQualifiedMethod(pos,
                         env,
@@ -1287,7 +1287,7 @@
                         List.<Type>nil());
             }
             finally {
-                log.deferDiagnostics = prevDeferDiags;
+                log.deferredDiagFilter = prevDeferDiagsFilter;
                 log.deferredDiagnostics = prevDeferredDiags;
             }
             if (close.kind == MTH &&
@@ -1881,12 +1881,12 @@
                 !clazztype.isErroneous() &&
                 clazztype.getTypeArguments().nonEmpty() &&
                 findDiamonds) {
-            boolean prevDeferDiags = log.deferDiagnostics;
+            Filter<JCDiagnostic> prevDeferDiagsFilter = log.deferredDiagFilter;
             Queue<JCDiagnostic> prevDeferredDiags = log.deferredDiagnostics;
             Type inferred = null;
             try {
                 //disable diamond-related diagnostics
-                log.deferDiagnostics = true;
+                log.deferAll();
                 log.deferredDiagnostics = ListBuffer.lb();
                 inferred = attribDiamond(localEnv,
                         tree,
@@ -1895,7 +1895,7 @@
                         typeargtypes);
             }
             finally {
-                log.deferDiagnostics = prevDeferDiags;
+                log.deferredDiagFilter = prevDeferDiagsFilter;
                 log.deferredDiagnostics = prevDeferredDiags;
             }
             if (inferred != null &&
@@ -2628,15 +2628,15 @@
 
             List<Type> argtypes = desc.getParameterTypes();
 
-            boolean prevDeferDiagnostics = log.deferDiagnostics;
+            Filter<JCDiagnostic> prevDeferDiagFilter = log.deferredDiagFilter;
             Symbol refSym = syms.noSymbol;
             try {
-                log.deferDiagnostics = true;
+                log.deferAll();
                 refSym = rs.resolveMemberReference(that.pos(), localEnv, that.expr.type,
                         that.name, argtypes, typeargtypes, TreeInfo.isStaticSelector(that.expr, names), resultInfo.checkContext.allowBoxing());
             }
             finally {
-                log.deferDiagnostics = prevDeferDiagnostics;
+                log.deferredDiagFilter = prevDeferDiagFilter;
             }
 
             if (refSym.kind != MTH) {
--- a/src/share/classes/com/sun/tools/javac/comp/DeferredAttr.java	Wed Jul 11 16:37:26 2012 +0100
+++ b/src/share/classes/com/sun/tools/javac/comp/DeferredAttr.java	Thu Jul 12 15:39:53 2012 +0100
@@ -35,6 +35,8 @@
 import com.sun.tools.javac.comp.Attr.ResultInfo;
 import com.sun.tools.javac.tree.JCTree.*;
 
+import javax.tools.JavaFileObject;
+
 import static com.sun.tools.javac.code.TypeTags.*;
 import static com.sun.tools.javac.tree.JCTree.Tag.*;
 
@@ -172,14 +174,17 @@
                 JCTree newTree = new TreeCopier<Object>(make).copy(dt.tree);
                 Env<AttrContext> speculativeEnv = dt.env.dup(newTree, dt.env.info.dup(dt.env.info.scope.dupUnshared()));
                 speculativeEnv.info.scope.owner = dt.env.info.scope.owner;
-                boolean prevDeferDiags = log.deferDiagnostics;
-                Queue<JCDiagnostic> prevDeferredDiags = log.deferredDiagnostics;
-                int prevErrors = log.nerrors;
-                int prevWarnings = log.nwarnings;
+                Filter<JCDiagnostic> prevDeferDiagsFilter = log.deferredDiagFilter;
+                Queue<JCDiagnostic> prevDeferredDiags = log.deferredDiagnostics;                
+                final JavaFileObject currentSource = log.currentSourceFile();
                 try {
                     speculativeEnv.info.speculativeAttrRound = true;
                     log.deferredDiagnostics = new ListBuffer<JCDiagnostic>();
-                    log.deferDiagnostics = true;
+                    log.deferredDiagFilter = new Filter<JCDiagnostic>() {
+                        public boolean accepts(JCDiagnostic t) {
+                            return t.getDiagnosticSource().getFile().equals(currentSource);
+                        }
+                    };
                     return attr.attribTree(newTree, speculativeEnv, result);
                 } catch (Abort ex) {
                     //if some very bad condition occurred during deferred attribution
@@ -188,10 +193,8 @@
                     throw ex;
                 } finally {
                     unenterScanner.scan(newTree);
-                    log.deferDiagnostics = prevDeferDiags;
-                    log.deferredDiagnostics = prevDeferredDiags;
-                    log.nerrors = prevErrors;
-                    log.nwarnings = prevWarnings;
+                    log.deferredDiagFilter = prevDeferDiagsFilter;
+                    log.deferredDiagnostics = prevDeferredDiags;                    
                 }
             }
 
--- a/src/share/classes/com/sun/tools/javac/comp/Flow.java	Wed Jul 11 16:37:26 2012 +0100
+++ b/src/share/classes/com/sun/tools/javac/comp/Flow.java	Thu Jul 12 15:39:53 2012 +0100
@@ -212,9 +212,9 @@
     
     public void analyzeLambda(Env<AttrContext> env, JCLambda that, TreeMaker make) {
         java.util.Queue<JCDiagnostic> prevDeferredDiagnostics = log.deferredDiagnostics;
-        boolean prevDeferDiags = log.deferDiagnostics;
+        Filter<JCDiagnostic> prevDeferDiagsFilter = log.deferredDiagFilter;
         if (!env.info.speculativeAttrRound) {
-            log.deferDiagnostics = true;
+            log.deferAll();
             log.deferredDiagnostics = ListBuffer.lb();
         }
         try {
@@ -223,7 +223,7 @@
             new FlowAnalyzer().analyzeTree(env, that, make);
         } finally {
             if (!env.info.speculativeAttrRound) {
-                log.deferDiagnostics = prevDeferDiags;
+                log.deferredDiagFilter = prevDeferDiagsFilter;
                 log.deferredDiagnostics = prevDeferredDiagnostics;
             }
         }
--- a/src/share/classes/com/sun/tools/javac/comp/LambdaToInnerClass.java	Wed Jul 11 16:37:26 2012 +0100
+++ b/src/share/classes/com/sun/tools/javac/comp/LambdaToInnerClass.java	Thu Jul 12 15:39:53 2012 +0100
@@ -566,9 +566,9 @@
             }
 
             @Override
-            protected boolean staticContext() {
-                return (owner.flags() & STATIC) != 0 &&
-                        lambdaClassSym.isStatic();
+            protected Type enclosingType() {
+                //local inner classes defined inside lambda are always non-static
+                return lambdaClassSym.type;
             }
             
             /**
@@ -579,7 +579,7 @@
              */
             class SuperCallAnalyzer extends TreeScanner {
                 
-                boolean captureSuper = true;
+                boolean captureSuper = false;
                 boolean nested = false;
                 
                 @Override
--- a/src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java	Wed Jul 11 16:37:26 2012 +0100
+++ b/src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java	Thu Jul 12 15:39:53 2012 +0100
@@ -700,8 +700,9 @@
             }
 
             @Override
-            protected boolean staticContext() {
-                return true;
+            protected Type enclosingType() {
+                //local inner classes defined inside lambda are always static
+                return Type.noType;
             }
 
             protected Type generatedLambdaSig() {
--- a/src/share/classes/com/sun/tools/javac/comp/LambdaTranslator.java	Wed Jul 11 16:37:26 2012 +0100
+++ b/src/share/classes/com/sun/tools/javac/comp/LambdaTranslator.java	Thu Jul 12 15:39:53 2012 +0100
@@ -388,10 +388,11 @@
         public void visitClassDef(JCClassDecl tree) {
             List<Frame> prevStack = frameStack;
             try {
-                if (frameStack.nonEmpty() && frameStack.head.tree.hasTag(LAMBDA)) {
+                if (frameStack.nonEmpty() && enclosingLambda() != null) {
                     tree.sym.owner = owner();
-                    LambdaTranslationContext lambdaContext = (LambdaTranslationContext)contextMap.get(frameStack.head.tree);
-                    if (lambdaContext.staticContext()) {
+                    LambdaTranslationContext lambdaContext = (LambdaTranslationContext)contextMap.get(enclosingLambda());
+                    Type encl = lambdaContext.enclosingType();
+                    if (encl.tag == TypeTags.NONE) {
                         //if the translated lambda body occurs in a static context,
                         //any class declaration within it must be made static
                         tree.sym.flags_field |= STATIC;
@@ -400,9 +401,6 @@
                         //if the translated lambda body is in an instance context
                         //the enclosing type of any class declaration within it
                         //must be updated to point to the new enclosing type (if any)
-                        Type encl = tree.sym.type.getEnclosingType() != Type.noType ?
-                                tree.sym.owner.enclClass().type :
-                                Type.noType;
                         ((ClassType)tree.sym.type).setEnclosingType(encl);
                     }
                 }
@@ -445,6 +443,23 @@
             Assert.error();
             return null;
         }
+        
+        JCTree enclosingLambda() {
+            List<Frame> frameStack2 = frameStack;
+            while (frameStack2.nonEmpty()) {
+                switch (frameStack2.head.tree.getTag()) {                    
+                    case CLASSDEF:
+                    case METHODDEF:
+                        return null;
+                    case LAMBDA:
+                        return frameStack2.head.tree;
+                    default:
+                        frameStack2 = frameStack2.tail;
+                }
+            }
+            Assert.error();
+            return null;
+        }
 
         /**
          * Return a valid instance owner given the current declaration stack
@@ -713,7 +728,7 @@
             /**
              * Does lambda body have access to enclosing instance scope?
              */
-            protected abstract boolean staticContext();
+            protected abstract Type enclosingType();
 
             protected void addSymbol(Symbol sym, LambdaSymbolKind skind) {
                 Map<Symbol, Symbol> transMap = null;
--- a/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java	Wed Jul 11 16:37:26 2012 +0100
+++ b/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java	Thu Jul 12 15:39:53 2012 +0100
@@ -1021,7 +1021,7 @@
                 genEndPos = true;
                 if (!taskListener.isEmpty())
                     taskListener.started(new TaskEvent(TaskEvent.Kind.ANNOTATION_PROCESSING));
-                log.deferDiagnostics = true;
+                log.deferAll();
             } else { // free resources
                 procEnvImpl.close();
             }
@@ -1131,7 +1131,7 @@
                 if (c != this)
                     annotationProcessingOccurred = c.annotationProcessingOccurred = true;
                 // doProcessing will have handled deferred diagnostics
-                Assert.check(c.log.deferDiagnostics == false
+                Assert.check(c.log.deferredDiagFilter == null
                         && c.log.deferredDiagnostics.size() == 0);
                 return c;
             } finally {
--- a/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java	Wed Jul 11 16:37:26 2012 +0100
+++ b/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java	Thu Jul 12 15:39:53 2012 +0100
@@ -806,7 +806,7 @@
             log = Log.instance(context);
             log.nerrors = priorErrors;
             log.nwarnings += priorWarnings;
-            log.deferDiagnostics = true;
+            log.deferAll();
 
             // the following is for the benefit of JavacProcessingEnvironment.getContext()
             JavacProcessingEnvironment.this.context = context;
--- a/src/share/classes/com/sun/tools/javac/util/Log.java	Wed Jul 11 16:37:26 2012 +0100
+++ b/src/share/classes/com/sun/tools/javac/util/Log.java	Thu Jul 12 15:39:53 2012 +0100
@@ -130,7 +130,7 @@
     /**
      * Deferred diagnostics
      */
-    public boolean deferDiagnostics;
+    public Filter<JCDiagnostic> deferredDiagFilter;
     public Queue<JCDiagnostic> deferredDiagnostics = new ListBuffer<JCDiagnostic>();
 
     /** Construct a log with given I/O redirections.
@@ -446,7 +446,7 @@
 
     /** Report selected deferred diagnostics, and clear the deferDiagnostics flag. */
     public void reportDeferredDiagnostics(Set<JCDiagnostic.Kind> kinds) {
-        deferDiagnostics = false;
+        deferredDiagFilter = null;
         JCDiagnostic d;
         while ((d = deferredDiagnostics.poll()) != null) {
             if (kinds.contains(d.getKind()))
@@ -460,7 +460,7 @@
      * reported so far, the diagnostic may be handed off to writeDiagnostic.
      */
     public void report(JCDiagnostic diagnostic) {
-        if (deferDiagnostics) {
+        if (deferredDiagFilter != null && deferredDiagFilter.accepts(diagnostic)) {
             deferredDiagnostics.add(diagnostic);
             return;
         }
@@ -546,6 +546,18 @@
             throw new Error();
         }
     }
+    
+    public void deferAll() {
+        deferredDiagFilter = new Filter<JCDiagnostic>() {
+            public boolean accepts(JCDiagnostic t) {
+                return true;
+            }
+        };
+    }
+    
+    public void deferNone() {
+        deferredDiagFilter = null;
+    }
 
     /** Find a localized string in the resource bundle.
      *  Because this method is static, it ignores the locale.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/lambda/LambdaCapture06.java	Thu Jul 12 15:39:53 2012 +0100
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2012, 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 Compiler crash when local inner class nested inside lambda captures local variables from enclosing scope
+ */
+public class LambdaCapture06 {
+    
+    static int assertionCount = 0;
+
+    static void assertTrue(boolean cond) {
+        assertionCount++;
+        if (!cond)
+            throw new AssertionError();
+    }
+    
+    interface SAM {
+        void m(int n);
+    }
+    
+    public static void main(String[] args) {
+        int n = 5;
+        SAM s = k -> {
+            new Object() {
+                void test() { int j = n; assertTrue(j == 5); }
+            }.test();
+        };
+        s.m(42);
+        assertTrue(assertionCount == 1);
+    }
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/lambda/speculative/A.java	Thu Jul 12 15:39:53 2012 +0100
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2012, 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.
+ */
+
+public class A {
+    public A(NonExistentClass nec) {}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/lambda/speculative/Main.java	Thu Jul 12 15:39:53 2012 +0100
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2012, 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 On-demand symbol completion during speculative attribution round fails to report error messages
+ * @compile/fail/ref=Main.out -XDrawDiagnostics Main.java
+ */
+class Main {
+    void test() {
+        m(new A(new Object()));
+        m(new A(null));
+    }
+
+    void m(Object o) {}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/lambda/speculative/Main.out	Thu Jul 12 15:39:53 2012 +0100
@@ -0,0 +1,2 @@
+A.java:25:14: compiler.err.cant.resolve.location: kindname.class, NonExistentClass, , , (compiler.misc.location: kindname.class, A, null)
+1 error