# HG changeset patch # User mcimadamore # Date 1415796092 0 # Node ID 14a74a56c4a0e703361d502e8bfad51540965449 # Parent 7687cc8669cd780006037ddb372bc8e49434e234 8064464: regression with type inference of conditional expression Summary: Bad classification of conditional leads to spurious error Reviewed-by: jlahoda diff -r 7687cc8669cd -r 14a74a56c4a0 langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java Mon Nov 10 20:29:58 2014 +0100 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java Wed Nov 12 12:41:32 2014 +0000 @@ -1429,21 +1429,28 @@ case APPLY: JCMethodInvocation speculativeMethodTree = (JCMethodInvocation)deferredAttr.attribSpeculative(tree, env, unknownExprInfo); - Type owntype = TreeInfo.symbol(speculativeMethodTree.meth).type.getReturnType(); - return types.unboxedTypeOrType(owntype).isPrimitive(); + Symbol msym = TreeInfo.symbol(speculativeMethodTree.meth); + Type receiverType = speculativeMethodTree.meth.hasTag(IDENT) ? + env.enclClass.type : + ((JCFieldAccess)speculativeMethodTree.meth).selected.type; + Type owntype = types.memberType(receiverType, msym).getReturnType(); + return primitiveOrBoxed(owntype); case NEWCLASS: JCExpression className = removeClassParams.translate(((JCNewClass)tree).clazz); JCExpression speculativeNewClassTree = (JCExpression)deferredAttr.attribSpeculative(className, env, unknownTypeInfo); - return types.unboxedTypeOrType(speculativeNewClassTree.type).isPrimitive(); + return primitiveOrBoxed(speculativeNewClassTree.type); default: Type speculativeType = deferredAttr.attribSpeculative(tree, env, unknownExprInfo).type; - speculativeType = types.unboxedTypeOrType(speculativeType); - return speculativeType.isPrimitive(); + return primitiveOrBoxed(speculativeType); } } //where + boolean primitiveOrBoxed(Type t) { + return (!t.hasTag(TYPEVAR) && types.unboxedTypeOrType(t).isPrimitive()); + } + TreeTranslator removeClassParams = new TreeTranslator() { @Override public void visitTypeApply(JCTypeApply tree) { diff -r 7687cc8669cd -r 14a74a56c4a0 langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/DeferredAttr.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/DeferredAttr.java Mon Nov 10 20:29:58 2014 +0100 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/DeferredAttr.java Wed Nov 12 12:41:32 2014 +0000 @@ -1213,7 +1213,10 @@ return; } scan(tree.falsepart); - result = reduce(ArgumentExpressionKind.PRIMITIVE); + result = reduce(ArgumentExpressionKind.PRIMITIVE).isPrimitive() ? + ArgumentExpressionKind.PRIMITIVE : + ArgumentExpressionKind.POLY; + } @Override diff -r 7687cc8669cd -r 14a74a56c4a0 langtools/test/tools/javac/ConditionalWithVoid.java --- a/langtools/test/tools/javac/ConditionalWithVoid.java Mon Nov 10 20:29:58 2014 +0100 +++ b/langtools/test/tools/javac/ConditionalWithVoid.java Wed Nov 12 12:41:32 2014 +0000 @@ -1,14 +1,16 @@ /* * @test /nodynamiccopyright/ - * @bug 4974927 + * @bug 4974927 8064464 * @summary The compiler was allowing void types in its parsing of conditional expressions. * @author tball * * @compile/fail/ref=ConditionalWithVoid.out -XDrawDiagnostics ConditionalWithVoid.java */ public class ConditionalWithVoid { - public int test(Object o) { - // Should fail to compile since Object.wait() has a void return type. + public void test(Object o) { + // Should fail to compile since Object.wait() has a void return type. Poly case. System.out.println(o instanceof String ? o.hashCode() : o.wait()); + // Should fail to compile since Object.wait() has a void return type. Standalone case. + (o instanceof String ? o.hashCode() : o.wait()).toString(); } } diff -r 7687cc8669cd -r 14a74a56c4a0 langtools/test/tools/javac/ConditionalWithVoid.out --- a/langtools/test/tools/javac/ConditionalWithVoid.out Mon Nov 10 20:29:58 2014 +0100 +++ b/langtools/test/tools/javac/ConditionalWithVoid.out Wed Nov 12 12:41:32 2014 +0000 @@ -1,2 +1,3 @@ -ConditionalWithVoid.java:12:48: compiler.err.neither.conditional.subtype: java.lang.Integer, void -1 error +ConditionalWithVoid.java:12:71: compiler.err.void.not.allowed.here +ConditionalWithVoid.java:14:30: compiler.err.neither.conditional.subtype: java.lang.Integer, void +2 errors diff -r 7687cc8669cd -r 14a74a56c4a0 langtools/test/tools/javac/conditional/8064464/T8064464.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/conditional/8064464/T8064464.java Wed Nov 12 12:41:32 2014 +0000 @@ -0,0 +1,23 @@ +/* + * @test /nodynamiccopyright/ + * @bug 8064464 + * @summary regression with type inference of conditional expression + * @compile/fail/ref=T8064464.out -XDrawDiagnostics T8064464.java + */ + +import java.util.List; + +class T8064464 { + + String f(Object o) { return null; } + Integer f(int i) { return null; } + + X id() { return null; } + + void m(List lx) { + Integer i1 = f(!lx.isEmpty() ? 0 : lx.get(0)); //ok --> f(int) + Integer i2 = f(!lx.isEmpty() ? lx.get(0) : 0); //ok --> f(int) + f(!lx.isEmpty() ? id() : 0); // ambiguous + f(!lx.isEmpty() ? 0 : id()); // ambiguous + } +} diff -r 7687cc8669cd -r 14a74a56c4a0 langtools/test/tools/javac/conditional/8064464/T8064464.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/conditional/8064464/T8064464.out Wed Nov 12 12:41:32 2014 +0000 @@ -0,0 +1,3 @@ +T8064464.java:20:5: compiler.err.ref.ambiguous: f, kindname.method, f(java.lang.Object), T8064464, kindname.method, f(int), T8064464 +T8064464.java:21:5: compiler.err.ref.ambiguous: f, kindname.method, f(java.lang.Object), T8064464, kindname.method, f(int), T8064464 +2 errors diff -r 7687cc8669cd -r 14a74a56c4a0 langtools/test/tools/javac/diags/examples/NeitherConditionalSubtype.java --- a/langtools/test/tools/javac/diags/examples/NeitherConditionalSubtype.java Mon Nov 10 20:29:58 2014 +0100 +++ b/langtools/test/tools/javac/diags/examples/NeitherConditionalSubtype.java Wed Nov 12 12:41:32 2014 +0000 @@ -24,9 +24,9 @@ // key: compiler.err.neither.conditional.subtype class NeitherConditionalSubtype { - public int test(Object o) { + public int test(boolean cond, Object o) { // Should fail to compile since Object.wait() has a void return type. - System.out.println(o instanceof String ? o.hashCode() : o.wait()); + (o instanceof String ? o.hashCode() : o.wait()).toString(); return 0; } }