[FIR] Fix TODOs and cleanup ConeTypeContext and ConeInferenceContext

This commit is contained in:
Dmitriy Novozhilov
2021-02-03 12:25:50 +03:00
parent 373bc578fb
commit 57d29009ee
5 changed files with 86 additions and 51 deletions
@@ -0,0 +1,31 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.fir.declarations
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
import org.jetbrains.kotlin.fir.resolve.substitution.createTypeSubstitutorByTypeConstructor
import org.jetbrains.kotlin.fir.resolve.toSymbol
import org.jetbrains.kotlin.fir.resolve.transformers.ensureResolved
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.types.model.typeConstructor
fun ConeKotlinType.substitutedUnderlyingTypeForInlineClass(session: FirSession, context: ConeTypeContext): ConeKotlinType? {
val symbol = (this.fullyExpandedType(session) as? ConeLookupTagBasedType)
?.lookupTag
?.toSymbol(session) as? FirRegularClassSymbol
?: return null
symbol.ensureResolved(FirResolvePhase.STATUS, session)
val firClass = symbol.fir
if (!firClass.status.isInline) return null
val constructor = firClass.declarations.singleOrNull { it is FirConstructor && it.isPrimary } as FirConstructor? ?: return null
val valueParameter = constructor.valueParameters.singleOrNull() ?: return null
val unsubstitutedType = valueParameter.returnTypeRef.coneType
val substitutor = createTypeSubstitutorByTypeConstructor(mapOf(this.typeConstructor(context) to this), context)
return substitutor.substituteOrNull(unsubstitutedType)
}
@@ -10,6 +10,10 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol
import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl
import org.jetbrains.kotlin.types.TypeApproximatorConfiguration import org.jetbrains.kotlin.types.TypeApproximatorConfiguration
import org.jetbrains.kotlin.types.model.KotlinTypeMarker
import org.jetbrains.kotlin.types.model.TypeConstructorMarker
import org.jetbrains.kotlin.types.model.TypeSubstitutorMarker
import org.jetbrains.kotlin.types.model.typeConstructor
abstract class AbstractConeSubstitutor : ConeSubstitutor() { abstract class AbstractConeSubstitutor : ConeSubstitutor() {
private fun wrapProjection(old: ConeTypeProjection, newType: ConeKotlinType): ConeTypeProjection { private fun wrapProjection(old: ConeTypeProjection, newType: ConeKotlinType): ConeTypeProjection {
@@ -162,3 +166,15 @@ data class ConeSubstitutorByMap(val substitution: Map<FirTypeParameterSymbol, Co
return result return result
} }
} }
fun createTypeSubstitutorByTypeConstructor(map: Map<TypeConstructorMarker, ConeKotlinType>, context: ConeTypeContext): ConeSubstitutor {
if (map.isEmpty()) return ConeSubstitutor.Empty
return object : AbstractConeSubstitutor(),
TypeSubstitutorMarker {
override fun substituteType(type: ConeKotlinType): ConeKotlinType? {
if (type !is ConeLookupTagBasedType && type !is ConeStubType) return null
val new = map[type.typeConstructor(context)] ?: return null
return new.approximateIntegerLiteralType().updateNullabilityIfNeeded(type)
}
}
}
@@ -11,7 +11,7 @@ fun ConeKotlinType.createOutArrayType(nullable: Boolean = false): ConeKotlinType
return ConeKotlinTypeProjectionOut(this).createArrayType(nullable) return ConeKotlinTypeProjectionOut(this).createArrayType(nullable)
} }
fun ConeTypeProjection.createArrayType(nullable: Boolean = false): ConeKotlinType { fun ConeTypeProjection.createArrayType(nullable: Boolean = false): ConeClassLikeType {
if (this is ConeKotlinTypeProjection) { if (this is ConeKotlinTypeProjection) {
val type = type.lowerBoundIfFlexible() val type = type.lowerBoundIfFlexible()
if (type is ConeClassLikeType && type.nullability != ConeNullability.NULLABLE) { if (type is ConeClassLikeType && type.nullability != ConeNullability.NULLABLE) {
@@ -13,8 +13,8 @@ import org.jetbrains.kotlin.fir.resolve.calls.NoSubstitutor
import org.jetbrains.kotlin.fir.resolve.inference.isBuiltinFunctionalType import org.jetbrains.kotlin.fir.resolve.inference.isBuiltinFunctionalType
import org.jetbrains.kotlin.fir.resolve.inference.isSuspendFunctionType import org.jetbrains.kotlin.fir.resolve.inference.isSuspendFunctionType
import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider
import org.jetbrains.kotlin.fir.resolve.substitution.AbstractConeSubstitutor
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
import org.jetbrains.kotlin.fir.resolve.substitution.createTypeSubstitutorByTypeConstructor
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
import org.jetbrains.kotlin.fir.symbols.ConeTypeParameterLookupTag import org.jetbrains.kotlin.fir.symbols.ConeTypeParameterLookupTag
import org.jetbrains.kotlin.fir.symbols.StandardClassIds import org.jetbrains.kotlin.fir.symbols.StandardClassIds
@@ -32,19 +32,19 @@ interface ConeInferenceContext : TypeSystemInferenceExtensionContext, ConeTypeCo
val symbolProvider: FirSymbolProvider get() = session.symbolProvider val symbolProvider: FirSymbolProvider get() = session.symbolProvider
override fun nullableNothingType(): SimpleTypeMarker { override fun nullableNothingType(): SimpleTypeMarker {
return session.builtinTypes.nullableNothingType.type//StandardClassIds.Nothing(symbolProvider).constructType(emptyArray(), true) return session.builtinTypes.nullableNothingType.type
} }
override fun nullableAnyType(): SimpleTypeMarker { override fun nullableAnyType(): SimpleTypeMarker {
return session.builtinTypes.nullableAnyType.type//StandardClassIds.Any(symbolProvider).constructType(emptyArray(), true) return session.builtinTypes.nullableAnyType.type
} }
override fun nothingType(): SimpleTypeMarker { override fun nothingType(): SimpleTypeMarker {
return session.builtinTypes.nothingType.type//StandardClassIds.Nothing(symbolProvider).constructType(emptyArray(), false) return session.builtinTypes.nothingType.type
} }
override fun anyType(): SimpleTypeMarker { override fun anyType(): SimpleTypeMarker {
return session.builtinTypes.anyType.type//StandardClassIds.Any(symbolProvider).constructType(emptyArray(), false) return session.builtinTypes.anyType.type
} }
override fun createFlexibleType(lowerBound: SimpleTypeMarker, upperBound: SimpleTypeMarker): KotlinTypeMarker { override fun createFlexibleType(lowerBound: SimpleTypeMarker, upperBound: SimpleTypeMarker): KotlinTypeMarker {
@@ -102,14 +102,13 @@ interface ConeInferenceContext : TypeSystemInferenceExtensionContext, ConeTypeCo
override fun KotlinTypeMarker.canHaveUndefinedNullability(): Boolean { override fun KotlinTypeMarker.canHaveUndefinedNullability(): Boolean {
require(this is ConeKotlinType) require(this is ConeKotlinType)
return this is ConeCapturedType /*|| this is ConeTypeVariable // TODO */ return this is ConeCapturedType || this is ConeTypeVariableType
|| this is ConeTypeParameterType || this is ConeTypeParameterType
} }
// TODO: implement checking for extension function
override fun SimpleTypeMarker.isExtensionFunction(): Boolean { override fun SimpleTypeMarker.isExtensionFunction(): Boolean {
require(this is ConeKotlinType) require(this is ConeKotlinType)
return false return this.isExtensionFunctionType
} }
override fun KotlinTypeMarker.typeDepth() = when (this) { override fun KotlinTypeMarker.typeDepth() = when (this) {
@@ -151,11 +150,6 @@ interface ConeInferenceContext : TypeSystemInferenceExtensionContext, ConeTypeCo
if (this == null) return false if (this == null) return false
if (!visited.add(this)) return false if (!visited.add(this)) return false
/*
TODO:?
UnwrappedType unwrappedType = type.unwrap();
*/
if (predicate(this)) return true if (predicate(this)) return true
val flexibleType = this as? ConeFlexibleType val flexibleType = this as? ConeFlexibleType
@@ -300,15 +294,8 @@ interface ConeInferenceContext : TypeSystemInferenceExtensionContext, ConeTypeCo
} }
override fun typeSubstitutorByTypeConstructor(map: Map<TypeConstructorMarker, KotlinTypeMarker>): ConeSubstitutor { override fun typeSubstitutorByTypeConstructor(map: Map<TypeConstructorMarker, KotlinTypeMarker>): ConeSubstitutor {
if (map.isEmpty()) return createEmptySubstitutor() @Suppress("UNCHECKED_CAST")
return object : AbstractConeSubstitutor(), return createTypeSubstitutorByTypeConstructor(map as Map<TypeConstructorMarker, ConeKotlinType>, this)
TypeSubstitutorMarker {
override fun substituteType(type: ConeKotlinType): ConeKotlinType? {
if (type !is ConeLookupTagBasedType && type !is ConeStubType) return null
val new = map[type.typeConstructor()] ?: return null
return (new as ConeKotlinType).approximateIntegerLiteralType().updateNullabilityIfNeeded(type)
}
}
} }
override fun createEmptySubstitutor(): ConeSubstitutor { override fun createEmptySubstitutor(): ConeSubstitutor {
@@ -328,7 +315,7 @@ interface ConeInferenceContext : TypeSystemInferenceExtensionContext, ConeTypeCo
} }
override fun KotlinTypeMarker.isSpecial(): Boolean { override fun KotlinTypeMarker.isSpecial(): Boolean {
// TODO // Cone type system doesn't have special types
return false return false
} }
@@ -17,7 +17,6 @@ import org.jetbrains.kotlin.fir.resolve.substitution.substitutorByMap
import org.jetbrains.kotlin.fir.resolve.toSymbol import org.jetbrains.kotlin.fir.resolve.toSymbol
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.firUnsafe import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.firUnsafe
import org.jetbrains.kotlin.fir.resolve.transformers.ensureResolved import org.jetbrains.kotlin.fir.resolve.transformers.ensureResolved
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
import org.jetbrains.kotlin.fir.symbols.ConeTypeParameterLookupTag import org.jetbrains.kotlin.fir.symbols.ConeTypeParameterLookupTag
import org.jetbrains.kotlin.fir.symbols.StandardClassIds import org.jetbrains.kotlin.fir.symbols.StandardClassIds
@@ -100,7 +99,6 @@ interface ConeTypeContext : TypeSystemContext, TypeSystemOptimizationContext, Ty
} }
override fun SimpleTypeMarker.asCapturedType(): CapturedTypeMarker? { override fun SimpleTypeMarker.asCapturedType(): CapturedTypeMarker? {
//require(this is ConeLookupTagBasedType)
return this as? ConeCapturedType return this as? ConeCapturedType
} }
@@ -124,7 +122,7 @@ interface ConeTypeContext : TypeSystemContext, TypeSystemOptimizationContext, Ty
is ConeClassLikeType -> lookupTag is ConeClassLikeType -> lookupTag
is ConeTypeParameterType -> lookupTag is ConeTypeParameterType -> lookupTag
is ConeCapturedType -> constructor is ConeCapturedType -> constructor
is ConeTypeVariableType -> lookupTag as ConeTypeVariableTypeConstructor // TODO: WTF is ConeTypeVariableType -> lookupTag
is ConeIntersectionType -> this is ConeIntersectionType -> this
is ConeStubType -> variable.typeConstructor is ConeStubType -> variable.typeConstructor
is ConeDefinitelyNotNullType -> original.typeConstructor() is ConeDefinitelyNotNullType -> original.typeConstructor()
@@ -150,20 +148,16 @@ interface ConeTypeContext : TypeSystemContext, TypeSystemOptimizationContext, Ty
override fun KotlinTypeMarker.argumentsCount(): Int { override fun KotlinTypeMarker.argumentsCount(): Int {
require(this is ConeKotlinType) require(this is ConeKotlinType)
return this.typeArguments.size return this.typeArguments.size
} }
override fun KotlinTypeMarker.getArgument(index: Int): TypeArgumentMarker { override fun KotlinTypeMarker.getArgument(index: Int): TypeArgumentMarker {
require(this is ConeKotlinType) require(this is ConeKotlinType)
return this.typeArguments.getOrNull(index) ?: ConeStarProjection
return this.typeArguments.getOrNull(index)
?: session.builtinTypes.anyType.type//StandardClassIds.Any(session.firSymbolProvider).constructType(emptyArray(), false) // TODO wtf
} }
override fun KotlinTypeMarker.asTypeArgument(): TypeArgumentMarker { override fun KotlinTypeMarker.asTypeArgument(): TypeArgumentMarker {
require(this is ConeKotlinType) require(this is ConeKotlinType)
return this return this
} }
@@ -196,7 +190,6 @@ interface ConeTypeContext : TypeSystemContext, TypeSystemOptimizationContext, Ty
} }
override fun TypeConstructorMarker.parametersCount(): Int { override fun TypeConstructorMarker.parametersCount(): Int {
//require(this is ConeSymbol)
return when (this) { return when (this) {
is ConeTypeParameterLookupTag, is ConeTypeParameterLookupTag,
is ConeCapturedTypeConstructor, is ConeCapturedTypeConstructor,
@@ -204,7 +197,7 @@ interface ConeTypeContext : TypeSystemContext, TypeSystemOptimizationContext, Ty
is ConeTypeVariableTypeConstructor, is ConeTypeVariableTypeConstructor,
is ConeIntersectionType -> 0 is ConeIntersectionType -> 0
is ConeClassLikeLookupTag -> { is ConeClassLikeLookupTag -> {
when(val symbol = toSymbol(session)) { when (val symbol = toSymbol(session)) {
is FirAnonymousObjectSymbol -> symbol.fir.typeParameters.size is FirAnonymousObjectSymbol -> symbol.fir.typeParameters.size
is FirRegularClassSymbol -> symbol.fir.typeParameters.size is FirRegularClassSymbol -> symbol.fir.typeParameters.size
is FirTypeAliasSymbol -> symbol.fir.typeParameters.size is FirTypeAliasSymbol -> symbol.fir.typeParameters.size
@@ -212,12 +205,11 @@ interface ConeTypeContext : TypeSystemContext, TypeSystemOptimizationContext, Ty
} }
} }
is ConeIntegerLiteralType -> 0 is ConeIntegerLiteralType -> 0
else -> error("?!:10") else -> unknownConstructorError()
} }
} }
override fun TypeConstructorMarker.getParameter(index: Int): TypeParameterMarker { override fun TypeConstructorMarker.getParameter(index: Int): TypeParameterMarker {
//require(this is ConeSymbol)
return when (val symbol = toClassLikeSymbol()) { return when (val symbol = toClassLikeSymbol()) {
is FirAnonymousObjectSymbol -> symbol.fir.typeParameters[index].symbol.toLookupTag() is FirAnonymousObjectSymbol -> symbol.fir.typeParameters[index].symbol.toLookupTag()
is FirRegularClassSymbol -> symbol.fir.typeParameters[index].symbol.toLookupTag() is FirRegularClassSymbol -> symbol.fir.typeParameters[index].symbol.toLookupTag()
@@ -243,7 +235,7 @@ interface ConeTypeContext : TypeSystemContext, TypeSystemOptimizationContext, Ty
is ConeCapturedTypeConstructor -> supertypes!! is ConeCapturedTypeConstructor -> supertypes!!
is ConeIntersectionType -> intersectedTypes is ConeIntersectionType -> intersectedTypes
is ConeIntegerLiteralType -> supertypes is ConeIntegerLiteralType -> supertypes
else -> error("?!:13") else -> unknownConstructorError()
} }
} }
@@ -252,7 +244,6 @@ interface ConeTypeContext : TypeSystemContext, TypeSystemOptimizationContext, Ty
} }
override fun TypeConstructorMarker.isClassTypeConstructor(): Boolean { override fun TypeConstructorMarker.isClassTypeConstructor(): Boolean {
//assert(this is ConeSymbol)
return this is ConeClassLikeLookupTag return this is ConeClassLikeLookupTag
} }
@@ -278,21 +269,21 @@ interface ConeTypeContext : TypeSystemContext, TypeSystemOptimizationContext, Ty
override fun areEqualTypeConstructors(c1: TypeConstructorMarker, c2: TypeConstructorMarker): Boolean { override fun areEqualTypeConstructors(c1: TypeConstructorMarker, c2: TypeConstructorMarker): Boolean {
if (c1 is ErrorTypeConstructor || c2 is ErrorTypeConstructor) return false if (c1 is ErrorTypeConstructor || c2 is ErrorTypeConstructor) return false
//assert(c1 is ConeSymbol)
//assert(c2 is ConeSymbol)
return c1 == c2 return c1 == c2
} }
override fun TypeConstructorMarker.isDenotable(): Boolean { override fun TypeConstructorMarker.isDenotable(): Boolean {
//TODO
return when (this) { return when (this) {
is ConeClassLikeLookupTag,
is ConeTypeParameterLookupTag -> true
is ConeCapturedTypeConstructor, is ConeCapturedTypeConstructor,
is ErrorTypeConstructor,
is ConeTypeVariableTypeConstructor, is ConeTypeVariableTypeConstructor,
is ConeIntersectionType, is ConeIntegerLiteralType,
is ConeIntegerLiteralType -> false is ConeIntersectionType -> false
is AbstractFirBasedSymbol<*> -> true
else -> true else -> unknownConstructorError()
} }
} }
@@ -413,9 +404,12 @@ interface ConeTypeContext : TypeSystemContext, TypeSystemOptimizationContext, Ty
return toClassLikeSymbol()?.fir as? FirRegularClass return toClassLikeSymbol()?.fir as? FirRegularClass
} }
override fun nullableAnyType(): SimpleTypeMarker = TODO("not implemented") override fun nullableAnyType(): SimpleTypeMarker = session.builtinTypes.nullableAnyType.type
override fun arrayType(componentType: KotlinTypeMarker): SimpleTypeMarker = TODO("not implemented") override fun arrayType(componentType: KotlinTypeMarker): SimpleTypeMarker {
require(componentType is ConeKotlinType)
return componentType.createArrayType(nullable = false)
}
override fun KotlinTypeMarker.isArrayOrNullableArray(): Boolean { override fun KotlinTypeMarker.isArrayOrNullableArray(): Boolean {
require(this is ConeKotlinType) require(this is ConeKotlinType)
@@ -459,8 +453,8 @@ interface ConeTypeContext : TypeSystemContext, TypeSystemOptimizationContext, Ty
} }
override fun KotlinTypeMarker.getSubstitutedUnderlyingType(): KotlinTypeMarker? { override fun KotlinTypeMarker.getSubstitutedUnderlyingType(): KotlinTypeMarker? {
// TODO: support inline classes require(this is ConeKotlinType)
return null return substitutedUnderlyingTypeForInlineClass(session, this@ConeTypeContext)
} }
override fun TypeConstructorMarker.getPrimitiveType() = override fun TypeConstructorMarker.getPrimitiveType() =
@@ -479,7 +473,10 @@ interface ConeTypeContext : TypeSystemContext, TypeSystemOptimizationContext, Ty
override fun TypeParameterMarker.getName() = (this as ConeTypeParameterLookupTag).name override fun TypeParameterMarker.getName() = (this as ConeTypeParameterLookupTag).name
override fun TypeParameterMarker.isReified(): Boolean = TODO("not implemented") override fun TypeParameterMarker.isReified(): Boolean {
require(this is ConeTypeParameterLookupTag)
return typeParameterSymbol.fir.isReified
}
override fun KotlinTypeMarker.isInterfaceOrAnnotationClass(): Boolean { override fun KotlinTypeMarker.isInterfaceOrAnnotationClass(): Boolean {
val classKind = typeConstructor().toFirRegularClass()?.classKind ?: return false val classKind = typeConstructor().toFirRegularClass()?.classKind ?: return false
@@ -489,6 +486,10 @@ interface ConeTypeContext : TypeSystemContext, TypeSystemOptimizationContext, Ty
override fun TypeConstructorMarker.isError(): Boolean { override fun TypeConstructorMarker.isError(): Boolean {
return this is ErrorTypeConstructor return this is ErrorTypeConstructor
} }
private fun TypeConstructorMarker.unknownConstructorError(): Nothing {
error("Unknown type constructor: ${this::class}")
}
} }
class ConeTypeCheckerContext( class ConeTypeCheckerContext(