[FIR] Handle open in interface correctly during status resolve

This commit is contained in:
Mikhail Glukhikh
2020-08-20 14:25:40 +03:00
parent 8e2c5bf4fe
commit 99d2fd7c4d
6 changed files with 75 additions and 6 deletions
@@ -0,0 +1,15 @@
interface Some {
open fun foo()
open fun bar() {}
open val x: Int
open val y = 1
open val z get() = 1
open var xx: Int
open var yy = 1
open var zz: Int
set(value) {
field = value
}
}
@@ -0,0 +1,33 @@
FILE: openInInterface.kt
public abstract interface Some : R|kotlin/Any| {
public abstract fun foo(): R|kotlin/Unit|
public open fun bar(): R|kotlin/Unit| {
}
public abstract val x: R|kotlin/Int|
public get(): R|kotlin/Int|
public open val y: R|kotlin/Int| = Int(1)
public get(): R|kotlin/Int|
public open val z: R|kotlin/Int|
public get(): R|kotlin/Int| {
^ Int(1)
}
public abstract var xx: R|kotlin/Int|
public get(): R|kotlin/Int|
public set(value: R|kotlin/Int|): R|kotlin/Unit|
public open var yy: R|kotlin/Int| = Int(1)
public get(): R|kotlin/Int|
public set(value: R|kotlin/Int|): R|kotlin/Unit|
public open var zz: R|kotlin/Int|
public get(): R|kotlin/Int|
public set(value: R|kotlin/Int|): R|kotlin/Unit| {
this@R|/Some|.F|/Some.zz| = R|<local>/value|
}
}
@@ -313,6 +313,11 @@ public class FirDiagnosticsTestGenerated extends AbstractFirDiagnosticsTest {
runTest("compiler/fir/analysis-tests/testData/resolve/offOrderMultiBoundGenericOverride.kt"); runTest("compiler/fir/analysis-tests/testData/resolve/offOrderMultiBoundGenericOverride.kt");
} }
@TestMetadata("openInInterface.kt")
public void testOpenInInterface() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/openInInterface.kt");
}
@TestMetadata("problems2.kt") @TestMetadata("problems2.kt")
public void testProblems2() throws Exception { public void testProblems2() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/problems2.kt"); runTest("compiler/fir/analysis-tests/testData/resolve/problems2.kt");
@@ -313,6 +313,11 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos
runTest("compiler/fir/analysis-tests/testData/resolve/offOrderMultiBoundGenericOverride.kt"); runTest("compiler/fir/analysis-tests/testData/resolve/offOrderMultiBoundGenericOverride.kt");
} }
@TestMetadata("openInInterface.kt")
public void testOpenInInterface() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/openInInterface.kt");
}
@TestMetadata("problems2.kt") @TestMetadata("problems2.kt")
public void testProblems2() throws Exception { public void testProblems2() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/problems2.kt"); runTest("compiler/fir/analysis-tests/testData/resolve/problems2.kt");
@@ -183,7 +183,7 @@ fun FirDeclaration.resolveStatus(
containingClass: FirClass<*>?, containingClass: FirClass<*>?,
isLocal: Boolean isLocal: Boolean
): FirDeclarationStatus { ): FirDeclarationStatus {
if (status.visibility == Visibilities.UNKNOWN || status.modality == null) { if (status.visibility == Visibilities.UNKNOWN || status.modality == null || status.modality == Modality.OPEN) {
val visibility = when (status.visibility) { val visibility = when (status.visibility) {
Visibilities.UNKNOWN -> when { Visibilities.UNKNOWN -> when {
isLocal -> Visibilities.LOCAL isLocal -> Visibilities.LOCAL
@@ -192,12 +192,26 @@ fun FirDeclaration.resolveStatus(
} }
else -> status.visibility else -> status.visibility
} }
val modality = status.modality ?: resolveModality(containingClass) val modality = status.modality?.let {
if (it == Modality.OPEN && containingClass?.classKind == ClassKind.INTERFACE && !hasOwnBodyOrAccessorBody()) {
Modality.ABSTRACT
} else {
it
}
} ?: resolveModality(containingClass)
return (status as FirDeclarationStatusImpl).resolved(visibility, modality) return (status as FirDeclarationStatusImpl).resolved(visibility, modality)
} }
return status return status
} }
private fun FirDeclaration.hasOwnBodyOrAccessorBody(): Boolean {
return when (this) {
is FirSimpleFunction -> this.body != null
is FirProperty -> this.initializer != null || this.getter?.body != null || this.setter?.body != null
else -> true
}
}
private fun FirDeclaration.resolveVisibility(containingClass: FirClass<*>?): Visibility { private fun FirDeclaration.resolveVisibility(containingClass: FirClass<*>?): Visibility {
// See DescriptorUtils#getDefaultConstructorVisibility in core.descriptors // See DescriptorUtils#getDefaultConstructorVisibility in core.descriptors
if (this is FirConstructor) { if (this is FirConstructor) {
@@ -221,9 +235,7 @@ private fun FirDeclaration.resolveModality(containingClass: FirClass<*>?): Modal
when { when {
visibility == Visibilities.PRIVATE -> visibility == Visibilities.PRIVATE ->
Modality.FINAL Modality.FINAL
this is FirSimpleFunction && body == null -> !this.hasOwnBodyOrAccessorBody() ->
Modality.ABSTRACT
this is FirProperty && initializer == null && getter?.body == null && setter?.body == null ->
Modality.ABSTRACT Modality.ABSTRACT
else -> else ->
Modality.OPEN Modality.OPEN
-1
View File
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
interface One { interface One {
public open fun foo() : Int public open fun foo() : Int
public open fun faz() : Int = 10 public open fun faz() : Int = 10