8064464: regression with type inference of conditional expression
Summary: Bad classification of conditional leads to spurious error
Reviewed-by: jlahoda
--- 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) {
--- 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
--- 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();
}
}
--- 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
--- /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 extends Integer> X id() { return null; }
+
+ void m(List<Integer> 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
+ }
+}
--- /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
--- 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;
}
}