changeset 1811:f8472e561a97

8015432: javac crashes with stack overflow when method called recursively from nested generic call Summary: Check.checkMethod should only be called after inference has completed Reviewed-by: jjg, vromero
author mcimadamore
date Thu, 06 Jun 2013 15:35:05 +0100
parents 349160289ba2
children f218bb5ebd53
files src/share/classes/com/sun/tools/javac/comp/Attr.java src/share/classes/com/sun/tools/javac/comp/Check.java test/tools/javac/6758789/T6758789b.out test/tools/javac/generics/7015430/T7015430.out test/tools/javac/generics/7151802/T7151802.out test/tools/javac/generics/inference/6718364/T6718364.out test/tools/javac/generics/inference/7177306/T7177306a.out test/tools/javac/lambda/TargetType74.java
diffstat 8 files changed, 89 insertions(+), 52 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/com/sun/tools/javac/comp/Attr.java	Thu Jun 06 15:33:40 2013 +0100
+++ b/src/share/classes/com/sun/tools/javac/comp/Attr.java	Thu Jun 06 15:35:05 2013 +0100
@@ -1833,9 +1833,6 @@
             // Check that value of resulting type is admissible in the
             // current context.  Also, capture the return type
             result = check(tree, capture(restype), VAL, resultInfo);
-
-            if (localEnv.info.lastResolveVarargs())
-                Assert.check(result.isErroneous() || tree.varargsElement != null);
         }
         chk.validate(tree.typeargs, localEnv);
     }
@@ -3733,8 +3730,28 @@
                     typeargtypes,
                     noteWarner);
 
+            DeferredAttr.DeferredTypeMap checkDeferredMap =
+                deferredAttr.new DeferredTypeMap(DeferredAttr.AttrMode.CHECK, sym, env.info.pendingResolutionPhase);
+
+            argtypes = Type.map(argtypes, checkDeferredMap);
+
+            if (noteWarner.hasNonSilentLint(LintCategory.UNCHECKED)) {
+                chk.warnUnchecked(env.tree.pos(),
+                        "unchecked.meth.invocation.applied",
+                        kindName(sym),
+                        sym.name,
+                        rs.methodArguments(sym.type.getParameterTypes()),
+                        rs.methodArguments(Type.map(argtypes, checkDeferredMap)),
+                        kindName(sym.location()),
+                        sym.location());
+               owntype = new MethodType(owntype.getParameterTypes(),
+                       types.erasure(owntype.getReturnType()),
+                       types.erasure(owntype.getThrownTypes()),
+                       syms.methodClass);
+            }
+
             return chk.checkMethod(owntype, sym, env, argtrees, argtypes, env.info.lastResolveVarargs(),
-                    noteWarner.hasNonSilentLint(LintCategory.UNCHECKED), resultInfo.checkContext.inferenceContext());
+                    resultInfo.checkContext.inferenceContext());
         } catch (Infer.InferenceException ex) {
             //invalid target type - propagate exception outwards or report error
             //depending on the current check context
--- a/src/share/classes/com/sun/tools/javac/comp/Check.java	Thu Jun 06 15:33:40 2013 +0100
+++ b/src/share/classes/com/sun/tools/javac/comp/Check.java	Thu Jun 06 15:35:05 2013 +0100
@@ -847,25 +847,31 @@
                     (s.flags() & (STATIC | FINAL)) != 0);
         }
 
-    Type checkMethod(Type owntype,
-                            Symbol sym,
-                            Env<AttrContext> env,
-                            final List<JCExpression> argtrees,
-                            List<Type> argtypes,
-                            boolean useVarargs,
-                            boolean unchecked,
-                            InferenceContext inferenceContext) {
+    Type checkMethod(final Type mtype,
+            final Symbol sym,
+            final Env<AttrContext> env,
+            final List<JCExpression> argtrees,
+            final List<Type> argtypes,
+            final boolean useVarargs,
+            InferenceContext inferenceContext) {
         // System.out.println("call   : " + env.tree);
         // System.out.println("method : " + owntype);
         // System.out.println("actuals: " + argtypes);
+        if (inferenceContext.free(mtype)) {
+            inferenceContext.addFreeTypeListener(List.of(mtype), new FreeTypeListener() {
+                public void typesInferred(InferenceContext inferenceContext) {
+                    checkMethod(inferenceContext.asInstType(mtype), sym, env, argtrees, argtypes, useVarargs, inferenceContext);
+                }
+            });
+            return mtype;
+        }
+        Type owntype = mtype;
         List<Type> formals = owntype.getParameterTypes();
         Type last = useVarargs ? formals.last() : null;
         if (sym.name == names.init &&
                 sym.owner == syms.enumSym)
                 formals = formals.tail.tail;
         List<JCExpression> args = argtrees;
-        DeferredAttr.DeferredTypeMap checkDeferredMap =
-                deferredAttr.new DeferredTypeMap(DeferredAttr.AttrMode.CHECK, sym, env.info.pendingResolutionPhase);
         if (args != null) {
             //this is null when type-checking a method reference
             while (formals.head != last) {
@@ -886,27 +892,13 @@
             } else if ((sym.flags() & VARARGS) != 0 && allowVarargs) {
                 // non-varargs call to varargs method
                 Type varParam = owntype.getParameterTypes().last();
-                Type lastArg = checkDeferredMap.apply(argtypes.last());
+                Type lastArg = argtypes.last();
                 if (types.isSubtypeUnchecked(lastArg, types.elemtype(varParam)) &&
                         !types.isSameType(types.erasure(varParam), types.erasure(lastArg)))
                     log.warning(argtrees.last().pos(), "inexact.non-varargs.call",
                             types.elemtype(varParam), varParam);
             }
         }
-        if (unchecked) {
-            warnUnchecked(env.tree.pos(),
-                    "unchecked.meth.invocation.applied",
-                    kindName(sym),
-                    sym.name,
-                    rs.methodArguments(sym.type.getParameterTypes()),
-                    rs.methodArguments(Type.map(argtypes, checkDeferredMap)),
-                    kindName(sym.location()),
-                    sym.location());
-           owntype = new MethodType(owntype.getParameterTypes(),
-                   types.erasure(owntype.getReturnType()),
-                   types.erasure(owntype.getThrownTypes()),
-                   syms.methodClass);
-        }
         if (useVarargs) {
             Type argtype = owntype.getParameterTypes().last();
             if (!types.isReifiable(argtype) &&
@@ -918,7 +910,7 @@
                                   argtype);
             }
             if (!((MethodSymbol)sym.baseSymbol()).isSignaturePolymorphic(types)) {
-                setVarargsElement(env, types.elemtype(argtype), inferenceContext);
+                TreeInfo.setVarargsElement(env.tree, types.elemtype(argtype));
             }
          }
          PolyKind pkind = (sym.type.hasTag(FORALL) &&
@@ -928,17 +920,6 @@
          return owntype;
     }
     //where
-        private void setVarargsElement(final Env<AttrContext> env, final Type elemtype, InferenceContext inferenceContext) {
-            if (inferenceContext.free(elemtype)) {
-                inferenceContext.addFreeTypeListener(List.of(elemtype), new FreeTypeListener() {
-                    public void typesInferred(InferenceContext inferenceContext) {
-                        setVarargsElement(env, inferenceContext.asInstType(elemtype), inferenceContext);
-                    }
-                });
-            }
-            TreeInfo.setVarargsElement(env.tree, elemtype);
-        }
-
         private void assertConvertible(JCTree tree, Type actual, Type formal, Warner warn) {
             if (types.isConvertible(actual, formal, warn))
                 return;
--- a/test/tools/javac/6758789/T6758789b.out	Thu Jun 06 15:33:40 2013 +0100
+++ b/test/tools/javac/6758789/T6758789b.out	Thu Jun 06 15:35:05 2013 +0100
@@ -1,5 +1,5 @@
+T6758789b.java:16:10: compiler.warn.unchecked.meth.invocation.applied: kindname.method, m, T6758789a.Foo<X>, T6758789a.Foo, kindname.class, T6758789a
 T6758789b.java:16:11: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), T6758789a.Foo, T6758789a.Foo<java.lang.Object>
-T6758789b.java:16:10: compiler.warn.unchecked.meth.invocation.applied: kindname.method, m, T6758789a.Foo<X>, T6758789a.Foo, kindname.class, T6758789a
 - compiler.err.warnings.and.werror
 1 error
 2 warnings
--- a/test/tools/javac/generics/7015430/T7015430.out	Thu Jun 06 15:33:40 2013 +0100
+++ b/test/tools/javac/generics/7015430/T7015430.out	Thu Jun 06 15:35:05 2013 +0100
@@ -1,15 +1,15 @@
+T7015430.java:41:14: compiler.warn.unchecked.meth.invocation.applied: kindname.method, empty, java.lang.Iterable<E>, java.lang.Iterable, kindname.class, T7015430
 T7015430.java:41:15: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), java.lang.Iterable, java.lang.Iterable<java.lang.Exception>
-T7015430.java:41:14: compiler.warn.unchecked.meth.invocation.applied: kindname.method, empty, java.lang.Iterable<E>, java.lang.Iterable, kindname.class, T7015430
+T7015430.java:50:41: compiler.warn.unchecked.meth.invocation.applied: kindname.method, empty, java.lang.Iterable<E>, java.lang.Iterable, kindname.class, T7015430
 T7015430.java:50:42: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), java.lang.Iterable, java.lang.Iterable<java.lang.RuntimeException>
-T7015430.java:50:41: compiler.warn.unchecked.meth.invocation.applied: kindname.method, empty, java.lang.Iterable<E>, java.lang.Iterable, kindname.class, T7015430
+T7015430.java:68:9: compiler.warn.unchecked.meth.invocation.applied: kindname.constructor, <init>, java.lang.Iterable<E>, java.lang.Iterable, kindname.class, T7015430
 T7015430.java:68:22: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), java.lang.Iterable, java.lang.Iterable<java.lang.Exception>
-T7015430.java:68:9: compiler.warn.unchecked.meth.invocation.applied: kindname.constructor, <init>, java.lang.Iterable<E>, java.lang.Iterable, kindname.class, T7015430
+T7015430.java:77:9: compiler.warn.unchecked.meth.invocation.applied: kindname.constructor, <init>, java.lang.Iterable<E>, java.lang.Iterable, kindname.class, T7015430
 T7015430.java:77:40: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), java.lang.Iterable, java.lang.Iterable<java.lang.RuntimeException>
-T7015430.java:77:9: compiler.warn.unchecked.meth.invocation.applied: kindname.constructor, <init>, java.lang.Iterable<E>, java.lang.Iterable, kindname.class, T7015430
+T7015430.java:104:9: compiler.warn.unchecked.meth.invocation.applied: kindname.constructor, <init>, java.lang.Iterable<E>, java.lang.Iterable, kindname.class, T7015430
 T7015430.java:104:41: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), java.lang.Iterable, java.lang.Iterable<java.lang.RuntimeException>
-T7015430.java:104:9: compiler.warn.unchecked.meth.invocation.applied: kindname.constructor, <init>, java.lang.Iterable<E>, java.lang.Iterable, kindname.class, T7015430
+T7015430.java:113:9: compiler.warn.unchecked.meth.invocation.applied: kindname.constructor, <init>, java.lang.Iterable<E>, java.lang.Iterable, kindname.class, T7015430
 T7015430.java:113:22: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), java.lang.Iterable, java.lang.Iterable<java.lang.Exception>
-T7015430.java:113:9: compiler.warn.unchecked.meth.invocation.applied: kindname.constructor, <init>, java.lang.Iterable<E>, java.lang.Iterable, kindname.class, T7015430
 T7015430.java:41:14: compiler.err.unreported.exception.need.to.catch.or.throw: java.lang.Exception
 T7015430.java:68:9: compiler.err.unreported.exception.need.to.catch.or.throw: java.lang.Exception
 T7015430.java:95:15: compiler.err.unreported.exception.need.to.catch.or.throw: java.lang.Exception
--- a/test/tools/javac/generics/7151802/T7151802.out	Thu Jun 06 15:33:40 2013 +0100
+++ b/test/tools/javac/generics/7151802/T7151802.out	Thu Jun 06 15:35:05 2013 +0100
@@ -1,9 +1,9 @@
 T7151802.java:14:31: compiler.warn.unchecked.meth.invocation.applied: kindname.method, get1, Z, T7151802.Foo, kindname.class, T7151802
+T7151802.java:22:30: compiler.warn.unchecked.meth.invocation.applied: kindname.method, get3, T7151802.Foo<Z>, T7151802.Foo, kindname.class, T7151802
 T7151802.java:22:31: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), T7151802.Foo, T7151802.Foo<java.lang.Object>
-T7151802.java:22:30: compiler.warn.unchecked.meth.invocation.applied: kindname.method, get3, T7151802.Foo<Z>, T7151802.Foo, kindname.class, T7151802
 T7151802.java:30:36: compiler.warn.unchecked.meth.invocation.applied: kindname.method, get5, compiler.misc.no.args, compiler.misc.no.args, kindname.class, T7151802
+T7151802.java:38:31: compiler.warn.unchecked.meth.invocation.applied: kindname.method, get7, T7151802.Foo<java.lang.String>, T7151802.Foo, kindname.class, T7151802
 T7151802.java:38:32: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), T7151802.Foo, T7151802.Foo<java.lang.String>
-T7151802.java:38:31: compiler.warn.unchecked.meth.invocation.applied: kindname.method, get7, T7151802.Foo<java.lang.String>, T7151802.Foo, kindname.class, T7151802
 - compiler.err.warnings.and.werror
 1 error
 6 warnings
--- a/test/tools/javac/generics/inference/6718364/T6718364.out	Thu Jun 06 15:33:40 2013 +0100
+++ b/test/tools/javac/generics/inference/6718364/T6718364.out	Thu Jun 06 15:35:05 2013 +0100
@@ -1,3 +1,3 @@
+T6718364.java:13:10: compiler.warn.unchecked.meth.invocation.applied: kindname.method, m, T6718364.X<T>,T, T6718364.X<T6718364.X<java.lang.Integer>>,T6718364.X, kindname.class, T6718364
 T6718364.java:13:32: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), T6718364.X, T6718364.X<java.lang.Integer>
-T6718364.java:13:10: compiler.warn.unchecked.meth.invocation.applied: kindname.method, m, T6718364.X<T>,T, T6718364.X<T6718364.X<java.lang.Integer>>,T6718364.X, kindname.class, T6718364
 2 warnings
--- a/test/tools/javac/generics/inference/7177306/T7177306a.out	Thu Jun 06 15:33:40 2013 +0100
+++ b/test/tools/javac/generics/inference/7177306/T7177306a.out	Thu Jun 06 15:35:05 2013 +0100
@@ -1,5 +1,5 @@
+T7177306a.java:13:33: compiler.warn.unchecked.meth.invocation.applied: kindname.method, m, java.util.List<E>, java.util.List, kindname.class, T7177306a
 T7177306a.java:13:34: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), java.util.List, java.util.List<java.lang.Object>
-T7177306a.java:13:33: compiler.warn.unchecked.meth.invocation.applied: kindname.method, m, java.util.List<E>, java.util.List, kindname.class, T7177306a
 T7177306a.java:13:33: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), T7177306a, T7177306a<java.lang.Object>
 - compiler.err.warnings.and.werror
 1 error
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/lambda/TargetType74.java	Thu Jun 06 15:35:05 2013 +0100
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2013, 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
+ * @bug 8015432
+ * @summary javac crashes with stack overflow when method called recursively from nested generic call
+ * @compile TargetType74.java
+ */
+class TargetType74 {
+
+    static class LazySeq<E> { }
+
+    <C> LazySeq<C> cons(LazySeq<C> tailFun) { return null; }
+
+    <T extends Comparable<T>> LazySeq<T> mergeSorted(LazySeq<T> a) {
+        return cons(mergeSorted(a));
+    }
+}