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.
This commit is contained in:
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+12
-4
@@ -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>): KotlinType =
|
||||
CommonSupertypes.commonSupertype(types)
|
||||
|
||||
@@ -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 <T> id(x: T): T = x
|
||||
fun <T> String.extId(x: T): T = x
|
||||
|
||||
fun <T> foo(value: T?): T? = value?.let(::id) // KFunction1<Nothing, T>
|
||||
fun <T> foo(value: T?): T? = value?.let(::id) // ::id = KFunction1<T!!, T!!>
|
||||
fun <T> bar(value: T?): T? = value?.let(""::extId)
|
||||
|
||||
fun box() = foo("O")!! + foo("K")!!
|
||||
fun box() = foo("O")!! + bar("K")!!
|
||||
|
||||
+3
-5
@@ -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 <T> id(x: T): T = x
|
||||
fun <T> String.extId(x: T): T = x
|
||||
|
||||
fun <T, R> T.myLet(block: (T) -> R): R = block(this)
|
||||
|
||||
fun <T> foo(value: T?): T? = value?.myLet(::id) // KFunction1<Nothing, T>
|
||||
fun <T> foo(value: T?): T? = value?.myLet(::id) // ::id = KFunction1<T!!, T!!>
|
||||
fun <T> bar(value: T?): T? = value?.myLet(""::extId)
|
||||
|
||||
fun box() = foo("O")!! + foo("K")!!
|
||||
fun box() = foo("O")!! + bar("K")!!
|
||||
|
||||
@@ -12,7 +12,7 @@ fun <S : Any?> select(x: S, y: S): S {
|
||||
}
|
||||
|
||||
fun <T : Any?> foo(a: Array<In<T>>, b: Array<In<String>>): Boolean {
|
||||
return select<Array<out In<Nothing>>>(x = a, y = b).get(index = 0).ofType<Any?>(y = true)
|
||||
return select<Array<out In<Nothing>>>(x = a, y = b).get(index = 0).ofType<Any>(y = true)
|
||||
}
|
||||
|
||||
inline fun <reified K : Any?> In<K>.ofType(y: Any?): Boolean {
|
||||
|
||||
@@ -33,7 +33,7 @@ FILE fqName:<root> fileName:/intersectionType1_NI.kt
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from='public final fun foo <T> (a: kotlin.Array<<root>.In<T of <root>.foo>>, b: kotlin.Array<<root>.In<kotlin.String>>): kotlin.Boolean declared in <root>'
|
||||
CALL 'public final fun ofType <K> (y: kotlin.Any?): kotlin.Boolean [inline] declared in <root>' type=kotlin.Boolean origin=null
|
||||
<K>: kotlin.Any?
|
||||
<K>: kotlin.Any
|
||||
$receiver: CALL 'public final fun get (index: kotlin.Int): T of kotlin.Array [operator] declared in kotlin.Array' type=<root>.In<kotlin.Nothing> origin=GET_ARRAY_ELEMENT
|
||||
$this: CALL 'public final fun select <S> (x: S of <root>.select, y: S of <root>.select): S of <root>.select declared in <root>' type=kotlin.Array<out <root>.In<kotlin.Nothing>> origin=null
|
||||
<S>: kotlin.Array<out <root>.In<kotlin.Nothing>>
|
||||
|
||||
js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/wasm/semantics/IrCodegenBoxWasmTestGenerated.java
Generated
+5
@@ -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");
|
||||
|
||||
Reference in New Issue
Block a user