[FIR] Add computing type attributes for deserialized types

This commit is contained in:
Dmitriy Novozhilov
2020-06-29 16:17:50 +03:00
parent cfa250957a
commit 840d3975cc
6 changed files with 44 additions and 35 deletions
@@ -29,6 +29,7 @@ import org.jetbrains.kotlin.fir.symbols.impl.ConeClassLikeLookupTagImpl
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol
import org.jetbrains.kotlin.fir.types.ConeAttributes
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl
import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl
@@ -105,7 +106,7 @@ fun deserializeClassToSymbol(
val classDeserializer = context.memberDeserializer val classDeserializer = context.memberDeserializer
val superTypesDeserialized = classProto.supertypes(context.typeTable).map { supertypeProto -> val superTypesDeserialized = classProto.supertypes(context.typeTable).map { supertypeProto ->
typeDeserializer.simpleType(supertypeProto) typeDeserializer.simpleType(supertypeProto, ConeAttributes.Empty)
}// TODO: + c.components.additionalClassPartsProvider.getSupertypes(this@DeserializedClassDescriptor) }// TODO: + c.components.additionalClassPartsProvider.getSupertypes(this@DeserializedClassDescriptor)
superTypesDeserialized.mapNotNullTo(superTypeRefs) { superTypesDeserialized.mapNotNullTo(superTypeRefs) {
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.fir.contracts.description.*
import org.jetbrains.kotlin.fir.declarations.FirContractDescriptionOwner import org.jetbrains.kotlin.fir.declarations.FirContractDescriptionOwner
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
import org.jetbrains.kotlin.fir.expressions.LogicOperationKind import org.jetbrains.kotlin.fir.expressions.LogicOperationKind
import org.jetbrains.kotlin.fir.types.ConeAttributes
import org.jetbrains.kotlin.fir.types.ConeKotlinType import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.fir.types.isBoolean import org.jetbrains.kotlin.fir.types.isBoolean
import org.jetbrains.kotlin.metadata.ProtoBuf import org.jetbrains.kotlin.metadata.ProtoBuf
@@ -148,7 +149,7 @@ class FirContractDeserializer(private val c: FirDeserializationContext) {
} }
private fun extractType(proto: ProtoBuf.Expression): ConeKotlinType? { private fun extractType(proto: ProtoBuf.Expression): ConeKotlinType? {
return c.typeDeserializer.type(proto.isInstanceType(c.typeTable) ?: return null) return c.typeDeserializer.type(proto.isInstanceType(c.typeTable) ?: return null, ConeAttributes.Empty)
} }
private fun loadConstant(value: ProtoBuf.Expression.ConstantValue): ConeConstantReference? = when (value) { private fun loadConstant(value: ProtoBuf.Expression.ConstantValue): ConeConstantReference? = when (value) {
@@ -16,8 +16,10 @@ import org.jetbrains.kotlin.fir.expressions.builder.buildExpressionStub
import org.jetbrains.kotlin.fir.symbols.CallableId import org.jetbrains.kotlin.fir.symbols.CallableId
import org.jetbrains.kotlin.fir.symbols.StandardClassIds import org.jetbrains.kotlin.fir.symbols.StandardClassIds
import org.jetbrains.kotlin.fir.symbols.impl.* import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.fir.types.ConeAttributes
import org.jetbrains.kotlin.fir.types.FirTypeRef import org.jetbrains.kotlin.fir.types.FirTypeRef
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
import org.jetbrains.kotlin.fir.types.computeTypeAttributes
import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl
import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl
import org.jetbrains.kotlin.fir.types.impl.FirImplicitUnitTypeRef import org.jetbrains.kotlin.fir.types.impl.FirImplicitUnitTypeRef
@@ -168,7 +170,7 @@ class FirMemberDeserializer(private val c: FirDeserializationContext) {
} }
symbol = FirTypeAliasSymbol(ClassId(c.packageFqName, name)) symbol = FirTypeAliasSymbol(ClassId(c.packageFqName, name))
expandedTypeRef = buildResolvedTypeRef { expandedTypeRef = buildResolvedTypeRef {
type = local.typeDeserializer.type(proto.underlyingType(c.typeTable)) type = local.typeDeserializer.type(proto.underlyingType(c.typeTable), ConeAttributes.Empty)
} }
resolvePhase = FirResolvePhase.ANALYZED_DEPENDENCIES resolvePhase = FirResolvePhase.ANALYZED_DEPENDENCIES
typeParameters += local.typeDeserializer.ownTypeParameters.map { it.fir } typeParameters += local.typeDeserializer.ownTypeParameters.map { it.fir }
@@ -423,8 +425,9 @@ class FirMemberDeserializer(private val c: FirDeserializationContext) {
private fun ProtoBuf.Type.toTypeRef(context: FirDeserializationContext): FirTypeRef { private fun ProtoBuf.Type.toTypeRef(context: FirDeserializationContext): FirTypeRef {
return buildResolvedTypeRef { return buildResolvedTypeRef {
type = context.typeDeserializer.type(this@toTypeRef)
annotations += context.annotationDeserializer.loadTypeAnnotations(this@toTypeRef, context.nameResolver) annotations += context.annotationDeserializer.loadTypeAnnotations(this@toTypeRef, context.nameResolver)
val attributes = annotations.computeTypeAttributes()
type = context.typeDeserializer.type(this@toTypeRef, attributes)
} }
} }
@@ -77,7 +77,7 @@ class FirTypeDeserializer(
val builder = builders[index] val builder = builders[index]
builder.apply { builder.apply {
proto.upperBoundList.mapTo(bounds) { proto.upperBoundList.mapTo(bounds) {
buildResolvedTypeRef { type = type(it) } buildResolvedTypeRef { type = type(it, ConeAttributes.Empty) }
} }
addDefaultBoundIfNecessary() addDefaultBoundIfNecessary()
}.build() }.build()
@@ -96,15 +96,15 @@ class FirTypeDeserializer(
} }
} }
fun type(proto: ProtoBuf.Type): ConeKotlinType { fun type(proto: ProtoBuf.Type, attributes: ConeAttributes): ConeKotlinType {
if (proto.hasFlexibleTypeCapabilitiesId()) { if (proto.hasFlexibleTypeCapabilitiesId()) {
val lowerBound = simpleType(proto) val lowerBound = simpleType(proto, attributes)
val upperBound = simpleType(proto.flexibleUpperBound(typeTable)!!) val upperBound = simpleType(proto.flexibleUpperBound(typeTable)!!, attributes)
return ConeFlexibleType(lowerBound!!, upperBound!!) return ConeFlexibleType(lowerBound!!, upperBound!!)
//c.components.flexibleTypeDeserializer.create(proto, id, lowerBound, upperBound) //c.components.flexibleTypeDeserializer.create(proto, id, lowerBound, upperBound)
} }
return simpleType(proto) ?: ConeKotlinErrorType("?!id:0") return simpleType(proto, attributes) ?: ConeKotlinErrorType("?!id:0")
} }
private fun typeParameterSymbol(typeParameterId: Int): ConeTypeParameterLookupTag? = private fun typeParameterSymbol(typeParameterId: Int): ConeTypeParameterLookupTag? =
@@ -123,7 +123,7 @@ class FirTypeDeserializer(
fun FirClassLikeSymbol<*>.typeParameters(): List<FirTypeParameterSymbol> = fun FirClassLikeSymbol<*>.typeParameters(): List<FirTypeParameterSymbol> =
(fir as? FirTypeParameterRefsOwner)?.typeParameters?.map { it.symbol }.orEmpty() (fir as? FirTypeParameterRefsOwner)?.typeParameters?.map { it.symbol }.orEmpty()
fun simpleType(proto: ProtoBuf.Type): ConeLookupTagBasedType? { fun simpleType(proto: ProtoBuf.Type, attributes: ConeAttributes): ConeLookupTagBasedType? {
val constructor = typeSymbol(proto) ?: return null val constructor = typeSymbol(proto) ?: return null
if (constructor is ConeTypeParameterLookupTag) return ConeTypeParameterTypeImpl(constructor, isNullable = proto.nullable) if (constructor is ConeTypeParameterLookupTag) return ConeTypeParameterTypeImpl(constructor, isNullable = proto.nullable)
@@ -135,14 +135,14 @@ class FirTypeDeserializer(
val arguments = proto.collectAllArguments().map(this::typeArgument).toTypedArray() val arguments = proto.collectAllArguments().map(this::typeArgument).toTypedArray()
val simpleType = if (Flags.SUSPEND_TYPE.get(proto.flags)) { val simpleType = if (Flags.SUSPEND_TYPE.get(proto.flags)) {
createSuspendFunctionType(constructor, arguments, isNullable = proto.nullable) createSuspendFunctionType(constructor, arguments, isNullable = proto.nullable, attributes)
} else { } else {
ConeClassLikeTypeImpl(constructor, arguments, isNullable = proto.nullable) ConeClassLikeTypeImpl(constructor, arguments, isNullable = proto.nullable, attributes)
} }
val abbreviatedTypeProto = proto.abbreviatedType(typeTable) ?: return simpleType val abbreviatedTypeProto = proto.abbreviatedType(typeTable) ?: return simpleType
return simpleType(abbreviatedTypeProto) return simpleType(abbreviatedTypeProto, attributes)
} }
@@ -150,7 +150,8 @@ class FirTypeDeserializer(
//annotations: Annotations, TODO?, //annotations: Annotations, TODO?,
functionTypeConstructor: ConeClassLikeLookupTag, functionTypeConstructor: ConeClassLikeLookupTag,
arguments: Array<ConeTypeProjection>, arguments: Array<ConeTypeProjection>,
isNullable: Boolean isNullable: Boolean,
attributes: ConeAttributes
): ConeClassLikeType? { ): ConeClassLikeType? {
fun ConeClassLikeType.isContinuation(): Boolean { fun ConeClassLikeType.isContinuation(): Boolean {
if (this.typeArguments.size != 1) return false if (this.typeArguments.size != 1) return false
@@ -161,7 +162,7 @@ class FirTypeDeserializer(
val returnType = arguments.lastOrNull() val returnType = arguments.lastOrNull()
val continuationType = arguments.getOrNull(arguments.lastIndex - 1) as? ConeClassLikeType ?: return null val continuationType = arguments.getOrNull(arguments.lastIndex - 1) as? ConeClassLikeType ?: return null
if (!continuationType.isContinuation()) return ConeClassLikeTypeImpl(functionTypeConstructor, arguments, isNullable) if (!continuationType.isContinuation()) return ConeClassLikeTypeImpl(functionTypeConstructor, arguments, isNullable, attributes)
val suspendReturnType = continuationType.typeArguments.single() as ConeKotlinTypeProjection val suspendReturnType = continuationType.typeArguments.single() as ConeKotlinTypeProjection
@@ -171,7 +172,7 @@ class FirTypeDeserializer(
return ConeClassLikeTypeImpl( return ConeClassLikeTypeImpl(
ConeClassLikeLookupTagImpl(ClassId(kind.packageFqName, kind.numberedClassName(valueParameters.size))), ConeClassLikeLookupTagImpl(ClassId(kind.packageFqName, kind.numberedClassName(valueParameters.size))),
(valueParameters + suspendReturnType).toTypedArray(), (valueParameters + suspendReturnType).toTypedArray(),
isNullable isNullable, attributes
) )
} }
@@ -179,11 +180,12 @@ class FirTypeDeserializer(
//annotations: Annotations, TODO? //annotations: Annotations, TODO?
functionTypeConstructor: ConeClassLikeLookupTag, functionTypeConstructor: ConeClassLikeLookupTag,
arguments: Array<ConeTypeProjection>, arguments: Array<ConeTypeProjection>,
isNullable: Boolean isNullable: Boolean,
attributes: ConeAttributes
): ConeClassLikeType { ): ConeClassLikeType {
val result = val result =
when (functionTypeConstructor.toSymbol(session)!!.firUnsafe<FirTypeParameterRefsOwner>().typeParameters.size - arguments.size) { when (functionTypeConstructor.toSymbol(session)!!.firUnsafe<FirTypeParameterRefsOwner>().typeParameters.size - arguments.size) {
0 -> createSuspendFunctionTypeForBasicCase(/* annotations, */ functionTypeConstructor, arguments, isNullable) 0 -> createSuspendFunctionTypeForBasicCase(/* annotations, */ functionTypeConstructor, arguments, isNullable, attributes)
// This case for types written by eap compiler 1.1 // This case for types written by eap compiler 1.1
1 -> { 1 -> {
val arity = arguments.size - 1 val arity = arguments.size - 1
@@ -192,7 +194,8 @@ class FirTypeDeserializer(
ConeClassLikeTypeImpl( ConeClassLikeTypeImpl(
ConeClassLikeLookupTagImpl(ClassId(kind.packageFqName, kind.numberedClassName(arity))), ConeClassLikeLookupTagImpl(ClassId(kind.packageFqName, kind.numberedClassName(arity))),
arguments, arguments,
isNullable isNullable,
attributes
) )
} else { } else {
null null
@@ -226,7 +229,8 @@ class FirTypeDeserializer(
val variance = ProtoEnumFlags.variance(typeArgumentProto.projection) val variance = ProtoEnumFlags.variance(typeArgumentProto.projection)
val type = typeArgumentProto.type(typeTable) ?: return ConeKotlinErrorType("No type recorded") val type = typeArgumentProto.type(typeTable) ?: return ConeKotlinErrorType("No type recorded")
val coneType = type(type) // TODO: check that here we don't have any attributes
val coneType = type(type, ConeAttributes.Empty)
return coneType.toTypeProjection(variance) return coneType.toTypeProjection(variance)
} }
@@ -84,23 +84,9 @@ class FirTypeResolverImpl(private val session: FirSession) : FirTypeResolver {
if (symbol == null) { if (symbol == null) {
return ConeKotlinErrorType("Symbol not found, for `${typeRef.render()}`") return ConeKotlinErrorType("Symbol not found, for `${typeRef.render()}`")
} }
return symbol.constructType(typeRef.qualifier, typeRef.isMarkedNullable, symbolOriginSession = session, typeRef.computeTypeAttributes()) return symbol.constructType(typeRef.qualifier, typeRef.isMarkedNullable, symbolOriginSession = session, typeRef.annotations.computeTypeAttributes())
} }
private fun FirTypeRef.computeTypeAttributes(): ConeAttributes {
if (annotations.isEmpty()) return ConeAttributes.Empty
val attributes = mutableListOf<ConeAttribute<*>>()
for (annotation in annotations) {
val type = annotation.annotationTypeRef.coneTypeSafe<ConeClassLikeType>() ?: continue
when (type.lookupTag.classId) {
CompilerConeAttributes.Exact.ANNOTATION_CLASS_ID -> attributes += CompilerConeAttributes.Exact
CompilerConeAttributes.NoInfer.ANNOTATION_CLASS_ID -> attributes += CompilerConeAttributes.NoInfer
}
}
return ConeAttributes.create(attributes)
}
private fun createFunctionalType(typeRef: FirFunctionTypeRef): ConeClassLikeType { private fun createFunctionalType(typeRef: FirFunctionTypeRef): ConeClassLikeType {
val parameters = val parameters =
listOfNotNull((typeRef.receiverTypeRef as FirResolvedTypeRef?)?.type) + listOfNotNull((typeRef.receiverTypeRef as FirResolvedTypeRef?)?.type) +
@@ -111,6 +97,7 @@ class FirTypeResolverImpl(private val session: FirSession) : FirTypeResolver {
} else { } else {
KotlinBuiltIns.getFunctionClassId(typeRef.parametersCount) KotlinBuiltIns.getFunctionClassId(typeRef.parametersCount)
} }
val attributes = typeRef.annotations.computeTypeAttributes()
return ConeClassLikeTypeImpl( return ConeClassLikeTypeImpl(
resolveBuiltInQualified(classId, session).toLookupTag(), resolveBuiltInQualified(classId, session).toLookupTag(),
parameters.toTypedArray(), parameters.toTypedArray(),
@@ -77,3 +77,16 @@ fun ConeClassLikeType.toConstKind(): FirConstKind<*>? = when (lookupTag.classId)
StandardClassIds.UByte -> FirConstKind.UnsignedByte StandardClassIds.UByte -> FirConstKind.UnsignedByte
else -> null else -> null
} }
fun List<FirAnnotationCall>.computeTypeAttributes(): ConeAttributes {
if (this.isEmpty()) return ConeAttributes.Empty
val attributes = mutableListOf<ConeAttribute<*>>()
for (annotation in this) {
val type = annotation.annotationTypeRef.coneTypeSafe<ConeClassLikeType>() ?: continue
when (type.lookupTag.classId) {
CompilerConeAttributes.Exact.ANNOTATION_CLASS_ID -> attributes += CompilerConeAttributes.Exact
CompilerConeAttributes.NoInfer.ANNOTATION_CLASS_ID -> attributes += CompilerConeAttributes.NoInfer
}
}
return ConeAttributes.create(attributes)
}