From fcabd02fe8684c426f24f4b8f21fb07b99754d97 Mon Sep 17 00:00:00 2001 From: Mikhail Glukhikh Date: Wed, 24 Jun 2020 17:04:21 +0300 Subject: [PATCH] [FIR] Take class expect flag into account in its substitution scope --- .../kotlin/fir/scopes/KotlinScopeProvider.kt | 19 +++++++++++---- .../scopes/impl/FirClassSubstitutionScope.kt | 16 ++++++++----- .../multiplatform/expectedEnumClass.fir.txt | 24 +++++++++---------- 3 files changed, 35 insertions(+), 24 deletions(-) diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/KotlinScopeProvider.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/KotlinScopeProvider.kt index 9753e15419f..49bcce6963a 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/KotlinScopeProvider.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/KotlinScopeProvider.kt @@ -8,7 +8,9 @@ package org.jetbrains.kotlin.fir.scopes import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.declarations.FirClass +import org.jetbrains.kotlin.fir.declarations.FirRegularClass import org.jetbrains.kotlin.fir.declarations.classId +import org.jetbrains.kotlin.fir.declarations.isExpect import org.jetbrains.kotlin.fir.resolve.* import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor import org.jetbrains.kotlin.fir.resolve.substitution.substitutorByMap @@ -43,7 +45,10 @@ class KotlinScopeProvider( if (symbol is FirRegularClassSymbol) { symbol.fir.scope( substitutor(symbol, useSiteSuperType, useSiteSession), - useSiteSession, scopeSession, skipPrivateMembers = true, klass.classId + useSiteSession, scopeSession, + skipPrivateMembers = true, + classId = klass.classId, + isFromExpectClass = (klass as? FirRegularClass)?.isExpect == true ).let { it as? FirTypeScope ?: error("$it is expected to be FirOverrideAwareScope") } @@ -85,7 +90,7 @@ class KotlinScopeProvider( data class ConeSubstitutionScopeKey( - val classId: ClassId?, val substitutor: ConeSubstitutor + val classId: ClassId?, val isFromExpectClass: Boolean, val substitutor: ConeSubstitutor ) : ScopeSessionKey, FirClassSubstitutionScope>() fun FirClass<*>.unsubstitutedScope(useSiteSession: FirSession, scopeSession: ScopeSession): FirScope { @@ -97,7 +102,8 @@ internal fun FirClass<*>.scope( useSiteSession: FirSession, scopeSession: ScopeSession, skipPrivateMembers: Boolean, - classId: ClassId? = this.classId + classId: ClassId? = this.classId, + isFromExpectClass: Boolean = false ): FirTypeScope { val basicScope = scopeProvider.getUseSiteMemberScope( this, useSiteSession, scopeSession @@ -105,8 +111,11 @@ internal fun FirClass<*>.scope( if (substitutor == ConeSubstitutor.Empty) return basicScope return scopeSession.getOrBuild( - this, ConeSubstitutionScopeKey(classId, substitutor) + this, ConeSubstitutionScopeKey(classId, isFromExpectClass, substitutor) ) { - FirClassSubstitutionScope(useSiteSession, basicScope, scopeSession, substitutor, skipPrivateMembers, classId) + FirClassSubstitutionScope( + useSiteSession, basicScope, scopeSession, substitutor, + skipPrivateMembers, classId, makeExpect = isFromExpectClass + ) } } 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 b38740aad99..65a355ec544 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 @@ -40,7 +40,8 @@ class FirClassSubstitutionScope( scopeSession: ScopeSession, private val substitutor: ConeSubstitutor, private val skipPrivateMembers: Boolean, - private val derivedClassId: ClassId? = null + private val derivedClassId: ClassId? = null, + private val makeExpect: Boolean = false ) : FirTypeScope() { private val fakeOverrideFunctions = mutableMapOf, FirFunctionSymbol<*>>() @@ -143,7 +144,8 @@ class FirClassSubstitutionScope( newReturnType, newParameterTypes, newTypeParameters as List, - derivedClassId + derivedClassId, + makeExpect ) } @@ -161,7 +163,7 @@ class FirClassSubstitutionScope( } return createFakeOverrideConstructor( FirConstructorSymbol(original.callableId, overriddenSymbol = original), - session, constructor, newReturnType, newParameterTypes, newTypeParameters + session, constructor, newReturnType, newParameterTypes, newTypeParameters, makeExpect ).symbol } @@ -185,7 +187,8 @@ class FirClassSubstitutionScope( newReceiverType, newReturnType, newTypeParameters as List, - derivedClassId + derivedClassId, + makeExpect ) } @@ -474,7 +477,8 @@ class FirClassSubstitutionScope( baseConstructor: FirConstructor, newReturnType: ConeKotlinType? = null, newParameterTypes: List? = null, - newTypeParameters: List? = null + newTypeParameters: List? = null, + isExpect: Boolean = baseConstructor.isExpect ): 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 @@ -484,7 +488,7 @@ class FirClassSubstitutionScope( origin = FirDeclarationOrigin.FakeOverride returnTypeRef = baseConstructor.returnTypeRef.withReplacedReturnType(newReturnType) receiverTypeRef = baseConstructor.receiverTypeRef?.withReplacedConeType(null) - status = baseConstructor.status + status = baseConstructor.status.withExpect(isExpect) symbol = fakeOverrideSymbol resolvePhase = baseConstructor.resolvePhase configureAnnotationsAndParameters(session, baseConstructor, newParameterTypes) diff --git a/compiler/testData/ir/irText/declarations/multiplatform/expectedEnumClass.fir.txt b/compiler/testData/ir/irText/declarations/multiplatform/expectedEnumClass.fir.txt index acf41918283..5e51982d0fa 100644 --- a/compiler/testData/ir/irText/declarations/multiplatform/expectedEnumClass.fir.txt +++ b/compiler/testData/ir/irText/declarations/multiplatform/expectedEnumClass.fir.txt @@ -8,42 +8,40 @@ FILE fqName: fileName:/expectedEnumClass.kt ENUM_ENTRY name:BAR init: EXPRESSION_BODY ENUM_CONSTRUCTOR_CALL 'private constructor () [primary,expect] declared in .MyEnum' - FUN ENUM_CLASS_SPECIAL_MEMBER name:values visibility:public modality:FINAL <> () returnType:kotlin.Array<.MyEnum> - SYNTHETIC_BODY kind=ENUM_VALUES - FUN ENUM_CLASS_SPECIAL_MEMBER name:valueOf visibility:public modality:FINAL <> (value:kotlin.String) returnType:.MyEnum + FUN ENUM_CLASS_SPECIAL_MEMBER name:values visibility:public modality:FINAL <> () returnType:kotlin.Array<.MyEnum> [expect] + FUN ENUM_CLASS_SPECIAL_MEMBER name:valueOf visibility:public modality:FINAL <> (value:kotlin.String) returnType:.MyEnum [expect] VALUE_PARAMETER name:value index:0 type:kotlin.String - SYNTHETIC_BODY kind=ENUM_VALUEOF - FUN FAKE_OVERRIDE name:clone visibility:protected modality:FINAL <> ($this:kotlin.Enum) returnType:kotlin.Any [fake_override] + FUN FAKE_OVERRIDE name:clone visibility:protected modality:FINAL <> ($this:kotlin.Enum) returnType:kotlin.Any [expect,fake_override] overridden: protected final fun clone (): kotlin.Any declared in kotlin.Enum $this: VALUE_PARAMETER name: type:kotlin.Enum - FUN FAKE_OVERRIDE name:compareTo visibility:public modality:FINAL <> ($this:kotlin.Enum, other:.MyEnum) returnType:kotlin.Int [fake_override,operator] + FUN FAKE_OVERRIDE name:compareTo visibility:public modality:FINAL <> ($this:kotlin.Enum, other:.MyEnum) returnType:kotlin.Int [expect,fake_override] overridden: public final fun compareTo (other: E of kotlin.Enum): kotlin.Int [operator] declared in kotlin.Enum $this: VALUE_PARAMETER name: type:kotlin.Enum VALUE_PARAMETER name:other index:0 type:.MyEnum - FUN FAKE_OVERRIDE name:equals visibility:public modality:FINAL <> ($this:kotlin.Enum, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator] + FUN FAKE_OVERRIDE name:equals visibility:public modality:FINAL <> ($this:kotlin.Enum, other:kotlin.Any?) returnType:kotlin.Boolean [expect,fake_override] overridden: public final fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Enum $this: VALUE_PARAMETER name: type:kotlin.Enum VALUE_PARAMETER name:other index:0 type:kotlin.Any? - FUN FAKE_OVERRIDE name:hashCode visibility:public modality:FINAL <> ($this:kotlin.Enum) returnType:kotlin.Int [fake_override] + FUN FAKE_OVERRIDE name:hashCode visibility:public modality:FINAL <> ($this:kotlin.Enum) returnType:kotlin.Int [expect,fake_override] overridden: public final fun hashCode (): kotlin.Int declared in kotlin.Enum $this: VALUE_PARAMETER name: type:kotlin.Enum - FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Enum) returnType:kotlin.String [fake_override] + FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Enum) returnType:kotlin.String [expect,fake_override] overridden: public open fun toString (): kotlin.String declared in kotlin.Enum $this: VALUE_PARAMETER name: type:kotlin.Enum - PROPERTY FAKE_OVERRIDE name:name visibility:public modality:FINAL [fake_override,val] + PROPERTY FAKE_OVERRIDE name:name visibility:public modality:FINAL [expect,fake_override,val] FUN FAKE_OVERRIDE name: visibility:public modality:FINAL <> ($this:kotlin.Enum) returnType:kotlin.String [fake_override] - correspondingProperty: PROPERTY FAKE_OVERRIDE name:name visibility:public modality:FINAL [fake_override,val] + correspondingProperty: PROPERTY FAKE_OVERRIDE name:name visibility:public modality:FINAL [expect,fake_override,val] overridden: public final fun (): kotlin.String declared in kotlin.Enum $this: VALUE_PARAMETER name: type:kotlin.Enum - PROPERTY FAKE_OVERRIDE name:ordinal visibility:public modality:FINAL [fake_override,val] + PROPERTY FAKE_OVERRIDE name:ordinal visibility:public modality:FINAL [expect,fake_override,val] FUN FAKE_OVERRIDE name: visibility:public modality:FINAL <> ($this:kotlin.Enum) returnType:kotlin.Int [fake_override] - correspondingProperty: PROPERTY FAKE_OVERRIDE name:ordinal visibility:public modality:FINAL [fake_override,val] + correspondingProperty: PROPERTY FAKE_OVERRIDE name:ordinal visibility:public modality:FINAL [expect,fake_override,val] overridden: public final fun (): kotlin.Int declared in kotlin.Enum $this: VALUE_PARAMETER name: type:kotlin.Enum