8064464: regression with type inference of conditional expression

Bad classification of conditional leads to spurious error

Reviewed-by: jlahoda
This commit is contained in:
Maurizio Cimadamore 2014-11-12 12:41:32 +00:00
parent 732c7c5e28
commit ed9c1bb743
7 changed files with 52 additions and 13 deletions

View file

@ -1429,21 +1429,28 @@ public class Attr extends JCTree.Visitor {
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) {

View file

@ -1213,7 +1213,10 @@ public class DeferredAttr extends JCTree.Visitor {
return;
}
scan(tree.falsepart);
result = reduce(ArgumentExpressionKind.PRIMITIVE);
result = reduce(ArgumentExpressionKind.PRIMITIVE).isPrimitive() ?
ArgumentExpressionKind.PRIMITIVE :
ArgumentExpressionKind.POLY;
}
@Override

View file

@ -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();
}
}

View file

@ -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

View file

@ -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
}
}

View file

@ -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

View file

@ -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;
}
}