[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.FirRegularClassSymbol
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.impl.ConeClassLikeTypeImpl
import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl
@@ -105,7 +106,7 @@ fun deserializeClassToSymbol(
val classDeserializer = context.memberDeserializer
val superTypesDeserialized = classProto.supertypes(context.typeTable).map { supertypeProto ->
typeDeserializer.simpleType(supertypeProto)
typeDeserializer.simpleType(supertypeProto, ConeAttributes.Empty)
}// TODO: + c.components.additionalClassPartsProvider.getSupertypes(this@DeserializedClassDescriptor)
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.FirSimpleFunction
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.isBoolean
import org.jetbrains.kotlin.metadata.ProtoBuf
@@ -148,7 +149,7 @@ class FirContractDeserializer(private val c: FirDeserializationContext) {
}
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) {
@@ -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.StandardClassIds
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.builder.buildResolvedTypeRef
import org.jetbrains.kotlin.fir.types.computeTypeAttributes
import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl
import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl
import org.jetbrains.kotlin.fir.types.impl.FirImplicitUnitTypeRef
@@ -168,7 +170,7 @@ class FirMemberDeserializer(private val c: FirDeserializationContext) {
}
symbol = FirTypeAliasSymbol(ClassId(c.packageFqName, name))
expandedTypeRef = buildResolvedTypeRef {
type = local.typeDeserializer.type(proto.underlyingType(c.typeTable))
type = local.typeDeserializer.type(proto.underlyingType(c.typeTable), ConeAttributes.Empty)
}
resolvePhase = FirResolvePhase.ANALYZED_DEPENDENCIES
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 {
return buildResolvedTypeRef {
type = context.typeDeserializer.type(this@toTypeRef)
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]
builder.apply {
proto.upperBoundList.mapTo(bounds) {
buildResolvedTypeRef { type = type(it) }
buildResolvedTypeRef { type = type(it, ConeAttributes.Empty) }
}
addDefaultBoundIfNecessary()
}.build()
@@ -96,15 +96,15 @@ class FirTypeDeserializer(
}
}
fun type(proto: ProtoBuf.Type): ConeKotlinType {
fun type(proto: ProtoBuf.Type, attributes: ConeAttributes): ConeKotlinType {
if (proto.hasFlexibleTypeCapabilitiesId()) {
val lowerBound = simpleType(proto)
val upperBound = simpleType(proto.flexibleUpperBound(typeTable)!!)
val lowerBound = simpleType(proto, attributes)
val upperBound = simpleType(proto.flexibleUpperBound(typeTable)!!, attributes)
return ConeFlexibleType(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? =
@@ -123,7 +123,7 @@ class FirTypeDeserializer(
fun FirClassLikeSymbol<*>.typeParameters(): List<FirTypeParameterSymbol> =
(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
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 simpleType = if (Flags.SUSPEND_TYPE.get(proto.flags)) {
createSuspendFunctionType(constructor, arguments, isNullable = proto.nullable)
createSuspendFunctionType(constructor, arguments, isNullable = proto.nullable, attributes)
} else {
ConeClassLikeTypeImpl(constructor, arguments, isNullable = proto.nullable)
ConeClassLikeTypeImpl(constructor, arguments, isNullable = proto.nullable, attributes)
}
val abbreviatedTypeProto = proto.abbreviatedType(typeTable) ?: return simpleType
return simpleType(abbreviatedTypeProto)
return simpleType(abbreviatedTypeProto, attributes)
}
@@ -150,7 +150,8 @@ class FirTypeDeserializer(
//annotations: Annotations, TODO?,
functionTypeConstructor: ConeClassLikeLookupTag,
arguments: Array<ConeTypeProjection>,
isNullable: Boolean
isNullable: Boolean,
attributes: ConeAttributes
): ConeClassLikeType? {
fun ConeClassLikeType.isContinuation(): Boolean {
if (this.typeArguments.size != 1) return false
@@ -161,7 +162,7 @@ class FirTypeDeserializer(
val returnType = arguments.lastOrNull()
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
@@ -171,7 +172,7 @@ class FirTypeDeserializer(
return ConeClassLikeTypeImpl(
ConeClassLikeLookupTagImpl(ClassId(kind.packageFqName, kind.numberedClassName(valueParameters.size))),
(valueParameters + suspendReturnType).toTypedArray(),
isNullable
isNullable, attributes
)
}
@@ -179,11 +180,12 @@ class FirTypeDeserializer(
//annotations: Annotations, TODO?
functionTypeConstructor: ConeClassLikeLookupTag,
arguments: Array<ConeTypeProjection>,
isNullable: Boolean
isNullable: Boolean,
attributes: ConeAttributes
): ConeClassLikeType {
val result =
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
1 -> {
val arity = arguments.size - 1
@@ -192,7 +194,8 @@ class FirTypeDeserializer(
ConeClassLikeTypeImpl(
ConeClassLikeLookupTagImpl(ClassId(kind.packageFqName, kind.numberedClassName(arity))),
arguments,
isNullable
isNullable,
attributes
)
} else {
null
@@ -226,7 +229,8 @@ class FirTypeDeserializer(
val variance = ProtoEnumFlags.variance(typeArgumentProto.projection)
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)
}
@@ -84,23 +84,9 @@ class FirTypeResolverImpl(private val session: FirSession) : FirTypeResolver {
if (symbol == null) {
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 {
val parameters =
listOfNotNull((typeRef.receiverTypeRef as FirResolvedTypeRef?)?.type) +
@@ -111,6 +97,7 @@ class FirTypeResolverImpl(private val session: FirSession) : FirTypeResolver {
} else {
KotlinBuiltIns.getFunctionClassId(typeRef.parametersCount)
}
val attributes = typeRef.annotations.computeTypeAttributes()
return ConeClassLikeTypeImpl(
resolveBuiltInQualified(classId, session).toLookupTag(),
parameters.toTypedArray(),
@@ -77,3 +77,16 @@ fun ConeClassLikeType.toConstKind(): FirConstKind<*>? = when (lookupTag.classId)
StandardClassIds.UByte -> FirConstKind.UnsignedByte
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)
}