FIR: fix substitution of type arguments in SAM type aliases

^KT-54730 Fixed
This commit is contained in:
pyos
2022-10-20 13:22:50 +02:00
committed by Space Team
parent 3253789093
commit 0d46dfc1ba
20 changed files with 125 additions and 72 deletions
@@ -7,7 +7,7 @@ KtSuccessCallInfo:
signature = KtFunctionLikeSignature:
receiverType = null
returnType = java.util.Comparator<kotlin.Int!>
symbol = java/util/Comparator(function: kotlin.Function2<ft<T & Any, T?>, ft<T & Any, T?>, kotlin.Int>): java.util.Comparator<T>
symbol = kotlin/Comparator(function: kotlin.Function2<ft<T & Any, T?>, ft<T & Any, T?>, kotlin.Int>): java.util.Comparator<T>
valueParameters = [
KtVariableLikeSignature:
name = function
@@ -16,7 +16,7 @@ KtSuccessCallInfo:
symbol = function: kotlin.Function2<ft<T & Any, T?>, ft<T & Any, T?>, kotlin.Int>
callableIdIfNonLocal = null
]
callableIdIfNonLocal = java/util/Comparator
callableIdIfNonLocal = kotlin/Comparator
typeArgumentsMapping = {
T -> (kotlin.Int!)
}
@@ -7,7 +7,7 @@ KtApplicableCallCandidateInfo:
signature = KtFunctionLikeSignature:
receiverType = null
returnType = java.util.Comparator<kotlin.Int!>
symbol = java/util/Comparator(function: kotlin.Function2<ft<T & Any, T?>, ft<T & Any, T?>, kotlin.Int>): java.util.Comparator<T>
symbol = kotlin/Comparator(function: kotlin.Function2<ft<T & Any, T?>, ft<T & Any, T?>, kotlin.Int>): java.util.Comparator<T>
valueParameters = [
KtVariableLikeSignature:
name = function
@@ -16,7 +16,7 @@ KtApplicableCallCandidateInfo:
symbol = function: kotlin.Function2<ft<T & Any, T?>, ft<T & Any, T?>, kotlin.Int>
callableIdIfNonLocal = null
]
callableIdIfNonLocal = java/util/Comparator
callableIdIfNonLocal = kotlin/Comparator
typeArgumentsMapping = {
T -> (kotlin.Int!)
}
@@ -1,6 +1,6 @@
FILE: kotlinComparatorAlias.kt
public final fun test_1(): R|kotlin/Unit| {
lval comp: R|java/util/Comparator<kotlin/Int>| = R|java/util/Comparator|<R|kotlin/Int|>(<L> = Comparator@fun <anonymous>(x: R|kotlin/Int!|, y: R|kotlin/Int!|): R|kotlin/Int| <inline=NoInline> {
lval comp: R|java/util/Comparator<kotlin/Int>| = R|kotlin/Comparator|<R|kotlin/Int|>(<L> = Comparator@fun <anonymous>(x: R|kotlin/Int!|, y: R|kotlin/Int!|): R|kotlin/Int| <inline=NoInline> {
^ Int(1)
}
)
@@ -18461,6 +18461,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
runTest("compiler/testData/codegen/box/funInterface/funInterfaceInheritance.kt");
}
@Test
@TestMetadata("funInterfaceTypealias.kt")
public void testFunInterfaceTypealias() throws Exception {
runTest("compiler/testData/codegen/box/funInterface/funInterfaceTypealias.kt");
}
@Test
@TestMetadata("funInterfaceWithReceiver.kt")
public void testFunInterfaceWithReceiver() throws Exception {
@@ -111,14 +111,7 @@ class FirSamResolverImpl(
val firRegularClass = classSymbol.fir
val (functionSymbol, functionType) = resolveFunctionTypeIfSamInterface(firRegularClass) ?: return null
val classId = firRegularClass.classId
val syntheticFunctionSymbol = FirSyntheticFunctionSymbol(
CallableId(
classId.packageFqName,
classId.relativeClassName.parent().takeIf { !it.isRoot },
classId.shortClassName,
),
)
val syntheticFunctionSymbol = classSymbol.createSyntheticConstructorSymbol()
val newTypeParameters = firRegularClass.typeParameters.map { typeParameter ->
val declaredTypeParameter = typeParameter.symbol.fir // TODO: or really declared?
@@ -160,7 +153,7 @@ class FirSamResolverImpl(
return buildSimpleFunction {
moduleData = session.moduleData
source = firRegularClass.source
name = classId.shortClassName
name = syntheticFunctionSymbol.name
origin = FirDeclarationOrigin.SamConstructor
val visibility = firRegularClass.visibility
status = FirResolvedDeclarationStatusImpl(
@@ -223,7 +216,10 @@ class FirSamResolverImpl(
val expansionRegularClass = type.lookupTag.toSymbol(session)?.fir as? FirRegularClass ?: return null
val samConstructorForClass = getSamConstructor(expansionRegularClass) ?: return null
val substitutor = expansionRegularClass.buildSubstitutorForSamTypeAlias(session, type)
// The constructor is something like `fun <T, ...> C(...): C<T, ...>`, meaning the type parameters
// we need to replace are owned by it, not by the class (see the substitutor in `buildSamConstructor`
// for `FirRegularClass` above).
val substitutor = samConstructorForClass.buildSubstitutorForSamTypeAlias(session, type)
?: return samConstructorForClass.symbol
val newReturnType = substitutor.substituteOrNull(samConstructorForClass.returnTypeRef.coneType)
val newParameterTypes = samConstructorForClass.valueParameters.map {
@@ -236,19 +232,28 @@ class FirSamResolverImpl(
return samConstructorForClass.symbol
}
val namedSymbol = samConstructorForClass.symbol
val symbolForOverride = FirFakeOverrideGenerator.createSymbolForSubstitutionOverride(namedSymbol, expansionRegularClass.classId)
return FirFakeOverrideGenerator.createSubstitutionOverrideFunction(
session, symbolForOverride, samConstructorForClass,
return FirFakeOverrideGenerator.createCopyForFirFunction(
typeAliasSymbol.createSyntheticConstructorSymbol(), samConstructorForClass,
derivedClassLookupTag = null,
session, FirDeclarationOrigin.SamConstructor,
newDispatchReceiverType = null,
newReceiverType = null,
newContextReceiverTypes,
newReturnType, newParameterTypes, typeAliasSymbol.fir.typeParameters,
)
newContextReceiverTypes = newContextReceiverTypes,
newReturnType = newReturnType,
newParameterTypes = newParameterTypes,
newTypeParameters = typeAliasSymbol.fir.typeParameters,
).symbol
}
private fun FirClassLikeSymbol<*>.createSyntheticConstructorSymbol() =
FirSyntheticFunctionSymbol(
CallableId(
classId.packageFqName,
classId.relativeClassName.parent().takeIf { !it.isRoot },
classId.shortClassName,
),
)
private fun resolveFunctionTypeIfSamInterface(firRegularClass: FirRegularClass): SAMInfo<ConeLookupTagBasedType>? {
return resolvedFunctionType.getOrPut(firRegularClass) {
if (!firRegularClass.status.isFun) return@getOrPut null
@@ -269,7 +274,7 @@ class FirSamResolverImpl(
}
}
private fun FirRegularClass.buildSubstitutorForSamTypeAlias(session: FirSession, type: ConeClassLikeType): ConeSubstitutor? {
private fun FirTypeParameterRefsOwner.buildSubstitutorForSamTypeAlias(session: FirSession, type: ConeClassLikeType): ConeSubstitutor? {
if (typeParameters.isEmpty()) return null
val mapping = typeParameters.zip(type.typeArguments).associate { (parameter, projection) ->
val typeArgument =
@@ -0,0 +1,30 @@
fun interface KRunnable {
fun invoke()
}
fun interface KConsumer<T> {
fun accept(value: T)
}
typealias KRunnableAlias = KRunnable
typealias StringConsumer = KConsumer<String>
fun foo(f: KRunnable) = f
fun <T> bar(f: KConsumer<T>) = f
fun box(): String {
var result = ""
foo(KRunnable {
bar(KConsumer<String> {
result += it
}).accept("O")
}).invoke()
foo(KRunnableAlias {
bar(StringConsumer {
result += it
}).accept("K")
}).invoke()
return result
}
@@ -1,8 +0,0 @@
// FILE: test.kt
typealias RunnableT = java.lang.Runnable
typealias ComparatorT<T> = java.util.Comparator<T>
typealias ComparatorStrT = ComparatorT<String>
val test1 = RunnableT { }
val test2 = ComparatorT<String> { s1, s2 -> s1.compareTo(s2) }
val test3 = <!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>ComparatorStrT<!> { <!CANNOT_INFER_PARAMETER_TYPE!>s1<!>, <!CANNOT_INFER_PARAMETER_TYPE!>s2<!> -> s1.compareTo(s2) }
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// FILE: test.kt
typealias RunnableT = java.lang.Runnable
typealias ComparatorT<T> = java.util.Comparator<T>
@@ -1,27 +0,0 @@
// FILE: JHost.java
public class JHost {
public static interface Runnable {
void run();
}
public static interface Consumer<T> {
void consume(T x);
}
public static interface Consumer2<T1, T2> {
void run(T1 x1, T2 x2);
}
}
// FILE: test.kt
typealias R = JHost.Runnable
typealias C<T> = JHost.Consumer<T>
typealias CStr = JHost.Consumer<String>
typealias CStrList = JHost.Consumer<List<String>>
typealias C2<T> = JHost.Consumer2<T, T>
val test1 = R { }
val test2 = C<String> { s -> println(s.length) }
val test3 = <!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>CStr<!> { <!CANNOT_INFER_PARAMETER_TYPE!>s<!> -> <!OVERLOAD_RESOLUTION_AMBIGUITY!>println<!>(s.<!UNRESOLVED_REFERENCE!>length<!>) }
val test4 = <!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>CStrList<!> { <!CANNOT_INFER_PARAMETER_TYPE!>ss<!> -> for (s in <!ITERATOR_AMBIGUITY!>ss<!>) { <!OVERLOAD_RESOLUTION_AMBIGUITY!>println<!>(s.<!UNRESOLVED_REFERENCE!>length<!>) } }
val test5 = <!INAPPLICABLE_CANDIDATE!>C2<!><<!CANNOT_INFER_PARAMETER_TYPE!>Int<!>> { <!CANNOT_INFER_PARAMETER_TYPE!>a<!>, <!CANNOT_INFER_PARAMETER_TYPE!>b<!> -> val x: Int = a <!OVERLOAD_RESOLUTION_AMBIGUITY!>+<!> b; println(x)}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// FILE: JHost.java
public class JHost {
public static interface Runnable {
@@ -112,15 +112,15 @@ FILE fqName:<root> fileName:/funInterfaceConstructorReference.kt
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun test2a (): kotlin.Function1<kotlin.Function0<kotlin.String>, <root>.KSupplier<kotlin.String>> declared in <root>'
BLOCK type=kotlin.reflect.KFunction1<kotlin.Function0<kotlin.String>, <root>.KSupplier<kotlin.String>> origin=FUN_INTERFACE_CONSTRUCTOR_REFERENCE
FUN ADAPTER_FOR_FUN_INTERFACE_CONSTRUCTOR name:KSupplier visibility:local modality:FINAL <> (function:kotlin.Function0<kotlin.String>) returnType:<root>.KSupplier<kotlin.String>
FUN ADAPTER_FOR_FUN_INTERFACE_CONSTRUCTOR name:KSS visibility:local modality:FINAL <> (function:kotlin.Function0<kotlin.String>) returnType:<root>.KSupplier<kotlin.String>
VALUE_PARAMETER ADAPTER_PARAMETER_FOR_CALLABLE_REFERENCE name:function index:0 type:kotlin.Function0<kotlin.String>
BLOCK_BODY
RETURN type=kotlin.Nothing from='local final fun KSupplier (function: kotlin.Function0<kotlin.String>): <root>.KSupplier<kotlin.String> declared in <root>.test2a'
RETURN type=kotlin.Nothing from='local final fun KSS (function: kotlin.Function0<kotlin.String>): <root>.KSupplier<kotlin.String> declared in <root>.test2a'
TYPE_OP type=<root>.KSupplier<kotlin.String> origin=SAM_CONVERSION typeOperand=<root>.KSupplier<kotlin.String>
CALL 'public final fun CHECK_NOT_NULL <T0> (arg0: T0 of kotlin.internal.ir.CHECK_NOT_NULL?): {T0 of kotlin.internal.ir.CHECK_NOT_NULL & Any} declared in kotlin.internal.ir' type=kotlin.Function0<kotlin.String> origin=EXCLEXCL
<T0>: kotlin.Function0<kotlin.String>
arg0: GET_VAR 'function: kotlin.Function0<kotlin.String> declared in <root>.test2a.KSupplier' type=kotlin.Function0<kotlin.String> origin=null
FUNCTION_REFERENCE 'local final fun KSupplier (function: kotlin.Function0<kotlin.String>): <root>.KSupplier<kotlin.String> declared in <root>.test2a' type=kotlin.reflect.KFunction1<kotlin.Function0<kotlin.String>, <root>.KSupplier<kotlin.String>> origin=FUN_INTERFACE_CONSTRUCTOR_REFERENCE reflectionTarget=<same>
arg0: GET_VAR 'function: kotlin.Function0<kotlin.String> declared in <root>.test2a.KSS' type=kotlin.Function0<kotlin.String> origin=null
FUNCTION_REFERENCE 'local final fun KSS (function: kotlin.Function0<kotlin.String>): <root>.KSupplier<kotlin.String> declared in <root>.test2a' type=kotlin.reflect.KFunction1<kotlin.Function0<kotlin.String>, <root>.KSupplier<kotlin.String>> origin=FUN_INTERFACE_CONSTRUCTOR_REFERENCE reflectionTarget=<same>
FUN name:test3 visibility:public modality:FINAL <> () returnType:kotlin.Function1<kotlin.Function1<kotlin.String, kotlin.Unit>, <root>.KConsumer<kotlin.String>>
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun test3 (): kotlin.Function1<kotlin.Function1<kotlin.String, kotlin.Unit>, <root>.KConsumer<kotlin.String>> declared in <root>'
@@ -138,15 +138,15 @@ FILE fqName:<root> fileName:/funInterfaceConstructorReference.kt
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun test3a (): kotlin.Function1<kotlin.Function1<kotlin.String, kotlin.Unit>, <root>.KConsumer<kotlin.String>> declared in <root>'
BLOCK type=kotlin.reflect.KFunction1<kotlin.Function1<kotlin.String, kotlin.Unit>, <root>.KConsumer<kotlin.String>> origin=FUN_INTERFACE_CONSTRUCTOR_REFERENCE
FUN ADAPTER_FOR_FUN_INTERFACE_CONSTRUCTOR name:KConsumer visibility:local modality:FINAL <> (function:kotlin.Function1<kotlin.String, kotlin.Unit>) returnType:<root>.KConsumer<kotlin.String>
FUN ADAPTER_FOR_FUN_INTERFACE_CONSTRUCTOR name:KCS visibility:local modality:FINAL <> (function:kotlin.Function1<kotlin.String, kotlin.Unit>) returnType:<root>.KConsumer<kotlin.String>
VALUE_PARAMETER ADAPTER_PARAMETER_FOR_CALLABLE_REFERENCE name:function index:0 type:kotlin.Function1<kotlin.String, kotlin.Unit>
BLOCK_BODY
RETURN type=kotlin.Nothing from='local final fun KConsumer (function: kotlin.Function1<kotlin.String, kotlin.Unit>): <root>.KConsumer<kotlin.String> declared in <root>.test3a'
RETURN type=kotlin.Nothing from='local final fun KCS (function: kotlin.Function1<kotlin.String, kotlin.Unit>): <root>.KConsumer<kotlin.String> declared in <root>.test3a'
TYPE_OP type=<root>.KConsumer<kotlin.String> origin=SAM_CONVERSION typeOperand=<root>.KConsumer<kotlin.String>
CALL 'public final fun CHECK_NOT_NULL <T0> (arg0: T0 of kotlin.internal.ir.CHECK_NOT_NULL?): {T0 of kotlin.internal.ir.CHECK_NOT_NULL & Any} declared in kotlin.internal.ir' type=kotlin.Function1<kotlin.String, kotlin.Unit> origin=EXCLEXCL
<T0>: kotlin.Function1<kotlin.String, kotlin.Unit>
arg0: GET_VAR 'function: kotlin.Function1<kotlin.String, kotlin.Unit> declared in <root>.test3a.KConsumer' type=kotlin.Function1<kotlin.String, kotlin.Unit> origin=null
FUNCTION_REFERENCE 'local final fun KConsumer (function: kotlin.Function1<kotlin.String, kotlin.Unit>): <root>.KConsumer<kotlin.String> declared in <root>.test3a' type=kotlin.reflect.KFunction1<kotlin.Function1<kotlin.String, kotlin.Unit>, <root>.KConsumer<kotlin.String>> origin=FUN_INTERFACE_CONSTRUCTOR_REFERENCE reflectionTarget=<same>
arg0: GET_VAR 'function: kotlin.Function1<kotlin.String, kotlin.Unit> declared in <root>.test3a.KCS' type=kotlin.Function1<kotlin.String, kotlin.Unit> origin=null
FUNCTION_REFERENCE 'local final fun KCS (function: kotlin.Function1<kotlin.String, kotlin.Unit>): <root>.KConsumer<kotlin.String> declared in <root>.test3a' type=kotlin.reflect.KFunction1<kotlin.Function1<kotlin.String, kotlin.Unit>, <root>.KConsumer<kotlin.String>> origin=FUN_INTERFACE_CONSTRUCTOR_REFERENCE reflectionTarget=<same>
FUN name:test3b visibility:public modality:FINAL <> () returnType:kotlin.reflect.KFunction<<root>.KConsumer<kotlin.String>>
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun test3b (): kotlin.reflect.KFunction<<root>.KConsumer<kotlin.String>> declared in <root>'
@@ -58,11 +58,11 @@ fun test2(): Function1<Function0<String>, KSupplier<String>> {
fun test2a(): Function1<Function0<String>, KSupplier<String>> {
return { // BLOCK
local fun KSupplier(function: Function0<String>): KSupplier<String> {
local fun KSS(function: Function0<String>): KSupplier<String> {
return CHECK_NOT_NULL<Function0<String>>(arg0 = function) /*-> KSupplier<String> */
}
::KSupplier
::KSS
}
}
@@ -78,11 +78,11 @@ fun test3(): Function1<Function1<String, Unit>, KConsumer<String>> {
fun test3a(): Function1<Function1<String, Unit>, KConsumer<String>> {
return { // BLOCK
local fun KConsumer(function: Function1<String, Unit>): KConsumer<String> {
local fun KCS(function: Function1<String, Unit>): KConsumer<String> {
return CHECK_NOT_NULL<Function1<String, Unit>>(arg0 = function) /*-> KConsumer<String> */
}
::KConsumer
::KCS
}
}
@@ -95,4 +95,3 @@ fun test3b(): KFunction<KConsumer<String>> {
::KConsumer
}
}
@@ -17723,6 +17723,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
runTest("compiler/testData/codegen/box/funInterface/funInterfaceInheritance.kt");
}
@Test
@TestMetadata("funInterfaceTypealias.kt")
public void testFunInterfaceTypealias() throws Exception {
runTest("compiler/testData/codegen/box/funInterface/funInterfaceTypealias.kt");
}
@Test
@TestMetadata("funInterfaceWithReceiver.kt")
public void testFunInterfaceWithReceiver() throws Exception {
@@ -18461,6 +18461,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
runTest("compiler/testData/codegen/box/funInterface/funInterfaceInheritance.kt");
}
@Test
@TestMetadata("funInterfaceTypealias.kt")
public void testFunInterfaceTypealias() throws Exception {
runTest("compiler/testData/codegen/box/funInterface/funInterfaceTypealias.kt");
}
@Test
@TestMetadata("funInterfaceWithReceiver.kt")
public void testFunInterfaceWithReceiver() throws Exception {
@@ -14710,6 +14710,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
runTest("compiler/testData/codegen/box/funInterface/funInterfaceInheritance.kt");
}
@TestMetadata("funInterfaceTypealias.kt")
public void testFunInterfaceTypealias() throws Exception {
runTest("compiler/testData/codegen/box/funInterface/funInterfaceTypealias.kt");
}
@TestMetadata("funInterfaceWithReceiver.kt")
public void testFunInterfaceWithReceiver() throws Exception {
runTest("compiler/testData/codegen/box/funInterface/funInterfaceWithReceiver.kt");
@@ -13609,6 +13609,12 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/funInterface/funInterfaceInheritance.kt");
}
@Test
@TestMetadata("funInterfaceTypealias.kt")
public void testFunInterfaceTypealias() throws Exception {
runTest("compiler/testData/codegen/box/funInterface/funInterfaceTypealias.kt");
}
@Test
@TestMetadata("funInterfaceWithReceiver.kt")
public void testFunInterfaceWithReceiver() throws Exception {
@@ -13705,6 +13705,12 @@ public class FirJsCodegenBoxTestGenerated extends AbstractFirJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/funInterface/funInterfaceInheritance.kt");
}
@Test
@TestMetadata("funInterfaceTypealias.kt")
public void testFunInterfaceTypealias() throws Exception {
runTest("compiler/testData/codegen/box/funInterface/funInterfaceTypealias.kt");
}
@Test
@TestMetadata("funInterfaceWithReceiver.kt")
public void testFunInterfaceWithReceiver() throws Exception {
@@ -13705,6 +13705,12 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/funInterface/funInterfaceInheritance.kt");
}
@Test
@TestMetadata("funInterfaceTypealias.kt")
public void testFunInterfaceTypealias() throws Exception {
runTest("compiler/testData/codegen/box/funInterface/funInterfaceTypealias.kt");
}
@Test
@TestMetadata("funInterfaceWithReceiver.kt")
public void testFunInterfaceWithReceiver() throws Exception {
@@ -12185,6 +12185,11 @@ public class IrCodegenBoxWasmTestGenerated extends AbstractIrCodegenBoxWasmTest
runTest("compiler/testData/codegen/box/funInterface/funInterfaceInheritance.kt");
}
@TestMetadata("funInterfaceTypealias.kt")
public void testFunInterfaceTypealias() throws Exception {
runTest("compiler/testData/codegen/box/funInterface/funInterfaceTypealias.kt");
}
@TestMetadata("funInterfaceWithReceiver.kt")
public void testFunInterfaceWithReceiver() throws Exception {
runTest("compiler/testData/codegen/box/funInterface/funInterfaceWithReceiver.kt");
@@ -14749,6 +14749,12 @@ public class NativeCodegenBoxTestGenerated extends AbstractNativeCodegenBoxTest
runTest("compiler/testData/codegen/box/funInterface/funInterfaceInheritance.kt");
}
@Test
@TestMetadata("funInterfaceTypealias.kt")
public void testFunInterfaceTypealias() throws Exception {
runTest("compiler/testData/codegen/box/funInterface/funInterfaceTypealias.kt");
}
@Test
@TestMetadata("funInterfaceWithReceiver.kt")
public void testFunInterfaceWithReceiver() throws Exception {