Fix SAM conversions for derived classes
#KT-39535 Fixed #KT-37149 Fixed
This commit is contained in:
+10
@@ -13661,6 +13661,16 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirOldFronte
|
||||
runTest("compiler/testData/diagnostics/tests/j+k/sam/compatibilityResolveToOuterScopeForKotlinFunctions.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("conversionForDerivedGenericClass.kt")
|
||||
public void testConversionForDerivedGenericClass() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/j+k/sam/conversionForDerivedGenericClass.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("conversionsWithNestedGenerics.kt")
|
||||
public void testConversionsWithNestedGenerics() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/j+k/sam/conversionsWithNestedGenerics.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("enhancedSamConstructor.kt")
|
||||
public void testEnhancedSamConstructor() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/j+k/sam/enhancedSamConstructor.kt");
|
||||
|
||||
+12
-9
@@ -64,19 +64,22 @@ object SamTypeConversions : ParameterTypeConversion {
|
||||
val callComponents = candidate.callComponents
|
||||
val originalExpectedType = argument.getExpectedType(parameter.original, callComponents.languageVersionSettings)
|
||||
|
||||
val convertedTypeByOriginal =
|
||||
callComponents.samConversionResolver.getFunctionTypeForPossibleSamType(
|
||||
originalExpectedType,
|
||||
callComponents.samConversionOracle
|
||||
) ?: return null
|
||||
|
||||
val convertedTypeByCandidate =
|
||||
callComponents.samConversionResolver.getFunctionTypeForPossibleSamType(
|
||||
expectedParameterType,
|
||||
callComponents.samConversionOracle
|
||||
)
|
||||
) ?: return null
|
||||
|
||||
assert(expectedParameterType.constructor == originalExpectedType.constructor && convertedTypeByCandidate != null) {
|
||||
val convertedTypeByOriginal =
|
||||
if (expectedParameterType.constructor == originalExpectedType.constructor)
|
||||
callComponents.samConversionResolver.getFunctionTypeForPossibleSamType(
|
||||
originalExpectedType,
|
||||
callComponents.samConversionOracle
|
||||
)
|
||||
else
|
||||
convertedTypeByCandidate
|
||||
|
||||
assert(convertedTypeByCandidate.constructor == convertedTypeByOriginal?.constructor) {
|
||||
"If original type is SAM type, then candidate should have same type constructor and corresponding function type\n" +
|
||||
"originalExpectType: $originalExpectedType, candidateExpectType: $expectedParameterType\n" +
|
||||
"functionTypeByOriginal: $convertedTypeByOriginal, functionTypeByCandidate: $convertedTypeByCandidate"
|
||||
@@ -84,7 +87,7 @@ object SamTypeConversions : ParameterTypeConversion {
|
||||
|
||||
candidate.resolvedCall.registerArgumentWithSamConversion(
|
||||
argument,
|
||||
SamConversionDescription(convertedTypeByOriginal, convertedTypeByCandidate!!)
|
||||
SamConversionDescription(convertedTypeByOriginal!!, convertedTypeByCandidate)
|
||||
)
|
||||
|
||||
if (needCompatibilityResolveForSAM(candidate, expectedParameterType)) {
|
||||
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
// FILE: A.java
|
||||
public interface A<T> {
|
||||
void f(T arg);
|
||||
}
|
||||
|
||||
// FILE: B.java
|
||||
public interface B extends A<Runnable> {}
|
||||
|
||||
// FILE: C.java
|
||||
public class C<K> {
|
||||
public void f(K k) {}
|
||||
public static <R> void g(R r) {}
|
||||
}
|
||||
|
||||
// FILE: test.kt
|
||||
fun test(a: A<Runnable>, b: B, c: C<Runnable>) {
|
||||
a.f { }
|
||||
b.f { }
|
||||
c.f { }
|
||||
C<Runnable>().f { }
|
||||
C.g<Runnable> { }
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
// FILE: A.java
|
||||
public interface A<T> {
|
||||
void f(T arg);
|
||||
}
|
||||
|
||||
// FILE: B.java
|
||||
public interface B extends A<Runnable> {}
|
||||
|
||||
// FILE: C.java
|
||||
public class C<K> {
|
||||
public void f(K k) {}
|
||||
public static <R> void g(R r) {}
|
||||
}
|
||||
|
||||
// FILE: test.kt
|
||||
fun test(a: A<Runnable>, b: B, c: C<Runnable>) {
|
||||
a.f { }
|
||||
b.f { }
|
||||
c.f { }
|
||||
C<Runnable>().f { }
|
||||
C.g<Runnable> <!TYPE_MISMATCH, TYPE_MISMATCH!>{ }<!>
|
||||
}
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
package
|
||||
|
||||
public fun test(/*0*/ a: A<java.lang.Runnable>, /*1*/ b: B, /*2*/ c: C<java.lang.Runnable>): kotlin.Unit
|
||||
|
||||
public interface A</*0*/ T : kotlin.Any!> {
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public abstract fun f(/*0*/ arg: T!): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public interface B : A<java.lang.Runnable!> {
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public abstract override /*1*/ /*fake_override*/ fun f(/*0*/ arg: java.lang.Runnable!): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public open class C</*0*/ K : kotlin.Any!> {
|
||||
public constructor C</*0*/ K : kotlin.Any!>()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open fun f(/*0*/ k: K!): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
|
||||
// Static members
|
||||
public open fun </*0*/ R : kotlin.Any!> g(/*0*/ r: R!): kotlin.Unit
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
// FIR_IDENTICAL
|
||||
|
||||
// FILE: Listener.java
|
||||
public interface Listener<T> {
|
||||
void on(T self);
|
||||
}
|
||||
|
||||
// FILE: Base.java
|
||||
public class Base<S, T extends Listener<S>> {
|
||||
public void addListener(T listener) {}
|
||||
}
|
||||
|
||||
// FILE: Derived.java
|
||||
public class Derived extends Base<Derived, Listener<Derived>> {}
|
||||
|
||||
// FILE: test.kt
|
||||
|
||||
fun test(w: Derived) {
|
||||
w.addListener { _ -> call() }
|
||||
}
|
||||
|
||||
fun call() {}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
package
|
||||
|
||||
public fun call(): kotlin.Unit
|
||||
public fun test(/*0*/ w: Derived): kotlin.Unit
|
||||
|
||||
public open class Base</*0*/ S : kotlin.Any!, /*1*/ T : Listener<S!>!> {
|
||||
public constructor Base</*0*/ S : kotlin.Any!, /*1*/ T : Listener<S!>!>()
|
||||
public open fun addListener(/*0*/ listener: T!): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public open class Derived : Base<Derived!, Listener<Derived!>!> {
|
||||
public constructor Derived()
|
||||
public open override /*1*/ /*fake_override*/ fun addListener(/*0*/ listener: Listener<Derived!>!): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public interface Listener</*0*/ T : kotlin.Any!> {
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public abstract fun on(/*0*/ self: T!): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
-18
@@ -1,18 +0,0 @@
|
||||
// !LANGUAGE: +NewInference
|
||||
// FILE: J.java
|
||||
public interface J<T> {
|
||||
public void foo(T r1, T r2);
|
||||
}
|
||||
|
||||
// FILE: Runnable.java
|
||||
public interface Runnable {
|
||||
void run();
|
||||
}
|
||||
|
||||
// FILE: 1.kt
|
||||
fun test(j: J<Runnable>, r: Runnable) {
|
||||
j.foo(r, r)
|
||||
j.foo(r, {})
|
||||
j.foo({}, r)
|
||||
j.foo({}, {})
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
// !LANGUAGE: +NewInference
|
||||
// FILE: J.java
|
||||
public interface J<T> {
|
||||
@@ -12,7 +13,7 @@ public interface Runnable {
|
||||
// FILE: 1.kt
|
||||
fun test(j: J<Runnable>, r: Runnable) {
|
||||
j.foo(r, r)
|
||||
j.foo(r, <!TYPE_MISMATCH!>{}<!>)
|
||||
j.foo(<!TYPE_MISMATCH!>{}<!>, r)
|
||||
j.foo(<!TYPE_MISMATCH!>{}<!>, <!TYPE_MISMATCH!>{}<!>)
|
||||
j.foo(r, {})
|
||||
j.foo({}, r)
|
||||
j.foo({}, {})
|
||||
}
|
||||
-17
@@ -1,17 +0,0 @@
|
||||
// !LANGUAGE: +NewInference +SamConversionForKotlinFunctions
|
||||
// FILE: Runnable.java
|
||||
public interface Runnable {
|
||||
void run();
|
||||
}
|
||||
|
||||
// FILE: 1.kt
|
||||
interface K<T> {
|
||||
fun foo(t1: T, t2: T)
|
||||
}
|
||||
|
||||
fun test(k: K<Runnable>, r: Runnable) {
|
||||
k.foo(r, r)
|
||||
k.foo(r, {})
|
||||
k.foo({}, r)
|
||||
k.foo({}, {})
|
||||
}
|
||||
+4
-3
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
// !LANGUAGE: +NewInference +SamConversionForKotlinFunctions
|
||||
// FILE: Runnable.java
|
||||
public interface Runnable {
|
||||
@@ -11,7 +12,7 @@ interface K<T> {
|
||||
|
||||
fun test(k: K<Runnable>, r: Runnable) {
|
||||
k.foo(r, r)
|
||||
k.foo(r, <!TYPE_MISMATCH!>{}<!>)
|
||||
k.foo(<!TYPE_MISMATCH!>{}<!>, r)
|
||||
k.foo(<!TYPE_MISMATCH!>{}<!>, <!TYPE_MISMATCH!>{}<!>)
|
||||
k.foo(r, {})
|
||||
k.foo({}, r)
|
||||
k.foo({}, {})
|
||||
}
|
||||
@@ -13668,6 +13668,16 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTestWithFirVali
|
||||
runTest("compiler/testData/diagnostics/tests/j+k/sam/compatibilityResolveToOuterScopeForKotlinFunctions.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("conversionForDerivedGenericClass.kt")
|
||||
public void testConversionForDerivedGenericClass() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/j+k/sam/conversionForDerivedGenericClass.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("conversionsWithNestedGenerics.kt")
|
||||
public void testConversionsWithNestedGenerics() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/j+k/sam/conversionsWithNestedGenerics.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("enhancedSamConstructor.kt")
|
||||
public void testEnhancedSamConstructor() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/j+k/sam/enhancedSamConstructor.kt");
|
||||
|
||||
Generated
+10
@@ -13663,6 +13663,16 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing
|
||||
runTest("compiler/testData/diagnostics/tests/j+k/sam/compatibilityResolveToOuterScopeForKotlinFunctions.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("conversionForDerivedGenericClass.kt")
|
||||
public void testConversionForDerivedGenericClass() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/j+k/sam/conversionForDerivedGenericClass.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("conversionsWithNestedGenerics.kt")
|
||||
public void testConversionsWithNestedGenerics() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/j+k/sam/conversionsWithNestedGenerics.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("enhancedSamConstructor.kt")
|
||||
public void testEnhancedSamConstructor() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/j+k/sam/enhancedSamConstructor.kt");
|
||||
|
||||
Reference in New Issue
Block a user