diff --git a/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirOldFrontendDiagnosticsTestGenerated.java b/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirOldFrontendDiagnosticsTestGenerated.java index 78afcf54b85..835a2ed1462 100644 --- a/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirOldFrontendDiagnosticsTestGenerated.java +++ b/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirOldFrontendDiagnosticsTestGenerated.java @@ -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"); diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/SamTypeConversions.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/SamTypeConversions.kt index 878a8b6deca..1615b5ba61b 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/SamTypeConversions.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/SamTypeConversions.kt @@ -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)) { diff --git a/compiler/testData/diagnostics/tests/j+k/sam/conversionForDerivedGenericClass.fir.kt b/compiler/testData/diagnostics/tests/j+k/sam/conversionForDerivedGenericClass.fir.kt new file mode 100644 index 00000000000..38f84a1dd39 --- /dev/null +++ b/compiler/testData/diagnostics/tests/j+k/sam/conversionForDerivedGenericClass.fir.kt @@ -0,0 +1,22 @@ +// FILE: A.java +public interface A { + void f(T arg); +} + +// FILE: B.java +public interface B extends A {} + +// FILE: C.java +public class C { + public void f(K k) {} + public static void g(R r) {} +} + +// FILE: test.kt +fun test(a: A, b: B, c: C) { + a.f { } + b.f { } + c.f { } + C().f { } + C.g { } +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/j+k/sam/conversionForDerivedGenericClass.kt b/compiler/testData/diagnostics/tests/j+k/sam/conversionForDerivedGenericClass.kt new file mode 100644 index 00000000000..a78d74bb7cd --- /dev/null +++ b/compiler/testData/diagnostics/tests/j+k/sam/conversionForDerivedGenericClass.kt @@ -0,0 +1,22 @@ +// FILE: A.java +public interface A { + void f(T arg); +} + +// FILE: B.java +public interface B extends A {} + +// FILE: C.java +public class C { + public void f(K k) {} + public static void g(R r) {} +} + +// FILE: test.kt +fun test(a: A, b: B, c: C) { + a.f { } + b.f { } + c.f { } + C().f { } + C.g { } +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/j+k/sam/conversionForDerivedGenericClass.txt b/compiler/testData/diagnostics/tests/j+k/sam/conversionForDerivedGenericClass.txt new file mode 100644 index 00000000000..c714ca5e196 --- /dev/null +++ b/compiler/testData/diagnostics/tests/j+k/sam/conversionForDerivedGenericClass.txt @@ -0,0 +1,28 @@ +package + +public fun test(/*0*/ a: A, /*1*/ b: B, /*2*/ c: C): kotlin.Unit + +public interface A { + 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 { + 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 { + public constructor C() + 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 g(/*0*/ r: R!): kotlin.Unit +} diff --git a/compiler/testData/diagnostics/tests/j+k/sam/conversionsWithNestedGenerics.kt b/compiler/testData/diagnostics/tests/j+k/sam/conversionsWithNestedGenerics.kt new file mode 100644 index 00000000000..9a3e60f721d --- /dev/null +++ b/compiler/testData/diagnostics/tests/j+k/sam/conversionsWithNestedGenerics.kt @@ -0,0 +1,22 @@ +// FIR_IDENTICAL + +// FILE: Listener.java +public interface Listener { + void on(T self); +} + +// FILE: Base.java +public class Base> { + public void addListener(T listener) {} +} + +// FILE: Derived.java +public class Derived extends Base> {} + +// FILE: test.kt + +fun test(w: Derived) { + w.addListener { _ -> call() } +} + +fun call() {} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/j+k/sam/conversionsWithNestedGenerics.txt b/compiler/testData/diagnostics/tests/j+k/sam/conversionsWithNestedGenerics.txt new file mode 100644 index 00000000000..e59c1b1a8b2 --- /dev/null +++ b/compiler/testData/diagnostics/tests/j+k/sam/conversionsWithNestedGenerics.txt @@ -0,0 +1,27 @@ +package + +public fun call(): kotlin.Unit +public fun test(/*0*/ w: Derived): kotlin.Unit + +public open class Base!> { + public constructor Base!>() + 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!> { + public constructor Derived() + public open override /*1*/ /*fake_override*/ fun addListener(/*0*/ listener: Listener!): 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 { + 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 +} diff --git a/compiler/testData/diagnostics/tests/samConversions/SAMAfterSubstitution.fir.kt b/compiler/testData/diagnostics/tests/samConversions/SAMAfterSubstitution.fir.kt deleted file mode 100644 index 9b2b73d56c3..00000000000 --- a/compiler/testData/diagnostics/tests/samConversions/SAMAfterSubstitution.fir.kt +++ /dev/null @@ -1,18 +0,0 @@ -// !LANGUAGE: +NewInference -// FILE: J.java -public interface J { - public void foo(T r1, T r2); -} - -// FILE: Runnable.java -public interface Runnable { - void run(); -} - -// FILE: 1.kt -fun test(j: J, r: Runnable) { - j.foo(r, r) - j.foo(r, {}) - j.foo({}, r) - j.foo({}, {}) -} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/samConversions/SAMAfterSubstitution.kt b/compiler/testData/diagnostics/tests/samConversions/SAMAfterSubstitution.kt index f27dc31f887..cb134631770 100644 --- a/compiler/testData/diagnostics/tests/samConversions/SAMAfterSubstitution.kt +++ b/compiler/testData/diagnostics/tests/samConversions/SAMAfterSubstitution.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // !LANGUAGE: +NewInference // FILE: J.java public interface J { @@ -12,7 +13,7 @@ public interface Runnable { // FILE: 1.kt fun test(j: J, r: Runnable) { j.foo(r, r) - j.foo(r, {}) - j.foo({}, r) - j.foo({}, {}) + j.foo(r, {}) + j.foo({}, r) + j.foo({}, {}) } \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/samConversions/SAMAfterSubstitutionKT.fir.kt b/compiler/testData/diagnostics/tests/samConversions/SAMAfterSubstitutionKT.fir.kt deleted file mode 100644 index b50318d674c..00000000000 --- a/compiler/testData/diagnostics/tests/samConversions/SAMAfterSubstitutionKT.fir.kt +++ /dev/null @@ -1,17 +0,0 @@ -// !LANGUAGE: +NewInference +SamConversionForKotlinFunctions -// FILE: Runnable.java -public interface Runnable { - void run(); -} - -// FILE: 1.kt -interface K { - fun foo(t1: T, t2: T) -} - -fun test(k: K, r: Runnable) { - k.foo(r, r) - k.foo(r, {}) - k.foo({}, r) - k.foo({}, {}) -} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/samConversions/SAMAfterSubstitutionKT.kt b/compiler/testData/diagnostics/tests/samConversions/SAMAfterSubstitutionKT.kt index ba2a0ed973f..cdc6cdba79e 100644 --- a/compiler/testData/diagnostics/tests/samConversions/SAMAfterSubstitutionKT.kt +++ b/compiler/testData/diagnostics/tests/samConversions/SAMAfterSubstitutionKT.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // !LANGUAGE: +NewInference +SamConversionForKotlinFunctions // FILE: Runnable.java public interface Runnable { @@ -11,7 +12,7 @@ interface K { fun test(k: K, r: Runnable) { k.foo(r, r) - k.foo(r, {}) - k.foo({}, r) - k.foo({}, {}) + k.foo(r, {}) + k.foo({}, r) + k.foo({}, {}) } \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index 81a5d70080b..0f502ee8249 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -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"); diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java index 0312e6c83e2..1c939580602 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java @@ -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");