8064464: regression with type inference of conditional expression

Bad classification of conditional leads to spurious error

Reviewed-by: jlahoda
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java
index 3206fe7..fff0595 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java
@@ -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 --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/DeferredAttr.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/DeferredAttr.java
index e60b603..64bd9ce 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/DeferredAttr.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/DeferredAttr.java
@@ -1213,7 +1213,10 @@
                 return;
             }
             scan(tree.falsepart);
-            result = reduce(ArgumentExpressionKind.PRIMITIVE);
+            result = reduce(ArgumentExpressionKind.PRIMITIVE).isPrimitive() ?
+                    ArgumentExpressionKind.PRIMITIVE :
+                    ArgumentExpressionKind.POLY;
+
         }
 
         @Override
diff --git a/langtools/test/tools/javac/ConditionalWithVoid.java b/langtools/test/tools/javac/ConditionalWithVoid.java
index cdb2caf..bc5753b 100644
--- a/langtools/test/tools/javac/ConditionalWithVoid.java
+++ b/langtools/test/tools/javac/ConditionalWithVoid.java
@@ -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 --git a/langtools/test/tools/javac/ConditionalWithVoid.out b/langtools/test/tools/javac/ConditionalWithVoid.out
index 61549db..6b4bf72 100644
--- a/langtools/test/tools/javac/ConditionalWithVoid.out
+++ b/langtools/test/tools/javac/ConditionalWithVoid.out
@@ -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 --git a/langtools/test/tools/javac/conditional/8064464/T8064464.java b/langtools/test/tools/javac/conditional/8064464/T8064464.java
new file mode 100644
index 0000000..388f5d6
--- /dev/null
+++ b/langtools/test/tools/javac/conditional/8064464/T8064464.java
@@ -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
+  }
+}
diff --git a/langtools/test/tools/javac/conditional/8064464/T8064464.out b/langtools/test/tools/javac/conditional/8064464/T8064464.out
new file mode 100644
index 0000000..0e234ae
--- /dev/null
+++ b/langtools/test/tools/javac/conditional/8064464/T8064464.out
@@ -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 --git a/langtools/test/tools/javac/diags/examples/NeitherConditionalSubtype.java b/langtools/test/tools/javac/diags/examples/NeitherConditionalSubtype.java
index 7237cf5..25f0618 100644
--- a/langtools/test/tools/javac/diags/examples/NeitherConditionalSubtype.java
+++ b/langtools/test/tools/javac/diags/examples/NeitherConditionalSubtype.java
@@ -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;
     }
 }