[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.impl.ConeClassLikeTypeImpl
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() {
private fun wrapProjection(old: ConeTypeProjection, newType: ConeKotlinType): ConeTypeProjection {
@@ -162,3 +166,15 @@ data class ConeSubstitutorByMap(val substitution: Map<FirTypeParameterSymbol, Co
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)
}
fun ConeTypeProjection.createArrayType(nullable: Boolean = false): ConeKotlinType {
fun ConeTypeProjection.createArrayType(nullable: Boolean = false): ConeClassLikeType {
if (this is ConeKotlinTypeProjection) {
val type = type.lowerBoundIfFlexible()
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.isSuspendFunctionType
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.createTypeSubstitutorByTypeConstructor
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
import org.jetbrains.kotlin.fir.symbols.ConeTypeParameterLookupTag
import org.jetbrains.kotlin.fir.symbols.StandardClassIds
@@ -32,19 +32,19 @@ interface ConeInferenceContext : TypeSystemInferenceExtensionContext, ConeTypeCo
val symbolProvider: FirSymbolProvider get() = session.symbolProvider
override fun nullableNothingType(): SimpleTypeMarker {
return session.builtinTypes.nullableNothingType.type//StandardClassIds.Nothing(symbolProvider).constructType(emptyArray(), true)
return session.builtinTypes.nullableNothingType.type
}
override fun nullableAnyType(): SimpleTypeMarker {
return session.builtinTypes.nullableAnyType.type//StandardClassIds.Any(symbolProvider).constructType(emptyArray(), true)
return session.builtinTypes.nullableAnyType.type
}
override fun nothingType(): SimpleTypeMarker {
return session.builtinTypes.nothingType.type//StandardClassIds.Nothing(symbolProvider).constructType(emptyArray(), false)
return session.builtinTypes.nothingType.type
}
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 {
@@ -102,14 +102,13 @@ interface ConeInferenceContext : TypeSystemInferenceExtensionContext, ConeTypeCo
override fun KotlinTypeMarker.canHaveUndefinedNullability(): Boolean {
require(this is ConeKotlinType)
return this is ConeCapturedType /*|| this is ConeTypeVariable // TODO */
return this is ConeCapturedType || this is ConeTypeVariableType
|| this is ConeTypeParameterType
}
// TODO: implement checking for extension function
override fun SimpleTypeMarker.isExtensionFunction(): Boolean {
require(this is ConeKotlinType)
return false
return this.isExtensionFunctionType
}
override fun KotlinTypeMarker.typeDepth() = when (this) {
@@ -151,11 +150,6 @@ interface ConeInferenceContext : TypeSystemInferenceExtensionContext, ConeTypeCo
if (this == null) return false
if (!visited.add(this)) return false
/*
TODO:?
UnwrappedType unwrappedType = type.unwrap();
*/
if (predicate(this)) return true
val flexibleType = this as? ConeFlexibleType
@@ -300,15 +294,8 @@ interface ConeInferenceContext : TypeSystemInferenceExtensionContext, ConeTypeCo
}
override fun typeSubstitutorByTypeConstructor(map: Map<TypeConstructorMarker, KotlinTypeMarker>): ConeSubstitutor {
if (map.isEmpty()) return createEmptySubstitutor()
return object : AbstractConeSubstitutor(),
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)
}
}
@Suppress("UNCHECKED_CAST")
return createTypeSubstitutorByTypeConstructor(map as Map<TypeConstructorMarker, ConeKotlinType>, this)
}
override fun createEmptySubstitutor(): ConeSubstitutor {
@@ -328,7 +315,7 @@ interface ConeInferenceContext : TypeSystemInferenceExtensionContext, ConeTypeCo
}
override fun KotlinTypeMarker.isSpecial(): Boolean {
// TODO
// Cone type system doesn't have special types
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.transformers.body.resolve.firUnsafe
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.ConeTypeParameterLookupTag
import org.jetbrains.kotlin.fir.symbols.StandardClassIds
@@ -100,7 +99,6 @@ interface ConeTypeContext : TypeSystemContext, TypeSystemOptimizationContext, Ty
}
override fun SimpleTypeMarker.asCapturedType(): CapturedTypeMarker? {
//require(this is ConeLookupTagBasedType)
return this as? ConeCapturedType
}
@@ -124,7 +122,7 @@ interface ConeTypeContext : TypeSystemContext, TypeSystemOptimizationContext, Ty
is ConeClassLikeType -> lookupTag
is ConeTypeParameterType -> lookupTag
is ConeCapturedType -> constructor
is ConeTypeVariableType -> lookupTag as ConeTypeVariableTypeConstructor // TODO: WTF
is ConeTypeVariableType -> lookupTag
is ConeIntersectionType -> this
is ConeStubType -> variable.typeConstructor
is ConeDefinitelyNotNullType -> original.typeConstructor()
@@ -150,20 +148,16 @@ interface ConeTypeContext : TypeSystemContext, TypeSystemOptimizationContext, Ty
override fun KotlinTypeMarker.argumentsCount(): Int {
require(this is ConeKotlinType)
return this.typeArguments.size
}
override fun KotlinTypeMarker.getArgument(index: Int): TypeArgumentMarker {
require(this is ConeKotlinType)
return this.typeArguments.getOrNull(index)
?: session.builtinTypes.anyType.type//StandardClassIds.Any(session.firSymbolProvider).constructType(emptyArray(), false) // TODO wtf
return this.typeArguments.getOrNull(index) ?: ConeStarProjection
}
override fun KotlinTypeMarker.asTypeArgument(): TypeArgumentMarker {
require(this is ConeKotlinType)
return this
}
@@ -196,7 +190,6 @@ interface ConeTypeContext : TypeSystemContext, TypeSystemOptimizationContext, Ty
}
override fun TypeConstructorMarker.parametersCount(): Int {
//require(this is ConeSymbol)
return when (this) {
is ConeTypeParameterLookupTag,
is ConeCapturedTypeConstructor,
@@ -204,7 +197,7 @@ interface ConeTypeContext : TypeSystemContext, TypeSystemOptimizationContext, Ty
is ConeTypeVariableTypeConstructor,
is ConeIntersectionType -> 0
is ConeClassLikeLookupTag -> {
when(val symbol = toSymbol(session)) {
when (val symbol = toSymbol(session)) {
is FirAnonymousObjectSymbol -> symbol.fir.typeParameters.size
is FirRegularClassSymbol -> symbol.fir.typeParameters.size
is FirTypeAliasSymbol -> symbol.fir.typeParameters.size
@@ -212,12 +205,11 @@ interface ConeTypeContext : TypeSystemContext, TypeSystemOptimizationContext, Ty
}
}
is ConeIntegerLiteralType -> 0
else -> error("?!:10")
else -> unknownConstructorError()
}
}
override fun TypeConstructorMarker.getParameter(index: Int): TypeParameterMarker {
//require(this is ConeSymbol)
return when (val symbol = toClassLikeSymbol()) {
is FirAnonymousObjectSymbol -> 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 ConeIntersectionType -> intersectedTypes
is ConeIntegerLiteralType -> supertypes
else -> error("?!:13")
else -> unknownConstructorError()
}
}
@@ -252,7 +244,6 @@ interface ConeTypeContext : TypeSystemContext, TypeSystemOptimizationContext, Ty
}
override fun TypeConstructorMarker.isClassTypeConstructor(): Boolean {
//assert(this is ConeSymbol)
return this is ConeClassLikeLookupTag
}
@@ -278,21 +269,21 @@ interface ConeTypeContext : TypeSystemContext, TypeSystemOptimizationContext, Ty
override fun areEqualTypeConstructors(c1: TypeConstructorMarker, c2: TypeConstructorMarker): Boolean {
if (c1 is ErrorTypeConstructor || c2 is ErrorTypeConstructor) return false
//assert(c1 is ConeSymbol)
//assert(c2 is ConeSymbol)
return c1 == c2
}
override fun TypeConstructorMarker.isDenotable(): Boolean {
//TODO
return when (this) {
is ConeClassLikeLookupTag,
is ConeTypeParameterLookupTag -> true
is ConeCapturedTypeConstructor,
is ErrorTypeConstructor,
is ConeTypeVariableTypeConstructor,
is ConeIntersectionType,
is ConeIntegerLiteralType -> false
is AbstractFirBasedSymbol<*> -> true
else -> true
is ConeIntegerLiteralType,
is ConeIntersectionType -> false
else -> unknownConstructorError()
}
}
@@ -413,9 +404,12 @@ interface ConeTypeContext : TypeSystemContext, TypeSystemOptimizationContext, Ty
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 {
require(this is ConeKotlinType)
@@ -459,8 +453,8 @@ interface ConeTypeContext : TypeSystemContext, TypeSystemOptimizationContext, Ty
}
override fun KotlinTypeMarker.getSubstitutedUnderlyingType(): KotlinTypeMarker? {
// TODO: support inline classes
return null
require(this is ConeKotlinType)
return substitutedUnderlyingTypeForInlineClass(session, this@ConeTypeContext)
}
override fun TypeConstructorMarker.getPrimitiveType() =
@@ -479,7 +473,10 @@ interface ConeTypeContext : TypeSystemContext, TypeSystemOptimizationContext, Ty
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 {
val classKind = typeConstructor().toFirRegularClass()?.classKind ?: return false
@@ -489,6 +486,10 @@ interface ConeTypeContext : TypeSystemContext, TypeSystemOptimizationContext, Ty
override fun TypeConstructorMarker.isError(): Boolean {
return this is ErrorTypeConstructor
}
private fun TypeConstructorMarker.unknownConstructorError(): Nothing {
error("Unknown type constructor: ${this::class}")
}
}
class ConeTypeCheckerContext(