changeset 1459:2a4b8b31381b

Misc improvements to deferred attribution architecture: *) out-of-order method checking should check as many arguments as possible in cases where method is not applicable *) fixed bug that caused silent compiler crash where void expression passed as argument to overloaded method
author mcimadamore
date Fri, 31 Aug 2012 18:03:48 +0100
parents 83720b655da4
children 0ea8d35cbe12
files src/share/classes/com/sun/tools/javac/comp/DeferredAttr.java src/share/classes/com/sun/tools/javac/comp/Resolve.java test/tools/javac/lambda/TargetType40.java test/tools/javac/lambda/TargetType40.out test/tools/javac/lambda/TargetType41.java test/tools/javac/lambda/TargetType41.out
diffstat 6 files changed, 117 insertions(+), 20 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/com/sun/tools/javac/comp/DeferredAttr.java	Fri Aug 31 13:42:13 2012 +0100
+++ b/src/share/classes/com/sun/tools/javac/comp/DeferredAttr.java	Fri Aug 31 18:03:48 2012 +0100
@@ -113,9 +113,15 @@
             this.env = env.dup(tree, env.info.dup());
             this.speculativeCache = new SpeculativeCache();
         }
+
+        @Override
+        public boolean isErroneous() {
+            return tree.type != null &&
+                    tree.type.isErroneous();
+        }
         
-        void attribDeferred(AttrMode mode, ResultInfo resultInfo, DeferredAttrContext deferredAttrContext) {
-            mode.attribDeferred(this, resultInfo, deferredAttrContext);
+        void attribDeferred(ResultInfo resultInfo, DeferredAttrContext deferredAttrContext) {
+            deferredAttrContext.mode.attribDeferred(this, resultInfo, deferredAttrContext);
         }
         
         class SpeculativeCache {
@@ -388,7 +394,7 @@
                 if (isStuck()) {
                     throw new IllegalStateException("Cannot process a stuck deferred node");
                 }
-                dt.attribDeferred(mode, resultInfo, DeferredAttrContext.this);
+                dt.attribDeferred(resultInfo, DeferredAttrContext.this);
             }
         }
     }
@@ -475,10 +481,10 @@
                     return dt;
                 default:
                     return attr.attribTree(tree2, dt.env, attr.new ResultInfo(Kinds.VAL, Type.noType) {
-                    @Override
-                    protected Type check(DiagnosticPosition pos, Type found) {
-                        return chk.checkNonVoid(pos, super.check(pos, found));
-                    }
+                        @Override
+                        protected Type check(DiagnosticPosition pos, Type found) {
+                            return chk.checkNonVoid(pos, super.check(pos, found));
+                        }
                 });
             }
         }
--- a/src/share/classes/com/sun/tools/javac/comp/Resolve.java	Fri Aug 31 13:42:13 2012 +0100
+++ b/src/share/classes/com/sun/tools/javac/comp/Resolve.java	Fri Aug 31 18:03:48 2012 +0100
@@ -672,15 +672,12 @@
         
         DeferredAttr.DeferredAttrContext deferredAttrContext =
                 deferredAttr.new DeferredAttrContext(mode, msym, currentResolutionContext.step, inferenceContext);
-
+        
+        ListBuffer<InapplicableMethodException> ex_list = ListBuffer.lb();
+        
         while (argtypes.nonEmpty() && formals.head != varargsFormal) {
             ResultInfo mresult = methodCheckResult(formals.head, allowBoxing, false, inferenceContext, deferredAttrContext, handler, warn);
-            if (argtypes.head.tag == DEFERRED) {
-                DeferredType<?> dt = (DeferredType<?>)argtypes.head;
-                dt.attribDeferred(mode, mresult, deferredAttrContext);
-            } else {
-                mresult.check(null, argtypes.head);
-            }
+            argumentApplicable(argtypes.head, mresult, deferredAttrContext, ex_list);
             argtypes = argtypes.tail;
             formals = formals.tail;
         }
@@ -695,20 +692,35 @@
             final Type elt = types.elemtype(varargsFormal);
             ResultInfo mresult = methodCheckResult(elt, allowBoxing, true, inferenceContext, deferredAttrContext, handler, warn);
             while (argtypes.nonEmpty()) {
-                if (argtypes.head.tag == DEFERRED) {
-                    DeferredType<?> dt = (DeferredType<?>)argtypes.head;
-                    dt.attribDeferred(mode, mresult, deferredAttrContext);
-                } else {
-                    mresult.check(null, argtypes.head);
-                }
+                argumentApplicable(argtypes.head, mresult, deferredAttrContext, ex_list);
                 argtypes = argtypes.tail;
             }
             //check varargs element type accessibility
             varargsAccessible(env, elt, handler, inferenceContext);
         }
         
+        //exception multiplexing - accumulate all inapplcable method exceptions during
+        //method applicability then propagate the first one - ensures all (non-stuck)
+        //arguments are type-checked - which allows for better diagnostics
+        if (ex_list.nonEmpty()) {
+            throw ex_list.first();
+        }
+        
         deferredAttrContext.complete();
     }
+    //where
+        void argumentApplicable(Type actual, ResultInfo mresult, DeferredAttrContext deferredAttrContext, ListBuffer<InapplicableMethodException> ex_list) {
+            try {
+                if (actual.tag == DEFERRED) {
+                    DeferredType<?> dt = (DeferredType<?>)actual;
+                    dt.attribDeferred(mresult, deferredAttrContext);
+                } else {
+                    mresult.check(null, actual);
+                }
+            } catch (InapplicableMethodException ex) {
+                ex_list.append(ex);
+            }
+        }
     
     void varargsAccessible(final Env<AttrContext> env, final Type t, final Resolve.MethodCheckHandler handler, final InferenceContext inferenceContext) {
         if (inferenceContext.free(t)) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/lambda/TargetType40.java	Fri Aug 31 18:03:48 2012 +0100
@@ -0,0 +1,39 @@
+/*
+ * 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 silently crashes when void method is passed as argument in overloaded call site 
+ * @compile/fail/ref=TargetType40.out -XDrawDiagnostics TargetType40.java
+ */
+
+class TargetType40 {
+    void m(String s) { }
+    void m(Integer i) { }
+
+    void void_method() {}
+
+    void test() {
+       m(void_method());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/lambda/TargetType40.out	Fri Aug 31 18:03:48 2012 +0100
@@ -0,0 +1,2 @@
+TargetType40.java:37:21: compiler.err.void.not.allowed.here
+1 error
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/lambda/TargetType41.java	Fri Aug 31 18:03:48 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 out-of-order method checking should check as many arguments as possible
+ * @compile/fail/ref=TargetType41.out -XDrawDiagnostics TargetType41.java
+ */
+
+class TargetType40 {
+    <X> void m(String s, java.util.List<String> lx) { }
+
+    void test() {
+        m(1, new java.util.ArrayList<>());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/lambda/TargetType41.out	Fri Aug 31 18:03:48 2012 +0100
@@ -0,0 +1,2 @@
+TargetType41.java:34:9: compiler.err.cant.apply.symbol: kindname.method, m, java.lang.String,java.util.List<java.lang.String>, int,java.util.ArrayList<java.lang.String>, kindname.class, TargetType40, null
+1 error