diff --git a/compiler/fir/analysis-tests/testData/resolve/implicitTypeInFakeOverride.txt b/compiler/fir/analysis-tests/testData/resolve/implicitTypeInFakeOverride.txt new file mode 100644 index 00000000000..fc36dce5145 --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolve/implicitTypeInFakeOverride.txt @@ -0,0 +1,17 @@ +FILE: implicitTypeInFakeOverride.kt + public final fun extract(x: R|Out|): R|T| { + ^extract R|/x|.R|/Out.get|() + } + public final class Out : R|kotlin/Any| { + public constructor(x: R|T|): R|Out| { + super() + } + + public final val x: R|T| = R|/x| + public get(): R|T| + + public final fun get(): R|T| { + ^get this@R|/Out|.R|/Out.x| + } + + } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/FakeOverrideTypeCalculator.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/FakeOverrideTypeCalculator.kt new file mode 100644 index 00000000000..4b066df0907 --- /dev/null +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/FakeOverrideTypeCalculator.kt @@ -0,0 +1,49 @@ +/* + * Copyright 2010-2020 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.scopes + +import org.jetbrains.kotlin.fir.declarations.FirDeclarationAttributes +import org.jetbrains.kotlin.fir.declarations.FirDeclarationDataKey +import org.jetbrains.kotlin.fir.declarations.FirDeclarationDataRegistry +import org.jetbrains.kotlin.fir.declarations.FirTypedDeclaration +import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor +import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol +import org.jetbrains.kotlin.fir.types.ConeKotlinType +import org.jetbrains.kotlin.fir.types.coneTypeSafe + +abstract class FakeOverrideTypeCalculator { + abstract fun computeReturnType(declaration: FirTypedDeclaration): ConeKotlinType? + + class DoNothing : FakeOverrideTypeCalculator() { + override fun computeReturnType(declaration: FirTypedDeclaration): ConeKotlinType? { + return declaration.returnTypeRef.coneTypeSafe() + } + } +} + +class ForcedFakeOverrideTypeCalculator : FakeOverrideTypeCalculator() { + override fun computeReturnType(declaration: FirTypedDeclaration): ConeKotlinType { + declaration.returnTypeRef.coneTypeSafe()?.let { return it } + val (substitutor, baseSymbol) = declaration.attributes.fakeOverrideSubstitution ?: error("") + val baseDeclaration = baseSymbol.fir as FirTypedDeclaration + val returnType = computeReturnType(baseDeclaration) + declaration.attributes.fakeOverrideSubstitution = null + return substitutor.substituteOrSelf(returnType) + } +} + +// --------------------------------------------------------------------------------------------------------------------------------------- + +object FakeOverrideSubstitutionKey : FirDeclarationDataKey() + +var FirDeclarationAttributes.fakeOverrideSubstitution: FakeOverrideSubstitution? by FirDeclarationDataRegistry.attributesAccessor( + FakeOverrideSubstitutionKey +) + +data class FakeOverrideSubstitution( + val substitutor: ConeSubstitutor, + val baseSymbol: AbstractFirBasedSymbol<*> +) diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirClassSubstitutionScope.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirClassSubstitutionScope.kt index 1f20b82a07b..a42e1b0c727 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirClassSubstitutionScope.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirClassSubstitutionScope.kt @@ -13,12 +13,14 @@ import org.jetbrains.kotlin.fir.declarations.synthetic.FirSyntheticProperty import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor import org.jetbrains.kotlin.fir.resolve.substitution.chain import org.jetbrains.kotlin.fir.resolve.substitution.substitutorByMap +import org.jetbrains.kotlin.fir.scopes.FakeOverrideSubstitution import org.jetbrains.kotlin.fir.scopes.FirTypeScope import org.jetbrains.kotlin.fir.scopes.ProcessorAction import org.jetbrains.kotlin.fir.symbols.impl.* import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.utils.addToStdlib.runIf class FirClassSubstitutionScope( private val session: FirSession, @@ -126,13 +128,13 @@ class FirClassSubstitutionScope( } if (skipPrivateMembers && member.visibility == Visibilities.Private) return original - val (newTypeParameters, newReceiverType, newReturnType, newSubstitutor) = createSubstitutedData(member) + val (newTypeParameters, newReceiverType, newReturnType, newSubstitutor, fakeOverrideSubstitution) = createSubstitutedData(member) val newParameterTypes = member.valueParameters.map { it.returnTypeRef.coneType.substitute(newSubstitutor) } if (newReceiverType == null && newReturnType == null && newParameterTypes.all { it == null } && - newTypeParameters === member.typeParameters) { + newTypeParameters === member.typeParameters && fakeOverrideSubstitution == null) { return original } @@ -150,7 +152,8 @@ class FirClassSubstitutionScope( newParameterTypes, newTypeParameters as List, derivedClassId, - makeExpect + makeExpect, + fakeOverrideSubstitution ) } @@ -158,7 +161,7 @@ class FirClassSubstitutionScope( if (substitutor == ConeSubstitutor.Empty) return original val constructor = original.fir - val (newTypeParameters, _, newReturnType, newSubstitutor) = createSubstitutedData(constructor) + val (newTypeParameters, _, newReturnType, newSubstitutor, fakeOverrideSubstitution) = createSubstitutedData(constructor) val newParameterTypes = constructor.valueParameters.map { it.returnTypeRef.coneType.substitute(newSubstitutor) } @@ -168,7 +171,7 @@ class FirClassSubstitutionScope( } return FirFakeOverrideGenerator.createFakeOverrideConstructor( FirConstructorSymbol(original.callableId, overriddenSymbol = original), - session, constructor, newReturnType, newParameterTypes, newTypeParameters, makeExpect + session, constructor, newReturnType, newParameterTypes, newTypeParameters, makeExpect, fakeOverrideSubstitution ).symbol } @@ -177,7 +180,7 @@ class FirClassSubstitutionScope( val member = original.fir if (skipPrivateMembers && member.visibility == Visibilities.Private) return original - val (newTypeParameters, newReceiverType, newReturnType, _) = createSubstitutedData(member) + val (newTypeParameters, newReceiverType, newReturnType, _, fakeOverrideSubstitution) = createSubstitutedData(member) if (newReceiverType == null && newReturnType == null && newTypeParameters === member.typeParameters ) { @@ -193,7 +196,8 @@ class FirClassSubstitutionScope( newReturnType, newTypeParameters as List, derivedClassId, - makeExpect + makeExpect, + fakeOverrideSubstitution ) } @@ -201,7 +205,8 @@ class FirClassSubstitutionScope( val typeParameters: List, val receiverType: ConeKotlinType?, val returnType: ConeKotlinType?, - val substitutor: ConeSubstitutor + val substitutor: ConeSubstitutor, + val fakeOverrideSubstitution: FakeOverrideSubstitution? ) private fun createSubstitutedData(member: FirCallableMemberDeclaration<*>): SubstitutedData { @@ -214,9 +219,10 @@ class FirClassSubstitutionScope( val receiverType = member.receiverTypeRef?.coneType val newReceiverType = receiverType?.substitute(substitutor) - val returnType = member.returnTypeRef.coneType - val newReturnType = returnType.substitute(substitutor) - return SubstitutedData(newTypeParameters, newReceiverType, newReturnType, substitutor) + val returnType = member.returnTypeRef.coneTypeSafe() + val fakeOverrideSubstitution = runIf(returnType == null) { FakeOverrideSubstitution(substitutor, member.symbol) } + val newReturnType = returnType?.substitute(substitutor) + return SubstitutedData(newTypeParameters, newReceiverType, newReturnType, substitutor, fakeOverrideSubstitution) } private fun createFakeOverrideField(original: FirFieldSymbol): FirFieldSymbol { @@ -224,8 +230,9 @@ class FirClassSubstitutionScope( val member = original.fir if (skipPrivateMembers && member.visibility == Visibilities.Private) return original - val returnType = member.returnTypeRef.coneType - val newReturnType = returnType.substitute() ?: return original + val returnType = member.returnTypeRef.coneTypeSafe() + // TODO: do we have fields with implicit type? + val newReturnType = returnType?.substitute() ?: return original return FirFakeOverrideGenerator.createFakeOverrideField(session, member, original, newReturnType, derivedClassId) } @@ -235,8 +242,9 @@ class FirClassSubstitutionScope( val member = original.fir as FirSyntheticProperty if (skipPrivateMembers && member.visibility == Visibilities.Private) return original - val returnType = member.returnTypeRef.coneType - val newReturnType = returnType.substitute() + val returnType = member.returnTypeRef.coneTypeSafe() + val fakeOverrideSubstitution = runIf(returnType == null) { FakeOverrideSubstitution(substitutor, original) } + val newReturnType = returnType?.substitute() val newParameterTypes = member.getter.valueParameters.map { it.returnTypeRef.coneType.substitute() @@ -246,7 +254,14 @@ class FirClassSubstitutionScope( return original } - return FirFakeOverrideGenerator.createFakeOverrideAccessor(session, member, original, newReturnType, newParameterTypes) + return FirFakeOverrideGenerator.createFakeOverrideAccessor( + session, + member, + original, + newReturnType, + newParameterTypes, + fakeOverrideSubstitution + ) } override fun processDeclaredConstructors(processor: (FirConstructorSymbol) -> Unit) { diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirFakeOverrideGenerator.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirFakeOverrideGenerator.kt index bf6bf7e2ed0..b836c0eafa1 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirFakeOverrideGenerator.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirFakeOverrideGenerator.kt @@ -16,12 +16,16 @@ import org.jetbrains.kotlin.fir.declarations.synthetic.buildSyntheticProperty import org.jetbrains.kotlin.fir.resolve.substitution.ChainedSubstitutor import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor import org.jetbrains.kotlin.fir.resolve.substitution.substitutorByMap +import org.jetbrains.kotlin.fir.scopes.FakeOverrideSubstitution +import org.jetbrains.kotlin.fir.scopes.fakeOverrideSubstitution import org.jetbrains.kotlin.fir.symbols.CallableId import org.jetbrains.kotlin.fir.symbols.impl.* import org.jetbrains.kotlin.fir.types.* +import org.jetbrains.kotlin.fir.types.builder.buildImplicitTypeRef import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl import org.jetbrains.kotlin.name.ClassId +import org.jetbrains.kotlin.utils.addToStdlib.runIf object FirFakeOverrideGenerator { fun createFakeOverrideFunction( @@ -33,14 +37,16 @@ object FirFakeOverrideGenerator { newParameterTypes: List? = null, newTypeParameters: List? = null, derivedClassId: ClassId? = null, - isExpect: Boolean = baseFunction.isExpect + isExpect: Boolean = baseFunction.isExpect, + fakeOverrideSubstitution: FakeOverrideSubstitution? = null ): FirNamedFunctionSymbol { val symbol = FirNamedFunctionSymbol( CallableId(derivedClassId ?: baseSymbol.callableId.classId!!, baseFunction.name), isFakeOverride = true, overriddenSymbol = baseSymbol ) createFakeOverrideFunction( - symbol, session, baseFunction, newReceiverType, newReturnType, newParameterTypes, newTypeParameters, isExpect + symbol, session, baseFunction, newReceiverType, newReturnType, + newParameterTypes, newTypeParameters, isExpect, fakeOverrideSubstitution ) return symbol } @@ -54,6 +60,7 @@ object FirFakeOverrideGenerator { newParameterTypes: List?, newTypeParameters: List?, isExpect: Boolean = baseFunction.isExpect, + fakeOverrideSubstitution: FakeOverrideSubstitution?, ): FirSimpleFunction { // TODO: consider using here some light-weight functions instead of pseudo-real FirMemberFunctionImpl // As second alternative, we can invent some light-weight kind of FirRegularClass @@ -66,7 +73,8 @@ object FirFakeOverrideGenerator { newParameterTypes, newTypeParameters, newReceiverType, - newReturnType + newReturnType, + fakeOverrideSubstitution = fakeOverrideSubstitution ) } @@ -82,6 +90,7 @@ object FirFakeOverrideGenerator { newReturnType: ConeKotlinType? = null, newModality: Modality? = null, newVisibility: Visibility? = null, + fakeOverrideSubstitution: FakeOverrideSubstitution? = null ): FirSimpleFunction { return buildSimpleFunction { source = baseFunction.source @@ -93,7 +102,8 @@ object FirFakeOverrideGenerator { resolvePhase = baseFunction.resolvePhase typeParameters += configureAnnotationsTypeParametersAndSignature( - session, baseFunction, newParameterTypes, newTypeParameters, newReceiverType, newReturnType + session, baseFunction, newParameterTypes, + newTypeParameters, newReceiverType, newReturnType, fakeOverrideSubstitution ).filterIsInstance() } } @@ -105,7 +115,8 @@ object FirFakeOverrideGenerator { newReturnType: ConeKotlinType?, newParameterTypes: List?, newTypeParameters: List?, - isExpect: Boolean + isExpect: Boolean, + fakeOverrideSubstitution: FakeOverrideSubstitution? ): FirConstructor { // TODO: consider using here some light-weight functions instead of pseudo-real FirMemberFunctionImpl // As second alternative, we can invent some light-weight kind of FirRegularClass @@ -119,7 +130,7 @@ object FirFakeOverrideGenerator { resolvePhase = baseConstructor.resolvePhase typeParameters += configureAnnotationsTypeParametersAndSignature( - session, baseConstructor, newParameterTypes, newTypeParameters, newReceiverType = null, newReturnType + session, baseConstructor, newParameterTypes, newTypeParameters, newReceiverType = null, newReturnType, fakeOverrideSubstitution ) } } @@ -130,11 +141,19 @@ object FirFakeOverrideGenerator { newParameterTypes: List?, newTypeParameters: List?, newReceiverType: ConeKotlinType?, - newReturnType: ConeKotlinType? + newReturnType: ConeKotlinType?, + fakeOverrideSubstitution: FakeOverrideSubstitution? ): List { return when { baseFunction.typeParameters.isEmpty() -> { - configureAnnotationsAndSignature(session, baseFunction, newParameterTypes, newReceiverType, newReturnType) + configureAnnotationsAndSignature( + session, + baseFunction, + newParameterTypes, + newReceiverType, + newReturnType, + fakeOverrideSubstitution + ) emptyList() } newTypeParameters == null -> { @@ -144,14 +163,33 @@ object FirFakeOverrideGenerator { val copiedParameterTypes = baseFunction.valueParameters.map { substitutor.substituteOrNull(it.returnTypeRef.coneType) } - val (copiedReceiverType, copiedReturnType) = substituteReceiverAndReturnType( + val symbol = baseFunction.symbol + val (copiedReceiverType, possibleReturnType) = substituteReceiverAndReturnType( baseFunction as FirCallableMemberDeclaration<*>, newReceiverType, newReturnType, substitutor ) - configureAnnotationsAndSignature(session, baseFunction, copiedParameterTypes, copiedReceiverType, copiedReturnType) + val (copiedReturnType, newFakeOverrideSubstitution) = when (possibleReturnType) { + is Maybe.Value -> possibleReturnType.value to null + else -> null to FakeOverrideSubstitution(substitutor, symbol) + } + configureAnnotationsAndSignature( + session, + baseFunction, + copiedParameterTypes, + copiedReceiverType, + copiedReturnType, + newFakeOverrideSubstitution + ) copiedTypeParameters } else -> { - configureAnnotationsAndSignature(session, baseFunction, newParameterTypes, newReceiverType, newReturnType) + configureAnnotationsAndSignature( + session, + baseFunction, + newParameterTypes, + newReceiverType, + newReturnType, + fakeOverrideSubstitution + ) newTypeParameters } } @@ -162,10 +200,22 @@ object FirFakeOverrideGenerator { baseFunction: FirFunction<*>, newParameterTypes: List?, newReceiverType: ConeKotlinType?, - newReturnType: ConeKotlinType? + newReturnType: ConeKotlinType?, + fakeOverrideSubstitution: FakeOverrideSubstitution? ) { annotations += baseFunction.annotations - returnTypeRef = replaceReturnTypeIfResolved(baseFunction, newReturnType) + + @Suppress("NAME_SHADOWING") + val fakeOverrideSubstitution = fakeOverrideSubstitution ?: runIf(baseFunction.returnTypeRef is FirImplicitTypeRef) { + FakeOverrideSubstitution(ConeSubstitutor.Empty, baseFunction.symbol) + } + + if (fakeOverrideSubstitution != null) { + returnTypeRef = buildImplicitTypeRef() + attributes.fakeOverrideSubstitution = fakeOverrideSubstitution + } else { + returnTypeRef = baseFunction.returnTypeRef.withReplacedReturnType(newReturnType) + } if (this is FirSimpleFunctionBuilder) { receiverTypeRef = baseFunction.receiverTypeRef?.withReplacedConeType(newReceiverType) @@ -181,14 +231,6 @@ object FirFakeOverrideGenerator { } } - private fun replaceReturnTypeIfResolved( - base: FirCallableDeclaration<*>, - newReturnType: ConeKotlinType? - ): FirTypeRef = if (base.returnTypeRef is FirResolvedTypeRef) - base.returnTypeRef.withReplacedConeType(newReturnType) - else - base.returnTypeRef - fun createFakeOverrideProperty( session: FirSession, baseProperty: FirProperty, @@ -197,7 +239,8 @@ object FirFakeOverrideGenerator { newReturnType: ConeKotlinType? = null, newTypeParameters: List? = null, derivedClassId: ClassId? = null, - isExpect: Boolean = baseProperty.isExpect + isExpect: Boolean = baseProperty.isExpect, + fakeOverrideSubstitution: FakeOverrideSubstitution? = null ): FirPropertySymbol { val symbol = FirPropertySymbol( CallableId(derivedClassId ?: baseSymbol.callableId.classId!!, baseProperty.name), @@ -205,7 +248,8 @@ object FirFakeOverrideGenerator { ) createCopyForFirProperty( symbol, baseProperty, session, isExpect, - newTypeParameters, newReceiverType, newReturnType + newTypeParameters, newReceiverType, newReturnType, + fakeOverrideSubstitution = fakeOverrideSubstitution ) return symbol } @@ -220,6 +264,7 @@ object FirFakeOverrideGenerator { newReturnType: ConeKotlinType? = null, newModality: Modality? = null, newVisibility: Visibility? = null, + fakeOverrideSubstitution: FakeOverrideSubstitution? = null ): FirProperty { return buildProperty { source = baseProperty.source @@ -236,7 +281,8 @@ object FirFakeOverrideGenerator { baseProperty, newTypeParameters, newReceiverType, - newReturnType + newReturnType, + fakeOverrideSubstitution ) } } @@ -245,25 +291,30 @@ object FirFakeOverrideGenerator { baseProperty: FirProperty, newTypeParameters: List?, newReceiverType: ConeKotlinType?, - newReturnType: ConeKotlinType? + newReturnType: ConeKotlinType?, + fakeOverrideSubstitution: FakeOverrideSubstitution? ): List { return when { baseProperty.typeParameters.isEmpty() -> { - configureAnnotationsAndSignature(baseProperty, newReceiverType, newReturnType) + configureAnnotationsAndSignature(baseProperty, newReceiverType, newReturnType, fakeOverrideSubstitution) emptyList() } newTypeParameters == null -> { val (copiedTypeParameters, substitutor) = createNewTypeParametersAndSubstitutor( baseProperty, ConeSubstitutor.Empty ) - val (copiedReceiverType, copiedReturnType) = substituteReceiverAndReturnType( + val (copiedReceiverType, possibleReturnType) = substituteReceiverAndReturnType( baseProperty, newReceiverType, newReturnType, substitutor ) - configureAnnotationsAndSignature(baseProperty, copiedReceiverType, copiedReturnType) + val (copiedReturnType, newFakeOverrideSubstitution) = when (possibleReturnType) { + is Maybe.Value -> possibleReturnType.value to null + else -> null to FakeOverrideSubstitution(substitutor, baseProperty.symbol) + } + configureAnnotationsAndSignature(baseProperty, copiedReceiverType, copiedReturnType, newFakeOverrideSubstitution) copiedTypeParameters.filterIsInstance() } else -> { - configureAnnotationsAndSignature(baseProperty, newReceiverType, newReturnType) + configureAnnotationsAndSignature(baseProperty, newReceiverType, newReturnType, fakeOverrideSubstitution) newTypeParameters } } @@ -274,27 +325,40 @@ object FirFakeOverrideGenerator { newReceiverType: ConeKotlinType?, newReturnType: ConeKotlinType?, substitutor: ConeSubstitutor - ): Pair { + ): Pair> { val copiedReceiverType = newReceiverType?.let { substitutor.substituteOrNull(it) } ?: baseCallable.receiverTypeRef?.let { substitutor.substituteOrNull(it.coneType) } + val copiedReturnType = newReturnType?.let { substitutor.substituteOrNull(it) } ?: baseCallable.returnTypeRef.let { - substitutor.substituteOrNull(it.coneType) + val coneType = baseCallable.returnTypeRef.coneTypeSafe() ?: return copiedReceiverType to Maybe.Nothing + substitutor.substituteOrNull(coneType) } - return copiedReceiverType to copiedReturnType + return copiedReceiverType to Maybe.Value(copiedReturnType) } private fun FirPropertyBuilder.configureAnnotationsAndSignature( baseProperty: FirProperty, newReceiverType: ConeKotlinType?, - newReturnType: ConeKotlinType? + newReturnType: ConeKotlinType?, + fakeOverrideSubstitution: FakeOverrideSubstitution? ) { annotations += baseProperty.annotations - returnTypeRef = replaceReturnTypeIfResolved(baseProperty, newReturnType) + + @Suppress("NAME_SHADOWING") + val fakeOverrideSubstitution = fakeOverrideSubstitution ?: runIf(baseProperty.returnTypeRef is FirImplicitTypeRef) { + FakeOverrideSubstitution(ConeSubstitutor.Empty, baseProperty.symbol) + } + if (fakeOverrideSubstitution != null) { + returnTypeRef = buildImplicitTypeRef() + attributes.fakeOverrideSubstitution = fakeOverrideSubstitution + } else { + returnTypeRef = baseProperty.returnTypeRef.withReplacedReturnType(newReturnType) + } receiverTypeRef = baseProperty.receiverTypeRef?.withReplacedConeType(newReceiverType) } @@ -329,7 +393,8 @@ object FirFakeOverrideGenerator { baseProperty: FirSyntheticProperty, baseSymbol: FirAccessorSymbol, newReturnType: ConeKotlinType?, - newParameterTypes: List? + newParameterTypes: List?, + fakeOverrideSubstitution: FakeOverrideSubstitution? ): FirAccessorSymbol { val functionSymbol = FirNamedFunctionSymbol(baseSymbol.accessorId) val function = createFakeOverrideFunction( @@ -339,7 +404,8 @@ object FirFakeOverrideGenerator { newReceiverType = null, newReturnType, newParameterTypes, - newTypeParameters = null + newTypeParameters = null, + fakeOverrideSubstitution = fakeOverrideSubstitution ) return buildSyntheticProperty { this.session = session @@ -417,4 +483,9 @@ object FirFakeOverrideGenerator { ChainedSubstitutor(substitutor, additionalSubstitutor) ) } + + private sealed class Maybe { + class Value(val value: A) : Maybe() + object Nothing : Maybe() + } } diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/FirDeclarationAttributes.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/FirDeclarationAttributes.kt index b477cdfef51..3e57cc4e459 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/FirDeclarationAttributes.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/FirDeclarationAttributes.kt @@ -39,6 +39,11 @@ object FirDeclarationDataRegistry : TypeRegistry() { return DeclarationDataAccessor(generateNullableAccessor(kClass), kClass) } + fun attributesAccessor(key: K): ReadWriteProperty { + val kClass = key::class + return AttributeDataAccessor(generateNullableAccessor(kClass), kClass) + } + private class DeclarationDataAccessor( val dataAccessor: NullableArrayMapAccessor, val key: KClass @@ -51,4 +56,17 @@ object FirDeclarationDataRegistry : TypeRegistry() { thisRef.attributes[key] = value } } + + private class AttributeDataAccessor( + val dataAccessor: NullableArrayMapAccessor, + val key: KClass + ) : ReadWriteProperty { + override fun getValue(thisRef: FirDeclarationAttributes, property: KProperty<*>): V? { + return dataAccessor.getValue(thisRef, property) + } + + override fun setValue(thisRef: FirDeclarationAttributes, property: KProperty<*>, value: V?) { + thisRef[key] = value + } + } }