From 6e58ba8f330910b55187d7fed342ef24c80e992c Mon Sep 17 00:00:00 2001 From: Mikhail Glukhikh Date: Tue, 23 May 2023 14:43:41 +0200 Subject: [PATCH] FE: don't approximate type variable based types for public/local declarations #KT-58618 Fixed --- .../kotlin/types/AbstractTypeApproximator.kt | 11 +++++++- .../types/TypeApproximatorConfiguration.kt | 16 +++++++++-- .../noInferenceFromWrappedDelegate.fir.kt | 13 --------- .../noInferenceFromWrappedDelegate.fir.txt | 28 +++++++++---------- .../noInferenceFromWrappedDelegate.kt | 7 +++-- 5 files changed, 41 insertions(+), 34 deletions(-) delete mode 100644 compiler/testData/diagnostics/tests/delegatedProperty/noInferenceFromWrappedDelegate.fir.kt diff --git a/compiler/resolution.common/src/org/jetbrains/kotlin/types/AbstractTypeApproximator.kt b/compiler/resolution.common/src/org/jetbrains/kotlin/types/AbstractTypeApproximator.kt index 135323d437b..89a322553a3 100644 --- a/compiler/resolution.common/src/org/jetbrains/kotlin/types/AbstractTypeApproximator.kt +++ b/compiler/resolution.common/src/org/jetbrains/kotlin/types/AbstractTypeApproximator.kt @@ -375,7 +375,7 @@ abstract class AbstractTypeApproximator( } if (typeConstructor is TypeVariableTypeConstructorMarker) { - return if (conf.typeVariable(typeConstructor)) null else type.defaultResult(toSuper) + return if (shouldHandleAsTypeVariable(conf, typeConstructor)) null else type.defaultResult(toSuper) } if (typeConstructor.isIntegerLiteralConstantTypeConstructor()) { @@ -393,6 +393,15 @@ abstract class AbstractTypeApproximator( return approximateLocalTypes(type, conf, toSuper, depth) // simple classifier type } + private fun shouldHandleAsTypeVariable( + conf: TypeApproximatorConfiguration, + typeConstructorMarker: TypeVariableTypeConstructorMarker, + ): Boolean = when (conf.typeVariable(typeConstructorMarker)) { + TypeApproximatorConfiguration.HandleAsTypeVariable.ALWAYS -> true + TypeApproximatorConfiguration.HandleAsTypeVariable.K2_ONLY -> isK2 + TypeApproximatorConfiguration.HandleAsTypeVariable.NEVER -> false + } + private fun approximateDefinitelyNotNullType( type: DefinitelyNotNullTypeMarker, conf: TypeApproximatorConfiguration, diff --git a/compiler/resolution.common/src/org/jetbrains/kotlin/types/TypeApproximatorConfiguration.kt b/compiler/resolution.common/src/org/jetbrains/kotlin/types/TypeApproximatorConfiguration.kt index e440b2d192d..61e2043d3c4 100644 --- a/compiler/resolution.common/src/org/jetbrains/kotlin/types/TypeApproximatorConfiguration.kt +++ b/compiler/resolution.common/src/org/jetbrains/kotlin/types/TypeApproximatorConfiguration.kt @@ -38,7 +38,13 @@ open class TypeApproximatorConfiguration { */ open val anonymous = false - open val typeVariable: (TypeVariableTypeConstructorMarker) -> Boolean = { false } + internal enum class HandleAsTypeVariable { + ALWAYS, + K2_ONLY, + NEVER + } + + internal open val typeVariable: (TypeVariableTypeConstructorMarker) -> HandleAsTypeVariable = { HandleAsTypeVariable.NEVER } open fun capturedType(ctx: TypeSystemInferenceExtensionContext, type: CapturedTypeMarker): Boolean = true // false means that this type we can leave as is @@ -56,6 +62,8 @@ open class TypeApproximatorConfiguration { override val errorType: Boolean get() = true override val integerLiteralConstantType: Boolean get() = true override val intersectionTypesInContravariantPositions: Boolean get() = true + + override val typeVariable: (TypeVariableTypeConstructorMarker) -> HandleAsTypeVariable get() = { HandleAsTypeVariable.K2_ONLY } } open class PublicDeclaration(override val localTypes: Boolean, override val anonymous: Boolean) : AllFlexibleSameValue() { @@ -65,6 +73,8 @@ open class TypeApproximatorConfiguration { override val integerLiteralConstantType: Boolean get() = true override val intersectionTypesInContravariantPositions: Boolean get() = true + override val typeVariable: (TypeVariableTypeConstructorMarker) -> HandleAsTypeVariable get() = { HandleAsTypeVariable.K2_ONLY } + object SaveAnonymousTypes : PublicDeclaration(localTypes = false, anonymous = false) object ApproximateAnonymousTypes : PublicDeclaration(localTypes = false, anonymous = true) } @@ -79,7 +89,7 @@ open class TypeApproximatorConfiguration { approximatedCapturedStatus != null && type.captureStatus(ctx) == approximatedCapturedStatus override val intersection: IntersectionStrategy get() = IntersectionStrategy.ALLOWED - override val typeVariable: (TypeVariableTypeConstructorMarker) -> Boolean get() = { true } + override val typeVariable: (TypeVariableTypeConstructorMarker) -> HandleAsTypeVariable get() = { HandleAsTypeVariable.ALWAYS } } object IncorporationConfiguration : AbstractCapturedTypesApproximation(CaptureStatus.FOR_INCORPORATION) @@ -108,7 +118,7 @@ open class TypeApproximatorConfiguration { override val integerLiteralConstantType: Boolean get() = true override val allFlexible: Boolean get() = true override val intersection: IntersectionStrategy get() = IntersectionStrategy.ALLOWED - override val typeVariable: (TypeVariableTypeConstructorMarker) -> Boolean get() = { true } + override val typeVariable: (TypeVariableTypeConstructorMarker) -> HandleAsTypeVariable get() = { HandleAsTypeVariable.ALWAYS } override val errorType: Boolean get() = true override fun capturedType(ctx: TypeSystemInferenceExtensionContext, type: CapturedTypeMarker): Boolean = false diff --git a/compiler/testData/diagnostics/tests/delegatedProperty/noInferenceFromWrappedDelegate.fir.kt b/compiler/testData/diagnostics/tests/delegatedProperty/noInferenceFromWrappedDelegate.fir.kt deleted file mode 100644 index 35a2d6023ca..00000000000 --- a/compiler/testData/diagnostics/tests/delegatedProperty/noInferenceFromWrappedDelegate.fir.kt +++ /dev/null @@ -1,13 +0,0 @@ -// FIR_DUMP -// WITH_REFLECT - -import kotlin.reflect.KProperty - -// Definitions -class State(var value: T) -inline operator fun State.getValue(thisRef: Any?, property: KProperty<*>): T = value -inline fun remember(block: () -> T): T = block() - -// list should have a type of List, not Any? -val list by remember { State(listOf(0)) } -val first = list.first() diff --git a/compiler/testData/diagnostics/tests/delegatedProperty/noInferenceFromWrappedDelegate.fir.txt b/compiler/testData/diagnostics/tests/delegatedProperty/noInferenceFromWrappedDelegate.fir.txt index 03acd3eae75..48d0006bd90 100644 --- a/compiler/testData/diagnostics/tests/delegatedProperty/noInferenceFromWrappedDelegate.fir.txt +++ b/compiler/testData/diagnostics/tests/delegatedProperty/noInferenceFromWrappedDelegate.fir.txt @@ -1,26 +1,26 @@ -FILE: noInferenceFromWrappedDelegate.fir.kt - public final class State : R|kotlin/Any| { - public constructor(value: R|T|): R|State| { +FILE: noInferenceFromWrappedDelegate.kt + public final class State : R|kotlin/Any| { + public constructor(value: R|S|): R|State| { super() } - public final var value: R|T| = R|/value| - public get(): R|T| - public set(value: R|T|): R|kotlin/Unit| + public final var value: R|S| = R|/value| + public get(): R|S| + public set(value: R|S|): R|kotlin/Unit| } - public final inline operator fun R|State|.getValue(thisRef: R|kotlin/Any?|, property: R|kotlin/reflect/KProperty<*>|): R|T| { - ^getValue this@R|/getValue|.R|SubstitutionOverride| + public final inline operator fun R|State|.getValue(thisRef: R|kotlin/Any?|, property: R|kotlin/reflect/KProperty<*>|): R|V| { + ^getValue this@R|/getValue|.R|SubstitutionOverride| } - public final inline fun remember(block: R|() -> T|): R|T| { - ^remember R|/block|.R|SubstitutionOverride|() + public final inline fun remember(block: R|() -> M|): R|M| { + ^remember R|/block|.R|SubstitutionOverride|() } - public final val list: R|kotlin/Any?|by R|/remember|>|>( = remember@fun (): R|State>| { + public final val list: R|kotlin/collections/List|by R|/remember|>|>( = remember@fun (): R|State>| { ^ R|/State.State||>(R|kotlin/collections/listOf|(Int(0))) } ) - public get(): R|kotlin/Any?| { + public get(): R|kotlin/collections/List| { ^ D|/list|.R|/getValue||>(Null(null), ::R|/list|) } - public final val first: = R|/list|.#() - public get(): + public final val first: R|kotlin/Int| = R|/list|.R|kotlin/collections/first|() + public get(): R|kotlin/Int| diff --git a/compiler/testData/diagnostics/tests/delegatedProperty/noInferenceFromWrappedDelegate.kt b/compiler/testData/diagnostics/tests/delegatedProperty/noInferenceFromWrappedDelegate.kt index c5bedb45330..ebf120330f6 100644 --- a/compiler/testData/diagnostics/tests/delegatedProperty/noInferenceFromWrappedDelegate.kt +++ b/compiler/testData/diagnostics/tests/delegatedProperty/noInferenceFromWrappedDelegate.kt @@ -1,12 +1,13 @@ +// FIR_IDENTICAL // FIR_DUMP // WITH_REFLECT import kotlin.reflect.KProperty // Definitions -class State(var value: T) -inline operator fun State.getValue(thisRef: Any?, property: KProperty<*>): T = value -inline fun remember(block: () -> T): T = block() +class State(var value: S) +inline operator fun State.getValue(thisRef: Any?, property: KProperty<*>): V = value +inline fun remember(block: () -> M): M = block() // list should have a type of List, not Any? val list by remember { State(listOf(0)) }