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 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 {
|
fun FirTypeRef.toIrType(typeContext: ConversionTypeContext = ConversionTypeContext.DEFAULT): IrType {
|
||||||
capturedTypeCache.clear()
|
capturedTypeCache.clear()
|
||||||
return when (this) {
|
return when (this) {
|
||||||
@@ -232,11 +240,9 @@ class Fir2IrTypeConverter(
|
|||||||
} else null
|
} else null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val typeWithSpecifiedIntersectionTypes = substitutor.substituteOrSelf(type)
|
return substitutor.substituteOrSelf(type).let {
|
||||||
return typeApproximator.approximateToSuperType(
|
typeApproximator.approximateToSuperType(it, typeApproximatorConfiguration) ?: it
|
||||||
typeWithSpecifiedIntersectionTypes,
|
}
|
||||||
TypeApproximatorConfiguration.PublicDeclaration
|
|
||||||
) ?: type
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+12
-4
@@ -8,9 +8,7 @@ package org.jetbrains.kotlin.psi2ir.generators
|
|||||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||||
import org.jetbrains.kotlin.ir.util.*
|
import org.jetbrains.kotlin.ir.util.*
|
||||||
import org.jetbrains.kotlin.types.CommonSupertypes
|
import org.jetbrains.kotlin.types.*
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
|
||||||
import org.jetbrains.kotlin.types.TypeApproximator
|
|
||||||
|
|
||||||
class TypeTranslatorImpl(
|
class TypeTranslatorImpl(
|
||||||
symbolTable: ReferenceSymbolTable,
|
symbolTable: ReferenceSymbolTable,
|
||||||
@@ -25,8 +23,18 @@ class TypeTranslatorImpl(
|
|||||||
|
|
||||||
private val typeApproximatorForNI = TypeApproximator(moduleDescriptor.builtIns, languageVersionSettings)
|
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 =
|
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 =
|
override fun commonSupertype(types: Collection<KotlinType>): KotlinType =
|
||||||
CommonSupertypes.commonSupertype(types)
|
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> id(x: T): T = x
|
||||||
fun <T> String.extId(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 <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
|
// 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> id(x: T): T = x
|
||||||
fun <T> String.extId(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, 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 <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 {
|
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 {
|
inline fun <reified K : Any?> In<K>.ofType(y: Any?): Boolean {
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ FILE fqName:<root> fileName:/intersectionType1_NI.kt
|
|||||||
BLOCK_BODY
|
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>'
|
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
|
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
|
$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
|
$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>>
|
<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);
|
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")
|
@TestMetadata("booleanNotIntrinsic.kt")
|
||||||
public void testBooleanNotIntrinsic() throws Exception {
|
public void testBooleanNotIntrinsic() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/callableReference/function/booleanNotIntrinsic.kt");
|
runTest("compiler/testData/codegen/box/callableReference/function/booleanNotIntrinsic.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user