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
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java Thu Jun 06 15:33:40 2013 +0100
+++ b/langtools/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/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java Thu Jun 06 15:33:40 2013 +0100
+++ b/langtools/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/langtools/test/tools/javac/6758789/T6758789b.out Thu Jun 06 15:33:40 2013 +0100
+++ b/langtools/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/langtools/test/tools/javac/generics/7015430/T7015430.out Thu Jun 06 15:33:40 2013 +0100
+++ b/langtools/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: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:68:22: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), java.lang.Iterable, java.lang.Iterable<java.lang.Exception>
+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/langtools/test/tools/javac/generics/7151802/T7151802.out Thu Jun 06 15:33:40 2013 +0100
+++ b/langtools/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: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:22:31: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), T7151802.Foo, T7151802.Foo<java.lang.Object>
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/langtools/test/tools/javac/generics/inference/6718364/T6718364.out Thu Jun 06 15:33:40 2013 +0100
+++ b/langtools/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/langtools/test/tools/javac/generics/inference/7177306/T7177306a.out Thu Jun 06 15:33:40 2013 +0100
+++ b/langtools/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/langtools/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));
+ }
+}