diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/ConversionUtils.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/ConversionUtils.kt index 867dcf37eab..ec5d19db417 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/ConversionUtils.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/ConversionUtils.kt @@ -50,53 +50,72 @@ internal fun FirElement.convertWithOffsets( internal fun createErrorType(): IrErrorType = IrErrorTypeImpl(null, emptyList(), Variance.INVARIANT) +internal enum class ConversionTypeOrigin { + DEFAULT, + SETTER +} + +class ConversionTypeContext internal constructor( + internal val definitelyNotNull: Boolean, + internal val origin: ConversionTypeOrigin +) { + fun definitelyNotNull() = ConversionTypeContext(true, origin) + + fun inSetter() = ConversionTypeContext(definitelyNotNull, ConversionTypeOrigin.SETTER) + + companion object { + internal val DEFAULT = ConversionTypeContext( + definitelyNotNull = false, origin = ConversionTypeOrigin.DEFAULT + ) + } +} + fun FirTypeRef.toIrType( session: FirSession, declarationStorage: Fir2IrDeclarationStorage, irBuiltIns: IrBuiltIns, - forSetter: Boolean = false + typeContext: ConversionTypeContext = ConversionTypeContext.DEFAULT ): IrType { if (this !is FirResolvedTypeRef) { return createErrorType() } - return type.toIrType(session, declarationStorage, irBuiltIns, forSetter = forSetter) + return type.toIrType(session, declarationStorage, irBuiltIns, typeContext) } fun ConeKotlinType.toIrType( session: FirSession, declarationStorage: Fir2IrDeclarationStorage, irBuiltIns: IrBuiltIns, - definitelyNotNull: Boolean = false, - forSetter: Boolean = false + typeContext: ConversionTypeContext = ConversionTypeContext.DEFAULT ): IrType { return when (this) { is ConeKotlinErrorType -> createErrorType() is ConeLookupTagBasedType -> { val irSymbol = getArrayType(this.classId, irBuiltIns) ?: run { val firSymbol = this.lookupTag.toSymbol(session) ?: return createErrorType() - firSymbol.toIrSymbol(session, declarationStorage, forSetter) + firSymbol.toIrSymbol(session, declarationStorage, typeContext) } // TODO: annotations IrSimpleTypeImpl( - irSymbol, !definitelyNotNull && this.isMarkedNullable, + irSymbol, !typeContext.definitelyNotNull && this.isMarkedNullable, typeArguments.map { it.toIrTypeArgument(session, declarationStorage, irBuiltIns) }, emptyList() ) } is ConeFlexibleType -> { // TODO: yet we take more general type. Not quite sure it's Ok - upperBound.toIrType(session, declarationStorage, irBuiltIns, definitelyNotNull) + upperBound.toIrType(session, declarationStorage, irBuiltIns, typeContext) } is ConeCapturedType -> TODO() is ConeDefinitelyNotNullType -> { - original.toIrType(session, declarationStorage, irBuiltIns, definitelyNotNull = true) + original.toIrType(session, declarationStorage, irBuiltIns, typeContext.definitelyNotNull()) } is ConeIntersectionType -> { // TODO: add intersectionTypeApproximation - intersectedTypes.first().toIrType(session, declarationStorage, irBuiltIns, definitelyNotNull) + intersectedTypes.first().toIrType(session, declarationStorage, irBuiltIns, typeContext) } is ConeStubType -> createErrorType() - is ConeIntegerLiteralType -> getApproximatedType().toIrType(session, declarationStorage, irBuiltIns, definitelyNotNull) + is ConeIntegerLiteralType -> getApproximatedType().toIrType(session, declarationStorage, irBuiltIns, typeContext) } } @@ -141,11 +160,11 @@ fun ConeTypeProjection.toIrTypeArgument( fun FirClassifierSymbol<*>.toIrSymbol( session: FirSession, declarationStorage: Fir2IrDeclarationStorage, - forSetter: Boolean = false + typeContext: ConversionTypeContext = ConversionTypeContext.DEFAULT ): IrClassifierSymbol { return when (this) { is FirTypeParameterSymbol -> { - toTypeParameterSymbol(declarationStorage, forSetter) + toTypeParameterSymbol(declarationStorage, typeContext) } is FirTypeAliasSymbol -> { val typeAlias = fir @@ -201,9 +220,9 @@ fun FirClassSymbol<*>.toClassSymbol(declarationStorage: Fir2IrDeclarationStorage fun FirTypeParameterSymbol.toTypeParameterSymbol( declarationStorage: Fir2IrDeclarationStorage, - forSetter: Boolean = false + typeContext: ConversionTypeContext = ConversionTypeContext.DEFAULT ): IrTypeParameterSymbol { - return declarationStorage.getIrTypeParameterSymbol(this, forSetter) + return declarationStorage.getIrTypeParameterSymbol(this, typeContext) } fun FirFunctionSymbol<*>.toFunctionSymbol(declarationStorage: Fir2IrDeclarationStorage): IrFunctionSymbol { diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrDeclarationStorage.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrDeclarationStorage.kt index faa4f802225..64c2de601f5 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrDeclarationStorage.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrDeclarationStorage.kt @@ -102,8 +102,11 @@ class Fir2IrDeclarationStorage( irSymbolTable.leaveScope(descriptor) } - private fun FirTypeRef.toIrType(session: FirSession, declarationStorage: Fir2IrDeclarationStorage, forSetter: Boolean = false) = - toIrType(session, declarationStorage, irBuiltIns, forSetter) + private fun FirTypeRef.toIrType( + session: FirSession, + declarationStorage: Fir2IrDeclarationStorage, + typeContext: ConversionTypeContext = ConversionTypeContext.DEFAULT + ) = toIrType(session, declarationStorage, irBuiltIns, typeContext) private fun getIrExternalPackageFragment(fqName: FqName): IrExternalPackageFragment { return fragmentCache.getOrPut(fqName) { @@ -151,14 +154,17 @@ class Fir2IrDeclarationStorage( owner.typeParameters.mapIndexed { index, typeParameter -> getIrTypeParameter(typeParameter, index) if (owner is FirProperty && owner.isVar) { - getIrTypeParameter(typeParameter, index, forSetter = true) + getIrTypeParameter(typeParameter, index, ConversionTypeContext.DEFAULT.inSetter()) } } } - private fun IrTypeParametersContainer.setTypeParameters(owner: FirTypeParametersOwner, forSetter: Boolean = false) { + private fun IrTypeParametersContainer.setTypeParameters( + owner: FirTypeParametersOwner, + typeContext: ConversionTypeContext = ConversionTypeContext.DEFAULT + ) { typeParameters = owner.typeParameters.mapIndexed { index, typeParameter -> - getIrTypeParameter(typeParameter, index, forSetter).apply { parent = this@setTypeParameters } + getIrTypeParameter(typeParameter, index, typeContext).apply { parent = this@setTypeParameters } } } @@ -328,12 +334,16 @@ class Fir2IrDeclarationStorage( }.declareSupertypesAndTypeParameters(anonymousObject) } - private fun getIrTypeParameter(typeParameter: FirTypeParameter, index: Int = -1, forSetter: Boolean = false): IrTypeParameter { + private fun getIrTypeParameter( + typeParameter: FirTypeParameter, + index: Int = -1, + typeContext: ConversionTypeContext = ConversionTypeContext.DEFAULT + ): IrTypeParameter { // Here transformation is a bit difficult because one FIR property type parameter // can be transformed to two different type parameters: one for getter and another one for setter val simpleCachedParameter = typeParameterCache[typeParameter] if (simpleCachedParameter != null) { - if (!forSetter) { + if (typeContext.origin != ConversionTypeOrigin.SETTER) { return simpleCachedParameter } if (index < 0) { @@ -343,7 +353,7 @@ class Fir2IrDeclarationStorage( } } } - if (forSetter) { + if (typeContext.origin == ConversionTypeOrigin.SETTER) { typeParameterCacheForSetter[typeParameter]?.let { return it } } return typeParameter.run { @@ -368,7 +378,7 @@ class Fir2IrDeclarationStorage( } // Cache the type parameter BEFORE processing its bounds/supertypes, to properly handle recursive type bounds. - if (forSetter) { + if (typeContext.origin == ConversionTypeOrigin.SETTER) { typeParameterCacheForSetter[typeParameter] = irTypeParameter } else { typeParameterCache[typeParameter] = irTypeParameter @@ -445,9 +455,13 @@ class Fir2IrDeclarationStorage( setTypeParameters(function) } val forSetter = function is FirPropertyAccessor && function.isSetter + val typeContext = ConversionTypeContext( + definitelyNotNull = false, + origin = if (forSetter) ConversionTypeOrigin.SETTER else ConversionTypeOrigin.DEFAULT + ) if (function is FirDefaultPropertySetter) { val type = function.valueParameters.first().returnTypeRef.toIrType( - session, this@Fir2IrDeclarationStorage, forSetter = true + session, this@Fir2IrDeclarationStorage, ConversionTypeContext.DEFAULT.inSetter() ) declareDefaultSetterParameter(type) } else if (function != null) { @@ -455,7 +469,7 @@ class Fir2IrDeclarationStorage( createAndSaveIrParameter( valueParameter, index, useStubForDefaultValueStub = function !is FirConstructor || containingClass?.name != Name.identifier("Enum"), - forSetter = forSetter + typeContext ).apply { this.parent = parent } @@ -468,7 +482,7 @@ class Fir2IrDeclarationStorage( extensionReceiverParameter = receiverTypeRef.convertWithOffsets { startOffset, endOffset -> declareThisReceiverParameter( parent, - thisType = receiverTypeRef.toIrType(session, this@Fir2IrDeclarationStorage, forSetter), + thisType = receiverTypeRef.toIrType(session, this@Fir2IrDeclarationStorage, typeContext), thisOrigin = thisOrigin, startOffset = startOffset, endOffset = endOffset @@ -657,10 +671,13 @@ class Fir2IrDeclarationStorage( isFakeOverride = origin == IrDeclarationOrigin.FAKE_OVERRIDE, isOperator = false ).apply { - setTypeParameters(property, forSetter = isSetter) + setTypeParameters(property, ConversionTypeContext( + definitelyNotNull = false, + origin = if (isSetter) ConversionTypeOrigin.SETTER else ConversionTypeOrigin.DEFAULT + )) if (propertyAccessor == null && isSetter) { declareDefaultSetterParameter( - property.returnTypeRef.toIrType(session, this@Fir2IrDeclarationStorage, forSetter = true) + property.returnTypeRef.toIrType(session, this@Fir2IrDeclarationStorage, ConversionTypeContext.DEFAULT.inSetter()) ) } }.bindAndDeclareParameters( @@ -799,7 +816,7 @@ class Fir2IrDeclarationStorage( valueParameter: FirValueParameter, index: Int = -1, useStubForDefaultValueStub: Boolean = true, - forSetter: Boolean = false + typeContext: ConversionTypeContext = ConversionTypeContext.DEFAULT ): IrValueParameter { val descriptor = WrappedValueParameterDescriptor() val origin = IrDeclarationOrigin.DEFINED @@ -813,7 +830,7 @@ class Fir2IrDeclarationStorage( valueParameter.name, index, type, if (!valueParameter.isVararg) null else valueParameter.returnTypeRef.coneTypeSafe()?.arrayElementType(session)?.toIrType( - session, this, irBuiltIns, forSetter + session, this, irBuiltIns, typeContext ), valueParameter.isCrossinline, valueParameter.isNoinline ).apply { @@ -894,8 +911,11 @@ class Fir2IrDeclarationStorage( return irSymbolTable.referenceClass(irClass.descriptor) } - fun getIrTypeParameterSymbol(firTypeParameterSymbol: FirTypeParameterSymbol, forSetter: Boolean): IrTypeParameterSymbol { - val irTypeParameter = getIrTypeParameter(firTypeParameterSymbol.fir, forSetter = forSetter) + fun getIrTypeParameterSymbol( + firTypeParameterSymbol: FirTypeParameterSymbol, + typeContext: ConversionTypeContext + ): IrTypeParameterSymbol { + val irTypeParameter = getIrTypeParameter(firTypeParameterSymbol.fir, typeContext = typeContext) return irSymbolTable.referenceTypeParameter(irTypeParameter.descriptor) }