8020147: Spurious errors when compiling nested stuck lambdas
authormcimadamore
Wed, 17 Jul 2013 14:13:15 +0100
changeset 18912 e25cd61d8e59
parent 18911 dcc1e26a8c9c
child 18913 a29ea2022929
8020147: Spurious errors when compiling nested stuck lambdas Summary: Scope of deferred types is not copied correctly; postAttr analyzer should not run on stuck expressions Reviewed-by: jjg
langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java
langtools/src/share/classes/com/sun/tools/javac/comp/DeferredAttr.java
langtools/src/share/classes/com/sun/tools/javac/comp/Flow.java
langtools/test/tools/javac/lambda/8020147/T8020147.java
langtools/test/tools/javac/lambda/8020147/T8020147.out
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java	Wed Jul 17 14:11:41 2013 +0100
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java	Wed Jul 17 14:13:15 2013 +0100
@@ -481,31 +481,7 @@
         static final long serialVersionUID = -6924771130405446405L;
         private Env<AttrContext> env;
         private BreakAttr(Env<AttrContext> env) {
-            this.env = copyEnv(env);
-        }
-
-        private Env<AttrContext> copyEnv(Env<AttrContext> env) {
-            Env<AttrContext> newEnv =
-                    env.dup(env.tree, env.info.dup(copyScope(env.info.scope)));
-            if (newEnv.outer != null) {
-                newEnv.outer = copyEnv(newEnv.outer);
-            }
-            return newEnv;
-        }
-
-        private Scope copyScope(Scope sc) {
-            Scope newScope = new Scope(sc.owner);
-            List<Symbol> elemsList = List.nil();
-            while (sc != null) {
-                for (Scope.Entry e = sc.elems ; e != null ; e = e.sibling) {
-                    elemsList = elemsList.prepend(e.sym);
-                }
-                sc = sc.next;
-            }
-            for (Symbol s : elemsList) {
-                newScope.enter(s);
-            }
-            return newScope;
+            this.env = env;
         }
     }
 
@@ -605,7 +581,7 @@
             tree.accept(this);
             if (tree == breakTree &&
                     resultInfo.checkContext.deferredAttrContext().mode == AttrMode.CHECK) {
-                throw new BreakAttr(env);
+                throw new BreakAttr(copyEnv(env));
             }
             return result;
         } catch (CompletionFailure ex) {
@@ -617,6 +593,30 @@
         }
     }
 
+    Env<AttrContext> copyEnv(Env<AttrContext> env) {
+        Env<AttrContext> newEnv =
+                env.dup(env.tree, env.info.dup(copyScope(env.info.scope)));
+        if (newEnv.outer != null) {
+            newEnv.outer = copyEnv(newEnv.outer);
+        }
+        return newEnv;
+    }
+
+    Scope copyScope(Scope sc) {
+        Scope newScope = new Scope(sc.owner);
+        List<Symbol> elemsList = List.nil();
+        while (sc != null) {
+            for (Scope.Entry e = sc.elems ; e != null ; e = e.sibling) {
+                elemsList = elemsList.prepend(e.sym);
+            }
+            sc = sc.next;
+        }
+        for (Symbol s : elemsList) {
+            newScope.enter(s);
+        }
+        return newScope;
+    }
+
     /** Derived visitor method: attribute an expression tree.
      */
     public Type attribExpr(JCTree tree, Env<AttrContext> env, Type pt) {
@@ -2431,7 +2431,7 @@
             boolean isSpeculativeRound =
                     resultInfo.checkContext.deferredAttrContext().mode == DeferredAttr.AttrMode.SPECULATIVE;
 
-            postAttr(that);
+            preFlow(that);
             flow.analyzeLambda(env, that, make, isSpeculativeRound);
 
             checkLambdaCompatible(that, lambdaType, resultInfo.checkContext, isSpeculativeRound);
@@ -2453,6 +2453,21 @@
         }
     }
     //where
+        void preFlow(JCLambda tree) {
+            new PostAttrAnalyzer() {
+                @Override
+                public void scan(JCTree tree) {
+                    if (tree == null ||
+                            (tree.type != null &&
+                            tree.type == Type.stuckType)) {
+                        //don't touch stuck expressions!
+                        return;
+                    }
+                    super.scan(tree);
+                }
+            }.scan(tree);
+        }
+
         Types.MapVisitor<DiagnosticPosition> targetChecker = new Types.MapVisitor<DiagnosticPosition>() {
 
             @Override
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/DeferredAttr.java	Wed Jul 17 14:11:41 2013 +0100
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/DeferredAttr.java	Wed Jul 17 14:13:15 2013 +0100
@@ -127,7 +127,7 @@
         DeferredType(JCExpression tree, Env<AttrContext> env) {
             super(null);
             this.tree = tree;
-            this.env = env.dup(tree, env.info.dup());
+            this.env = attr.copyEnv(env);
             this.speculativeCache = new SpeculativeCache();
         }
 
@@ -263,7 +263,7 @@
     DeferredTypeCompleter dummyCompleter = new DeferredTypeCompleter() {
         public Type complete(DeferredType dt, ResultInfo resultInfo, DeferredAttrContext deferredAttrContext) {
             Assert.check(deferredAttrContext.mode == AttrMode.CHECK);
-            return dt.tree.type = Type.noType;
+            return dt.tree.type = Type.stuckType;
         }
     };
 
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Flow.java	Wed Jul 17 14:11:41 2013 +0100
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Flow.java	Wed Jul 17 14:13:15 2013 +0100
@@ -373,6 +373,15 @@
         boolean resolveBreaks(JCTree tree, ListBuffer<P> oldPendingExits) {
             return resolveJump(tree, oldPendingExits, JumpKind.BREAK);
         }
+
+        @Override
+        public void scan(JCTree tree) {
+            if (tree != null && (
+                    tree.type == null ||
+                    tree.type != Type.stuckType)) {
+                super.scan(tree);
+            }
+        }
     }
 
     /**
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/lambda/8020147/T8020147.java	Wed Jul 17 14:13:15 2013 +0100
@@ -0,0 +1,19 @@
+/*
+ * @test /nodynamiccopyright/
+ * @bug 8020147
+ * @summary Spurious errors when compiling nested stuck lambdas
+ * @compile/fail/ref=T8020147.out -Werror -Xlint:cast -XDrawDiagnostics T8020147.java
+ */
+class T8020147 {
+    interface Function<X, Y> {
+        Y apply(X x);
+    }
+
+    <T> void g(Function<String, T> f) { }
+    <U> String m(U u, Function<U, U> fuu) { return null; }
+
+    void test() {
+        g(x->m("", i->(String)i));
+        g(x->m("", i->(String)x));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/lambda/8020147/T8020147.out	Wed Jul 17 14:13:15 2013 +0100
@@ -0,0 +1,5 @@
+T8020147.java:16:23: compiler.warn.redundant.cast: java.lang.String
+T8020147.java:17:23: compiler.warn.redundant.cast: java.lang.String
+- compiler.err.warnings.and.werror
+1 error
+2 warnings