[Expect/Actual] Add ability to skip matching of constructors of expect enums

In terms of MPP there are no such thing as `expect constructor` for enums,
  but they are physically exist in FIR and IR, so we need a switch which
  skips matching for them

FE 1.0 implementation did not touch to avoid any hidden changes
This commit is contained in:
Dmitriy Novozhilov
2023-06-06 17:26:41 +03:00
committed by Space Team
parent ba41e8ec38
commit 8b9079d026
8 changed files with 22 additions and 59 deletions
@@ -37,6 +37,9 @@ class FirExpectActualMatchingContext(
override val shouldCheckReturnTypesOfCallables: Boolean
get() = false
override val enumConstructorsAreAlwaysCompatible: Boolean
get() = true
private fun CallableSymbolMarker.asSymbol(): FirCallableSymbol<*> = this as FirCallableSymbol<*>
private fun FunctionSymbolMarker.asSymbol(): FirFunctionSymbol<*> = this as FirFunctionSymbol<*>
private fun PropertySymbolMarker.asSymbol(): FirPropertySymbol = this as FirPropertySymbol
@@ -260,14 +263,7 @@ class FirExpectActualMatchingContext(
override fun CallableSymbolMarker.shouldSkipMatching(containingExpectClass: RegularClassSymbolMarker): Boolean {
val symbol = asSymbol()
val classSymbol = containingExpectClass.asSymbol()
val isConstructor = symbol is FirConstructorSymbol
if (isConstructor && classSymbol.classKind.isEnumClass) {
/*
* Expect enums in FIR have (expect) constructors, but actually there is no need to map them
*/
return true
}
if (!isConstructor && symbol.dispatchReceiverType?.classId != classSymbol.classId) {
if (symbol !is FirConstructorSymbol && symbol.dispatchReceiverType?.classId != classSymbol.classId) {
// Skip fake overrides
return true
}
@@ -77,6 +77,9 @@ internal abstract class IrExpectActualMatchingContext(
override val innerClassesCapturesOuterTypeParameters: Boolean
get() = false
override val enumConstructorsAreAlwaysCompatible: Boolean
get() = true
override val RegularClassSymbolMarker.classId: ClassId
get() = asIr().classIdOrFail
@@ -256,6 +256,16 @@ object AbstractExpectActualCompatibilityChecker {
return Incompatible.CallableKind
}
if (
enumConstructorsAreAlwaysCompatible &&
expectContainingClass?.classKind == ClassKind.ENUM_CLASS &&
actualContainingClass?.classKind == ClassKind.ENUM_CLASS &&
expectDeclaration is ConstructorSymbolMarker &&
actualDeclaration is ConstructorSymbolMarker
) {
return ExpectActualCompatibility.Compatible
}
val expectedReceiverType = expectDeclaration.extensionReceiverType
val actualReceiverType = actualDeclaration.extensionReceiverType
if ((expectedReceiverType != null) != (actualReceiverType != null)) {
@@ -36,6 +36,9 @@ interface ExpectActualMatchingContext<T : DeclarationSymbolMarker> : TypeSystemC
val innerClassesCapturesOuterTypeParameters: Boolean
get() = true
val enumConstructorsAreAlwaysCompatible: Boolean
get() = false
val RegularClassSymbolMarker.classId: ClassId
val TypeAliasSymbolMarker.classId: ClassId
val CallableSymbolMarker.callableId: CallableId
@@ -1,34 +0,0 @@
// MODULE: m1-common
// FILE: common.kt
<!INCOMPATIBLE_MATCHING{JVM}, INCOMPATIBLE_MATCHING{JVM}!>expect enum class Foo {
ENTRY
}<!>
expect enum class _TimeUnit
// MODULE: m2-jvm()()(m1-common)
// FILE: jvm.kt
actual typealias Foo = FooImpl
actual typealias _TimeUnit = java.util.concurrent.TimeUnit
// FILE: FooImpl.java
public enum FooImpl {
ENTRY("OK") {
@Override
public String getResult() {
return value;
}
};
protected final String value;
public FooImpl(String value) {
this.value = value;
}
public abstract String getResult();
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// MODULE: m1-common
// FILE: common.kt
@@ -1,17 +0,0 @@
// MODULE: m1-common
// FILE: common.kt
<!INCOMPATIBLE_MATCHING{JVM}, INCOMPATIBLE_MATCHING{JVM}!>expect enum class Foo {
ENTRY1,
ENTRY2,
ENTRY3;
}<!>
// MODULE: m2-jvm()()(m1-common)
// FILE: jvm.kt
actual enum class Foo(val x: String) {
ENTRY1("1"),
ENTRY2("2"),
ENTRY3("3");
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// MODULE: m1-common
// FILE: common.kt