diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/declarations/InlineClassesUtils.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/declarations/InlineClassesUtils.kt new file mode 100644 index 00000000000..a461821e11a --- /dev/null +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/declarations/InlineClassesUtils.kt @@ -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) +} diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/substitution/Substitutors.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/substitution/Substitutors.kt index 9f79646b701..2305d17099f 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/substitution/Substitutors.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/substitution/Substitutors.kt @@ -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, 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) + } + } +} diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/types/ArrayUtils.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/types/ArrayUtils.kt index 499f40ed57b..757442b9144 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/types/ArrayUtils.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/types/ArrayUtils.kt @@ -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) { diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/types/ConeInferenceContext.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/types/ConeInferenceContext.kt index b70a0b5a4a5..875fef476b1 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/types/ConeInferenceContext.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/types/ConeInferenceContext.kt @@ -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): 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, 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 } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/types/ConeTypeContext.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/types/ConeTypeContext.kt index 4fec0ecf1af..2097cc95621 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/types/ConeTypeContext.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/types/ConeTypeContext.kt @@ -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(