8144767: Fix handling of capture variables in most-specific test
Reviewed-by: vromero
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java Fri Jun 10 11:11:52 2016 +0000
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java Fri Jun 10 15:08:00 2016 -0600
@@ -1155,12 +1155,18 @@
/** Parameters {@code t} and {@code s} are unrelated functional interface types. */
private boolean functionalInterfaceMostSpecific(Type t, Type s, JCTree tree) {
- Type tDesc = types.findDescriptorType(t);
+ Type tDesc = types.findDescriptorType(types.capture(t));
+ Type tDescNoCapture = types.findDescriptorType(t);
Type sDesc = types.findDescriptorType(s);
-
- // compare type parameters -- can't use Types.hasSameBounds because bounds may have ivars
final List<Type> tTypeParams = tDesc.getTypeArguments();
+ final List<Type> tTypeParamsNoCapture = tDescNoCapture.getTypeArguments();
final List<Type> sTypeParams = sDesc.getTypeArguments();
+
+ // compare type parameters
+ if (tDesc.hasTag(FORALL) && !types.hasSameBounds((ForAll) tDesc, (ForAll) tDescNoCapture)) {
+ return false;
+ }
+ // can't use Types.hasSameBounds on sDesc because bounds may have ivars
List<Type> tIter = tTypeParams;
List<Type> sIter = sTypeParams;
while (tIter.nonEmpty() && sIter.nonEmpty()) {
@@ -1181,20 +1187,26 @@
// compare parameters
List<Type> tParams = tDesc.getParameterTypes();
+ List<Type> tParamsNoCapture = tDescNoCapture.getParameterTypes();
List<Type> sParams = sDesc.getParameterTypes();
- while (tParams.nonEmpty() && sParams.nonEmpty()) {
+ while (tParams.nonEmpty() && tParamsNoCapture.nonEmpty() && sParams.nonEmpty()) {
Type tParam = tParams.head;
+ Type tParamNoCapture = types.subst(tParamsNoCapture.head, tTypeParamsNoCapture, tTypeParams);
Type sParam = types.subst(sParams.head, sTypeParams, tTypeParams);
if (tParam.containsAny(tTypeParams) && inferenceContext().free(sParam)) {
return false;
}
- if (!types.isSameType(tParam, inferenceContext().asUndetVar(sParam))) {
+ if (!types.isSubtype(inferenceContext().asUndetVar(sParam), tParam)) {
+ return false;
+ }
+ if (!types.isSameType(tParamNoCapture, inferenceContext().asUndetVar(sParam))) {
return false;
}
tParams = tParams.tail;
+ tParamsNoCapture = tParamsNoCapture.tail;
sParams = sParams.tail;
}
- if (!tParams.isEmpty() || !sParams.isEmpty()) {
+ if (!tParams.isEmpty() || !tParamsNoCapture.isEmpty() || !sParams.isEmpty()) {
return false;
}
--- a/langtools/test/tools/javac/lambda/MostSpecific28.java Fri Jun 10 11:11:52 2016 +0000
+++ b/langtools/test/tools/javac/lambda/MostSpecific28.java Fri Jun 10 15:08:00 2016 -0600
@@ -12,8 +12,6 @@
static void m1(Pred<? super Integer> f) {}
static void m1(Fun<Number, Boolean> f) {}
- static String foo(Object in) { return "a"; }
-
void test() {
m1((Number n) -> true);
}
--- a/langtools/test/tools/javac/lambda/MostSpecific28.out Fri Jun 10 11:11:52 2016 +0000
+++ b/langtools/test/tools/javac/lambda/MostSpecific28.out Fri Jun 10 15:08:00 2016 -0600
@@ -1,2 +1,2 @@
-MostSpecific28.java:18:9: compiler.err.ref.ambiguous: m1, kindname.method, m1(MostSpecific28.Pred<? super java.lang.Integer>), MostSpecific28, kindname.method, m1(MostSpecific28.Fun<java.lang.Number,java.lang.Boolean>), MostSpecific28
+MostSpecific28.java:16:9: compiler.err.ref.ambiguous: m1, kindname.method, m1(MostSpecific28.Pred<? super java.lang.Integer>), MostSpecific28, kindname.method, m1(MostSpecific28.Fun<java.lang.Number,java.lang.Boolean>), MostSpecific28
1 error
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/lambda/MostSpecific29.java Fri Jun 10 15:08:00 2016 -0600
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2016, 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 8144767
+ * @summary Correct most-specific test when wildcards appear in functional interface type
+ * @compile MostSpecific29.java
+ */
+class MostSpecific29 {
+
+ interface Pred<T> { boolean test(T arg); }
+ interface Fun<T,R> { R apply(T arg); }
+
+ static void m1(Pred<? super Integer> f) {}
+ static void m1(Fun<Integer, Boolean> f) {}
+
+ void test() {
+ m1((Integer n) -> true);
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/lambda/MostSpecific30.java Fri Jun 10 15:08:00 2016 -0600
@@ -0,0 +1,19 @@
+/*
+ * @test /nodynamiccopyright/
+ * @bug 8144767
+ * @summary Correct most-specific test when wildcards appear in functional interface type
+ * @compile/fail/ref=MostSpecific30.out -XDrawDiagnostics MostSpecific30.java
+ */
+class MostSpecific30 {
+
+ interface Pred<T> { boolean test(T arg); }
+ interface Fun<T,R> { R apply(T arg); }
+
+ static void m1(Pred<? extends Integer> f) {}
+ static void m1(Fun<Integer, Boolean> f) {}
+
+ void test() {
+ m1((Integer n) -> true);
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/lambda/MostSpecific30.out Fri Jun 10 15:08:00 2016 -0600
@@ -0,0 +1,2 @@
+MostSpecific30.java:16:9: compiler.err.ref.ambiguous: m1, kindname.method, m1(MostSpecific30.Pred<? extends java.lang.Integer>), MostSpecific30, kindname.method, m1(MostSpecific30.Fun<java.lang.Integer,java.lang.Boolean>), MostSpecific30
+1 error
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/lambda/MostSpecific31.java Fri Jun 10 15:08:00 2016 -0600
@@ -0,0 +1,21 @@
+/*
+ * @test /nodynamiccopyright/
+ * @bug 8144767
+ * @summary Correct most-specific test when wildcards appear in functional interface type
+ * @compile/fail/ref=MostSpecific31.out -XDrawDiagnostics MostSpecific31.java
+ */
+class MostSpecific31 {
+
+ interface Pred<T> { boolean test(T arg); }
+ interface Fun<T,R> { R apply(T arg); }
+
+ static void m1(Pred<? super Number> f) {}
+ static void m1(Fun<Integer, Boolean> f) {}
+
+ static boolean foo(Object arg) { return false; }
+
+ void test() {
+ m1(MostSpecific31::foo);
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/lambda/MostSpecific31.out Fri Jun 10 15:08:00 2016 -0600
@@ -0,0 +1,2 @@
+MostSpecific31.java:18:9: compiler.err.ref.ambiguous: m1, kindname.method, m1(MostSpecific31.Pred<? super java.lang.Number>), MostSpecific31, kindname.method, m1(MostSpecific31.Fun<java.lang.Integer,java.lang.Boolean>), MostSpecific31
+1 error
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/lambda/MostSpecific32.java Fri Jun 10 15:08:00 2016 -0600
@@ -0,0 +1,22 @@
+/*
+ * @test /nodynamiccopyright/
+ * @bug 8144767
+ * @summary Correct most-specific test when wildcards appear in functional interface type
+ * @compile/fail/ref=MostSpecific32.out -XDrawDiagnostics MostSpecific32.java
+ */
+class MostSpecific32 {
+
+ interface A<T> {}
+ interface B<T> extends A<T> {}
+
+ interface F1<S> { A<S> apply(); }
+ interface F2<S> { B<S> apply(); }
+
+ static void m1(F1<? extends Number> f1) {}
+ static void m1(F2<? extends Number> f2) {}
+
+ void test() {
+ m1(() -> null); // B<CAP ext Number> </: A<Number>
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/lambda/MostSpecific32.out Fri Jun 10 15:08:00 2016 -0600
@@ -0,0 +1,2 @@
+MostSpecific32.java:19:9: compiler.err.ref.ambiguous: m1, kindname.method, m1(MostSpecific32.F1<? extends java.lang.Number>), MostSpecific32, kindname.method, m1(MostSpecific32.F2<? extends java.lang.Number>), MostSpecific32
+1 error