mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-17 09:34:38 +02:00
8034223: Most-specific should not have any special treatment for boxed vs. unboxed types
Rewrite most-specific logic to conform to JLS 8 15.12.2.5 Reviewed-by: vromero
This commit is contained in:
parent
10fb266571
commit
9798cbad4c
18 changed files with 393 additions and 119 deletions
|
@ -234,7 +234,7 @@ public enum Source {
|
||||||
public boolean allowGraphInference() {
|
public boolean allowGraphInference() {
|
||||||
return compareTo(JDK1_8) >= 0;
|
return compareTo(JDK1_8) >= 0;
|
||||||
}
|
}
|
||||||
public boolean allowStructuralMostSpecific() {
|
public boolean allowFunctionalInterfaceMostSpecific() {
|
||||||
return compareTo(JDK1_8) >= 0;
|
return compareTo(JDK1_8) >= 0;
|
||||||
}
|
}
|
||||||
public static SourceVersion toSourceVersion(Source source) {
|
public static SourceVersion toSourceVersion(Source source) {
|
||||||
|
|
|
@ -94,7 +94,7 @@ public class Resolve {
|
||||||
public final boolean boxingEnabled;
|
public final boolean boxingEnabled;
|
||||||
public final boolean varargsEnabled;
|
public final boolean varargsEnabled;
|
||||||
public final boolean allowMethodHandles;
|
public final boolean allowMethodHandles;
|
||||||
public final boolean allowStructuralMostSpecific;
|
public final boolean allowFunctionalInterfaceMostSpecific;
|
||||||
private final boolean debugResolve;
|
private final boolean debugResolve;
|
||||||
private final boolean compactMethodDiags;
|
private final boolean compactMethodDiags;
|
||||||
final EnumSet<VerboseResolutionMode> verboseResolutionMode;
|
final EnumSet<VerboseResolutionMode> verboseResolutionMode;
|
||||||
|
@ -135,7 +135,7 @@ public class Resolve {
|
||||||
verboseResolutionMode = VerboseResolutionMode.getVerboseResolutionMode(options);
|
verboseResolutionMode = VerboseResolutionMode.getVerboseResolutionMode(options);
|
||||||
Target target = Target.instance(context);
|
Target target = Target.instance(context);
|
||||||
allowMethodHandles = target.hasMethodHandles();
|
allowMethodHandles = target.hasMethodHandles();
|
||||||
allowStructuralMostSpecific = source.allowStructuralMostSpecific();
|
allowFunctionalInterfaceMostSpecific = source.allowFunctionalInterfaceMostSpecific();
|
||||||
polymorphicSignatureScope = new Scope(syms.noSymbol);
|
polymorphicSignatureScope = new Scope(syms.noSymbol);
|
||||||
|
|
||||||
inapplicableMethodException = new InapplicableMethodException(diags);
|
inapplicableMethodException = new InapplicableMethodException(diags);
|
||||||
|
@ -1084,50 +1084,47 @@ public class Resolve {
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean compatible(Type found, Type req, Warner warn) {
|
public boolean compatible(Type found, Type req, Warner warn) {
|
||||||
if (!allowStructuralMostSpecific || actual == null) {
|
if (allowFunctionalInterfaceMostSpecific &&
|
||||||
return super.compatible(found, req, warn);
|
unrelatedFunctionalInterfaces(found, req) &&
|
||||||
} else {
|
(actual != null && actual.getTag() == DEFERRED)) {
|
||||||
switch (actual.getTag()) {
|
|
||||||
case DEFERRED:
|
|
||||||
DeferredType dt = (DeferredType) actual;
|
DeferredType dt = (DeferredType) actual;
|
||||||
DeferredType.SpeculativeCache.Entry e = dt.speculativeCache.get(deferredAttrContext.msym, deferredAttrContext.phase);
|
DeferredType.SpeculativeCache.Entry e =
|
||||||
return (e == null || e.speculativeTree == deferredAttr.stuckTree)
|
dt.speculativeCache.get(deferredAttrContext.msym, deferredAttrContext.phase);
|
||||||
? super.compatible(found, req, warn) :
|
if (e != null && e.speculativeTree != deferredAttr.stuckTree) {
|
||||||
mostSpecific(found, req, e.speculativeTree, warn);
|
return functionalInterfaceMostSpecific(found, req, e.speculativeTree, warn);
|
||||||
default:
|
|
||||||
return standaloneMostSpecific(found, req, actual, warn);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return super.compatible(found, req, warn);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean mostSpecific(Type t, Type s, JCTree tree, Warner warn) {
|
/** Whether {@code t} and {@code s} are unrelated functional interface types. */
|
||||||
MostSpecificChecker msc = new MostSpecificChecker(t, s, warn);
|
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);
|
msc.scan(tree);
|
||||||
return msc.result;
|
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 t;
|
||||||
final Type s;
|
final Type s;
|
||||||
final Warner warn;
|
final Warner warn;
|
||||||
boolean result;
|
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.t = t;
|
||||||
this.s = s;
|
this.s = s;
|
||||||
this.warn = warn;
|
this.warn = warn;
|
||||||
|
@ -1136,102 +1133,96 @@ public class Resolve {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void skip(JCTree tree) {
|
void skip(JCTree tree) {
|
||||||
result &= standaloneMostSpecific(t, s, tree.type, warn);
|
result &= false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitConditional(JCConditional tree) {
|
public void visitConditional(JCConditional tree) {
|
||||||
if (tree.polyKind == PolyKind.STANDALONE) {
|
scan(tree.truepart);
|
||||||
result &= standaloneMostSpecific(t, s, tree.type, warn);
|
scan(tree.falsepart);
|
||||||
} else {
|
|
||||||
super.visitConditional(tree);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@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
|
@Override
|
||||||
public void visitReference(JCMemberReference tree) {
|
public void visitReference(JCMemberReference tree) {
|
||||||
if (types.isFunctionalInterface(t.tsym) &&
|
|
||||||
types.isFunctionalInterface(s.tsym)) {
|
|
||||||
Type desc_t = types.findDescriptorType(t);
|
Type desc_t = types.findDescriptorType(t);
|
||||||
Type desc_s = types.findDescriptorType(s);
|
Type desc_s = types.findDescriptorType(s);
|
||||||
if (types.isSameTypes(desc_t.getParameterTypes(),
|
// use inference variables here for more-specific inference (18.5.4)
|
||||||
|
if (!types.isSameTypes(desc_t.getParameterTypes(),
|
||||||
inferenceContext().asUndetVars(desc_s.getParameterTypes()))) {
|
inferenceContext().asUndetVars(desc_s.getParameterTypes()))) {
|
||||||
if (types.asSuper(t, s.tsym) != null ||
|
result &= false;
|
||||||
types.asSuper(s, t.tsym) != null) {
|
} else {
|
||||||
result &= MostSpecificCheckContext.super.compatible(t, s, warn);
|
// compare return types
|
||||||
} else if (!desc_s.getReturnType().hasTag(VOID)) {
|
|
||||||
//perform structural comparison
|
|
||||||
Type ret_t = desc_t.getReturnType();
|
Type ret_t = desc_t.getReturnType();
|
||||||
Type ret_s = desc_s.getReturnType();
|
Type ret_s = desc_s.getReturnType();
|
||||||
result &= ((tree.refPolyKind == PolyKind.STANDALONE)
|
if (ret_s.hasTag(VOID)) {
|
||||||
? standaloneMostSpecific(ret_t, ret_s, tree.sym.type.getReturnType(), warn)
|
result &= true;
|
||||||
: polyMostSpecific(ret_t, ret_s, warn));
|
} else if (ret_t.hasTag(VOID)) {
|
||||||
} else {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
result &= false;
|
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
|
@Override
|
||||||
public void visitLambda(JCLambda tree) {
|
public void visitLambda(JCLambda tree) {
|
||||||
if (types.isFunctionalInterface(t.tsym) &&
|
|
||||||
types.isFunctionalInterface(s.tsym)) {
|
|
||||||
Type desc_t = types.findDescriptorType(t);
|
Type desc_t = types.findDescriptorType(t);
|
||||||
Type desc_s = types.findDescriptorType(s);
|
Type desc_s = types.findDescriptorType(s);
|
||||||
if (types.isSameTypes(desc_t.getParameterTypes(),
|
// use inference variables here for more-specific inference (18.5.4)
|
||||||
|
if (!types.isSameTypes(desc_t.getParameterTypes(),
|
||||||
inferenceContext().asUndetVars(desc_s.getParameterTypes()))) {
|
inferenceContext().asUndetVars(desc_s.getParameterTypes()))) {
|
||||||
if (types.asSuper(t, s.tsym) != null ||
|
result &= false;
|
||||||
types.asSuper(s, t.tsym) != null) {
|
} else {
|
||||||
result &= MostSpecificCheckContext.super.compatible(t, s, warn);
|
// compare return types
|
||||||
} else if (!desc_s.getReturnType().hasTag(VOID)) {
|
|
||||||
//perform structural comparison
|
|
||||||
Type ret_t = desc_t.getReturnType();
|
Type ret_t = desc_t.getReturnType();
|
||||||
Type ret_s = desc_s.getReturnType();
|
Type ret_s = desc_s.getReturnType();
|
||||||
scanLambdaBody(tree, ret_t, ret_s);
|
if (ret_s.hasTag(VOID)) {
|
||||||
} else {
|
result &= true;
|
||||||
return;
|
} else if (ret_t.hasTag(VOID)) {
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
result &= false;
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//where
|
//where
|
||||||
|
|
||||||
void scanLambdaBody(JCLambda lambda, final Type t, final Type s) {
|
private List<JCExpression> lambdaResults(JCLambda lambda) {
|
||||||
if (lambda.getBodyKind() == JCTree.JCLambda.BodyKind.EXPRESSION) {
|
if (lambda.getBodyKind() == JCTree.JCLambda.BodyKind.EXPRESSION) {
|
||||||
result &= MostSpecificCheckContext.this.mostSpecific(t, s, lambda.body, warn);
|
return List.of((JCExpression) lambda.body);
|
||||||
} else {
|
} else {
|
||||||
|
final ListBuffer<JCExpression> buffer = new ListBuffer<>();
|
||||||
DeferredAttr.LambdaReturnScanner lambdaScanner =
|
DeferredAttr.LambdaReturnScanner lambdaScanner =
|
||||||
new DeferredAttr.LambdaReturnScanner() {
|
new DeferredAttr.LambdaReturnScanner() {
|
||||||
@Override
|
@Override
|
||||||
public void visitReturn(JCReturn tree) {
|
public void visitReturn(JCReturn tree) {
|
||||||
if (tree.expr != null) {
|
if (tree.expr != null) {
|
||||||
result &= MostSpecificCheckContext.this.mostSpecific(t, s, tree.expr, warn);
|
buffer.append(tree.expr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
lambdaScanner.scan(lambda.body);
|
lambdaScanner.scan(lambda.body);
|
||||||
|
return buffer.toList();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public MethodCheck mostSpecificCheck(List<Type> actuals, boolean strict) {
|
public MethodCheck mostSpecificCheck(List<Type> actuals, boolean strict) {
|
||||||
|
|
|
@ -643,6 +643,9 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
|
||||||
super.setPos(pos);
|
super.setPos(pos);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isPoly() { return false; }
|
||||||
|
public boolean isStandalone() { return true; }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -663,6 +666,9 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
|
||||||
|
|
||||||
/** is this poly expression a 'true' poly expression? */
|
/** is this poly expression a 'true' poly expression? */
|
||||||
public PolyKind polyKind;
|
public PolyKind polyKind;
|
||||||
|
|
||||||
|
@Override public boolean isPoly() { return polyKind == PolyKind.POLY; }
|
||||||
|
@Override public boolean isStandalone() { return polyKind == PolyKind.STANDALONE; }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
54
langtools/test/tools/javac/lambda/MostSpecific10.java
Normal file
54
langtools/test/tools/javac/lambda/MostSpecific10.java
Normal file
|
@ -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) ));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
42
langtools/test/tools/javac/lambda/MostSpecific11.java
Normal file
42
langtools/test/tools/javac/lambda/MostSpecific11.java
Normal file
|
@ -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(); });
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
38
langtools/test/tools/javac/lambda/MostSpecific12.java
Normal file
38
langtools/test/tools/javac/lambda/MostSpecific12.java
Normal file
|
@ -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) {}
|
||||||
|
|
||||||
|
}
|
4
langtools/test/tools/javac/lambda/MostSpecific12.out
Normal file
4
langtools/test/tools/javac/lambda/MostSpecific12.out
Normal file
|
@ -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
|
21
langtools/test/tools/javac/lambda/MostSpecific13.java
Normal file
21
langtools/test/tools/javac/lambda/MostSpecific13.java
Normal file
|
@ -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; }
|
||||||
|
}
|
3
langtools/test/tools/javac/lambda/MostSpecific13.out
Normal file
3
langtools/test/tools/javac/lambda/MostSpecific13.out
Normal file
|
@ -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
|
33
langtools/test/tools/javac/lambda/MostSpecific14.java
Normal file
33
langtools/test/tools/javac/lambda/MostSpecific14.java
Normal file
|
@ -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; }
|
||||||
|
}
|
3
langtools/test/tools/javac/lambda/MostSpecific14.out
Normal file
3
langtools/test/tools/javac/lambda/MostSpecific14.out
Normal file
|
@ -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
|
|
@ -1,9 +1,9 @@
|
||||||
/*
|
/*
|
||||||
* @test /nodynamiccopyright/
|
* @test /nodynamiccopyright/
|
||||||
* @bug 8003280
|
* @bug 8003280 8034223
|
||||||
* @summary Add lambda tests
|
* @summary Add lambda tests
|
||||||
* Check void-compatibility in strict vs. loose conversion contexts
|
* Check void-compatibility in strict vs. loose conversion contexts
|
||||||
* @compile/fail/ref=TargetType16.out -XDrawDiagnostics TargetType16.java
|
* @compile TargetType16.java
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class TargetType16 {
|
class TargetType16 {
|
||||||
|
@ -20,6 +20,6 @@ class TargetType16 {
|
||||||
static <T> void m(SAM2<T> s2) { }
|
static <T> void m(SAM2<T> s2) { }
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
m(() -> { throw new AssertionError(); }); //ambiguous
|
m(() -> { throw new AssertionError(); }); // prefer SAM2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
|
|
@ -31,7 +31,12 @@ class TargetType23 {
|
||||||
void call(Sam2 s) { }
|
void call(Sam2 s) { }
|
||||||
<Z> void call(Sam3<Z> s) { }
|
<Z> void call(Sam3<Z> s) { }
|
||||||
|
|
||||||
|
void call2(Sam0 s) { }
|
||||||
|
void call2(Sam2 s) { }
|
||||||
|
<Z> void call2(Sam3<Z> s) { }
|
||||||
|
|
||||||
void test() {
|
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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
1 error
|
||||||
|
|
|
@ -23,8 +23,8 @@
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @test
|
* @test
|
||||||
* @bug 7098660 8014649
|
* @bug 7098660 8014649 8034223
|
||||||
* @summary Write better overload resolution/inference tests
|
* @summary Test harness for overload resolution/inference tests
|
||||||
* @library /tools/javac/lib
|
* @library /tools/javac/lib
|
||||||
* @build JavacTestingAbstractProcessor ResolveHarness
|
* @build JavacTestingAbstractProcessor ResolveHarness
|
||||||
* @run main ResolveHarness
|
* @run main ResolveHarness
|
||||||
|
|
|
@ -23,44 +23,44 @@
|
||||||
|
|
||||||
@TraceResolve(keys={"compiler.err.ref.ambiguous"})
|
@TraceResolve(keys={"compiler.err.ref.ambiguous"})
|
||||||
class PrimitiveOverReferenceVarargsAmbiguous {
|
class PrimitiveOverReferenceVarargsAmbiguous {
|
||||||
@Candidate(applicable=Phase.VARARGS, mostSpecific=true)
|
@Candidate(applicable=Phase.VARARGS, mostSpecific=false)
|
||||||
static void m_byte(byte... b) {}
|
static void m_byte(byte... b) {}
|
||||||
@Candidate(applicable=Phase.VARARGS)
|
@Candidate(applicable=Phase.VARARGS, mostSpecific=false)
|
||||||
static void m_byte(Byte... b) {}
|
static void m_byte(Byte... b) {}
|
||||||
|
|
||||||
@Candidate(applicable=Phase.VARARGS, mostSpecific=true)
|
@Candidate(applicable=Phase.VARARGS, mostSpecific=false)
|
||||||
static void m_short(short... s) {}
|
static void m_short(short... s) {}
|
||||||
@Candidate(applicable=Phase.VARARGS)
|
@Candidate(applicable=Phase.VARARGS, mostSpecific=false)
|
||||||
static void m_short(Short... s) {}
|
static void m_short(Short... s) {}
|
||||||
|
|
||||||
@Candidate(applicable=Phase.VARARGS, mostSpecific=true)
|
@Candidate(applicable=Phase.VARARGS, mostSpecific=false)
|
||||||
static void m_int(int... i) {}
|
static void m_int(int... i) {}
|
||||||
@Candidate(applicable=Phase.VARARGS)
|
@Candidate(applicable=Phase.VARARGS, mostSpecific=false)
|
||||||
static void m_int(Integer... i) {}
|
static void m_int(Integer... i) {}
|
||||||
|
|
||||||
@Candidate(applicable=Phase.VARARGS, mostSpecific=true)
|
@Candidate(applicable=Phase.VARARGS, mostSpecific=false)
|
||||||
static void m_long(long... l) {}
|
static void m_long(long... l) {}
|
||||||
@Candidate(applicable=Phase.VARARGS)
|
@Candidate(applicable=Phase.VARARGS, mostSpecific=false)
|
||||||
static void m_long(Long... l) {}
|
static void m_long(Long... l) {}
|
||||||
|
|
||||||
@Candidate(applicable=Phase.VARARGS, mostSpecific=true)
|
@Candidate(applicable=Phase.VARARGS, mostSpecific=false)
|
||||||
static void m_float(float... f) {}
|
static void m_float(float... f) {}
|
||||||
@Candidate(applicable=Phase.VARARGS)
|
@Candidate(applicable=Phase.VARARGS, mostSpecific=false)
|
||||||
static void m_float(Float... f) {}
|
static void m_float(Float... f) {}
|
||||||
|
|
||||||
@Candidate(applicable=Phase.VARARGS, mostSpecific=true)
|
@Candidate(applicable=Phase.VARARGS, mostSpecific=false)
|
||||||
static void m_double(double... d) {}
|
static void m_double(double... d) {}
|
||||||
@Candidate(applicable=Phase.VARARGS)
|
@Candidate(applicable=Phase.VARARGS, mostSpecific=false)
|
||||||
static void m_double(Double... d) {}
|
static void m_double(Double... d) {}
|
||||||
|
|
||||||
@Candidate(applicable=Phase.VARARGS, mostSpecific=true)
|
@Candidate(applicable=Phase.VARARGS, mostSpecific=false)
|
||||||
static void m_char(char... c) {}
|
static void m_char(char... c) {}
|
||||||
@Candidate(applicable=Phase.VARARGS)
|
@Candidate(applicable=Phase.VARARGS, mostSpecific=false)
|
||||||
static void m_char(Character... c) {}
|
static void m_char(Character... c) {}
|
||||||
|
|
||||||
@Candidate(applicable=Phase.VARARGS, mostSpecific=true)
|
@Candidate(applicable=Phase.VARARGS, mostSpecific=false)
|
||||||
static void m_bool(boolean... z) {}
|
static void m_bool(boolean... z) {}
|
||||||
@Candidate(applicable=Phase.VARARGS)
|
@Candidate(applicable=Phase.VARARGS, mostSpecific=false)
|
||||||
static void m_bool(Boolean... z) {}
|
static void m_bool(Boolean... z) {}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue