diff --git a/compiler/fir/lightTree/src/org/jetbrains/kotlin/fir/lightTree/converter/DeclarationsConverter.kt b/compiler/fir/lightTree/src/org/jetbrains/kotlin/fir/lightTree/converter/DeclarationsConverter.kt index 9cbceef6cb7..d6f5982adc5 100644 --- a/compiler/fir/lightTree/src/org/jetbrains/kotlin/fir/lightTree/converter/DeclarationsConverter.kt +++ b/compiler/fir/lightTree/src/org/jetbrains/kotlin/fir/lightTree/converter/DeclarationsConverter.kt @@ -645,6 +645,8 @@ class DeclarationsConverter( isExpect = modifiers.hasExpect() isActual = modifiers.hasActual() isInner = classWrapper.isInner() + isFromSealedClass = classWrapper.isSealed() + isFromEnumClass = classWrapper.isEnum() } return PrimaryConstructor( @@ -713,6 +715,8 @@ class DeclarationsConverter( isExpect = modifiers.hasExpect() isActual = modifiers.hasActual() isInner = classWrapper.isInner() + isFromSealedClass = classWrapper.isSealed() + isFromEnumClass = classWrapper.isEnum() } val target = FirFunctionTarget(labelName = null, isLambda = false) diff --git a/compiler/fir/lightTree/src/org/jetbrains/kotlin/fir/lightTree/fir/ClassWrapper.kt b/compiler/fir/lightTree/src/org/jetbrains/kotlin/fir/lightTree/fir/ClassWrapper.kt index 2fb96dea8e0..4c7eb1abb30 100644 --- a/compiler/fir/lightTree/src/org/jetbrains/kotlin/fir/lightTree/fir/ClassWrapper.kt +++ b/compiler/fir/lightTree/src/org/jetbrains/kotlin/fir/lightTree/fir/ClassWrapper.kt @@ -40,11 +40,11 @@ class ClassWrapper( return classKind == ClassKind.OBJECT } - private fun isSealed(): Boolean { + fun isSealed(): Boolean { return modifiers.hasModality(Modality.SEALED) } - private fun isEnum(): Boolean { + fun isEnum(): Boolean { return modifiers.isEnum() } diff --git a/compiler/fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt b/compiler/fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt index d3341d42f6b..d36648dd8b7 100644 --- a/compiler/fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt +++ b/compiler/fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt @@ -472,6 +472,8 @@ class RawFirBuilder(session: FirSession, val baseScopeProvider: FirScopeProvider isExpect = this@toFirConstructor?.hasExpectModifier() ?: false isActual = this@toFirConstructor?.hasActualModifier() ?: false isInner = owner.hasModifier(INNER_KEYWORD) + isFromSealedClass = owner.hasModifier(SEALED_KEYWORD) + isFromEnumClass = owner.hasModifier(ENUM_KEYWORD) } return buildPrimaryConstructor { source = constructorSource @@ -842,6 +844,8 @@ class RawFirBuilder(session: FirSession, val baseScopeProvider: FirScopeProvider isExpect = hasExpectModifier() isActual = hasActualModifier() isInner = owner.hasModifier(INNER_KEYWORD) + isFromSealedClass = owner.hasModifier(SEALED_KEYWORD) + isFromEnumClass = owner.hasModifier(ENUM_KEYWORD) } symbol = FirConstructorSymbol(callableIdForClassConstructor()) delegatedConstructor = getDelegationCall().convert(delegatedSuperTypeRef, delegatedSelfTypeRef, hasPrimaryConstructor) diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ResolverParts.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ResolverParts.kt index 3d19bf1656d..377b56a2492 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ResolverParts.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ResolverParts.kt @@ -421,7 +421,7 @@ internal object CheckVisibility : CheckerStage() { } Visibilities.PRIVATE, Visibilities.PRIVATE_TO_THIS -> { if (declaration.session == callInfo.session) { - if (ownerId == null) { + if (ownerId == null || declaration is FirConstructor && declaration.status.isFromSealedClass) { // Top-level: visible in file candidateFile == useSiteFile } else { diff --git a/compiler/fir/resolve/testData/resolve/sealedClass.kt b/compiler/fir/resolve/testData/resolve/sealedClass.kt new file mode 100644 index 00000000000..7599e562784 --- /dev/null +++ b/compiler/fir/resolve/testData/resolve/sealedClass.kt @@ -0,0 +1,3 @@ +sealed class Foo(val value: String) + +class Bar : Foo("OK") diff --git a/compiler/fir/resolve/testData/resolve/sealedClass.txt b/compiler/fir/resolve/testData/resolve/sealedClass.txt new file mode 100644 index 00000000000..82782c3a2ff --- /dev/null +++ b/compiler/fir/resolve/testData/resolve/sealedClass.txt @@ -0,0 +1,16 @@ +FILE: sealedClass.kt + public sealed class Foo : R|kotlin/Any| { + private constructor(value: R|kotlin/String|): R|Foo| { + super() + } + + public final val value: R|kotlin/String| = R|/value| + public get(): R|kotlin/String| + + } + public final class Bar : R|Foo| { + public constructor(): R|Bar| { + super(String(OK)) + } + + } diff --git a/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsTestGenerated.java b/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsTestGenerated.java index a8a18992ae5..36d68d1d40c 100644 --- a/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsTestGenerated.java +++ b/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsTestGenerated.java @@ -263,6 +263,11 @@ public class FirDiagnosticsTestGenerated extends AbstractFirDiagnosticsTest { runTest("compiler/fir/resolve/testData/resolve/recursiveCallOnWhenWithSealedClass.kt"); } + @TestMetadata("sealedClass.kt") + public void testSealedClass() throws Exception { + runTest("compiler/fir/resolve/testData/resolve/sealedClass.kt"); + } + @TestMetadata("simpleClass.kt") public void testSimpleClass() throws Exception { runTest("compiler/fir/resolve/testData/resolve/simpleClass.kt"); diff --git a/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsWithLightTreeTestGenerated.java b/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsWithLightTreeTestGenerated.java index 74038ed0400..146000f7fa0 100644 --- a/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsWithLightTreeTestGenerated.java +++ b/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsWithLightTreeTestGenerated.java @@ -263,6 +263,11 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos runTest("compiler/fir/resolve/testData/resolve/recursiveCallOnWhenWithSealedClass.kt"); } + @TestMetadata("sealedClass.kt") + public void testSealedClass() throws Exception { + runTest("compiler/fir/resolve/testData/resolve/sealedClass.kt"); + } + @TestMetadata("simpleClass.kt") public void testSimpleClass() throws Exception { runTest("compiler/fir/resolve/testData/resolve/simpleClass.kt"); diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/FirDeclarationStatus.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/FirDeclarationStatus.kt index 81b48585fbf..9b1a8561515 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/FirDeclarationStatus.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/FirDeclarationStatus.kt @@ -35,6 +35,8 @@ interface FirDeclarationStatus : FirElement { val isData: Boolean val isSuspend: Boolean val isStatic: Boolean + val isFromSealedClass: Boolean + val isFromEnumClass: Boolean override fun accept(visitor: FirVisitor, data: D): R = visitor.visitDeclarationStatus(this, data) } diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/FirResolvedDeclarationStatus.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/FirResolvedDeclarationStatus.kt index 44c45a4c243..6166df8225c 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/FirResolvedDeclarationStatus.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/FirResolvedDeclarationStatus.kt @@ -34,6 +34,8 @@ interface FirResolvedDeclarationStatus : FirDeclarationStatus { override val isData: Boolean override val isSuspend: Boolean override val isStatic: Boolean + override val isFromSealedClass: Boolean + override val isFromEnumClass: Boolean override fun accept(visitor: FirVisitor, data: D): R = visitor.visitResolvedDeclarationStatus(this, data) } diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/impl/FirDeclarationStatusImpl.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/impl/FirDeclarationStatusImpl.kt index 082ca04e221..f93b9f8e673 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/impl/FirDeclarationStatusImpl.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/impl/FirDeclarationStatusImpl.kt @@ -121,6 +121,18 @@ open class FirDeclarationStatusImpl( this[STATIC] = value } + override var isFromSealedClass: Boolean + get() = this[FROM_SEALED] + set(value) { + this[FROM_SEALED] = value + } + + override var isFromEnumClass: Boolean + get() = this[FROM_ENUM] + set(value) { + this[FROM_ENUM] = value + } + private enum class Modifier(val mask: Int) { EXPECT(0x1), ACTUAL(0x2), @@ -136,7 +148,9 @@ open class FirDeclarationStatusImpl( COMPANION(0x800), DATA(0x1000), SUSPEND(0x2000), - STATIC(0x4000) + STATIC(0x4000), + FROM_SEALED(0x8000), + FROM_ENUM(0x10000) } override fun acceptChildren(visitor: FirVisitor, data: D) {} diff --git a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/NodeConfigurator.kt b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/NodeConfigurator.kt index 7238e1df4a9..688ee5d2037 100644 --- a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/NodeConfigurator.kt +++ b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/NodeConfigurator.kt @@ -296,7 +296,8 @@ object NodeConfigurator : AbstractFieldConfigurator(FirTreeBuild +modality generateBooleanFields( "expect", "actual", "override", "operator", "infix", "inline", "tailRec", - "external", "const", "lateInit", "inner", "companion", "data", "suspend", "static" + "external", "const", "lateInit", "inner", "companion", "data", "suspend", "static", + "fromSealedClass", "fromEnumClass" ) } diff --git a/compiler/testData/codegen/box/multifileClasses/sealedClassHierarchy.kt b/compiler/testData/codegen/box/multifileClasses/sealedClassHierarchy.kt index 38482ed9580..9aff61d2774 100644 --- a/compiler/testData/codegen/box/multifileClasses/sealedClassHierarchy.kt +++ b/compiler/testData/codegen/box/multifileClasses/sealedClassHierarchy.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND_FIR: JVM_IR // TARGET_BACKEND: JVM // WITH_RUNTIME diff --git a/compiler/testData/ir/irText/declarations/multiplatform/expectedSealedClass.fir.txt b/compiler/testData/ir/irText/declarations/multiplatform/expectedSealedClass.fir.txt index a4092d8bc71..4a5d659ca64 100644 --- a/compiler/testData/ir/irText/declarations/multiplatform/expectedSealedClass.fir.txt +++ b/compiler/testData/ir/irText/declarations/multiplatform/expectedSealedClass.fir.txt @@ -60,7 +60,7 @@ FILE fqName: fileName:/expectedSealedClass.kt $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.Add CONSTRUCTOR visibility:public <> () returnType:.Add [primary] BLOCK_BODY - ERROR_CALL 'Cannot find delegated constructor call' type=.Add + DELEGATING_CONSTRUCTOR_CALL 'private constructor () [primary] declared in .Ops' INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:Add modality:FINAL visibility:public superTypes:[.Ops]' FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator] overridden: