[FIR] Allow actualization of expect classes by classes with wider visibility

^KT-59355 Fixed
This commit is contained in:
Dmitriy Novozhilov
2023-06-16 16:22:20 +03:00
committed by Space Team
parent 583aad2350
commit d972b78627
25 changed files with 257 additions and 4 deletions
@@ -106,7 +106,7 @@ object AbstractExpectActualCompatibilityChecker {
return Incompatible.Modality
}
if (expectClassSymbol.visibility != actualClass.visibility) {
if (!areCompatibleClassVisibilities(expectClassSymbol, actualClass)) {
return Incompatible.Visibility
}
@@ -330,7 +330,7 @@ object AbstractExpectActualCompatibilityChecker {
return Incompatible.Modality
}
if (!areDeclarationsWithCompatibleVisibilities(expectDeclaration.visibility, expectModality, actualDeclaration.visibility)) {
if (!areCompatibleCallableVisibilities(expectDeclaration.visibility, expectModality, actualDeclaration.visibility)) {
return Incompatible.Visibility
}
@@ -436,7 +436,7 @@ object AbstractExpectActualCompatibilityChecker {
Modality.SEALED to enumSetOf(Modality.SEALED),
)
private fun areDeclarationsWithCompatibleVisibilities(
private fun areCompatibleCallableVisibilities(
expectVisibility: Visibility,
expectModality: Modality?,
actualVisibility: Visibility,
@@ -451,6 +451,19 @@ object AbstractExpectActualCompatibilityChecker {
}
}
context(ExpectActualMatchingContext<*>)
private fun areCompatibleClassVisibilities(
expectClassSymbol: RegularClassSymbolMarker,
actualClassSymbol: RegularClassSymbolMarker,
): Boolean {
val expectVisibility = expectClassSymbol.visibility
val actualVisibility = actualClassSymbol.visibility
if (expectVisibility == actualVisibility) return true
if (!allowClassActualizationWithWiderVisibility) return false
val result = Visibilities.compare(actualVisibility, expectVisibility)
return result != null && result > 0
}
context(ExpectActualMatchingContext<*>)
private fun areCompatibleTypeParameters(
expectTypeParameterSymbols: List<TypeParameterSymbolMarker>,
@@ -525,7 +538,7 @@ object AbstractExpectActualCompatibilityChecker {
): Boolean {
val expectedSetter = expected.setter ?: return true
val actualSetter = actual.setter ?: return true
return areDeclarationsWithCompatibleVisibilities(expectedSetter.visibility, expectedSetter.modality, actualSetter.visibility)
return areCompatibleCallableVisibilities(expectedSetter.visibility, expectedSetter.modality, actualSetter.visibility)
}
// ---------------------------------------- Utils ----------------------------------------
@@ -39,6 +39,17 @@ interface ExpectActualMatchingContext<T : DeclarationSymbolMarker> : TypeSystemC
val enumConstructorsAreAlwaysCompatible: Boolean
get() = false
/**
* This flag determines, how visibilities for classes/typealiases will be matched
* - `false` means that visibilities should be identical
* - `true` means that visibility of actual class should be the same or wider comparing to expect visibility
* this means that following actualizations will be additionally allowed:
* - protected -> public
* - internal -> public
*/
val allowClassActualizationWithWiderVisibility: Boolean
get() = false
val RegularClassSymbolMarker.classId: ClassId
val TypeAliasSymbolMarker.classId: ClassId
val CallableSymbolMarker.callableId: CallableId