From 2bdbed978ba36c0d536210f7bdc8bf7b701ea133 Mon Sep 17 00:00:00 2001 From: Denis Zharkov Date: Tue, 17 Sep 2019 13:05:01 +0700 Subject: [PATCH] FIR: Support SAM constructors --- .../kotlin/fir/resolve/SamResolution.kt | 93 ++++++++++++++++++- .../kotlin/fir/resolve/calls/CallKind.kt | 3 +- .../kotlin/fir/resolve/calls/TowerLevels.kt | 32 ++++++- .../diagnostics/samConstructors/genericSam.kt | 20 ++++ .../samConstructors/genericSam.txt | 15 +++ .../genericSamInferenceFromExpectType.kt | 38 ++++++++ .../genericSamInferenceFromExpectType.txt | 29 ++++++ .../diagnostics/samConstructors/kotlinSam.kt | 18 ++++ .../diagnostics/samConstructors/kotlinSam.txt | 22 +++++ .../realConstructorFunction.kt | 22 +++++ .../realConstructorFunction.txt | 21 +++++ .../diagnostics/samConstructors/runnable.kt | 5 + .../diagnostics/samConstructors/runnable.txt | 9 ++ .../diagnostics/samConstructors/simple.kt | 20 ++++ .../diagnostics/samConstructors/simple.txt | 18 ++++ .../fir/FirDiagnosticsTestGenerated.java | 43 +++++++++ .../expressions/sam/samConstructors.fir.txt | 26 +++--- .../sam/samConversionToGeneric.fir.txt | 42 ++++----- .../ir/irText/lambdas/samAdapter.fir.txt | 15 +-- 19 files changed, 443 insertions(+), 48 deletions(-) create mode 100644 compiler/fir/resolve/testData/diagnostics/samConstructors/genericSam.kt create mode 100644 compiler/fir/resolve/testData/diagnostics/samConstructors/genericSam.txt create mode 100644 compiler/fir/resolve/testData/diagnostics/samConstructors/genericSamInferenceFromExpectType.kt create mode 100644 compiler/fir/resolve/testData/diagnostics/samConstructors/genericSamInferenceFromExpectType.txt create mode 100644 compiler/fir/resolve/testData/diagnostics/samConstructors/kotlinSam.kt create mode 100644 compiler/fir/resolve/testData/diagnostics/samConstructors/kotlinSam.txt create mode 100644 compiler/fir/resolve/testData/diagnostics/samConstructors/realConstructorFunction.kt create mode 100644 compiler/fir/resolve/testData/diagnostics/samConstructors/realConstructorFunction.txt create mode 100644 compiler/fir/resolve/testData/diagnostics/samConstructors/runnable.kt create mode 100644 compiler/fir/resolve/testData/diagnostics/samConstructors/runnable.txt create mode 100644 compiler/fir/resolve/testData/diagnostics/samConstructors/simple.kt create mode 100644 compiler/fir/resolve/testData/diagnostics/samConstructors/simple.txt 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 abb472c22ac..325e30b074f 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 @@ -10,18 +10,29 @@ import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.FirSessionComponent import org.jetbrains.kotlin.fir.declarations.* +import org.jetbrains.kotlin.fir.declarations.impl.FirMemberFunctionImpl +import org.jetbrains.kotlin.fir.declarations.impl.FirTypeParameterImpl +import org.jetbrains.kotlin.fir.declarations.impl.FirValueParameterImpl +import org.jetbrains.kotlin.fir.resolve.calls.FirSyntheticFunctionSymbol +import org.jetbrains.kotlin.fir.resolve.calls.SAM_PARAMETER_NAME import org.jetbrains.kotlin.fir.resolve.substitution.substitutorByMap import org.jetbrains.kotlin.fir.scopes.ProcessorAction +import org.jetbrains.kotlin.fir.symbols.CallableId import org.jetbrains.kotlin.fir.symbols.StandardClassIds import org.jetbrains.kotlin.fir.symbols.impl.ConeClassLikeLookupTagImpl import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol +import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.fir.types.impl.ConeClassTypeImpl +import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl +import org.jetbrains.kotlin.fir.types.impl.FirResolvedTypeRefImpl import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.types.Variance interface FirSamResolver : FirSessionComponent { fun getFunctionTypeForPossibleSamType(type: ConeKotlinType): ConeKotlinType? fun shouldRunSamConversionForFunction(firNamedFunction: FirNamedFunction): Boolean + fun getSamConstructor(firRegularClass: FirRegularClass): FirNamedFunction? } private val NULL_STUB = Any() @@ -31,7 +42,8 @@ class FirSamResolverImpl( private val scopeSession: ScopeSession ) : FirSamResolver { - private val cache: MutableMap = mutableMapOf() + private val resolvedFunctionType: MutableMap = mutableMapOf() + private val samConstructor: MutableMap = mutableMapOf() override fun getFunctionTypeForPossibleSamType(type: ConeKotlinType): ConeKotlinType? { return when (type) { @@ -80,8 +92,85 @@ class FirSamResolverImpl( return result } + override fun getSamConstructor(firRegularClass: FirRegularClass): FirNamedFunction? { + return samConstructor.getOrPut(firRegularClass) { + buildSamConstructor(firRegularClass) ?: return@getOrPut NULL_STUB + } as? FirNamedFunction + } + + private fun buildSamConstructor(firRegularClass: FirRegularClass): FirNamedFunction? { + val functionType = resolveFunctionTypeIfSamInterface(firRegularClass) ?: return null + + val classId = firRegularClass.classId + val symbol = FirSyntheticFunctionSymbol( + CallableId( + classId.packageFqName, + classId.relativeClassName.parent().takeIf { !it.isRoot }, + classId.shortClassName + ) + ) + + val newTypeParameters = firRegularClass.typeParameters.map { typeParameter -> + FirTypeParameterImpl( + firSession, typeParameter.psi, FirTypeParameterSymbol(), typeParameter.name, Variance.INVARIANT, + isReified = false + ).apply { + annotations += typeParameter.annotations + } + } + + val newTypeParameterTypes = + newTypeParameters + .map { ConeTypeParameterTypeImpl(it.symbol.toLookupTag(), isNullable = false) } + + val substitutor = substitutorByMap( + firRegularClass.typeParameters + .map { it.symbol } + .zip(newTypeParameterTypes).toMap() + ) + + for ((newTypeParameter, oldTypeParameter) in newTypeParameters.zip(firRegularClass.typeParameters)) { + newTypeParameter.bounds += oldTypeParameter.bounds.mapNotNull { typeRef -> + FirResolvedTypeRefImpl(typeRef.psi, substitutor.substituteOrSelf(typeRef.coneTypeSafe() ?: return@mapNotNull null)) + } + } + + val substitutedFunctionType = substitutor.substituteOrSelf(functionType) + val substitutedReturnType = + ConeClassTypeImpl( + firRegularClass.symbol.toLookupTag(), newTypeParameterTypes.toTypedArray(), isNullable = false + ) + + return FirMemberFunctionImpl( + firSession, null, symbol, classId.shortClassName, + firRegularClass.visibility, Modality.FINAL, + isExpect = firRegularClass.isExpect, + isActual = firRegularClass.isActual, + isOverride = false, + isOperator = false, + isInfix = false, + isExternal = false, + isInline = false, + isSuspend = false, + isTailRec = false, + receiverTypeRef = null, + returnTypeRef = FirResolvedTypeRefImpl(null, substitutedReturnType) + ).apply { + valueParameters += listOf( + FirValueParameterImpl( + session, psi, SAM_PARAMETER_NAME, + FirResolvedTypeRefImpl(firRegularClass.psi, substitutedFunctionType), + defaultValue = null, + isCrossinline = false, isNoinline = false, isVararg = false + ) + ) + typeParameters += newTypeParameters + resolvePhase = FirResolvePhase.BODY_RESOLVE + } + } + private fun resolveFunctionTypeIfSamInterface(firRegularClass: FirRegularClass): ConeKotlinType? { - return cache.getOrPut(firRegularClass) { + return resolvedFunctionType.getOrPut(firRegularClass) { val abstractMethod = firRegularClass.getSingleAbstractMethodOrNull(firSession, scopeSession) ?: return@getOrPut NULL_STUB // TODO: val shouldConvertFirstParameterToDescriptor = samWithReceiverResolvers.any { it.shouldConvertFirstSamParameterToReceiver(abstractMethod) } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/CallKind.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/CallKind.kt index ee43caadf59..07b5cda678c 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/CallKind.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/CallKind.kt @@ -23,6 +23,7 @@ sealed class CallKind { object Function : CallKind() { override val resolutionSequence: List = listOf( CheckVisibility, + DiscriminateSynthetics, MapArguments, CheckExplicitReceiverConsistency, CreateFreshTypeVariableSubstitutorStage, @@ -42,4 +43,4 @@ sealed class CallKind { CheckReceivers.Extension ) } -} \ No newline at end of file +} diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/TowerLevels.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/TowerLevels.kt index ea61065d171..54c928d5054 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/TowerLevels.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/TowerLevels.kt @@ -191,7 +191,7 @@ class ScopeTowerLevel( TowerScopeLevel.Token.Functions -> scope.processFunctionsAndConstructorsByName( name, session, - bodyResolveComponents.scopeSession + bodyResolveComponents ) { candidate -> if (candidate.hasConsistentReceivers(extensionReceiver)) { processor.consumeCandidate( @@ -252,7 +252,7 @@ class QualifiedReceiverTowerLevel( processor.consumeCandidate(it as T, null, null) } TowerScopeLevel.Token.Functions -> { - scope.processFunctionsAndConstructorsByName(name, session, bodyResolveComponents.scopeSession, processorForCallables) + scope.processFunctionsAndConstructorsByName(name, session, bodyResolveComponents, processorForCallables) } TowerScopeLevel.Token.Properties -> scope.processPropertiesByName(name, processorForCallables) @@ -275,7 +275,7 @@ private fun FirCallableSymbol<*>.hasExtensionReceiver(): Boolean = this.fir.rece private fun FirScope.processFunctionsAndConstructorsByName( name: Name, session: FirSession, - scopeSession: ScopeSession, + bodyResolveComponents: BodyResolveComponents, processor: (FirCallableSymbol<*>) -> ProcessorAction ): ProcessorAction { val matchedClassSymbol = getFirstClassifierOrNull(name) as? FirClassLikeSymbol<*> @@ -284,13 +284,22 @@ private fun FirScope.processFunctionsAndConstructorsByName( matchedClassSymbol, processor, session, - scopeSession, + bodyResolveComponents.scopeSession, name ).stop() ) { return ProcessorAction.STOP } + if (processSyntheticConstructors( + matchedClassSymbol, + processor, + bodyResolveComponents + ).stop() + ) { + return ProcessorAction.STOP + } + return processFunctionsByName(name, processor) } @@ -315,6 +324,21 @@ private fun finalExpansionName(symbol: FirTypeAliasSymbol, session: FirSession): } +val SAM_PARAMETER_NAME = Name.identifier("block") + +private fun processSyntheticConstructors( + matchedSymbol: FirClassLikeSymbol<*>?, + processor: (FirFunctionSymbol<*>) -> ProcessorAction, + bodyResolveComponents: BodyResolveComponents +): ProcessorAction { + if (matchedSymbol == null) return ProcessorAction.NEXT + if (matchedSymbol !is FirClassSymbol) return ProcessorAction.NEXT + + val function = bodyResolveComponents.samResolver.getSamConstructor(matchedSymbol.fir) ?: return ProcessorAction.NEXT + + return processor(function.symbol) +} + private fun processConstructors( matchedSymbol: FirClassLikeSymbol<*>?, processor: (FirFunctionSymbol<*>) -> ProcessorAction, diff --git a/compiler/fir/resolve/testData/diagnostics/samConstructors/genericSam.kt b/compiler/fir/resolve/testData/diagnostics/samConstructors/genericSam.kt new file mode 100644 index 00000000000..e8bd5587cd3 --- /dev/null +++ b/compiler/fir/resolve/testData/diagnostics/samConstructors/genericSam.kt @@ -0,0 +1,20 @@ +// FILE: MyFunction.java +public interface MyFunction { + R foo(T x); +} + +// FILE: main.kt + +fun main() { + MyFunction{ x -> + x.toInt().toString() + } + + MyFunction { x: Int -> + x.toString() + } + + MyFunction { x -> + "" + } +} diff --git a/compiler/fir/resolve/testData/diagnostics/samConstructors/genericSam.txt b/compiler/fir/resolve/testData/diagnostics/samConstructors/genericSam.txt new file mode 100644 index 00000000000..c59652481d7 --- /dev/null +++ b/compiler/fir/resolve/testData/diagnostics/samConstructors/genericSam.txt @@ -0,0 +1,15 @@ +FILE: main.kt + public final fun main(): R|kotlin/Unit| { + R|/MyFunction|( = MyFunction@fun (x: R|kotlin/Int|): R|kotlin/String| { + R|/x|.R|kotlin/Int.toInt|().R|kotlin/Any.toString|() + } + ) + R|/MyFunction||>( = MyFunction@fun (x: R|kotlin/Int|): R|kotlin/String| { + R|/x|.R|kotlin/Any.toString|() + } + ) + R|/MyFunction||>( = MyFunction@fun (x: R|kotlin/Any?|): R|kotlin/String| { + String() + } + ) + } diff --git a/compiler/fir/resolve/testData/diagnostics/samConstructors/genericSamInferenceFromExpectType.kt b/compiler/fir/resolve/testData/diagnostics/samConstructors/genericSamInferenceFromExpectType.kt new file mode 100644 index 00000000000..06e0db10fd4 --- /dev/null +++ b/compiler/fir/resolve/testData/diagnostics/samConstructors/genericSamInferenceFromExpectType.kt @@ -0,0 +1,38 @@ +// FILE: MyFunction.java +public interface MyFunction { + R foo(T x); +} + +// FILE: main.kt + +fun foo1(x: MyFunction) {} +fun foo2(x: MyFunction) {} +fun foo3(f: MyFunction, x: X) {} + +fun main() { + foo1(MyFunction { x -> + x.toInt().toString() + }) + + foo2(MyFunction { x -> + x.toInt().toString() + }) + + foo2(MyFunction { x: Int -> + x.toString() + }) + + foo3( + MyFunction { x -> + (x + 1).toString() + }, + 1 + ) + + foo3( + MyFunction { x: Number -> + x.toInt().toString() + }, + 2 + ) +} diff --git a/compiler/fir/resolve/testData/diagnostics/samConstructors/genericSamInferenceFromExpectType.txt b/compiler/fir/resolve/testData/diagnostics/samConstructors/genericSamInferenceFromExpectType.txt new file mode 100644 index 00000000000..1dc463f7c03 --- /dev/null +++ b/compiler/fir/resolve/testData/diagnostics/samConstructors/genericSamInferenceFromExpectType.txt @@ -0,0 +1,29 @@ +FILE: main.kt + public final fun foo1(x: R|MyFunction|): R|kotlin/Unit| { + } + public final fun foo2(x: R|MyFunction|): R|kotlin/Unit| { + } + public final fun foo3(f: R|MyFunction|, x: R|X|): R|kotlin/Unit| { + } + public final fun main(): R|kotlin/Unit| { + R|/foo1|(R|/MyFunction|( = MyFunction@fun (x: R|kotlin/Int|): R|kotlin/String| { + R|/x|.R|kotlin/Int.toInt|().R|kotlin/Any.toString|() + } + )) + R|/foo2|(R|/MyFunction||>( = MyFunction@fun (x: R|kotlin/Number|): R|kotlin/String| { + R|/x|.R|kotlin/Number.toInt|().R|kotlin/Any.toString|() + } + )) + R|/foo2|(R|/MyFunction||>( = MyFunction@fun (x: R|kotlin/Int|): R|kotlin/String| { + R|/x|.R|kotlin/Any.toString|() + } + )) + R|/foo3||>(R|/MyFunction||>( = MyFunction@fun (x: R|kotlin/Int|): R|kotlin/String| { + R|/x|.R|kotlin/Int.plus|(Int(1)).R|kotlin/Any.toString|() + } + ), Int(1)) + R|/foo3||>(R|/MyFunction||>( = MyFunction@fun (x: R|kotlin/Number|): R|kotlin/String| { + R|/x|.R|kotlin/Number.toInt|().R|kotlin/Any.toString|() + } + ), Int(2)) + } diff --git a/compiler/fir/resolve/testData/diagnostics/samConstructors/kotlinSam.kt b/compiler/fir/resolve/testData/diagnostics/samConstructors/kotlinSam.kt new file mode 100644 index 00000000000..19adf795633 --- /dev/null +++ b/compiler/fir/resolve/testData/diagnostics/samConstructors/kotlinSam.kt @@ -0,0 +1,18 @@ +// TODO: This interface must be marked as "fun" ones that modifier is supported +interface MyRunnable { + fun foo(x: Int): Boolean +} + +fun foo(m: MyRunnable) {} + +fun main() { + foo(MyRunnable { x -> + x > 1 + }) + + foo(MyRunnable({ it > 1 })) + + val x = { x: Int -> x > 1 } + + foo(MyRunnable(x)) +} diff --git a/compiler/fir/resolve/testData/diagnostics/samConstructors/kotlinSam.txt b/compiler/fir/resolve/testData/diagnostics/samConstructors/kotlinSam.txt new file mode 100644 index 00000000000..381c746a761 --- /dev/null +++ b/compiler/fir/resolve/testData/diagnostics/samConstructors/kotlinSam.txt @@ -0,0 +1,22 @@ +FILE: kotlinSam.kt + public abstract interface MyRunnable : R|kotlin/Any| { + public abstract fun foo(x: R|kotlin/Int|): R|kotlin/Boolean| + + } + public final fun foo(m: R|MyRunnable|): R|kotlin/Unit| { + } + public final fun main(): R|kotlin/Unit| { + R|/foo|(R|/MyRunnable|( = MyRunnable@fun (x: R|kotlin/Int|): R|kotlin/Boolean| { + >(R|/x|, Int(1)) + } + )) + R|/foo|(R|/MyRunnable|(MyRunnable@fun (it: R|kotlin/Int|): R|kotlin/Boolean| { + >(R|/it|, Int(1)) + } + )) + lval x: R|kotlin/Function1| = fun (x: R|kotlin/Int|): kotlin/Boolean { + >(R|/x|, Int(1)) + } + + R|/foo|(R|/MyRunnable|(R|/x|)) + } diff --git a/compiler/fir/resolve/testData/diagnostics/samConstructors/realConstructorFunction.kt b/compiler/fir/resolve/testData/diagnostics/samConstructors/realConstructorFunction.kt new file mode 100644 index 00000000000..4f6982ca11b --- /dev/null +++ b/compiler/fir/resolve/testData/diagnostics/samConstructors/realConstructorFunction.kt @@ -0,0 +1,22 @@ +// FILE: MyRunnable.java +public interface MyRunnable { + boolean foo(int x); +} + +// FILE: main.kt + +fun foo(m: MyRunnable) {} + +fun MyRunnable(x: (Int) -> Boolean) = 1 + +fun main() { + foo(MyRunnable { x -> + x > 1 + }) + + foo(MyRunnable({ it > 1 })) + + val x = { x: Int -> x > 1 } + + foo(MyRunnable(x)) +} diff --git a/compiler/fir/resolve/testData/diagnostics/samConstructors/realConstructorFunction.txt b/compiler/fir/resolve/testData/diagnostics/samConstructors/realConstructorFunction.txt new file mode 100644 index 00000000000..875ae75236b --- /dev/null +++ b/compiler/fir/resolve/testData/diagnostics/samConstructors/realConstructorFunction.txt @@ -0,0 +1,21 @@ +FILE: main.kt + public final fun foo(m: R|MyRunnable|): R|kotlin/Unit| { + } + public final fun MyRunnable(x: R|kotlin/Function1|): R|kotlin/Int| { + ^MyRunnable Int(1) + } + public final fun main(): R|kotlin/Unit| { + #(R|/MyRunnable|( = MyRunnable@fun (x: R|kotlin/Int|): R|kotlin/Boolean| { + >(R|/x|, Int(1)) + } + )) + #(R|/MyRunnable|(MyRunnable@fun (it: R|kotlin/Int|): R|kotlin/Boolean| { + >(R|/it|, Int(1)) + } + )) + lval x: R|kotlin/Function1| = fun (x: R|kotlin/Int|): kotlin/Boolean { + >(R|/x|, Int(1)) + } + + #(R|/MyRunnable|(R|/x|)) + } diff --git a/compiler/fir/resolve/testData/diagnostics/samConstructors/runnable.kt b/compiler/fir/resolve/testData/diagnostics/samConstructors/runnable.kt new file mode 100644 index 00000000000..1ef8af49188 --- /dev/null +++ b/compiler/fir/resolve/testData/diagnostics/samConstructors/runnable.kt @@ -0,0 +1,5 @@ +fun foo(runnable: Runnable) {} + +fun main() { + foo(Runnable {}) +} diff --git a/compiler/fir/resolve/testData/diagnostics/samConstructors/runnable.txt b/compiler/fir/resolve/testData/diagnostics/samConstructors/runnable.txt new file mode 100644 index 00000000000..ef3b5298228 --- /dev/null +++ b/compiler/fir/resolve/testData/diagnostics/samConstructors/runnable.txt @@ -0,0 +1,9 @@ +FILE: runnable.kt + public final fun foo(runnable: R|java/lang/Runnable|): R|kotlin/Unit| { + } + public final fun main(): R|kotlin/Unit| { + R|/foo|(R|java/lang/Runnable|( = Runnable@fun (): R|kotlin/Unit| { + Unit + } + )) + } diff --git a/compiler/fir/resolve/testData/diagnostics/samConstructors/simple.kt b/compiler/fir/resolve/testData/diagnostics/samConstructors/simple.kt new file mode 100644 index 00000000000..b2f0d3e09dd --- /dev/null +++ b/compiler/fir/resolve/testData/diagnostics/samConstructors/simple.kt @@ -0,0 +1,20 @@ +// FILE: MyRunnable.java +public interface MyRunnable { + boolean foo(int x); +} + +// FILE: main.kt + +fun foo(m: MyRunnable) {} + +fun main() { + foo(MyRunnable { x -> + x > 1 + }) + + foo(MyRunnable({ it > 1 })) + + val x = { x: Int -> x > 1 } + + foo(MyRunnable(x)) +} diff --git a/compiler/fir/resolve/testData/diagnostics/samConstructors/simple.txt b/compiler/fir/resolve/testData/diagnostics/samConstructors/simple.txt new file mode 100644 index 00000000000..b637733d6b6 --- /dev/null +++ b/compiler/fir/resolve/testData/diagnostics/samConstructors/simple.txt @@ -0,0 +1,18 @@ +FILE: main.kt + public final fun foo(m: R|MyRunnable|): R|kotlin/Unit| { + } + public final fun main(): R|kotlin/Unit| { + R|/foo|(R|/MyRunnable|( = MyRunnable@fun (x: R|kotlin/Int|): R|kotlin/Boolean| { + >(R|/x|, Int(1)) + } + )) + R|/foo|(R|/MyRunnable|(MyRunnable@fun (it: R|kotlin/Int|): R|kotlin/Boolean| { + >(R|/it|, Int(1)) + } + )) + lval x: R|kotlin/Function1| = fun (x: R|kotlin/Int|): kotlin/Boolean { + >(R|/x|, Int(1)) + } + + R|/foo|(R|/MyRunnable|(R|/x|)) + } diff --git a/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsTestGenerated.java b/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsTestGenerated.java index 5ed71efe9be..ad9096be1ae 100644 --- a/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsTestGenerated.java +++ b/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsTestGenerated.java @@ -92,6 +92,49 @@ public class FirDiagnosticsTestGenerated extends AbstractFirDiagnosticsTest { } } + @TestMetadata("compiler/fir/resolve/testData/diagnostics/samConstructors") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class SamConstructors extends AbstractFirDiagnosticsTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath); + } + + public void testAllFilesPresentInSamConstructors() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/fir/resolve/testData/diagnostics/samConstructors"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); + } + + @TestMetadata("genericSam.kt") + public void testGenericSam() throws Exception { + runTest("compiler/fir/resolve/testData/diagnostics/samConstructors/genericSam.kt"); + } + + @TestMetadata("genericSamInferenceFromExpectType.kt") + public void testGenericSamInferenceFromExpectType() throws Exception { + runTest("compiler/fir/resolve/testData/diagnostics/samConstructors/genericSamInferenceFromExpectType.kt"); + } + + @TestMetadata("kotlinSam.kt") + public void testKotlinSam() throws Exception { + runTest("compiler/fir/resolve/testData/diagnostics/samConstructors/kotlinSam.kt"); + } + + @TestMetadata("realConstructorFunction.kt") + public void testRealConstructorFunction() throws Exception { + runTest("compiler/fir/resolve/testData/diagnostics/samConstructors/realConstructorFunction.kt"); + } + + @TestMetadata("runnable.kt") + public void testRunnable() throws Exception { + runTest("compiler/fir/resolve/testData/diagnostics/samConstructors/runnable.kt"); + } + + @TestMetadata("simple.kt") + public void testSimple() throws Exception { + runTest("compiler/fir/resolve/testData/diagnostics/samConstructors/simple.kt"); + } + } + @TestMetadata("compiler/fir/resolve/testData/diagnostics/samConversions") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/compiler/testData/ir/irText/expressions/sam/samConstructors.fir.txt b/compiler/testData/ir/irText/expressions/sam/samConstructors.fir.txt index a264dfbc25d..bfec7a249d8 100644 --- a/compiler/testData/ir/irText/expressions/sam/samConstructors.fir.txt +++ b/compiler/testData/ir/irText/expressions/sam/samConstructors.fir.txt @@ -1,25 +1,25 @@ FILE fqName: fileName:/samConstructors.kt - FUN name:test1 visibility:public modality:FINAL <> () returnType:IrErrorType + FUN name:test1 visibility:public modality:FINAL <> () returnType:java.lang.Runnable BLOCK_BODY - RETURN type=kotlin.Nothing from='public final fun test1 (): IrErrorType declared in ' - ERROR_CALL 'Unresolved reference: #' type=IrErrorType - FUN_EXPR type=IrErrorType origin=LAMBDA - FUN LOCAL_FUNCTION_FOR_LAMBDA name: visibility:local modality:FINAL <> () returnType:IrErrorType + RETURN type=kotlin.Nothing from='public final fun test1 (): java.lang.Runnable declared in ' + CALL 'public final fun Runnable (block: kotlin.Function0): java.lang.Runnable declared in java.lang' type=java.lang.Runnable origin=null + block: FUN_EXPR type=kotlin.Function0 origin=LAMBDA + FUN LOCAL_FUNCTION_FOR_LAMBDA name: visibility:local modality:FINAL <> () returnType:kotlin.Unit BLOCK_BODY GET_OBJECT 'CLASS IR_EXTERNAL_DECLARATION_STUB OBJECT name:Unit modality:FINAL visibility:public superTypes:[kotlin.Any]' type=kotlin.Unit - FUN name:test2 visibility:public modality:FINAL <> (a:kotlin.Function0) returnType:IrErrorType + FUN name:test2 visibility:public modality:FINAL <> (a:kotlin.Function0) returnType:java.lang.Runnable VALUE_PARAMETER name:a index:0 type:kotlin.Function0 BLOCK_BODY - RETURN type=kotlin.Nothing from='public final fun test2 (a: kotlin.Function0): IrErrorType declared in ' - ERROR_CALL 'Unresolved reference: #' type=IrErrorType - GET_VAR 'a: kotlin.Function0 declared in .test2' type=kotlin.Function0 origin=null + RETURN type=kotlin.Nothing from='public final fun test2 (a: kotlin.Function0): java.lang.Runnable declared in ' + CALL 'public final fun Runnable (block: kotlin.Function0): java.lang.Runnable declared in java.lang' type=java.lang.Runnable origin=null + block: GET_VAR 'a: kotlin.Function0 declared in .test2' type=kotlin.Function0 origin=null FUN name:foo visibility:public modality:FINAL <> () returnType:kotlin.Unit BLOCK_BODY - FUN name:test3 visibility:public modality:FINAL <> () returnType:IrErrorType + FUN name:test3 visibility:public modality:FINAL <> () returnType:java.lang.Runnable BLOCK_BODY - RETURN type=kotlin.Nothing from='public final fun test3 (): IrErrorType declared in ' - ERROR_CALL 'Unresolved reference: #' type=IrErrorType - ERROR_CALL 'Unsupported callable reference: ::#' type=IrErrorType + RETURN type=kotlin.Nothing from='public final fun test3 (): java.lang.Runnable declared in ' + CALL 'public final fun Runnable (block: kotlin.Function0): java.lang.Runnable declared in java.lang' type=java.lang.Runnable origin=null + block: ERROR_CALL 'Unsupported callable reference: ::#' type=IrErrorType FUN name:test4 visibility:public modality:FINAL <> () returnType:IrErrorType BLOCK_BODY RETURN type=kotlin.Nothing from='public final fun test4 (): IrErrorType declared in ' diff --git a/compiler/testData/ir/irText/expressions/sam/samConversionToGeneric.fir.txt b/compiler/testData/ir/irText/expressions/sam/samConversionToGeneric.fir.txt index 44d18cb598f..edaacdf5b5f 100644 --- a/compiler/testData/ir/irText/expressions/sam/samConversionToGeneric.fir.txt +++ b/compiler/testData/ir/irText/expressions/sam/samConversionToGeneric.fir.txt @@ -1,22 +1,22 @@ FILE fqName: fileName:/samConversionToGeneric.kt - FUN name:test1 visibility:public modality:FINAL <> () returnType:IrErrorType + FUN name:test1 visibility:public modality:FINAL <> () returnType:.J BLOCK_BODY - RETURN type=kotlin.Nothing from='public final fun test1 (): IrErrorType declared in ' - ERROR_CALL 'Unresolved reference: #' type=IrErrorType - FUN_EXPR type=IrErrorType origin=LAMBDA - FUN LOCAL_FUNCTION_FOR_LAMBDA name: visibility:local modality:FINAL <> (x:IrErrorType) returnType:IrErrorType - VALUE_PARAMETER name:x index:0 type:IrErrorType - BLOCK_BODY - ERROR_CALL 'Unresolved reference: x#' type=IrErrorType - FUN name:test2 visibility:public modality:FINAL <> () returnType:IrErrorType - BLOCK_BODY - RETURN type=kotlin.Nothing from='public final fun test2 (): IrErrorType declared in ' - ERROR_CALL 'Unresolved reference: #' type=IrErrorType - FUN_EXPR type=IrErrorType origin=LAMBDA - FUN LOCAL_FUNCTION_FOR_LAMBDA name: visibility:local modality:FINAL <> (x:kotlin.String) returnType:IrErrorType + RETURN type=kotlin.Nothing from='public final fun test1 (): .J declared in ' + CALL 'public final fun J (block: kotlin.Function1?, T of ?>): .J> declared in ' type=.J origin=null + block: FUN_EXPR type=kotlin.Function1 origin=LAMBDA + FUN LOCAL_FUNCTION_FOR_LAMBDA name: visibility:local modality:FINAL <> (x:kotlin.String) returnType:kotlin.String VALUE_PARAMETER name:x index:0 type:kotlin.String BLOCK_BODY - ERROR_CALL 'Unresolved reference: x#' type=IrErrorType + GET_VAR 'x: kotlin.String declared in .test1.' type=kotlin.String origin=null + FUN name:test2 visibility:public modality:FINAL <> () returnType:.J + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun test2 (): .J declared in ' + CALL 'public final fun J (block: kotlin.Function1?, T of ?>): .J> declared in ' type=.J origin=null + block: FUN_EXPR type=kotlin.Function1 origin=LAMBDA + FUN LOCAL_FUNCTION_FOR_LAMBDA name: visibility:local modality:FINAL <> (x:kotlin.String) returnType:kotlin.String + VALUE_PARAMETER name:x index:0 type:kotlin.String + BLOCK_BODY + GET_VAR 'x: kotlin.String declared in .test2.' type=kotlin.String origin=null FUN name:test3 visibility:public modality:FINAL <> () returnType:kotlin.Unit BLOCK_BODY RETURN type=kotlin.Nothing from='public final fun test3 (): kotlin.Unit declared in ' @@ -54,12 +54,12 @@ FILE fqName: fileName:/samConversionToGeneric.kt GET_VAR 'a: kotlin.Any declared in .test7' type=kotlin.Any origin=null CALL 'public open fun bar (j: .J?>?): kotlin.Unit declared in .H' type=kotlin.Unit origin=null j: GET_VAR 'a: kotlin.Any declared in .test7' type=kotlin.Function1.test7, T of .test7> origin=null - FUN name:test8 visibility:public modality:FINAL <> (efn:kotlin.Function1) returnType:IrErrorType + FUN name:test8 visibility:public modality:FINAL <> (efn:kotlin.Function1) returnType:.J VALUE_PARAMETER name:efn index:0 type:kotlin.Function1 BLOCK_BODY - RETURN type=kotlin.Nothing from='public final fun test8 (efn: kotlin.Function1): IrErrorType declared in ' - ERROR_CALL 'Unresolved reference: #' type=IrErrorType - GET_VAR 'efn: kotlin.Function1 declared in .test8' type=kotlin.Function1 origin=null + RETURN type=kotlin.Nothing from='public final fun test8 (efn: kotlin.Function1): .J declared in ' + CALL 'public final fun J (block: kotlin.Function1?, T of ?>): .J> declared in ' type=.J origin=null + block: GET_VAR 'efn: kotlin.Function1 declared in .test8' type=kotlin.Function1 origin=null FUN name:test9 visibility:public modality:FINAL <> (efn:kotlin.Function1) returnType:kotlin.Unit VALUE_PARAMETER name:efn index:0 type:kotlin.Function1 BLOCK_BODY @@ -68,5 +68,5 @@ FILE fqName: fileName:/samConversionToGeneric.kt FUN name:test10 visibility:public modality:FINAL <> (fn:kotlin.Function1) returnType:kotlin.Unit VALUE_PARAMETER name:fn index:0 type:kotlin.Function1 BLOCK_BODY - ERROR_CALL 'Unresolved reference: #' type=IrErrorType - GET_VAR 'fn: kotlin.Function1 declared in .test10' type=kotlin.Function1 origin=null + CALL 'public open fun bar2x (j2x: .J2X?>?): kotlin.Unit declared in .H' type=kotlin.Unit origin=null + j2x: GET_VAR 'fn: kotlin.Function1 declared in .test10' type=kotlin.Function1 origin=null diff --git a/compiler/testData/ir/irText/lambdas/samAdapter.fir.txt b/compiler/testData/ir/irText/lambdas/samAdapter.fir.txt index 59d8dad1387..94d80f6f9d8 100644 --- a/compiler/testData/ir/irText/lambdas/samAdapter.fir.txt +++ b/compiler/testData/ir/irText/lambdas/samAdapter.fir.txt @@ -1,11 +1,12 @@ FILE fqName: fileName:/samAdapter.kt FUN name:test1 visibility:public modality:FINAL <> () returnType:kotlin.Unit BLOCK_BODY - VAR name:hello type:IrErrorType [val] - ERROR_CALL 'Unresolved reference: #' type=IrErrorType - FUN_EXPR type=IrErrorType origin=LAMBDA - FUN LOCAL_FUNCTION_FOR_LAMBDA name: visibility:local modality:FINAL <> () returnType:IrErrorType + VAR name:hello type:java.lang.Runnable [val] + CALL 'public final fun Runnable (block: kotlin.Function0): java.lang.Runnable declared in java.lang' type=java.lang.Runnable origin=null + block: FUN_EXPR type=kotlin.Function0 origin=LAMBDA + FUN LOCAL_FUNCTION_FOR_LAMBDA name: visibility:local modality:FINAL <> () returnType:kotlin.Unit BLOCK_BODY - ERROR_CALL 'Unresolved reference: println#' type=IrErrorType - CONST String type=IrErrorType value="Hello, world!" - ERROR_CALL 'Unresolved reference: #' type=IrErrorType + CALL 'public final fun println (message: kotlin.Any?): kotlin.Unit [inline] declared in kotlin.io' type=kotlin.Unit origin=null + message: CONST String type=kotlin.String value="Hello, world!" + CALL 'public abstract fun run (): kotlin.Unit declared in java.lang.Runnable' type=kotlin.Unit origin=null + $this: GET_VAR 'val hello: java.lang.Runnable [val] declared in .test1' type=java.lang.Runnable origin=null