From d5d6736e672ced8a9578e3a583a48d272b63abff Mon Sep 17 00:00:00 2001 From: pyos Date: Mon, 10 May 2021 13:12:02 +0200 Subject: [PATCH] PSI2IR/FIR2IR: do not approximate T!! before translation This leads to weird effects when it's in a contravariant position, because it's approximated by Nothing. --- .../kotlin/fir/backend/Fir2IrTypeConverter.kt | 16 +++++++++++----- .../psi2ir/generators/TypeTranslatorImpl.kt | 16 ++++++++++++---- .../callableReference/function/argumentTypes.kt | 8 ++------ .../function/argumentTypesNoinline.kt | 8 +++----- .../ir/irText/types/intersectionType1_NI.kt.txt | 2 +- .../ir/irText/types/intersectionType1_NI.txt | 2 +- .../semantics/IrCodegenBoxWasmTestGenerated.java | 5 +++++ 7 files changed, 35 insertions(+), 22 deletions(-) diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrTypeConverter.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrTypeConverter.kt index 91848564cd5..48ad011a667 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrTypeConverter.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrTypeConverter.kt @@ -67,6 +67,14 @@ class Fir2IrTypeConverter( private val typeApproximator = ConeTypeApproximator(session.typeContext, session.languageVersionSettings) + private val typeApproximatorConfiguration = + object : TypeApproximatorConfiguration.AllFlexibleSameValue() { + override val allFlexible: Boolean get() = true + override val errorType: Boolean get() = true + override val integerLiteralType: Boolean get() = true + override val intersectionTypesInContravariantPositions: Boolean get() = true + } + fun FirTypeRef.toIrType(typeContext: ConversionTypeContext = ConversionTypeContext.DEFAULT): IrType { capturedTypeCache.clear() return when (this) { @@ -232,11 +240,9 @@ class Fir2IrTypeConverter( } else null } } - val typeWithSpecifiedIntersectionTypes = substitutor.substituteOrSelf(type) - return typeApproximator.approximateToSuperType( - typeWithSpecifiedIntersectionTypes, - TypeApproximatorConfiguration.PublicDeclaration - ) ?: type + return substitutor.substituteOrSelf(type).let { + typeApproximator.approximateToSuperType(it, typeApproximatorConfiguration) ?: it + } } } diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/TypeTranslatorImpl.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/TypeTranslatorImpl.kt index f74e1e58fda..14f11cf7c5d 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/TypeTranslatorImpl.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/TypeTranslatorImpl.kt @@ -8,9 +8,7 @@ package org.jetbrains.kotlin.psi2ir.generators import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.ir.util.* -import org.jetbrains.kotlin.types.CommonSupertypes -import org.jetbrains.kotlin.types.KotlinType -import org.jetbrains.kotlin.types.TypeApproximator +import org.jetbrains.kotlin.types.* class TypeTranslatorImpl( symbolTable: ReferenceSymbolTable, @@ -25,8 +23,18 @@ class TypeTranslatorImpl( private val typeApproximatorForNI = TypeApproximator(moduleDescriptor.builtIns, languageVersionSettings) + private val typeApproximatorConfiguration = + object : TypeApproximatorConfiguration.AllFlexibleSameValue() { + override val allFlexible: Boolean get() = true + override val errorType: Boolean get() = true + override val integerLiteralType: Boolean get() = true + override val intersectionTypesInContravariantPositions: Boolean get() = true + } + override fun approximateType(type: KotlinType): KotlinType = - typeApproximatorForNI.approximateDeclarationType(type, local = false) + substituteAlternativesInPublicType(type).let { + typeApproximatorForNI.approximateToSuperType(it, typeApproximatorConfiguration) ?: it + } override fun commonSupertype(types: Collection): KotlinType = CommonSupertypes.commonSupertype(types) diff --git a/compiler/testData/codegen/box/callableReference/function/argumentTypes.kt b/compiler/testData/codegen/box/callableReference/function/argumentTypes.kt index 459465d976b..0b65af1abd6 100644 --- a/compiler/testData/codegen/box/callableReference/function/argumentTypes.kt +++ b/compiler/testData/codegen/box/callableReference/function/argumentTypes.kt @@ -1,11 +1,7 @@ -// IGNORE_BACKEND: JVM_IR -// IGNORE_BACKEND_FIR: JVM_IR -// DONT_TARGET_EXACT_BACKEND: WASM -// WASM_MUTE_REASON: CALLABLE_REFERENCES_FAIL fun id(x: T): T = x fun String.extId(x: T): T = x -fun foo(value: T?): T? = value?.let(::id) // KFunction1 +fun foo(value: T?): T? = value?.let(::id) // ::id = KFunction1 fun bar(value: T?): T? = value?.let(""::extId) -fun box() = foo("O")!! + foo("K")!! +fun box() = foo("O")!! + bar("K")!! diff --git a/compiler/testData/codegen/box/callableReference/function/argumentTypesNoinline.kt b/compiler/testData/codegen/box/callableReference/function/argumentTypesNoinline.kt index afb44b7bf53..757bc97d72d 100644 --- a/compiler/testData/codegen/box/callableReference/function/argumentTypesNoinline.kt +++ b/compiler/testData/codegen/box/callableReference/function/argumentTypesNoinline.kt @@ -1,13 +1,11 @@ -// IGNORE_BACKEND: JVM_IR -// IGNORE_BACKEND_FIR: JVM_IR // DONT_TARGET_EXACT_BACKEND: WASM -// WASM_MUTE_REASON: CALLABLE_REFERENCES_FAIL +// WASM_MUTE_REASON: BINDING_RECEIVERS fun id(x: T): T = x fun String.extId(x: T): T = x fun T.myLet(block: (T) -> R): R = block(this) -fun foo(value: T?): T? = value?.myLet(::id) // KFunction1 +fun foo(value: T?): T? = value?.myLet(::id) // ::id = KFunction1 fun bar(value: T?): T? = value?.myLet(""::extId) -fun box() = foo("O")!! + foo("K")!! +fun box() = foo("O")!! + bar("K")!! diff --git a/compiler/testData/ir/irText/types/intersectionType1_NI.kt.txt b/compiler/testData/ir/irText/types/intersectionType1_NI.kt.txt index 00b80c7c3ab..7aaeee102a3 100644 --- a/compiler/testData/ir/irText/types/intersectionType1_NI.kt.txt +++ b/compiler/testData/ir/irText/types/intersectionType1_NI.kt.txt @@ -12,7 +12,7 @@ fun select(x: S, y: S): S { } fun foo(a: Array>, b: Array>): Boolean { - return select>>(x = a, y = b).get(index = 0).ofType(y = true) + return select>>(x = a, y = b).get(index = 0).ofType(y = true) } inline fun In.ofType(y: Any?): Boolean { diff --git a/compiler/testData/ir/irText/types/intersectionType1_NI.txt b/compiler/testData/ir/irText/types/intersectionType1_NI.txt index 5193f4a299f..990165170a8 100644 --- a/compiler/testData/ir/irText/types/intersectionType1_NI.txt +++ b/compiler/testData/ir/irText/types/intersectionType1_NI.txt @@ -33,7 +33,7 @@ FILE fqName: fileName:/intersectionType1_NI.kt BLOCK_BODY RETURN type=kotlin.Nothing from='public final fun foo (a: kotlin.Array<.In.foo>>, b: kotlin.Array<.In>): kotlin.Boolean declared in ' CALL 'public final fun ofType (y: kotlin.Any?): kotlin.Boolean [inline] declared in ' type=kotlin.Boolean origin=null - : kotlin.Any? + : kotlin.Any $receiver: CALL 'public final fun get (index: kotlin.Int): T of kotlin.Array [operator] declared in kotlin.Array' type=.In origin=GET_ARRAY_ELEMENT $this: CALL 'public final fun select (x: S of .select, y: S of .select): S of .select declared in ' type=kotlin.Array.In> origin=null : kotlin.Array.In> diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/wasm/semantics/IrCodegenBoxWasmTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/wasm/semantics/IrCodegenBoxWasmTestGenerated.java index f8c4feb0d11..c987aa08263 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/wasm/semantics/IrCodegenBoxWasmTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/wasm/semantics/IrCodegenBoxWasmTestGenerated.java @@ -1437,6 +1437,11 @@ public class IrCodegenBoxWasmTestGenerated extends AbstractIrCodegenBoxWasmTest KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/callableReference/function"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.WASM, true); } + @TestMetadata("argumentTypes.kt") + public void testArgumentTypes() throws Exception { + runTest("compiler/testData/codegen/box/callableReference/function/argumentTypes.kt"); + } + @TestMetadata("booleanNotIntrinsic.kt") public void testBooleanNotIntrinsic() throws Exception { runTest("compiler/testData/codegen/box/callableReference/function/booleanNotIntrinsic.kt");