[FIR] Check visibility correctly for sealed class in file
This commit is contained in:
+4
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
sealed class Foo(val value: String)
|
||||
|
||||
class Bar : Foo("OK")
|
||||
@@ -0,0 +1,16 @@
|
||||
FILE: sealedClass.kt
|
||||
public sealed class Foo : R|kotlin/Any| {
|
||||
private constructor(value: R|kotlin/String|): R|Foo| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
public final val value: R|kotlin/String| = R|<local>/value|
|
||||
public get(): R|kotlin/String|
|
||||
|
||||
}
|
||||
public final class Bar : R|Foo| {
|
||||
public constructor(): R|Bar| {
|
||||
super<R|Foo|>(String(OK))
|
||||
}
|
||||
|
||||
}
|
||||
+5
@@ -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");
|
||||
|
||||
Generated
+5
@@ -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");
|
||||
|
||||
@@ -35,6 +35,8 @@ interface FirDeclarationStatus : FirElement {
|
||||
val isData: Boolean
|
||||
val isSuspend: Boolean
|
||||
val isStatic: Boolean
|
||||
val isFromSealedClass: Boolean
|
||||
val isFromEnumClass: Boolean
|
||||
|
||||
override fun <R, D> accept(visitor: FirVisitor<R, D>, data: D): R = visitor.visitDeclarationStatus(this, data)
|
||||
}
|
||||
|
||||
+2
@@ -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 <R, D> accept(visitor: FirVisitor<R, D>, data: D): R = visitor.visitResolvedDeclarationStatus(this, data)
|
||||
}
|
||||
|
||||
+15
-1
@@ -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 <R, D> acceptChildren(visitor: FirVisitor<R, D>, data: D) {}
|
||||
|
||||
+2
-1
@@ -296,7 +296,8 @@ object NodeConfigurator : AbstractFieldConfigurator<FirTreeBuilder>(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"
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
// WITH_RUNTIME
|
||||
|
||||
|
||||
+1
-1
@@ -60,7 +60,7 @@ FILE fqName:<root> fileName:/expectedSealedClass.kt
|
||||
$this: VALUE_PARAMETER INSTANCE_RECEIVER name:<this> type:<root>.Add
|
||||
CONSTRUCTOR visibility:public <> () returnType:<root>.Add [primary]
|
||||
BLOCK_BODY
|
||||
ERROR_CALL 'Cannot find delegated constructor call' type=<root>.Add
|
||||
DELEGATING_CONSTRUCTOR_CALL 'private constructor <init> () [primary] declared in <root>.Ops'
|
||||
INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:Add modality:FINAL visibility:public superTypes:[<root>.Ops]'
|
||||
FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator]
|
||||
overridden:
|
||||
|
||||
Reference in New Issue
Block a user