changeset 3351:4525f3a38730

8034223: Most-specific should not have any special treatment for boxed vs. unboxed types Summary: Rewrite most-specific logic to conform to JLS 8 15.12.2.5 Reviewed-by: vromero
author dlsmith
date Tue, 13 May 2014 15:29:09 -0600
parents 9c2c24a6785d
children 464d69f73516
files src/share/classes/com/sun/tools/javac/code/Source.java src/share/classes/com/sun/tools/javac/comp/Resolve.java src/share/classes/com/sun/tools/javac/tree/JCTree.java test/tools/javac/lambda/MostSpecific10.java test/tools/javac/lambda/MostSpecific11.java test/tools/javac/lambda/MostSpecific12.java test/tools/javac/lambda/MostSpecific12.out test/tools/javac/lambda/MostSpecific13.java test/tools/javac/lambda/MostSpecific13.out test/tools/javac/lambda/MostSpecific14.java test/tools/javac/lambda/MostSpecific14.out test/tools/javac/lambda/TargetType16.java test/tools/javac/lambda/TargetType16.out test/tools/javac/lambda/TargetType23.java test/tools/javac/lambda/TargetType23.out test/tools/javac/resolve/ResolveHarness.java test/tools/javac/resolve/tests/PrimitiveOverReferenceVarargsAmbiguous.java test/tools/javac/resolve/tests/PrimitiveVsReferenceSamePhase.java
diffstat 18 files changed, 397 insertions(+), 123 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/com/sun/tools/javac/code/Source.java	Fri May 09 22:27:07 2014 -0400
+++ b/src/share/classes/com/sun/tools/javac/code/Source.java	Tue May 13 15:29:09 2014 -0600
@@ -234,7 +234,7 @@
     public boolean allowGraphInference() {
         return compareTo(JDK1_8) >= 0;
     }
-    public boolean allowStructuralMostSpecific() {
+    public boolean allowFunctionalInterfaceMostSpecific() {
         return compareTo(JDK1_8) >= 0;
     }
     public static SourceVersion toSourceVersion(Source source) {
--- a/src/share/classes/com/sun/tools/javac/comp/Resolve.java	Fri May 09 22:27:07 2014 -0400
+++ b/src/share/classes/com/sun/tools/javac/comp/Resolve.java	Tue May 13 15:29:09 2014 -0600
@@ -94,7 +94,7 @@
     public final boolean boxingEnabled;
     public final boolean varargsEnabled;
     public final boolean allowMethodHandles;
-    public final boolean allowStructuralMostSpecific;
+    public final boolean allowFunctionalInterfaceMostSpecific;
     private final boolean debugResolve;
     private final boolean compactMethodDiags;
     final EnumSet<VerboseResolutionMode> verboseResolutionMode;
@@ -135,7 +135,7 @@
         verboseResolutionMode = VerboseResolutionMode.getVerboseResolutionMode(options);
         Target target = Target.instance(context);
         allowMethodHandles = target.hasMethodHandles();
-        allowStructuralMostSpecific = source.allowStructuralMostSpecific();
+        allowFunctionalInterfaceMostSpecific = source.allowFunctionalInterfaceMostSpecific();
         polymorphicSignatureScope = new Scope(syms.noSymbol);
 
         inapplicableMethodException = new InapplicableMethodException(diags);
@@ -1084,50 +1084,47 @@
             }
 
             public boolean compatible(Type found, Type req, Warner warn) {
-                if (!allowStructuralMostSpecific || actual == null) {
-                    return super.compatible(found, req, warn);
-                } else {
-                    switch (actual.getTag()) {
-                        case DEFERRED:
-                            DeferredType dt = (DeferredType) actual;
-                            DeferredType.SpeculativeCache.Entry e = dt.speculativeCache.get(deferredAttrContext.msym, deferredAttrContext.phase);
-                            return (e == null || e.speculativeTree == deferredAttr.stuckTree)
-                                    ? super.compatible(found, req, warn) :
-                                      mostSpecific(found, req, e.speculativeTree, warn);
-                        default:
-                            return standaloneMostSpecific(found, req, actual, warn);
+                if (allowFunctionalInterfaceMostSpecific &&
+                        unrelatedFunctionalInterfaces(found, req) &&
+                        (actual != null && actual.getTag() == DEFERRED)) {
+                    DeferredType dt = (DeferredType) actual;
+                    DeferredType.SpeculativeCache.Entry e =
+                            dt.speculativeCache.get(deferredAttrContext.msym, deferredAttrContext.phase);
+                    if (e != null && e.speculativeTree != deferredAttr.stuckTree) {
+                        return functionalInterfaceMostSpecific(found, req, e.speculativeTree, warn);
                     }
                 }
+                return super.compatible(found, req, warn);
             }
 
-            private boolean mostSpecific(Type t, Type s, JCTree tree, Warner warn) {
-                MostSpecificChecker msc = new MostSpecificChecker(t, s, warn);
+            /** Whether {@code t} and {@code s} are unrelated functional interface types. */
+            private boolean unrelatedFunctionalInterfaces(Type t, Type s) {
+                return types.isFunctionalInterface(t.tsym) &&
+                       types.isFunctionalInterface(s.tsym) &&
+                       types.asSuper(t, s.tsym) == null &&
+                       types.asSuper(s, t.tsym) == null;
+            }
+
+            /** Parameters {@code t} and {@code s} are unrelated functional interface types. */
+            private boolean functionalInterfaceMostSpecific(Type t, Type s, JCTree tree, Warner warn) {
+                FunctionalInterfaceMostSpecificChecker msc = new FunctionalInterfaceMostSpecificChecker(t, s, warn);
                 msc.scan(tree);
                 return msc.result;
             }
 
-            boolean polyMostSpecific(Type t1, Type t2, Warner warn) {
-                return (!t1.isPrimitive() && t2.isPrimitive())
-                        ? true : super.compatible(t1, t2, warn);
-            }
-
-            boolean standaloneMostSpecific(Type t1, Type t2, Type exprType, Warner warn) {
-                return (exprType.isPrimitive() == t1.isPrimitive()
-                        && exprType.isPrimitive() != t2.isPrimitive())
-                        ? true : super.compatible(t1, t2, warn);
-            }
-
             /**
-             * Structural checker for most specific.
+             * Tests whether one functional interface type can be considered more specific
+             * than another unrelated functional interface type for the scanned expression.
              */
-            class MostSpecificChecker extends DeferredAttr.PolyScanner {
+            class FunctionalInterfaceMostSpecificChecker extends DeferredAttr.PolyScanner {
 
                 final Type t;
                 final Type s;
                 final Warner warn;
                 boolean result;
 
-                MostSpecificChecker(Type t, Type s, Warner warn) {
+                /** Parameters {@code t} and {@code s} are unrelated functional interface types. */
+                FunctionalInterfaceMostSpecificChecker(Type t, Type s, Warner warn) {
                     this.t = t;
                     this.s = s;
                     this.warn = warn;
@@ -1136,102 +1133,96 @@
 
                 @Override
                 void skip(JCTree tree) {
-                    result &= standaloneMostSpecific(t, s, tree.type, warn);
+                    result &= false;
                 }
 
                 @Override
                 public void visitConditional(JCConditional tree) {
-                    if (tree.polyKind == PolyKind.STANDALONE) {
-                        result &= standaloneMostSpecific(t, s, tree.type, warn);
+                    scan(tree.truepart);
+                    scan(tree.falsepart);
+                }
+
+                @Override
+                public void visitReference(JCMemberReference tree) {
+                    Type desc_t = types.findDescriptorType(t);
+                    Type desc_s = types.findDescriptorType(s);
+                    // use inference variables here for more-specific inference (18.5.4)
+                    if (!types.isSameTypes(desc_t.getParameterTypes(),
+                            inferenceContext().asUndetVars(desc_s.getParameterTypes()))) {
+                        result &= false;
                     } else {
-                        super.visitConditional(tree);
+                        // compare return types
+                        Type ret_t = desc_t.getReturnType();
+                        Type ret_s = desc_s.getReturnType();
+                        if (ret_s.hasTag(VOID)) {
+                            result &= true;
+                        } else if (ret_t.hasTag(VOID)) {
+                            result &= false;
+                        } else if (ret_t.isPrimitive() != ret_s.isPrimitive()) {
+                            boolean retValIsPrimitive =
+                                    tree.refPolyKind == PolyKind.STANDALONE &&
+                                    tree.sym.type.getReturnType().isPrimitive();
+                            result &= (retValIsPrimitive == ret_t.isPrimitive()) &&
+                                      (retValIsPrimitive != ret_s.isPrimitive());
+                        } else {
+                            result &= MostSpecificCheckContext.super.compatible(ret_t, ret_s, warn);
+                        }
                     }
                 }
 
                 @Override
-                public void visitApply(JCMethodInvocation tree) {
-                    result &= (tree.polyKind == PolyKind.STANDALONE)
-                            ? standaloneMostSpecific(t, s, tree.type, warn)
-                            : polyMostSpecific(t, s, warn);
-                }
-
-                @Override
-                public void visitNewClass(JCNewClass tree) {
-                    result &= (tree.polyKind == PolyKind.STANDALONE)
-                            ? standaloneMostSpecific(t, s, tree.type, warn)
-                            : polyMostSpecific(t, s, warn);
-                }
-
-                @Override
-                public void visitReference(JCMemberReference tree) {
-                    if (types.isFunctionalInterface(t.tsym) &&
-                            types.isFunctionalInterface(s.tsym)) {
-                        Type desc_t = types.findDescriptorType(t);
-                        Type desc_s = types.findDescriptorType(s);
-                        if (types.isSameTypes(desc_t.getParameterTypes(),
-                                inferenceContext().asUndetVars(desc_s.getParameterTypes()))) {
-                            if (types.asSuper(t, s.tsym) != null ||
-                                types.asSuper(s, t.tsym) != null) {
-                                result &= MostSpecificCheckContext.super.compatible(t, s, warn);
-                            } else if (!desc_s.getReturnType().hasTag(VOID)) {
-                                //perform structural comparison
-                                Type ret_t = desc_t.getReturnType();
-                                Type ret_s = desc_s.getReturnType();
-                                result &= ((tree.refPolyKind == PolyKind.STANDALONE)
-                                        ? standaloneMostSpecific(ret_t, ret_s, tree.sym.type.getReturnType(), warn)
-                                        : polyMostSpecific(ret_t, ret_s, warn));
-                            } else {
-                                return;
+                public void visitLambda(JCLambda tree) {
+                    Type desc_t = types.findDescriptorType(t);
+                    Type desc_s = types.findDescriptorType(s);
+                    // use inference variables here for more-specific inference (18.5.4)
+                    if (!types.isSameTypes(desc_t.getParameterTypes(),
+                            inferenceContext().asUndetVars(desc_s.getParameterTypes()))) {
+                        result &= false;
+                    } else {
+                        // compare return types
+                        Type ret_t = desc_t.getReturnType();
+                        Type ret_s = desc_s.getReturnType();
+                        if (ret_s.hasTag(VOID)) {
+                            result &= true;
+                        } else if (ret_t.hasTag(VOID)) {
+                            result &= false;
+                        } else if (unrelatedFunctionalInterfaces(ret_t, ret_s)) {
+                            for (JCExpression expr : lambdaResults(tree)) {
+                                result &= functionalInterfaceMostSpecific(ret_t, ret_s, expr, warn);
                             }
+                        } else if (ret_t.isPrimitive() != ret_s.isPrimitive()) {
+                            for (JCExpression expr : lambdaResults(tree)) {
+                                boolean retValIsPrimitive = expr.isStandalone() && expr.type.isPrimitive();
+                                result &= (retValIsPrimitive == ret_t.isPrimitive()) &&
+                                          (retValIsPrimitive != ret_s.isPrimitive());
+                            }
+                        } else {
+                            result &= MostSpecificCheckContext.super.compatible(ret_t, ret_s, warn);
                         }
-                    } else {
-                        result &= false;
-                    }
-                }
-
-                @Override
-                public void visitLambda(JCLambda tree) {
-                    if (types.isFunctionalInterface(t.tsym) &&
-                            types.isFunctionalInterface(s.tsym)) {
-                        Type desc_t = types.findDescriptorType(t);
-                        Type desc_s = types.findDescriptorType(s);
-                        if (types.isSameTypes(desc_t.getParameterTypes(),
-                                inferenceContext().asUndetVars(desc_s.getParameterTypes()))) {
-                            if (types.asSuper(t, s.tsym) != null ||
-                                types.asSuper(s, t.tsym) != null) {
-                                result &= MostSpecificCheckContext.super.compatible(t, s, warn);
-                            } else if (!desc_s.getReturnType().hasTag(VOID)) {
-                                //perform structural comparison
-                                Type ret_t = desc_t.getReturnType();
-                                Type ret_s = desc_s.getReturnType();
-                                scanLambdaBody(tree, ret_t, ret_s);
-                            } else {
-                                return;
-                            }
-                        }
-                    } else {
-                        result &= false;
                     }
                 }
                 //where
 
-                void scanLambdaBody(JCLambda lambda, final Type t, final Type s) {
+                private List<JCExpression> lambdaResults(JCLambda lambda) {
                     if (lambda.getBodyKind() == JCTree.JCLambda.BodyKind.EXPRESSION) {
-                        result &= MostSpecificCheckContext.this.mostSpecific(t, s, lambda.body, warn);
+                        return List.of((JCExpression) lambda.body);
                     } else {
+                        final ListBuffer<JCExpression> buffer = new ListBuffer<>();
                         DeferredAttr.LambdaReturnScanner lambdaScanner =
                                 new DeferredAttr.LambdaReturnScanner() {
                                     @Override
                                     public void visitReturn(JCReturn tree) {
                                         if (tree.expr != null) {
-                                            result &= MostSpecificCheckContext.this.mostSpecific(t, s, tree.expr, warn);
+                                            buffer.append(tree.expr);
                                         }
                                     }
                                 };
                         lambdaScanner.scan(lambda.body);
+                        return buffer.toList();
                     }
                 }
             }
+
         }
 
         public MethodCheck mostSpecificCheck(List<Type> actuals, boolean strict) {
--- a/src/share/classes/com/sun/tools/javac/tree/JCTree.java	Fri May 09 22:27:07 2014 -0400
+++ b/src/share/classes/com/sun/tools/javac/tree/JCTree.java	Tue May 13 15:29:09 2014 -0600
@@ -643,6 +643,9 @@
             super.setPos(pos);
             return this;
         }
+
+        public boolean isPoly() { return false; }
+        public boolean isStandalone() { return true; }
     }
 
     /**
@@ -663,6 +666,9 @@
 
         /** is this poly expression a 'true' poly expression? */
         public PolyKind polyKind;
+
+        @Override public boolean isPoly() { return polyKind == PolyKind.POLY; }
+        @Override public boolean isStandalone() { return polyKind == PolyKind.STANDALONE; }
     }
 
     /**
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/lambda/MostSpecific10.java	Tue May 13 15:29:09 2014 -0600
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2014, 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 8034223
+ * @summary Structural most-specific logic for lambdas, method refs, parens, and conditionals
+ * @compile MostSpecific10.java
+ */
+class MostSpecific10 {
+
+    interface GetInt {
+        int get();
+    }
+
+    interface GetInteger {
+        Integer get();
+    }
+
+    void m(GetInt getter) {}
+    void m(GetInteger getter) {}
+
+    void test(boolean cond) {
+        m(() -> 23);
+        m("abc"::length);
+        m(( () -> 23 ));
+        m(( "abc"::length ));
+        m(cond ? () -> 23 : "abc"::length);
+        m(( cond ? () -> 23 : "abc"::length ));
+        m(cond ? (() -> 23) : ("abc"::length) );
+        m(( cond ? () -> 23 : cond ? ("abc"::length) : (() -> 23) ));
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/lambda/MostSpecific11.java	Tue May 13 15:29:09 2014 -0600
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2014, 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 8034223
+ * @summary Return type Object is not more specific than return type String
+ * @compile MostSpecific11.java
+ */
+class MostSpecific11 {
+
+    interface I { Object run(); }
+    interface J { String run(); }
+
+    void m(I arg) {}
+    void m(J arg) {}
+
+    void test() {
+        m(() -> { throw new RuntimeException(); });
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/lambda/MostSpecific12.java	Tue May 13 15:29:09 2014 -0600
@@ -0,0 +1,38 @@
+/*
+ * @test /nodynamiccopyright/
+ * @bug 8034223
+ * @summary Most-specific testing with inference variables in function parameter types
+ * @compile/fail/ref=MostSpecific12.out -XDrawDiagnostics MostSpecific12.java
+ */
+class MostSpecific12 {
+
+    interface I<T> { void take(T arg1, String arg2); }
+    interface J<T> { void take(String arg1, T arg2); }
+    interface K { void take(String arg1, String arg2); }
+
+    <T> void m1(I<T> arg) {}
+    void m1(K arg) {}
+
+    <T> void m2(J<T> arg) {}
+    <T> void m2(K arg) {}
+
+    <T> void m3(I<T> arg) {}
+    <T> void m3(J<T> arg) {}
+
+    void test() {
+        m1((String s1, String s2) -> {}); // ok
+        m2((String s1, String s2) -> {}); // ok
+        m3((String s1, String s2) -> {}); // error
+
+        m1(this::referencedMethod); // ok
+        m2(this::referencedMethod); // ok
+        m3(this::referencedMethod); // error
+
+        m1(String::compareTo); // ok
+        m2(String::compareTo); // ok
+        m3(String::compareTo); // error
+    }
+
+    void referencedMethod(String s1, String s2) {}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/lambda/MostSpecific12.out	Tue May 13 15:29:09 2014 -0600
@@ -0,0 +1,4 @@
+MostSpecific12.java:25:9: compiler.err.ref.ambiguous: m3, kindname.method, <T>m3(MostSpecific12.I<T>), MostSpecific12, kindname.method, <T>m3(MostSpecific12.J<T>), MostSpecific12
+MostSpecific12.java:29:9: compiler.err.ref.ambiguous: m3, kindname.method, <T>m3(MostSpecific12.I<T>), MostSpecific12, kindname.method, <T>m3(MostSpecific12.J<T>), MostSpecific12
+MostSpecific12.java:33:9: compiler.err.ref.ambiguous: m3, kindname.method, <T>m3(MostSpecific12.I<T>), MostSpecific12, kindname.method, <T>m3(MostSpecific12.J<T>), MostSpecific12
+3 errors
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/lambda/MostSpecific13.java	Tue May 13 15:29:09 2014 -0600
@@ -0,0 +1,21 @@
+/*
+ * @test /nodynamiccopyright/
+ * @bug 8034223
+ * @summary Most-specific testing with inference variables in function parameter types
+ * @compile/fail/ref=MostSpecific13.out -XDrawDiagnostics MostSpecific13.java
+ */
+class MostSpecific13 {
+
+    interface UnaryOp<T> { T apply(T arg); }
+    interface IntegerToNumber { Number apply(Integer arg); }
+
+    <T> void m(UnaryOp<T> f) {}
+    void m(IntegerToNumber f) {}
+
+    void test() {
+        m((Integer i) -> i); // error
+        m(this::id); // error
+    }
+
+    Integer id(Integer arg) { return arg; }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/lambda/MostSpecific13.out	Tue May 13 15:29:09 2014 -0600
@@ -0,0 +1,3 @@
+MostSpecific13.java:16:9: compiler.err.ref.ambiguous: m, kindname.method, <T>m(MostSpecific13.UnaryOp<T>), MostSpecific13, kindname.method, m(MostSpecific13.IntegerToNumber), MostSpecific13
+MostSpecific13.java:17:9: compiler.err.ref.ambiguous: m, kindname.method, <T>m(MostSpecific13.UnaryOp<T>), MostSpecific13, kindname.method, m(MostSpecific13.IntegerToNumber), MostSpecific13
+2 errors
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/lambda/MostSpecific14.java	Tue May 13 15:29:09 2014 -0600
@@ -0,0 +1,33 @@
+/*
+ * @test /nodynamiccopyright/
+ * @bug 8034223
+ * @summary Most-specific testing for nested functional interface types
+ * @compile/fail/ref=MostSpecific14.out -XDrawDiagnostics MostSpecific14.java
+ */
+class MostSpecific14 {
+    interface ToNumber { Number get(); }
+    interface ToToNumber { ToNumber get(); }
+    interface Factory<T> { T get(); }
+
+    void m1(Factory<Factory<Object>> f) {}
+    void m1(ToToNumber f) {}
+
+    void m2(Factory<Factory<Number>> f) {}
+    void m2(ToToNumber f) {}
+
+    void m3(Factory<Factory<Integer>> f) {}
+    void m3(ToToNumber f) {}
+
+
+    void test() {
+        m1(() -> () -> 23); // ok: choose ToToNumber
+        m2(() -> () -> 23); // error: ambiguous
+        m3(() -> () -> 23); // ok: choose Factory<Factory<Integer>>
+
+        m1(() -> this::getInteger); // ok: choose ToToNumber
+        m2(() -> this::getInteger); // error: ambiguous
+        m3(() -> this::getInteger); // ok: choose Factory<Factory<Integer>>
+    }
+
+    Integer getInteger() { return 23; }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/lambda/MostSpecific14.out	Tue May 13 15:29:09 2014 -0600
@@ -0,0 +1,3 @@
+MostSpecific14.java:24:9: compiler.err.ref.ambiguous: m2, kindname.method, m2(MostSpecific14.Factory<MostSpecific14.Factory<java.lang.Number>>), MostSpecific14, kindname.method, m2(MostSpecific14.ToToNumber), MostSpecific14
+MostSpecific14.java:28:9: compiler.err.ref.ambiguous: m2, kindname.method, m2(MostSpecific14.Factory<MostSpecific14.Factory<java.lang.Number>>), MostSpecific14, kindname.method, m2(MostSpecific14.ToToNumber), MostSpecific14
+2 errors
--- a/test/tools/javac/lambda/TargetType16.java	Fri May 09 22:27:07 2014 -0400
+++ b/test/tools/javac/lambda/TargetType16.java	Tue May 13 15:29:09 2014 -0600
@@ -1,9 +1,9 @@
 /*
  * @test /nodynamiccopyright/
- * @bug 8003280
+ * @bug 8003280 8034223
  * @summary Add lambda tests
  *  Check void-compatibility in strict vs. loose conversion contexts
- * @compile/fail/ref=TargetType16.out -XDrawDiagnostics TargetType16.java
+ * @compile TargetType16.java
  */
 
 class TargetType16 {
@@ -20,6 +20,6 @@
     static <T> void m(SAM2<T> s2) { }
 
     public static void main(String[] args) {
-        m(() -> { throw new AssertionError(); }); //ambiguous
+        m(() -> { throw new AssertionError(); }); // prefer SAM2
     }
 }
--- a/test/tools/javac/lambda/TargetType16.out	Fri May 09 22:27:07 2014 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-TargetType16.java:23:9: compiler.err.ref.ambiguous: m, kindname.method, m(TargetType16.SAM1), TargetType16, kindname.method, <T>m(TargetType16.SAM2<T>), TargetType16
-1 error
--- a/test/tools/javac/lambda/TargetType23.java	Fri May 09 22:27:07 2014 -0400
+++ b/test/tools/javac/lambda/TargetType23.java	Tue May 13 15:29:09 2014 -0600
@@ -31,7 +31,12 @@
     void call(Sam2 s) { }
     <Z> void call(Sam3<Z> s) { }
 
+    void call2(Sam0 s) { }
+    void call2(Sam2 s) { }
+    <Z> void call2(Sam3<Z> s) { }
+
     void test() {
-        call(()-> { throw new RuntimeException(); }); //ambiguous - both call(Sam0), call(Sam2), call(Sam3) match
+        call(()-> { throw new RuntimeException(); }); // ambiguous - call(Sam1) vs. call(Sam2)
+        call2(()-> { throw new RuntimeException(); }); // ok
     }
 }
--- a/test/tools/javac/lambda/TargetType23.out	Fri May 09 22:27:07 2014 -0400
+++ b/test/tools/javac/lambda/TargetType23.out	Tue May 13 15:29:09 2014 -0600
@@ -1,2 +1,2 @@
-TargetType23.java:35:9: compiler.err.ref.ambiguous: call, kindname.method, call(TargetType23.Sam2), TargetType23, kindname.method, <Z>call(TargetType23.Sam3<Z>), TargetType23
+TargetType23.java:39:9: compiler.err.ref.ambiguous: call, kindname.method, call(TargetType23.Sam1), TargetType23, kindname.method, call(TargetType23.Sam2), TargetType23
 1 error
--- a/test/tools/javac/resolve/ResolveHarness.java	Fri May 09 22:27:07 2014 -0400
+++ b/test/tools/javac/resolve/ResolveHarness.java	Tue May 13 15:29:09 2014 -0600
@@ -23,8 +23,8 @@
 
 /*
  * @test
- * @bug 7098660 8014649
- * @summary Write better overload resolution/inference tests
+ * @bug 7098660 8014649 8034223
+ * @summary Test harness for overload resolution/inference tests
  * @library /tools/javac/lib
  * @build JavacTestingAbstractProcessor ResolveHarness
  * @run main ResolveHarness
--- a/test/tools/javac/resolve/tests/PrimitiveOverReferenceVarargsAmbiguous.java	Fri May 09 22:27:07 2014 -0400
+++ b/test/tools/javac/resolve/tests/PrimitiveOverReferenceVarargsAmbiguous.java	Tue May 13 15:29:09 2014 -0600
@@ -23,44 +23,44 @@
 
 @TraceResolve(keys={"compiler.err.ref.ambiguous"})
 class PrimitiveOverReferenceVarargsAmbiguous {
-    @Candidate(applicable=Phase.VARARGS, mostSpecific=true)
+    @Candidate(applicable=Phase.VARARGS, mostSpecific=false)
     static void m_byte(byte... b) {}
-    @Candidate(applicable=Phase.VARARGS)
+    @Candidate(applicable=Phase.VARARGS, mostSpecific=false)
     static void m_byte(Byte... b) {}
 
-    @Candidate(applicable=Phase.VARARGS, mostSpecific=true)
+    @Candidate(applicable=Phase.VARARGS, mostSpecific=false)
     static void m_short(short... s) {}
-    @Candidate(applicable=Phase.VARARGS)
+    @Candidate(applicable=Phase.VARARGS, mostSpecific=false)
     static void m_short(Short... s) {}
 
-    @Candidate(applicable=Phase.VARARGS, mostSpecific=true)
+    @Candidate(applicable=Phase.VARARGS, mostSpecific=false)
     static void m_int(int... i) {}
-    @Candidate(applicable=Phase.VARARGS)
+    @Candidate(applicable=Phase.VARARGS, mostSpecific=false)
     static void m_int(Integer... i) {}
 
-    @Candidate(applicable=Phase.VARARGS, mostSpecific=true)
+    @Candidate(applicable=Phase.VARARGS, mostSpecific=false)
     static void m_long(long... l) {}
-    @Candidate(applicable=Phase.VARARGS)
+    @Candidate(applicable=Phase.VARARGS, mostSpecific=false)
     static void m_long(Long... l) {}
 
-    @Candidate(applicable=Phase.VARARGS, mostSpecific=true)
+    @Candidate(applicable=Phase.VARARGS, mostSpecific=false)
     static void m_float(float... f) {}
-    @Candidate(applicable=Phase.VARARGS)
+    @Candidate(applicable=Phase.VARARGS, mostSpecific=false)
     static void m_float(Float... f) {}
 
-    @Candidate(applicable=Phase.VARARGS, mostSpecific=true)
+    @Candidate(applicable=Phase.VARARGS, mostSpecific=false)
     static void m_double(double... d) {}
-    @Candidate(applicable=Phase.VARARGS)
+    @Candidate(applicable=Phase.VARARGS, mostSpecific=false)
     static void m_double(Double... d) {}
 
-    @Candidate(applicable=Phase.VARARGS, mostSpecific=true)
+    @Candidate(applicable=Phase.VARARGS, mostSpecific=false)
     static void m_char(char... c) {}
-    @Candidate(applicable=Phase.VARARGS)
+    @Candidate(applicable=Phase.VARARGS, mostSpecific=false)
     static void m_char(Character... c) {}
 
-    @Candidate(applicable=Phase.VARARGS, mostSpecific=true)
+    @Candidate(applicable=Phase.VARARGS, mostSpecific=false)
     static void m_bool(boolean... z) {}
-    @Candidate(applicable=Phase.VARARGS)
+    @Candidate(applicable=Phase.VARARGS, mostSpecific=false)
     static void m_bool(Boolean... z) {}
 
     {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/resolve/tests/PrimitiveVsReferenceSamePhase.java	Tue May 13 15:29:09 2014 -0600
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2014 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.
+ */
+
+@TraceResolve(keys={"compiler.err.ref.ambiguous"})
+class PrimitiveVsReferenceSamePhase {
+    @Candidate(applicable=Phase.BOX, mostSpecific=false)
+    static void m_byte(Byte b1, byte b2) {}
+    @Candidate(applicable=Phase.BOX, mostSpecific=false)
+    static void m_byte(Byte b1, Byte b2) {}
+
+    @Candidate(applicable=Phase.BOX, mostSpecific=false)
+    static void m_short(Short s1, short s2) {}
+    @Candidate(applicable=Phase.BOX, mostSpecific=false)
+    static void m_short(Short s1, Short s2) {}
+
+    @Candidate(applicable=Phase.BOX, mostSpecific=false)
+    static void m_int(Integer i1, int i2) {}
+    @Candidate(applicable=Phase.BOX, mostSpecific=false)
+    static void m_int(Integer i1, Integer i2) {}
+
+    @Candidate(applicable=Phase.BOX, mostSpecific=false)
+    static void m_long(Long l1, long l2) {}
+    @Candidate(applicable=Phase.BOX, mostSpecific=false)
+    static void m_long(Long l1, Long l2) {}
+
+    @Candidate(applicable=Phase.BOX, mostSpecific=false)
+    static void m_float(Float f1, float f2) {}
+    @Candidate(applicable=Phase.BOX, mostSpecific=false)
+    static void m_float(Float f1, Float f2) {}
+
+    @Candidate(applicable=Phase.BOX, mostSpecific=false)
+    static void m_double(Double d1, double d2) {}
+    @Candidate(applicable=Phase.BOX, mostSpecific=false)
+    static void m_double(Double d1, Double d2) {}
+
+    @Candidate(applicable=Phase.BOX, mostSpecific=false)
+    static void m_char(Character c1, char c2) {}
+    @Candidate(applicable=Phase.BOX, mostSpecific=false)
+    static void m_char(Character c1, Character c2) {}
+
+    @Candidate(applicable=Phase.BOX, mostSpecific=false)
+    static void m_bool(Boolean z1, boolean z2) {}
+    @Candidate(applicable=Phase.BOX, mostSpecific=false)
+    static void m_bool(Boolean z1, Boolean z2) {}
+
+    {
+        m_byte((byte)0, (byte)0);
+        m_short((short)0, (short)0);
+        m_int(0, 0);
+        m_long(0L, 0L);
+        m_float(0.0f, 0.0f);
+        m_double(0.0, 0.0);
+        m_char('?', '?');
+        m_bool(false, false);
+    }
+}