Type Approximation: add separate flag to control approx. anonymous type

This extra flexibility is useful for IDE where we always want to
approximate anonymous types but may not want to approximate other local
 types
This commit is contained in:
Tianyu Geng
2021-12-07 10:31:29 -08:00
committed by teamcity
parent c5c606924c
commit a5844b754e
7 changed files with 28 additions and 2 deletions
@@ -28,5 +28,6 @@ internal object PublicTypeApproximator {
override val definitelyNotNullType: Boolean get() = false override val definitelyNotNullType: Boolean get() = false
override val integerLiteralType: Boolean get() = true override val integerLiteralType: Boolean get() = true
override val intersectionTypesInContravariantPositions: Boolean get() = true override val intersectionTypesInContravariantPositions: Boolean get() = true
override val anonymous: Boolean get() = true
} }
} }
@@ -24,6 +24,7 @@ import org.jetbrains.kotlin.fir.symbols.ensureResolved
import org.jetbrains.kotlin.fir.symbols.impl.* import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.FqNameUnsafe import org.jetbrains.kotlin.name.FqNameUnsafe
import org.jetbrains.kotlin.name.SpecialNames
import org.jetbrains.kotlin.name.StandardClassIds import org.jetbrains.kotlin.name.StandardClassIds
import org.jetbrains.kotlin.types.TypeCheckerState import org.jetbrains.kotlin.types.TypeCheckerState
import org.jetbrains.kotlin.types.TypeCheckerState.SupertypesPolicy.DoCustomTransform import org.jetbrains.kotlin.types.TypeCheckerState.SupertypesPolicy.DoCustomTransform
@@ -47,6 +48,11 @@ interface ConeTypeContext : TypeSystemContext, TypeSystemOptimizationContext, Ty
return classId.isLocal return classId.isLocal
} }
override fun TypeConstructorMarker.isAnonymous(): Boolean {
if (this !is ConeClassLikeLookupTag) return false
return name == SpecialNames.ANONYMOUS
}
override val TypeVariableTypeConstructorMarker.typeParameter: TypeParameterMarker? override val TypeVariableTypeConstructorMarker.typeParameter: TypeParameterMarker?
get() { get() {
require(this is ConeTypeVariableTypeConstructor) require(this is ConeTypeVariableTypeConstructor)
@@ -24,6 +24,7 @@ import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.FqNameUnsafe import org.jetbrains.kotlin.name.FqNameUnsafe
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.name.SpecialNames
import org.jetbrains.kotlin.types.TypeCheckerState import org.jetbrains.kotlin.types.TypeCheckerState
import org.jetbrains.kotlin.types.TypeSystemCommonBackendContext import org.jetbrains.kotlin.types.TypeSystemCommonBackendContext
import org.jetbrains.kotlin.types.Variance import org.jetbrains.kotlin.types.Variance
@@ -310,6 +311,11 @@ interface IrTypeSystemContext : TypeSystemContext, TypeSystemCommonSuperTypesCon
return this.owner.classId?.isLocal == true return this.owner.classId?.isLocal == true
} }
override fun TypeConstructorMarker.isAnonymous(): Boolean {
if (this !is IrClassSymbol) return false
return this.owner.classId?.shortClassName == SpecialNames.ANONYMOUS
}
override val TypeVariableTypeConstructorMarker.typeParameter: TypeParameterMarker? override val TypeVariableTypeConstructorMarker.typeParameter: TypeParameterMarker?
get() = error("Type variables is unsupported in IR") get() = error("Type variables is unsupported in IR")
@@ -169,9 +169,9 @@ abstract class AbstractTypeApproximator(
private fun approximateLocalTypes(type: SimpleTypeMarker, conf: TypeApproximatorConfiguration, toSuper: Boolean): SimpleTypeMarker? { private fun approximateLocalTypes(type: SimpleTypeMarker, conf: TypeApproximatorConfiguration, toSuper: Boolean): SimpleTypeMarker? {
if (!toSuper) return null if (!toSuper) return null
if (!conf.localTypes) return null if (!conf.localTypes && !conf.anonymous) return null
val constructor = type.typeConstructor() val constructor = type.typeConstructor()
val needApproximate = conf.localTypes && constructor.isLocalType() val needApproximate = (conf.localTypes && constructor.isLocalType()) || (conf.anonymous && constructor.isAnonymous())
if (!needApproximate) return null if (!needApproximate) return null
val superConstructor = constructor.supertypes().first().typeConstructor() val superConstructor = constructor.supertypes().first().typeConstructor()
val typeCheckerContext = newTypeCheckerState( val typeCheckerContext = newTypeCheckerState(
@@ -25,6 +25,12 @@ open class TypeApproximatorConfiguration {
open val intersectionTypesInContravariantPositions = false open val intersectionTypesInContravariantPositions = false
open val localTypes = false open val localTypes = false
/**
* Whether to approximate anonymous type. This flag does not have any effect if `localTypes` is true because all anonymous types are
* local.
*/
open val anonymous = false
open val typeVariable: (TypeVariableTypeConstructorMarker) -> Boolean = { false } open val typeVariable: (TypeVariableTypeConstructorMarker) -> Boolean = { false }
open fun capturedType(ctx: TypeSystemInferenceExtensionContext, type: CapturedTypeMarker): Boolean = open fun capturedType(ctx: TypeSystemInferenceExtensionContext, type: CapturedTypeMarker): Boolean =
true // false means that this type we can leave as is true // false means that this type we can leave as is
@@ -377,6 +377,7 @@ interface TypeSystemContext : TypeSystemOptimizationContext {
fun TypeConstructorMarker.isInterface(): Boolean fun TypeConstructorMarker.isInterface(): Boolean
fun TypeConstructorMarker.isIntegerLiteralTypeConstructor(): Boolean fun TypeConstructorMarker.isIntegerLiteralTypeConstructor(): Boolean
fun TypeConstructorMarker.isLocalType(): Boolean fun TypeConstructorMarker.isLocalType(): Boolean
fun TypeConstructorMarker.isAnonymous(): Boolean
fun TypeConstructorMarker.getTypeParameterClassifier(): TypeParameterMarker? fun TypeConstructorMarker.getTypeParameterClassifier(): TypeParameterMarker?
val TypeVariableTypeConstructorMarker.typeParameter: TypeParameterMarker? val TypeVariableTypeConstructorMarker.typeParameter: TypeParameterMarker?
@@ -15,6 +15,7 @@ import org.jetbrains.kotlin.descriptors.impl.AbstractTypeParameterDescriptor
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.FqNameUnsafe import org.jetbrains.kotlin.name.FqNameUnsafe
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.name.SpecialNames
import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.calls.inference.CapturedType import org.jetbrains.kotlin.resolve.calls.inference.CapturedType
import org.jetbrains.kotlin.resolve.constants.IntegerLiteralTypeConstructor import org.jetbrains.kotlin.resolve.constants.IntegerLiteralTypeConstructor
@@ -44,6 +45,11 @@ interface ClassicTypeSystemContext : TypeSystemInferenceExtensionContext, TypeSy
return declarationDescriptor?.classId?.isLocal == true return declarationDescriptor?.classId?.isLocal == true
} }
override fun TypeConstructorMarker.isAnonymous(): Boolean {
require(this is TypeConstructor, this::errorMessage)
return declarationDescriptor?.classId?.shortClassName == SpecialNames.ANONYMOUS
}
override val TypeVariableTypeConstructorMarker.typeParameter: TypeParameterMarker? override val TypeVariableTypeConstructorMarker.typeParameter: TypeParameterMarker?
get() { get() {
require(this is NewTypeVariableConstructor, this::errorMessage) require(this is NewTypeVariableConstructor, this::errorMessage)