[FIR] Introduce different synthetic origins for FIR declarations

This is needed to be able to precisely distinguish different synthetic
  declarations (like fields for delegates and functions for data classes)
  in fir2ir
This commit is contained in:
Dmitriy Novozhilov
2023-07-27 15:07:29 +03:00
committed by Space Team
parent 5b7b885dac
commit 69a35970eb
20 changed files with 45 additions and 27 deletions
@@ -64,10 +64,10 @@ internal tailrec fun FirDeclaration.ktSymbolOrigin(): KtSymbolOrigin = when (ori
FirDeclarationOrigin.Enhancement -> KtSymbolOrigin.JAVA
FirDeclarationOrigin.IntersectionOverride -> KtSymbolOrigin.INTERSECTION_OVERRIDE
FirDeclarationOrigin.Delegated -> KtSymbolOrigin.DELEGATED
FirDeclarationOrigin.Synthetic -> {
is FirDeclarationOrigin.Synthetic -> {
when {
source?.kind == KtFakeSourceElementKind.DataClassGeneratedMembers -> KtSymbolOrigin.SOURCE_MEMBER_GENERATED
this is FirValueParameter && this.containingFunctionSymbol.origin == FirDeclarationOrigin.Synthetic -> KtSymbolOrigin.SOURCE_MEMBER_GENERATED
this is FirValueParameter && this.containingFunctionSymbol.origin is FirDeclarationOrigin.Synthetic -> KtSymbolOrigin.SOURCE_MEMBER_GENERATED
this is FirSyntheticProperty || this is FirSyntheticPropertyAccessor -> KtSymbolOrigin.JAVA_SYNTHETIC_PROPERTY
else -> errorWithAttachment("Invalid FirDeclarationOrigin ${origin::class.simpleName}") {
@@ -8,7 +8,7 @@ D:
[Source]: public abstract val x: R|kotlin/Int| from Use site scope of /A [id: 1]
[Source]: public abstract val x: R|kotlin/String| from Use site scope of /B [id: 2]
[Java(Source)]: private open field y: R|kotlin/Int| from Java enhancement scope for /D [id: 0]
[Synthetic]: public abstract val y: R|kotlin/Int| from Java enhancement scope for /D [id: 0]
[JavaProperty]: public abstract val y: R|kotlin/Int| from Java enhancement scope for /D [id: 0]
[Source]: public abstract val y: R|kotlin/Int| from Use site scope of /A [id: 1]
[Source]: public abstract val y: R|kotlin/Int| from Use site scope of /B [id: 2]
[Enhancement]: public abstract fun getX(): R|kotlin/Any!| from Java enhancement scope for /D [id: 0]
@@ -1,4 +1,4 @@
C:
[Synthetic]: public open val foo: R|kotlin/Int| from Java enhancement scope for /C [id: 0]
[JavaProperty]: public open val foo: R|kotlin/Int| from Java enhancement scope for /C [id: 0]
[Source]: public abstract val foo: R|kotlin/Int| from Use site scope of /B [id: 1]
@@ -1,8 +1,8 @@
D:
[Synthetic]: public open val x: R|kotlin/Int| from Java enhancement scope for /D [id: 0]
[Synthetic]: public open val x: R|kotlin/Int| from Java enhancement scope for /B [id: 1]
[JavaProperty]: public open val x: R|kotlin/Int| from Java enhancement scope for /D [id: 0]
[JavaProperty]: public open val x: R|kotlin/Int| from Java enhancement scope for /B [id: 1]
[Source]: public open val x: R|kotlin/Int| from Use site scope of /A [id: 2]
[Synthetic]: public open val y: R|kotlin/Int| from Java enhancement scope for /D [id: 0]
[JavaProperty]: public open val y: R|kotlin/Int| from Java enhancement scope for /D [id: 0]
[Source]: public open val y: R|kotlin/Int| from Java enhancement scope for /B [id: 1]
[Source]: public open val y: R|kotlin/Int| from Use site scope of /A [id: 1]
@@ -87,7 +87,7 @@ class NativeForwardDeclarationsSymbolProvider(
buildRegularClass {
moduleData = forwardDeclarationsModuleData
origin = FirDeclarationOrigin.Synthetic
origin = FirDeclarationOrigin.Synthetic.ForwardDeclaration
check(!classId.isNestedClass) { "Expected top-level class when building forward declaration, got $classId" }
name = classId.shortClassName
status = FirResolvedDeclarationStatusImpl(
@@ -598,7 +598,7 @@ class FirElementSerializer private constructor(
private fun FirFunction.memberKind(): MemberKind {
return when (origin) {
FirDeclarationOrigin.Delegated -> MemberKind.DELEGATION
FirDeclarationOrigin.Synthetic -> MemberKind.SYNTHESIZED
is FirDeclarationOrigin.Synthetic -> MemberKind.SYNTHESIZED
else -> MemberKind.DECLARATION
}
}
@@ -699,7 +699,7 @@ fun FirSession.createFilesWithGeneratedDeclarations(): List<FirFile> {
moduleData = this@createFilesWithGeneratedDeclarations.moduleData
containingFileSymbol = this@buildFile.symbol
}
origin = FirDeclarationOrigin.Synthetic
origin = FirDeclarationOrigin.Synthetic.PluginFile
moduleData = this@createFilesWithGeneratedDeclarations.moduleData
packageDirective = buildPackageDirective {
this.packageFqName = packageFqName
@@ -137,7 +137,7 @@ class Fir2IrConverter(
else ->
NaiveSourceBasedFileEntryImpl(file.sourceFile?.path ?: file.sourceFile?.name ?: file.name)
}
FirDeclarationOrigin.Synthetic -> NaiveSourceBasedFileEntryImpl(file.name)
is FirDeclarationOrigin.Synthetic -> NaiveSourceBasedFileEntryImpl(file.name)
else -> error("Unsupported file origin: ${file.origin}")
}
val irFile = IrFileImpl(
@@ -160,7 +160,7 @@ class DataClassMembersGenerator(val components: Fir2IrComponents) : Fir2IrCompon
for (name in listOf(EQUALS, HASHCODE_NAME, TO_STRING)) {
scope.processFunctionsByName(name) {
// We won't synthesize a function if there is a user-contributed (non-synthetic) one.
if (it.origin != FirDeclarationOrigin.Synthetic) return@processFunctionsByName
if (it.origin !is FirDeclarationOrigin.Synthetic) return@processFunctionsByName
if (it.containingClassLookupTag() != klass.symbol.toLookupTag()) return@processFunctionsByName
require(!contains(name)) {
"Two synthetic functions $name were found in data/value class ${klass.name}:\n" +
@@ -25,6 +25,9 @@ import org.jetbrains.kotlin.fir.declarations.builder.buildSimpleFunction
import org.jetbrains.kotlin.fir.declarations.builder.buildValueParameter
import org.jetbrains.kotlin.fir.declarations.impl.FirResolvedDeclarationStatusImpl
import org.jetbrains.kotlin.fir.declarations.isEquals
import org.jetbrains.kotlin.fir.declarations.utils.isData
import org.jetbrains.kotlin.fir.declarations.utils.isInline
import org.jetbrains.kotlin.fir.render
import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.resolve.defaultType
import org.jetbrains.kotlin.fir.resolve.lookupSuperTypes
@@ -52,6 +55,11 @@ class FirClassAnySynthesizedMemberScope(
klass: FirRegularClass,
scopeSession: ScopeSession,
) : FirContainingNamesAwareScope() {
private val originForFunctions = when {
klass.isData -> FirDeclarationOrigin.Synthetic.DataClassMember
klass.isInline -> FirDeclarationOrigin.Synthetic.ValueClassMember
else -> error("This scope should not be created for non-data and non-value class. ${klass.render()}")
}
private val lookupTag = klass.symbol.toLookupTag()
private val baseModuleData = klass.moduleData
@@ -139,7 +147,7 @@ class FirClassAnySynthesizedMemberScope(
this.valueParameters.add(
buildValueParameter {
this.name = Name.identifier("other")
origin = FirDeclarationOrigin.Synthetic
origin = originForFunctions
moduleData = baseModuleData
this.returnTypeRef = FirImplicitNullableAnyTypeRef(null)
this.symbol = FirValueParameterSymbol(this.name)
@@ -169,7 +177,7 @@ class FirClassAnySynthesizedMemberScope(
) {
this.source = synthesizedSource
moduleData = baseModuleData
origin = FirDeclarationOrigin.Synthetic
origin = originForFunctions
this.name = name
status = FirResolvedDeclarationStatusImpl(Visibilities.Public, Modality.OPEN, EffectiveVisibility.Public).apply {
this.isOperator = isOperator
@@ -1915,7 +1915,7 @@ class LightTreeRawFirDeclarationBuilder(
buildField {
source = explicitDelegation.toFirSourceElement().fakeElement(KtFakeSourceElementKind.ClassDelegationField)
moduleData = baseModuleData
origin = FirDeclarationOrigin.Synthetic
origin = FirDeclarationOrigin.Synthetic.DelegateField
name = NameUtils.delegateFieldName(delegateFieldsMap.size)
returnTypeRef = firTypeRef
symbol = FirFieldSymbol(CallableId(context.currentClassId, name))
@@ -880,7 +880,7 @@ open class PsiRawFirBuilder(
return buildField {
source = delegateSource
moduleData = baseModuleData
origin = FirDeclarationOrigin.Synthetic
origin = FirDeclarationOrigin.Synthetic.DelegateField
name = NameUtils.delegateFieldName(fieldOrd)
returnTypeRef = type
symbol = FirFieldSymbol(CallableId(this@PsiRawFirBuilder.context.currentClassId, name))
@@ -907,7 +907,7 @@ abstract class AbstractRawFirBuilder<T>(val baseSession: FirSession, val context
val componentFunction = buildSimpleFunction {
source = sourceNode?.toFirSourceElement(KtFakeSourceElementKind.DataClassGeneratedMembers)
moduleData = baseModuleData
origin = FirDeclarationOrigin.Synthetic
origin = FirDeclarationOrigin.Synthetic.DataClassMember
returnTypeRef = firProperty.returnTypeRef.copyWithNewSourceKind(KtFakeSourceElementKind.DataClassGeneratedMembers)
this.name = name
status = FirDeclarationStatusImpl(firProperty.visibility, Modality.FINAL).apply {
@@ -1100,7 +1100,7 @@ fun <TBase, TSource : TBase, TParameter : TBase> FirRegularClassBuilder.createDa
val classTypeRef = createClassTypeRefWithSourceKind(KtFakeSourceElementKind.DataClassGeneratedMembers)
this.source = toFirSource(sourceElement, KtFakeSourceElementKind.DataClassGeneratedMembers)
moduleData = this@createDataClassCopyFunction.moduleData
origin = FirDeclarationOrigin.Synthetic
origin = FirDeclarationOrigin.Synthetic.DataClassMember
returnTypeRef = classTypeRef
name = StandardNames.DATA_CLASS_COPY
status = FirDeclarationStatusImpl(Visibilities.Public, Modality.FINAL)
@@ -1116,7 +1116,7 @@ fun <TBase, TSource : TBase, TParameter : TBase> FirRegularClassBuilder.createDa
source = parameterSource
containingFunctionSymbol = this@buildSimpleFunction.symbol
moduleData = this@createDataClassCopyFunction.moduleData
origin = FirDeclarationOrigin.Synthetic
origin = FirDeclarationOrigin.Synthetic.DataClassMember
returnTypeRef = propertyReturnTypeRef
name = propertyName
symbol = FirValueParameterSymbol(propertyName)
@@ -166,7 +166,7 @@ class CandidateFactory private constructor(
buildErrorFunction {
moduleData = context.session.moduleData
resolvePhase = FirResolvePhase.BODY_RESOLVE
origin = FirDeclarationOrigin.Synthetic
origin = FirDeclarationOrigin.Synthetic.Error
this.diagnostic = diagnostic
symbol = it
}
@@ -178,7 +178,7 @@ class CandidateFactory private constructor(
buildErrorProperty {
moduleData = context.session.moduleData
resolvePhase = FirResolvePhase.BODY_RESOLVE
origin = FirDeclarationOrigin.Synthetic
origin = FirDeclarationOrigin.Synthetic.Error
name = FirErrorPropertySymbol.NAME
this.diagnostic = diagnostic
symbol = it
@@ -229,7 +229,7 @@ private class TypeAliasConstructorsSubstitutingScope(
processor(
buildConstructorCopy(originalConstructorSymbol.fir) {
symbol = FirConstructorSymbol(originalConstructorSymbol.callableId)
origin = FirDeclarationOrigin.Synthetic
origin = FirDeclarationOrigin.Synthetic.TypeAliasConstructor
this.typeParameters.clear()
this.typeParameters += typeParameters.map { buildConstructedClassTypeParameterRef { symbol = it.symbol } }
@@ -436,7 +436,7 @@ class FirSyntheticCallGenerator(
): FirSimpleFunctionBuilder {
return FirSimpleFunctionBuilder().apply {
moduleData = session.moduleData
origin = FirDeclarationOrigin.Synthetic
origin = FirDeclarationOrigin.Synthetic.FakeFunction
this.symbol = symbol
this.name = name
status = FirDeclarationStatusImpl(Visibilities.Public, Modality.FINAL)
@@ -23,7 +23,17 @@ sealed class FirDeclarationOrigin(
object Library : Java("Java(Library)")
}
object Synthetic : FirDeclarationOrigin()
sealed class Synthetic : FirDeclarationOrigin() {
object DataClassMember : Synthetic()
object ValueClassMember : Synthetic()
object JavaProperty : Synthetic()
object DelegateField : Synthetic()
object PluginFile : Synthetic()
object Error : Synthetic()
object TypeAliasConstructor : Synthetic()
object FakeFunction : Synthetic()
object ForwardDeclaration : Synthetic()
}
object DynamicScope : FirDeclarationOrigin()
object SamConstructor : FirDeclarationOrigin()
object Enhancement : FirDeclarationOrigin()
@@ -51,7 +51,7 @@ class FirSyntheticProperty(
get() = null
override val origin: FirDeclarationOrigin
get() = FirDeclarationOrigin.Synthetic
get() = FirDeclarationOrigin.Synthetic.JavaProperty
override val initializer: FirExpression?
get() = null
@@ -34,7 +34,7 @@ class FirSyntheticPropertyAccessor(
get() = delegate.moduleData
override val origin: FirDeclarationOrigin
get() = FirDeclarationOrigin.Synthetic
get() = FirDeclarationOrigin.Synthetic.JavaProperty
override val returnTypeRef: FirTypeRef
get() = delegate.returnTypeRef
@@ -34,7 +34,7 @@ inline val FirDeclaration.isFromLibrary: Boolean
inline val FirDeclaration.isPrecompiled: Boolean
get() = origin == FirDeclarationOrigin.Precompiled
inline val FirDeclaration.isSynthetic: Boolean
get() = origin == FirDeclarationOrigin.Synthetic
get() = origin is FirDeclarationOrigin.Synthetic
// NB: This function checks transitive localness. That is,
// if a declaration `isNonLocal`, then its parent also `isNonLocal`.