diff --git a/compiler/fir/analysis-tests/testData/resolve/rawTypeSam.kt b/compiler/fir/analysis-tests/testData/resolve/rawTypeSam.kt new file mode 100644 index 00000000000..9b38b48514e --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolve/rawTypeSam.kt @@ -0,0 +1,17 @@ +// FILE: main.kt + +fun foo() { + RawType.bar { + it.length > 0 + } +} + +// FILE: Processor.java +public interface Processor { + boolean process(T t); +} + +// FILE: RawType.java +public class RawType { + public static void bar(Processor x) {} +} diff --git a/compiler/fir/analysis-tests/testData/resolve/rawTypeSam.txt b/compiler/fir/analysis-tests/testData/resolve/rawTypeSam.txt new file mode 100644 index 00000000000..e06e80d4aa7 --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolve/rawTypeSam.txt @@ -0,0 +1,7 @@ +FILE: main.kt + public final fun foo(): R|kotlin/Unit| { + Q|RawType|.R|/RawType.bar|( = bar@fun (it: R|ft!|): R|kotlin/Boolean| { + ^ CMP(>, R|/it|.R|kotlin/CharSequence.length|.R|kotlin/Int.compareTo|(Int(0))) + } + ) + } diff --git a/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsTestGenerated.java b/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsTestGenerated.java index 9d05e59ab2c..004f7721ef6 100644 --- a/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsTestGenerated.java +++ b/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsTestGenerated.java @@ -358,6 +358,11 @@ public class FirDiagnosticsTestGenerated extends AbstractFirDiagnosticsTest { runTest("compiler/fir/analysis-tests/testData/resolve/qualifierWithCompanion.kt"); } + @TestMetadata("rawTypeSam.kt") + public void testRawTypeSam() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/rawTypeSam.kt"); + } + @TestMetadata("recursiveCallOnWhenWithSealedClass.kt") public void testRecursiveCallOnWhenWithSealedClass() throws Exception { runTest("compiler/fir/analysis-tests/testData/resolve/recursiveCallOnWhenWithSealedClass.kt"); diff --git a/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsWithLightTreeTestGenerated.java b/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsWithLightTreeTestGenerated.java index 3d06916a9db..9bee8dba59b 100644 --- a/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsWithLightTreeTestGenerated.java +++ b/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsWithLightTreeTestGenerated.java @@ -358,6 +358,11 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos runTest("compiler/fir/analysis-tests/testData/resolve/qualifierWithCompanion.kt"); } + @TestMetadata("rawTypeSam.kt") + public void testRawTypeSam() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/rawTypeSam.kt"); + } + @TestMetadata("recursiveCallOnWhenWithSealedClass.kt") public void testRecursiveCallOnWhenWithSealedClass() throws Exception { runTest("compiler/fir/analysis-tests/testData/resolve/recursiveCallOnWhenWithSealedClass.kt"); diff --git a/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/LazyBodyIsNotTouchedTilContractsPhaseTestGenerated.java b/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/LazyBodyIsNotTouchedTilContractsPhaseTestGenerated.java index 06a47258dd3..88e959d957b 100644 --- a/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/LazyBodyIsNotTouchedTilContractsPhaseTestGenerated.java +++ b/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/LazyBodyIsNotTouchedTilContractsPhaseTestGenerated.java @@ -358,6 +358,11 @@ public class LazyBodyIsNotTouchedTilContractsPhaseTestGenerated extends Abstract runTest("compiler/fir/analysis-tests/testData/resolve/qualifierWithCompanion.kt"); } + @TestMetadata("rawTypeSam.kt") + public void testRawTypeSam() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/rawTypeSam.kt"); + } + @TestMetadata("recursiveCallOnWhenWithSealedClass.kt") public void testRecursiveCallOnWhenWithSealedClass() throws Exception { runTest("compiler/fir/analysis-tests/testData/resolve/recursiveCallOnWhenWithSealedClass.kt"); diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/SamResolution.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/SamResolution.kt index 0d844106096..d616f0cb1b6 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/SamResolution.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/SamResolution.kt @@ -77,17 +77,26 @@ class FirSamResolverImpl( ?: return null val unsubstitutedFunctionType = resolveFunctionTypeIfSamInterface(firRegularClass) ?: return null + + if (firRegularClass.typeParameters.isEmpty()) { + return unsubstitutedFunctionType.withNullability(ConeNullability.create(type.isMarkedNullable), firSession.typeContext) + } + val substitutor = substitutorByMap( firRegularClass.typeParameters .map { it.symbol } .zip( - type.typeArguments.map { - (it as? ConeKotlinTypeProjection)?.type + type.typeArguments, + ).map { (parameterSymbol, projection) -> + val typeArgument = + (projection as? ConeKotlinTypeProjection)?.type + // TODO: Consider using `parameterSymbol.fir.bounds.first().coneType` once sure that it won't fail with exception + ?: parameterSymbol.fir.bounds.firstOrNull()?.coneTypeSafe() ?: firSession.builtinTypes.nullableAnyType.type - //ConeClassLikeTypeImpl(ConeClassLikeLookupTagImpl(StandardClassIds.Any), emptyArray(), isNullable = true) - }, - ) + + Pair(parameterSymbol, typeArgument) + } .toMap(), ) @@ -147,7 +156,7 @@ class FirSamResolverImpl( for ((newTypeParameter, oldTypeParameter) in newTypeParameters.zip(firRegularClass.typeParameters)) { val declared = oldTypeParameter.symbol.fir // TODO: or really declared? - newTypeParameter.bounds += declared.bounds.mapNotNull { typeRef -> + newTypeParameter.bounds += declared.bounds.map { typeRef -> buildResolvedTypeRef { source = typeRef.source type = substitutor.substituteOrSelf(typeRef.coneType) @@ -204,14 +213,14 @@ class FirSamResolverImpl( } } - private fun resolveFunctionTypeIfSamInterface(firRegularClass: FirRegularClass): ConeKotlinType? { + private fun resolveFunctionTypeIfSamInterface(firRegularClass: FirRegularClass): ConeLookupTagBasedType? { return resolvedFunctionType.getOrPut(firRegularClass) { if (!firRegularClass.status.isFun) return@getOrPut NULL_STUB val abstractMethod = firRegularClass.getSingleAbstractMethodOrNull(firSession, scopeSession) ?: return@getOrPut NULL_STUB // TODO: val shouldConvertFirstParameterToDescriptor = samWithReceiverResolvers.any { it.shouldConvertFirstSamParameterToReceiver(abstractMethod) } abstractMethod.getFunctionTypeForAbstractMethod() - } as? ConeKotlinType + } as? ConeLookupTagBasedType } override fun shouldRunSamConversionForFunction(firFunction: FirFunction<*>): Boolean { diff --git a/compiler/testData/diagnostics/tests/j+k/samByProjectedType/starProjectionComplexUpperBound.fir.kt b/compiler/testData/diagnostics/tests/j+k/samByProjectedType/starProjectionComplexUpperBound.fir.kt deleted file mode 100644 index 648e6875297..00000000000 --- a/compiler/testData/diagnostics/tests/j+k/samByProjectedType/starProjectionComplexUpperBound.fir.kt +++ /dev/null @@ -1,33 +0,0 @@ -// !CHECK_TYPE -// FILE: Function.java -public interface Function, F extends CharSequence> { - F handle(E e); -} - -// FILE: A.java -public class A { - public void foo(Function l) { - } - - public static void bar(Function l) { - } -} - -// FILE: main.kt -fun main() { - A().foo { - x -> - x checkType { _?>() } - "" - } - - A.bar { - x -> - x checkType { _>() } - "" - } - - val block: (Map) -> CharSequence = { x -> x.toString() } - A().foo(block) - A.bar(block) -} diff --git a/compiler/testData/diagnostics/tests/j+k/samByProjectedType/starProjectionComplexUpperBound.kt b/compiler/testData/diagnostics/tests/j+k/samByProjectedType/starProjectionComplexUpperBound.kt index efd82efc5b7..2c235efb746 100644 --- a/compiler/testData/diagnostics/tests/j+k/samByProjectedType/starProjectionComplexUpperBound.kt +++ b/compiler/testData/diagnostics/tests/j+k/samByProjectedType/starProjectionComplexUpperBound.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // !CHECK_TYPE // FILE: Function.java public interface Function, F extends CharSequence> { diff --git a/compiler/testData/ir/irText/expressions/sam/samByProjectedType.fir.txt b/compiler/testData/ir/irText/expressions/sam/samByProjectedType.fir.txt index b60ea9db1a7..c6a4b9d1f5d 100644 --- a/compiler/testData/ir/irText/expressions/sam/samByProjectedType.fir.txt +++ b/compiler/testData/ir/irText/expressions/sam/samByProjectedType.fir.txt @@ -1,10 +1,11 @@ FILE fqName: fileName:/samByProjectedType.kt FUN name:test1 visibility:public modality:FINAL <> () returnType:kotlin.Unit BLOCK_BODY - ERROR_CALL 'Unresolved reference: #' type=kotlin.Unit - FUN_EXPR type=kotlin.Function1 origin=LAMBDA - FUN LOCAL_FUNCTION_FOR_LAMBDA name: visibility:local modality:FINAL <> (x:kotlin.Any) returnType:kotlin.Any? - VALUE_PARAMETER name:x index:0 type:kotlin.Any - BLOCK_BODY - RETURN type=kotlin.Nothing from='local final fun (x: kotlin.Any): kotlin.Any? declared in .test1' - GET_VAR 'x: kotlin.Any declared in .test1.' type=kotlin.Any origin=null + CALL 'public open fun bar (j: .J<*>?): kotlin.Unit declared in .H' type=kotlin.Unit origin=null + j: TYPE_OP type=.J<*>? origin=SAM_CONVERSION typeOperand=.J<*>? + FUN_EXPR type=kotlin.Function1 origin=LAMBDA + FUN LOCAL_FUNCTION_FOR_LAMBDA name: visibility:local modality:FINAL <> (x:kotlin.Any) returnType:kotlin.Any? + VALUE_PARAMETER name:x index:0 type:kotlin.Any + BLOCK_BODY + RETURN type=kotlin.Nothing from='local final fun (x: kotlin.Any): kotlin.Any? declared in .test1' + GET_VAR 'x: kotlin.Any declared in .test1.' type=kotlin.Any origin=null