diff --git a/compiler/cli/cli-js/src/org/jetbrains/kotlin/cli/js/klib/compilerPipeline.kt b/compiler/cli/cli-js/src/org/jetbrains/kotlin/cli/js/klib/compilerPipeline.kt
index c933a933c2b..55a6f9f7105 100644
--- a/compiler/cli/cli-js/src/org/jetbrains/kotlin/cli/js/klib/compilerPipeline.kt
+++ b/compiler/cli/cli-js/src/org/jetbrains/kotlin/cli/js/klib/compilerPipeline.kt
@@ -14,7 +14,6 @@ import org.jetbrains.kotlin.cli.common.fir.FirDiagnosticsCompilerResultsReporter
import org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
import org.jetbrains.kotlin.config.CommonConfigurationKeys
-import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.config.languageVersionSettings
import org.jetbrains.kotlin.constant.EvaluatedConstTracker
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
@@ -36,6 +35,7 @@ import org.jetbrains.kotlin.incremental.js.IncrementalDataProvider
import org.jetbrains.kotlin.ir.backend.js.*
import org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir.JsManglerDesc
import org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir.JsManglerIr
+import org.jetbrains.kotlin.ir.types.IrTypeSystemContextImpl
import org.jetbrains.kotlin.ir.util.IrMessageLogger
import org.jetbrains.kotlin.js.config.JSConfigurationKeys
import org.jetbrains.kotlin.js.resolve.JsPlatformAnalyzerServices
@@ -217,6 +217,7 @@ fun transformFirToIr(
visibilityConverter = Fir2IrVisibilityConverter.Default,
kotlinBuiltIns = builtInsModule ?: DefaultBuiltIns.Instance,
diagnosticReporter = diagnosticsReporter,
+ actualizerTypeContextProvider = ::IrTypeSystemContextImpl,
fir2IrResultPostCompute = {
(this.irModuleFragment.descriptor as? FirModuleDescriptor)?.let { it.allDependencyModules = librariesDescriptors }
}
diff --git a/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/pipeline/convertToIr.kt b/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/pipeline/convertToIr.kt
index 4aa33416a09..32b3711673a 100644
--- a/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/pipeline/convertToIr.kt
+++ b/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/pipeline/convertToIr.kt
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.fir.pipeline
import org.jetbrains.kotlin.backend.common.actualizer.IrActualizedResult
import org.jetbrains.kotlin.backend.common.actualizer.IrActualizer
import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension
+import org.jetbrains.kotlin.backend.jvm.JvmIrTypeSystemContext
import org.jetbrains.kotlin.backend.jvm.serialization.JvmIdSignatureDescriptor
import org.jetbrains.kotlin.builtins.DefaultBuiltIns
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
@@ -20,10 +21,12 @@ import org.jetbrains.kotlin.fir.backend.jvm.FirJvmVisibilityConverter
import org.jetbrains.kotlin.fir.declarations.FirFile
import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.signaturer.FirMangler
+import org.jetbrains.kotlin.ir.IrBuiltIns
import org.jetbrains.kotlin.ir.backend.jvm.serialization.JvmDescriptorMangler
import org.jetbrains.kotlin.ir.backend.jvm.serialization.JvmIrMangler
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
import org.jetbrains.kotlin.ir.declarations.impl.IrFactoryImpl
+import org.jetbrains.kotlin.ir.types.IrTypeSystemContext
import org.jetbrains.kotlin.ir.util.IdSignatureComposer
import org.jetbrains.kotlin.ir.util.KotlinMangler
@@ -57,6 +60,7 @@ fun FirResult.convertToIrAndActualizeForJvm(
visibilityConverter = FirJvmVisibilityConverter,
diagnosticReporter = diagnosticReporter,
kotlinBuiltIns = DefaultBuiltIns.Instance,
+ actualizerTypeContextProvider = ::JvmIrTypeSystemContext,
)
fun signatureComposerForJvmFir2Ir(generateSignatures: Boolean): IdSignatureComposer {
@@ -78,6 +82,7 @@ fun FirResult.convertToIrAndActualize(
visibilityConverter: Fir2IrVisibilityConverter,
kotlinBuiltIns: KotlinBuiltIns,
diagnosticReporter: DiagnosticReporter,
+ actualizerTypeContextProvider: (IrBuiltIns) -> IrTypeSystemContext,
fir2IrResultPostCompute: Fir2IrResult.() -> Unit = {},
): Fir2IrActualizedResult {
val fir2IrResult: Fir2IrResult
@@ -140,6 +145,7 @@ fun FirResult.convertToIrAndActualize(
fir2IrResult.irModuleFragment,
commonIrOutputs.map { it.irModuleFragment },
diagnosticReporter,
+ actualizerTypeContextProvider(fir2IrResult.irModuleFragment.irBuiltins),
fir2IrConfiguration.languageVersionSettings
)
}
diff --git a/compiler/frontend.common/src/org/jetbrains/kotlin/diagnostics/DiagnosticReporter.kt b/compiler/frontend.common/src/org/jetbrains/kotlin/diagnostics/DiagnosticReporter.kt
index 55ac3626eb0..901866cbff2 100644
--- a/compiler/frontend.common/src/org/jetbrains/kotlin/diagnostics/DiagnosticReporter.kt
+++ b/compiler/frontend.common/src/org/jetbrains/kotlin/diagnostics/DiagnosticReporter.kt
@@ -70,6 +70,13 @@ open class KtDiagnosticReporterWithContext(
}
}
+ fun report(factory: KtDiagnosticFactory3, a: A, b: B, c: C) {
+ sourceElement?.let {
+ reportOn(it, factory, a, b, c, this)
+ checkAndCommitReportsOn(it, this)
+ }
+ }
+
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other !is DiagnosticContextImpl) return false
diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/CommonBackendErrors.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/CommonBackendErrors.kt
index 44c4e70eee5..7ad75ad7339 100644
--- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/CommonBackendErrors.kt
+++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/CommonBackendErrors.kt
@@ -6,18 +6,24 @@
package org.jetbrains.kotlin.backend.common
import com.intellij.psi.PsiElement
+import org.jetbrains.kotlin.backend.common.BackendDiagnosticRenderers.INCOMPATIBILITY
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.diagnostics.KtDiagnosticFactoryToRendererMap
+import org.jetbrains.kotlin.diagnostics.error0
import org.jetbrains.kotlin.diagnostics.error2
+import org.jetbrains.kotlin.diagnostics.error3
import org.jetbrains.kotlin.diagnostics.rendering.BaseDiagnosticRendererFactory
import org.jetbrains.kotlin.diagnostics.rendering.CommonRenderers.STRING
+import org.jetbrains.kotlin.diagnostics.rendering.Renderer
import org.jetbrains.kotlin.diagnostics.rendering.Renderers.MODULE_WITH_PLATFORM
import org.jetbrains.kotlin.diagnostics.rendering.RootDiagnosticRendererFactory
+import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualCompatibility
object CommonBackendErrors {
val NO_ACTUAL_FOR_EXPECT by error2()
val MANY_INTERFACES_MEMBER_NOT_IMPLEMENTED by error2()
val MANY_IMPL_MEMBER_NOT_IMPLEMENTED by error2()
+ val INCOMPATIBLE_MATCHING by error3>()
init {
RootDiagnosticRendererFactory.registerFactory(KtDefaultCommonBackendErrorMessages)
@@ -44,5 +50,18 @@ object KtDefaultCommonBackendErrorMessages : BaseDiagnosticRendererFactory() {
STRING,
STRING,
)
+ map.put(
+ CommonBackendErrors.INCOMPATIBLE_MATCHING,
+ "Expect declaration `{0}` doesn''t match actual `{1}` because {2}",
+ STRING,
+ STRING,
+ INCOMPATIBILITY
+ )
+ }
+}
+
+object BackendDiagnosticRenderers {
+ val INCOMPATIBILITY = Renderer> {
+ it.reason ?: ""
}
}
diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/actualizer/ActualFakeOverridesAdder.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/actualizer/ActualFakeOverridesAdder.kt
index 96d2b0b5f08..e48f15cd2fe 100644
--- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/actualizer/ActualFakeOverridesAdder.kt
+++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/actualizer/ActualFakeOverridesAdder.kt
@@ -8,13 +8,18 @@ package org.jetbrains.kotlin.backend.common.actualizer
import org.jetbrains.kotlin.KtDiagnosticReporterWithImplicitIrBasedContext
import org.jetbrains.kotlin.backend.common.CommonBackendErrors
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
+import org.jetbrains.kotlin.ir.IrBuiltIns
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.declarations.*
+import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.ir.symbols.IrSymbol
+import org.jetbrains.kotlin.ir.types.IrTypeSystemContext
import org.jetbrains.kotlin.ir.types.classifierOrFail
import org.jetbrains.kotlin.ir.util.isInterface
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
+import org.jetbrains.kotlin.name.ClassId
+import org.jetbrains.kotlin.name.Name
/**
* It adds fake overrides to non-expect classes inside common or multi-platform module,
@@ -27,9 +32,11 @@ import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
*/
internal class ActualFakeOverridesAdder(
private val expectActualMap: Map,
- private val diagnosticsReporter: KtDiagnosticReporterWithImplicitIrBasedContext
+ private val expectToActualClassMap: Map,
+ private val diagnosticsReporter: KtDiagnosticReporterWithImplicitIrBasedContext,
+ private val typeSystemContext: IrTypeSystemContext
) : IrElementVisitorVoid {
- private val missingActualMembersMap = mutableMapOf>>()
+ private val missingActualMembersMap = mutableMapOf()
override fun visitClass(declaration: IrClass) {
extractMissingActualMembersFromSupertypes(declaration)
@@ -40,20 +47,20 @@ internal class ActualFakeOverridesAdder(
element.acceptChildrenVoid(this)
}
- private fun extractMissingActualMembersFromSupertypes(klass: IrClass): Map> {
+ private fun extractMissingActualMembersFromSupertypes(klass: IrClass): FakeOverrideInfo {
missingActualMembersMap[klass]?.let { return it }
- val missingActualMembers = mutableMapOf>()
+ val missingActualMembers = FakeOverrideInfo()
missingActualMembersMap[klass] = missingActualMembers
// New members from supertypes are only relevant for not expect (ordinary) classes
// New members from the current class are only relevant for actualized expect classes
- val processedMembers = mutableMapOf>()
+ val processedMembers = FakeOverrideInfo()
for (superType in klass.superTypes) {
val membersFromSupertype = extractMissingActualMembersFromSupertypes(superType.classifierOrFail.owner as IrClass)
if (!klass.isExpect) {
- missingActualMembers.appendMissingMembersToNotExpectClass(klass, membersFromSupertype, processedMembers)
+ appendMissingMembersToNotExpectClass(missingActualMembers, klass, membersFromSupertype.allSymbols(), processedMembers)
}
}
@@ -64,22 +71,35 @@ internal class ActualFakeOverridesAdder(
return missingActualMembers
}
- private fun MutableMap>.appendMissingMembersToNotExpectClass(
+ private fun appendMissingMembersToNotExpectClass(
+ fakeOverrideInfo: FakeOverrideInfo,
klass: IrClass,
- membersFromSupertype: Map>,
- processedMembers: MutableMap>
+ membersFromSupertype: List,
+ processedMembers: FakeOverrideInfo
) {
- for (memberFromSupertype in membersFromSupertype.flatMap { it.value }) {
+ for (symbolFromSupertype in membersFromSupertype) {
+ val memberFromSupertype = symbolFromSupertype.owner as IrDeclaration
val newMember = createFakeOverrideMember(listOf(memberFromSupertype), klass)
- val name = newMember.getFunctionOrPropertyName()
- if (getMatches(name, newMember, expectActualMap).isEmpty()) {
+ val matchingFakeOverrides = collectActualCallablesMatchingToSpecificExpect(
+ newMember.symbol,
+ fakeOverrideInfo.getMembersForActual(newMember),
+ expectToActualClassMap,
+ typeSystemContext
+ )
+ if (matchingFakeOverrides.isEmpty()) {
processedMembers.addMember(memberFromSupertype as IrOverridableDeclaration<*>)
- addMember(newMember)
+ fakeOverrideInfo.addMember(newMember)
klass.addMember(newMember)
} else {
- val baseMember = processedMembers.getMatches(name, newMember, expectActualMap).single()
+ val baseMembers = collectActualCallablesMatchingToSpecificExpect(
+ newMember.symbol,
+ processedMembers.getMembersForActual(newMember),
+ expectToActualClassMap,
+ typeSystemContext
+ )
+
val errorFactory =
- if ((baseMember.parent as IrClass).isInterface && (memberFromSupertype.parent as IrClass).isInterface)
+ if (baseMembers.all { ((it.owner as IrDeclaration).parent as IrClass).isInterface } && (memberFromSupertype.parent as IrClass).isInterface)
CommonBackendErrors.MANY_INTERFACES_MEMBER_NOT_IMPLEMENTED
else
CommonBackendErrors.MANY_IMPL_MEMBER_NOT_IMPLEMENTED
@@ -92,7 +112,7 @@ internal class ActualFakeOverridesAdder(
}
}
- private fun MutableMap>.appendMissingMembersFromActualizedExpectClass(
+ private fun FakeOverrideInfo.appendMissingMembersFromActualizedExpectClass(
expectClass: IrClass,
actualClass: IrClass,
) {
@@ -110,11 +130,31 @@ internal class ActualFakeOverridesAdder(
}
}
- private fun MutableMap>.addMember(member: IrOverridableDeclaration<*>) {
- getOrPut(member.getFunctionOrPropertyName()) { mutableListOf() }.add(member)
- }
+ private class FakeOverrideInfo {
+ val functionsByName: MutableMap> = mutableMapOf()
+ val propertiesByName: MutableMap> = mutableMapOf()
- private fun IrOverridableDeclaration<*>.getFunctionOrPropertyName(): String {
- return (this as IrDeclarationWithName).name.asString() + (if (this is IrSimpleFunction) "()" else "")
+ fun allSymbols(): List {
+ return buildList {
+ functionsByName.values.flatMapTo(this) { it }
+ propertiesByName.values.flatMapTo(this) { it }
+ }
+ }
+
+ private fun getCorrespondingMap(member: IrOverridableDeclaration<*>): MutableMap> {
+ return when (member) {
+ is IrFunction -> functionsByName
+ is IrProperty -> propertiesByName
+ else -> error("Unsupported declaration type: $member")
+ }
+ }
+
+ fun addMember(member: IrOverridableDeclaration<*>) {
+ getCorrespondingMap(member).getOrPut(member.name) { mutableListOf() } += member.symbol
+ }
+
+ fun getMembersForActual(actualMember: IrOverridableDeclaration<*>): List {
+ return getCorrespondingMap(actualMember)[actualMember.name].orEmpty()
+ }
}
-}
\ No newline at end of file
+}
diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/actualizer/ExpectActualCollector.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/actualizer/ExpectActualCollector.kt
index d0696009c13..3f4e380daab 100644
--- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/actualizer/ExpectActualCollector.kt
+++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/actualizer/ExpectActualCollector.kt
@@ -8,66 +8,97 @@ package org.jetbrains.kotlin.backend.common.actualizer
import org.jetbrains.kotlin.KtDiagnosticReporterWithImplicitIrBasedContext
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.declarations.*
-import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
-import org.jetbrains.kotlin.ir.symbols.IrSymbol
+import org.jetbrains.kotlin.ir.symbols.*
+import org.jetbrains.kotlin.ir.types.IrTypeSystemContext
import org.jetbrains.kotlin.ir.types.classifierOrFail
-import org.jetbrains.kotlin.ir.util.isFakeOverride
-import org.jetbrains.kotlin.ir.util.kotlinFqName
+import org.jetbrains.kotlin.ir.util.callableId
+import org.jetbrains.kotlin.ir.util.classIdOrFail
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
-import org.jetbrains.kotlin.name.FqName
+import org.jetbrains.kotlin.mpp.DeclarationSymbolMarker
+import org.jetbrains.kotlin.name.CallableId
+import org.jetbrains.kotlin.name.ClassId
+import org.jetbrains.kotlin.resolve.calls.mpp.AbstractExpectActualCompatibilityChecker
+import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualCompatibility
+/**
+ * This class is used to collect mapping between all expect and actuals declarations, which are declared in passed module fragments
+ * It does not process any declarations which may appear after actualization of supertypes (like fake-overrides in classes with
+ * expect supertypes)
+ *
+ * The main method of this class, `collect` returns a pair of two values:
+ * - `expectToActualMap` is the main storage of all mapped declarations. Key is symbol of expect declaration and the value is symbol of
+ * corresponding actual declaration
+ * - `classActualizationInfo` is a storage which keeps information about types (class) actualization, which can be used later for type
+ * refinement if needed
+ *
+ * If some declarations didn't match (or there was missing/actual) then corresponding declarations won't be stored in `expectToActualMap`.
+ * Instead of that an error will be reported to `diagnosticReporter`
+ */
internal class ExpectActualCollector(
private val mainFragment: IrModuleFragment,
private val dependentFragments: List,
- private val diagnosticsReporter: KtDiagnosticReporterWithImplicitIrBasedContext
+ private val typeSystemContext: IrTypeSystemContext,
+ private val diagnosticsReporter: KtDiagnosticReporterWithImplicitIrBasedContext,
) {
- fun collect(): MutableMap {
+ data class Result(val expectToActualMap: MutableMap, val classActualizationInfo: ClassActualizationInfo)
+
+ fun collect(): Result {
val result = mutableMapOf()
// Collect and link classes at first to make it possible to expand type aliases on the members linking
- val (actualMembers, expectActualTypeAliasMap) = result.appendExpectActualClassMap()
- result.appendExpectActualMemberMap(actualMembers, expectActualTypeAliasMap)
- return result
+ val actualDeclarations = collectActualDeclarations()
+ matchAllExpectDeclarations(result, actualDeclarations)
+ return Result(result, actualDeclarations)
}
- private fun MutableMap.appendExpectActualClassMap(): Pair, Map> {
- val actualClasses = mutableMapOf()
- // There is no list for builtins declarations; that's why they are being collected from typealiases
- val actualMembers = mutableListOf()
- val expectActualTypeAliasMap = mutableMapOf() // It's used to link members from expect class that have typealias actual
-
+ private fun collectActualDeclarations(): ClassActualizationInfo {
val fragmentsWithActuals = dependentFragments.drop(1) + mainFragment
- val actualClassesAndMembersCollector = ActualClassesAndMembersCollector(actualClasses, actualMembers, expectActualTypeAliasMap)
- fragmentsWithActuals.forEach { actualClassesAndMembersCollector.collect(it) }
-
- val linkCollector = ClassLinksCollector(this, actualClasses, expectActualTypeAliasMap, diagnosticsReporter)
- dependentFragments.forEach { linkCollector.visitModuleFragment(it) }
-
- return actualMembers to expectActualTypeAliasMap
+ return ActualDeclarationsCollector.collectActualsFromFragments(fragmentsWithActuals)
}
- private fun MutableMap.appendExpectActualMemberMap(
- actualMembers: List,
- expectActualTypeAliasMap: Map
+ private fun matchAllExpectDeclarations(
+ destination: MutableMap,
+ classActualizationInfo: ClassActualizationInfo,
) {
- val actualMembersMap = mutableMapOf>()
- for (actualMember in actualMembers) {
- actualMembersMap.getOrPut(generateIrElementFullNameFromExpect(actualMember, expectActualTypeAliasMap)) { mutableListOf() }
- .add(actualMember)
- }
- val collector = MemberLinksCollector(this, actualMembersMap, expectActualTypeAliasMap, diagnosticsReporter)
- dependentFragments.forEach { collector.visitModuleFragment(it) }
+ val linkCollector = ExpectActualLinkCollector(destination, classActualizationInfo, typeSystemContext, diagnosticsReporter)
+ dependentFragments.forEach { linkCollector.visitModuleFragment(it) }
}
}
-private class ActualClassesAndMembersCollector(
- private val actualClasses: MutableMap,
- private val actualMembers: MutableList,
- private val expectActualTypeAliasMap: MutableMap
+internal data class ClassActualizationInfo(
+ // mapping from classId of actual class/typealias to itself/typealias expansion
+ val actualClasses: Map,
+ // mapping from classId to actual typealias
+ val actualTypeAliases: Map,
+ val actualTopLevels: Map>,
) {
+ fun getActualWithoutExpansion(classId: ClassId): IrSymbol? {
+ return actualTypeAliases[classId] ?: actualClasses[classId]
+ }
+}
+
+private class ActualDeclarationsCollector {
+ companion object {
+ fun collectActualsFromFragments(fragments: List): ClassActualizationInfo {
+ val collector = ActualDeclarationsCollector()
+ for (fragment in fragments) {
+ collector.collect(fragment)
+ }
+ return ClassActualizationInfo(
+ collector.actualClasses,
+ collector.actualTypeAliasesWithoutExpansion,
+ collector.actualTopLevels
+ )
+ }
+ }
+
+ private val actualClasses: MutableMap = mutableMapOf()
+ private val actualTypeAliasesWithoutExpansion: MutableMap = mutableMapOf()
+ private val actualTopLevels: MutableMap> = mutableMapOf()
+
private val visitedActualClasses = mutableSetOf()
- fun collect(element: IrElement) {
+ private fun collect(element: IrElement) {
when (element) {
is IrModuleFragment -> {
for (file in element.files) {
@@ -77,16 +108,18 @@ private class ActualClassesAndMembersCollector(
is IrTypeAlias -> {
if (!element.isActual) return
+ val classId = element.classIdOrFail
val expandedTypeSymbol = element.expandedType.classifierOrFail as IrClassSymbol
- addActualClass(element, expandedTypeSymbol)
- collect(expandedTypeSymbol.owner)
- expectActualTypeAliasMap[element.kotlinFqName] = expandedTypeSymbol.owner.kotlinFqName
+ actualClasses[classId] = expandedTypeSymbol
+ actualTypeAliasesWithoutExpansion[classId] = element.symbol
+
+ collect(expandedTypeSymbol.owner)
}
is IrClass -> {
if (element.isExpect || !visitedActualClasses.add(element)) return
- addActualClass(element, element.symbol)
+ actualClasses[element.classIdOrFail] = element.symbol
for (declaration in element.declarations) {
collect(declaration)
}
@@ -97,101 +130,99 @@ private class ActualClassesAndMembersCollector(
}
}
is IrEnumEntry -> {
- actualMembers.add(element) // If enum entry is located inside expect enum, then this code is not executed
+ recordActualCallable(element, element.callableId) // If enum entry is located inside expect enum, then this code is not executed
}
is IrProperty -> {
if (element.isExpect) return
- actualMembers.add(element)
+ recordActualCallable(element, element.callableId)
}
is IrFunction -> {
if (element.isExpect) return
- actualMembers.add(element)
+ recordActualCallable(element, element.callableId)
}
}
}
- private fun addActualClass(classOrTypeAlias: IrElement, classSymbol: IrClassSymbol) {
- actualClasses[generateActualIrClassOrTypeAliasFullName(classOrTypeAlias)] = classSymbol
+ private fun recordActualCallable(callableDeclaration: IrDeclarationWithName, callableId: CallableId) {
+ if (callableId.classId == null) {
+ actualTopLevels
+ .getOrPut(callableId) { mutableListOf() }
+ .add(callableDeclaration)
+ }
}
}
-private class ClassLinksCollector(
- private val expectActualMap: MutableMap,
- private val actualClasses: Map,
- private val expectActualTypeAliasMap: Map,
- private val diagnosticsReporter: KtDiagnosticReporterWithImplicitIrBasedContext
+private class ExpectActualLinkCollector(
+ private val destination: MutableMap,
+ private val classActualizationInfo: ClassActualizationInfo,
+ typeSystemContext: IrTypeSystemContext,
+ private val diagnosticsReporter: KtDiagnosticReporterWithImplicitIrBasedContext,
) : IrElementVisitorVoid {
+ private val context = MatchingContext(typeSystemContext)
+
+ override fun visitFunction(declaration: IrFunction) {
+ if (declaration.isExpect) {
+ matchExpectCallable(declaration, declaration.callableId)
+ }
+ }
+
+ override fun visitProperty(declaration: IrProperty) {
+ if (declaration.isExpect) {
+ matchExpectCallable(declaration, declaration.callableId)
+ }
+ }
+
+ private fun matchExpectCallable(declaration: IrDeclarationWithName, callableId: CallableId) {
+ val actualSymbols = classActualizationInfo.actualTopLevels[callableId]?.map { it.symbol }.orEmpty()
+ matchExpectDeclaration(declaration.symbol, actualSymbols)
+ }
+
override fun visitClass(declaration: IrClass) {
if (!declaration.isExpect) return
+ val classId = declaration.classIdOrFail
+ val expectClassSymbol = declaration.symbol
+ val actualClassLikeSymbol = classActualizationInfo.getActualWithoutExpansion(classId)
+ matchExpectDeclaration(expectClassSymbol, listOfNotNull(actualClassLikeSymbol))
+ }
- val actualClassSymbol = actualClasses[generateIrElementFullNameFromExpect(declaration, expectActualTypeAliasMap)]
- if (actualClassSymbol != null) {
- expectActualMap[declaration.symbol] = actualClassSymbol
- expectActualMap.appendTypeParametersMap(declaration, actualClassSymbol.owner)
- } else if (!declaration.containsOptionalExpectation()) {
- diagnosticsReporter.reportMissingActual(declaration)
- }
-
- visitElement(declaration)
+ private fun matchExpectDeclaration(expectSymbol: IrSymbol, actualSymbols: List) {
+ AbstractExpectActualCompatibilityChecker.matchSingleExpectTopLevelDeclarationAgainstPotentialActuals(
+ expectSymbol,
+ actualSymbols,
+ context
+ )
}
override fun visitElement(element: IrElement) {
element.acceptChildrenVoid(this)
}
-}
-private class MemberLinksCollector(
- private val expectActualMap: MutableMap,
- private val actualMembers: Map>,
- private val typeAliasMap: Map,
- private val diagnosticsReporter: KtDiagnosticReporterWithImplicitIrBasedContext
-) : IrElementVisitorVoid {
- override fun visitFunction(declaration: IrFunction) {
- if (declaration.isExpect) addLink(declaration)
- }
+ private inner class MatchingContext(
+ typeSystemContext: IrTypeSystemContext,
+ ) : IrExpectActualMatchingContext(typeSystemContext, classActualizationInfo.actualClasses) {
+ override fun onMatchedClasses(expectClassSymbol: IrClassSymbol, actualClassSymbol: IrClassSymbol) {
+ destination[expectClassSymbol] = actualClassSymbol
+ recordActualForExpectDeclaration(expectClassSymbol, actualClassSymbol, destination)
+ }
- override fun visitProperty(declaration: IrProperty) {
- if (declaration.isExpect) addLink(declaration)
- }
+ override fun onMatchedCallables(expectSymbol: IrSymbol, actualSymbol: IrSymbol) {
+ recordActualForExpectDeclaration(expectSymbol, actualSymbol, destination)
+ }
- override fun visitEnumEntry(declaration: IrEnumEntry) {
- if ((declaration.parent as IrClass).isExpect) addLink(declaration)
- }
-
- private fun addLink(expectDeclaration: IrDeclarationBase) {
- val actualMemberMatches = actualMembers.getMatches(expectDeclaration, expectActualMap, typeAliasMap)
- when {
- actualMemberMatches.size == 1 -> {
- expectActualMap.addLink(expectDeclaration, actualMemberMatches.single())
+ override fun onMismatchedMembersFromClassScope(
+ expectSymbol: DeclarationSymbolMarker,
+ actualSymbolsByIncompatibility: Map, List>,
+ ) {
+ require(expectSymbol is IrSymbol)
+ if (actualSymbolsByIncompatibility.isEmpty() && !expectSymbol.owner.containsOptionalExpectation()) {
+ diagnosticsReporter.reportMissingActual(expectSymbol)
}
- actualMemberMatches.size > 1 -> {
- // TODO: report AMBIGUOUS_ACTUALS here, see KT-57932
- }
- (expectDeclaration.parent as? IrClass)?.isExpect == false && expectDeclaration.isFakeOverride -> {
- // Remaining expect fake override members from not expect classes will be actualized in FakeOverridesTransformer
- // It occurs in a separated step because they require filled expectActualMap for members from expect classes
- }
- else -> {
- if (shouldReportMissingActual(expectDeclaration)) {
- diagnosticsReporter.reportMissingActual(expectDeclaration)
+ for ((incompatibility, actualMemberSymbols) in actualSymbolsByIncompatibility) {
+ for (actualSymbol in actualMemberSymbols) {
+ require(actualSymbol is IrSymbol)
+ diagnosticsReporter.reportIncompatibleExpectActual(expectSymbol, actualSymbol, incompatibility)
}
}
}
}
-
- private fun shouldReportMissingActual(declaration: IrDeclarationBase): Boolean {
- return !declaration.parent.containsOptionalExpectation() && !(declaration is IrConstructor && declaration.isPrimary)
- }
-
- override fun visitElement(element: IrElement) {
- element.acceptChildrenVoid(this)
- }
}
-
-fun MutableMap.appendTypeParametersMap(
- expectTypeParametersContainer: IrTypeParametersContainer,
- actualTypeParametersContainer: IrTypeParametersContainer
-) {
- expectTypeParametersContainer.typeParameters.zip(actualTypeParametersContainer.typeParameters)
- .forEach { (expectTypeParameter, actualTypeParameter) -> this[expectTypeParameter.symbol] = actualTypeParameter.symbol }
-}
\ No newline at end of file
diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/actualizer/FakeOverridesActualizer.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/actualizer/FakeOverridesActualizer.kt
index f1b4887b39b..e96aa67cc92 100644
--- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/actualizer/FakeOverridesActualizer.kt
+++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/actualizer/FakeOverridesActualizer.kt
@@ -47,11 +47,11 @@ internal class FakeOverridesActualizer(private val expectActualMap: MutableMap)
@@ -19,15 +20,17 @@ object IrActualizer {
mainFragment: IrModuleFragment,
dependentFragments: List,
diagnosticReporter: DiagnosticReporter,
+ typeSystemContext: IrTypeSystemContext,
languageVersionSettings: LanguageVersionSettings
): IrActualizedResult {
val ktDiagnosticReporter = KtDiagnosticReporterWithImplicitIrBasedContext(diagnosticReporter, languageVersionSettings)
// The ir modules processing is performed phase-to-phase:
// 1. Collect expect-actual links for classes and their members from dependent fragments
- val expectActualMap = ExpectActualCollector(
+ val (expectActualMap, actualDeclarations) = ExpectActualCollector(
mainFragment,
dependentFragments,
+ typeSystemContext,
ktDiagnosticReporter
).collect()
@@ -44,7 +47,9 @@ object IrActualizer {
// taken from these non-expect classes actualized super classes.
ActualFakeOverridesAdder(
expectActualMap,
- ktDiagnosticReporter
+ actualDeclarations.actualClasses,
+ ktDiagnosticReporter,
+ typeSystemContext
).apply { dependentFragments.forEach { visitModuleFragment(it) } }
// 5. Copy and actualize function parameter default values from expect functions
@@ -91,4 +96,4 @@ object IrActualizer {
private fun mergeIrFragments(mainFragment: IrModuleFragment, dependentFragments: List) {
mainFragment.files.addAll(0, dependentFragments.flatMap { it.files })
}
-}
\ No newline at end of file
+}
diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/actualizer/IrActualizerUtils.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/actualizer/IrActualizerUtils.kt
index 433643fd18a..44d1459d4c4 100644
--- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/actualizer/IrActualizerUtils.kt
+++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/actualizer/IrActualizerUtils.kt
@@ -13,182 +13,89 @@ import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
import org.jetbrains.kotlin.ir.builders.declarations.buildFun
import org.jetbrains.kotlin.ir.builders.declarations.buildProperty
import org.jetbrains.kotlin.ir.declarations.*
+import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.ir.symbols.IrPropertySymbol
import org.jetbrains.kotlin.ir.symbols.IrSymbol
-import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
-import org.jetbrains.kotlin.ir.types.IrDynamicType
-import org.jetbrains.kotlin.ir.types.classifierOrFail
-import org.jetbrains.kotlin.ir.types.isNullable
+import org.jetbrains.kotlin.ir.types.IrTypeSystemContext
import org.jetbrains.kotlin.ir.util.*
-import org.jetbrains.kotlin.name.FqName
-import org.jetbrains.kotlin.name.StandardClassIds
+import org.jetbrains.kotlin.name.ClassId
+import org.jetbrains.kotlin.resolve.calls.mpp.AbstractExpectActualCompatibilityChecker
+import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualCompatibility
import org.jetbrains.kotlin.resolve.multiplatform.OptionalAnnotationUtil
import org.jetbrains.kotlin.utils.addToStdlib.runIf
+import org.jetbrains.kotlin.utils.addToStdlib.shouldNotBeCalled
-private val FLEXIBLE_NULLABILITY_ANNOTATION_FQ_NAME = StandardClassIds.Annotations.FlexibleNullability.asSingleFqName()
+internal fun collectActualCallablesMatchingToSpecificExpect(
+ expectSymbol: IrSymbol,
+ actualSymbols: List,
+ expectToActualClassMap: Map,
+ typeSystemContext: IrTypeSystemContext,
+): List {
+ val baseExpectSymbol = expectSymbol
+ val matchingActuals = mutableListOf()
+ val context = object : IrExpectActualMatchingContext(typeSystemContext, expectToActualClassMap) {
+ override fun onMatchedClasses(expectClassSymbol: IrClassSymbol, actualClassSymbol: IrClassSymbol) {
+ shouldNotBeCalled()
+ }
-internal fun Map>.getMatches(
- expectDeclaration: IrDeclaration,
- expectActualTypesMap: Map,
- expectActualTypeAliasMap: Map
-): List =
- getMatches(generateIrElementFullNameFromExpect(expectDeclaration, expectActualTypeAliasMap), expectDeclaration, expectActualTypesMap)
-
-internal fun Map>.getMatches(
- mainSignature: String,
- expectDeclaration: IrDeclaration,
- expectActualTypesMap: Map
-): List {
- val members = this[mainSignature] ?: return emptyList()
- return when (expectDeclaration) {
- is IrFunction -> members.getMatches(expectDeclaration, expectActualTypesMap) { it as IrFunction }
- is IrProperty -> members.getMatches(expectDeclaration, expectActualTypesMap) { (it as IrProperty).getter!! }
- else -> members
+ override fun onMatchedCallables(expectSymbol: IrSymbol, actualSymbol: IrSymbol) {
+ require(expectSymbol == baseExpectSymbol)
+ matchingActuals += actualSymbol
+ }
}
+ AbstractExpectActualCompatibilityChecker.matchSingleExpectTopLevelDeclarationAgainstPotentialActuals(
+ expectSymbol,
+ actualSymbols,
+ context
+ )
+ return matchingActuals
}
-private inline fun List.getMatches(
- expect: IrDeclaration,
- expectActualTypesMap: Map,
- functionExtractor: (IrDeclaration) -> IrFunction
-): List {
- val expectFunction = functionExtractor(expect)
- return filter { expectFunction.match(functionExtractor(it), expectActualTypesMap) }
-}
-
-private fun IrFunction.match(actualFunction: IrFunction, expectActualTypesMap: Map): Boolean {
- fun getActualizedTypeClassifierSymbol(
- expectParameter: IrValueParameter,
- localTypeParametersMap: Map? = null
- ): IrSymbol {
- return expectParameter.type.classifierOrFail.let {
- val localMappedSymbol = if (localTypeParametersMap != null && it is IrTypeParameterSymbol) {
- localTypeParametersMap[it]
- } else {
- null
- }
- localMappedSymbol ?: expectActualTypesMap[it] ?: it
- }
- }
-
- fun checkParameter(
- expectParameter: IrValueParameter?,
- actualParameter: IrValueParameter?,
- localTypeParametersMap: Map
- ): Boolean {
- if (expectParameter == null) {
- return actualParameter == null
- }
- if (actualParameter == null) {
- return false
- }
-
- if (expectParameter.type is IrDynamicType || actualParameter.type is IrDynamicType) {
- return true
- }
-
- if (expectParameter.type.isNullable() != actualParameter.type.isNullable() &&
- !expectParameter.type.annotations.hasAnnotation(FLEXIBLE_NULLABILITY_ANNOTATION_FQ_NAME) &&
- !actualParameter.type.annotations.hasAnnotation(FLEXIBLE_NULLABILITY_ANNOTATION_FQ_NAME)
- ) {
- return false
- }
-
- if (getActualizedTypeClassifierSymbol(expectParameter, localTypeParametersMap) !=
- getActualizedTypeClassifierSymbol(actualParameter)
- ) {
- return false
- }
-
- return true
- }
-
- if (valueParameters.size != actualFunction.valueParameters.size || typeParameters.size != actualFunction.typeParameters.size) {
- return false
- }
-
- val localTypeParametersMap = mutableMapOf()
- for ((expectTypeParameter, actualTypeParameter) in typeParameters.zip(actualFunction.typeParameters)) {
- if (expectTypeParameter.name != actualTypeParameter.name) {
- return false
- }
- localTypeParametersMap[expectTypeParameter.symbol] = actualTypeParameter.symbol
- }
-
- if (!checkParameter(extensionReceiverParameter, actualFunction.extensionReceiverParameter, localTypeParametersMap)) {
- return false
- }
-
- for ((expectParameter, actualParameter) in valueParameters.zip(actualFunction.valueParameters)) {
- if (!checkParameter(expectParameter, actualParameter, localTypeParametersMap)) {
- return false
- }
- }
-
- return true
-}
-
-internal fun generateActualIrClassOrTypeAliasFullName(declaration: IrElement) = generateIrElementFullNameFromExpect(declaration, emptyMap())
-
-internal fun generateIrElementFullNameFromExpect(
- declaration: IrElement,
- expectActualTypeAliasMap: Map
-): String {
- return buildString { appendElementFullName(declaration, this, expectActualTypeAliasMap) }
-}
-
-private fun appendElementFullName(
- declaration: IrElement,
- result: StringBuilder,
- expectActualTypeAliasMap: Map
+internal fun recordActualForExpectDeclaration(
+ expectSymbol: IrSymbol,
+ actualSymbol: IrSymbol,
+ destination: MutableMap,
) {
- if (declaration !is IrDeclarationBase) return
-
- val parents = mutableListOf()
- var parent: IrDeclarationParent? = declaration.parent
- while (parent != null) {
- if (parent is IrDeclarationWithName) {
- val parentParent = parent.parent
- if (parentParent is IrClass) {
- parents.add(parent.name.asString())
- parent = parentParent
- continue
- }
+ val expectDeclaration = expectSymbol.owner as IrDeclarationBase
+ val actualDeclaration = actualSymbol.owner as IrDeclaration
+ val registeredActual = destination.put(expectSymbol, actualSymbol)
+ require(registeredActual == null || registeredActual == actualSymbol) {
+ """
+ Expect symbol already has registered mapping
+
+ Expect declaration: ${expectDeclaration.render()}
+ Actual declaration: ${actualDeclaration.render()}
+ Already registered: ${registeredActual!!.owner.render()}
+ """.trimIndent()
+ }
+ if (expectDeclaration is IrTypeParametersContainer) {
+ recordTypeParametersMapping(destination, expectDeclaration, actualDeclaration as IrTypeParametersContainer)
+ }
+ if (expectDeclaration is IrProperty) {
+ val actualProperty = actualDeclaration as IrProperty
+ expectDeclaration.getter!!.let {
+ val getter = actualProperty.getter!!
+ destination[it.symbol] = getter.symbol
+ recordTypeParametersMapping(destination, it, getter)
}
- val parentString = parent.kotlinFqName.let { (expectActualTypeAliasMap[it] ?: it).asString() }
- if (parentString.isNotEmpty()) {
- parents.add(parentString)
- }
- parent = null
- }
-
- if (parents.isNotEmpty()) {
- result.append(parents.asReversed().joinToString(separator = "."))
- result.append('.')
- }
-
- if (declaration is IrDeclarationWithName) {
- result.append(declaration.name)
- }
-
- if (declaration is IrFunction) {
- result.append("()")
+ expectDeclaration.setter?.symbol?.let { destination[it] = actualProperty.setter!!.symbol }
}
}
-internal fun MutableMap.addLink(expectMember: IrDeclarationBase, actualMember: IrDeclaration) {
- this[expectMember.symbol] = actualMember.symbol
- if (expectMember is IrProperty) {
- val actualProperty = actualMember as IrProperty
- expectMember.getter!!.let {
- val getter = actualProperty.getter!!
- this[it.symbol] = getter.symbol
- this.appendTypeParametersMap(it, getter)
+private fun recordTypeParametersMapping(
+ destination: MutableMap,
+ expectTypeParametersContainer: IrTypeParametersContainer,
+ actualTypeParametersContainer: IrTypeParametersContainer
+) {
+ expectTypeParametersContainer.typeParameters
+ .zip(actualTypeParametersContainer.typeParameters)
+ .forEach { (expectTypeParameter, actualTypeParameter) ->
+ destination[expectTypeParameter.symbol] = actualTypeParameter.symbol
}
- expectMember.setter?.symbol?.let { this[it] = actualProperty.setter!!.symbol }
- } else if (expectMember is IrFunction) {
- this.appendTypeParametersMap(expectMember, actualMember as IrFunction)
- }
+}
+
+internal fun KtDiagnosticReporterWithImplicitIrBasedContext.reportMissingActual(expectSymbol: IrSymbol) {
+ reportMissingActual(expectSymbol.owner as IrDeclaration)
}
@OptIn(ObsoleteDescriptorBasedAPI::class)
@@ -200,6 +107,21 @@ internal fun KtDiagnosticReporterWithImplicitIrBasedContext.reportMissingActual(
)
}
+internal fun KtDiagnosticReporterWithImplicitIrBasedContext.reportIncompatibleExpectActual(
+ expectSymbol: IrSymbol,
+ actualSymbol: IrSymbol,
+ incompatibility: ExpectActualCompatibility.Incompatible<*>
+) {
+ val expectDeclaration = expectSymbol.owner as IrDeclaration
+ val actualDeclaration = actualSymbol.owner as IrDeclaration
+ at(expectDeclaration).report(
+ CommonBackendErrors.INCOMPATIBLE_MATCHING,
+ expectDeclaration.getNameWithAssert().asString(),
+ actualDeclaration.getNameWithAssert().asString(),
+ incompatibility
+ )
+}
+
internal fun IrElement.containsOptionalExpectation(): Boolean {
return this is IrClass &&
this.kind == ClassKind.ANNOTATION_CLASS &&
@@ -268,4 +190,4 @@ private fun createFakeOverrideFunction(
it.attributeOwnerId = it
it.correspondingPropertySymbol = correspondingPropertySymbol
}
-}
\ No newline at end of file
+}
diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/actualizer/IrExpectActualMatchingContext.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/actualizer/IrExpectActualMatchingContext.kt
new file mode 100644
index 00000000000..442dcf1f77f
--- /dev/null
+++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/actualizer/IrExpectActualMatchingContext.kt
@@ -0,0 +1,401 @@
+/*
+ * Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
+ */
+
+package org.jetbrains.kotlin.backend.common.actualizer
+
+import org.jetbrains.kotlin.descriptors.ClassKind
+import org.jetbrains.kotlin.descriptors.Modality
+import org.jetbrains.kotlin.descriptors.Visibilities
+import org.jetbrains.kotlin.descriptors.Visibility
+import org.jetbrains.kotlin.ir.declarations.*
+import org.jetbrains.kotlin.ir.symbols.*
+import org.jetbrains.kotlin.ir.types.*
+import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
+import org.jetbrains.kotlin.ir.types.impl.IrTypeBase
+import org.jetbrains.kotlin.ir.types.impl.IrTypeProjectionImpl
+import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection
+import org.jetbrains.kotlin.ir.util.*
+import org.jetbrains.kotlin.mpp.*
+import org.jetbrains.kotlin.name.CallableId
+import org.jetbrains.kotlin.name.ClassId
+import org.jetbrains.kotlin.name.Name
+import org.jetbrains.kotlin.resolve.calls.mpp.ExpectActualMatchingContext
+import org.jetbrains.kotlin.types.AbstractTypeChecker
+import org.jetbrains.kotlin.types.Variance
+import org.jetbrains.kotlin.types.model.*
+import org.jetbrains.kotlin.utils.addToStdlib.UnsafeCastFunction
+import org.jetbrains.kotlin.utils.addToStdlib.castAll
+import org.jetbrains.kotlin.utils.addToStdlib.shouldNotBeCalled
+
+internal abstract class IrExpectActualMatchingContext(
+ val typeContext: IrTypeSystemContext,
+ val expectToActualClassMap: Map
+) : ExpectActualMatchingContext, TypeSystemContext by typeContext {
+ private inline fun CallableSymbolMarker.processIr(
+ onFunction: (IrFunction) -> R,
+ onProperty: (IrProperty) -> R,
+ onField: (IrField) -> R,
+ onValueParameter: (IrValueParameter) -> R,
+ onEnumEntry: (IrEnumEntry) -> R,
+ ): R {
+ return when (this) {
+ is IrFunctionSymbol -> onFunction(owner)
+ is IrPropertySymbol -> onProperty(owner)
+ is IrFieldSymbol -> onField(owner)
+ is IrValueParameterSymbol -> onValueParameter(owner)
+ is IrEnumEntrySymbol -> onEnumEntry(owner)
+ else -> error("Unsupported declaration: $this")
+ }
+ }
+
+ private inline fun ClassLikeSymbolMarker.processIr(
+ onClass: (IrClass) -> R,
+ onTypeAlias: (IrTypeAlias) -> R,
+ ): R {
+ return when (this) {
+ is IrClassSymbol -> onClass(owner)
+ is IrTypeAliasSymbol -> onTypeAlias(owner)
+ else -> error("Unsupported declaration: $this")
+ }
+ }
+
+ private fun DeclarationSymbolMarker.asIr(): IrDeclaration = (this as IrSymbol).owner as IrDeclaration
+ private fun FunctionSymbolMarker.asIr(): IrFunction = (this as IrFunctionSymbol).owner
+ private fun PropertySymbolMarker.asIr(): IrProperty = (this as IrPropertySymbol).owner
+ private fun ValueParameterSymbolMarker.asIr(): IrValueParameter = (this as IrValueParameterSymbol).owner
+ private fun TypeParameterSymbolMarker.asIr(): IrTypeParameter = (this as IrTypeParameterSymbol).owner
+ private fun RegularClassSymbolMarker.asIr(): IrClass = (this as IrClassSymbol).owner
+ private fun TypeAliasSymbolMarker.asIr(): IrTypeAlias = (this as IrTypeAliasSymbol).owner
+
+ private inline fun DeclarationSymbolMarker.safeAsIr(): T? = (this as IrSymbol).owner as? T
+
+ override val shouldCheckReturnTypesOfCallables: Boolean
+ get() = true
+
+ override val innerClassesCapturesOuterTypeParameters: Boolean
+ get() = false
+
+ override val RegularClassSymbolMarker.classId: ClassId
+ get() = asIr().classIdOrFail
+
+ override val TypeAliasSymbolMarker.classId: ClassId
+ get() = asIr().classIdOrFail
+
+ override val CallableSymbolMarker.callableId: CallableId
+ get() = processIr(
+ onFunction = { it.callableId },
+ onProperty = { it.callableId },
+ onField = { it.callableId },
+ onValueParameter = { shouldNotBeCalled() },
+ onEnumEntry = { it.callableId }
+ )
+
+ override val TypeParameterSymbolMarker.parameterName: Name
+ get() = asIr().name
+ override val ValueParameterSymbolMarker.parameterName: Name
+ get() = asIr().name
+
+ override fun TypeAliasSymbolMarker.expandToRegularClass(): RegularClassSymbolMarker? {
+ return asIr().expandedType.getClass()?.symbol
+ }
+
+ override val RegularClassSymbolMarker.classKind: ClassKind
+ get() = asIr().kind
+ override val RegularClassSymbolMarker.isCompanion: Boolean
+ get() = asIr().isCompanion
+ override val RegularClassSymbolMarker.isInner: Boolean
+ get() = asIr().isInner
+ override val RegularClassSymbolMarker.isInline: Boolean
+ get() = asIr().isValue
+ override val RegularClassSymbolMarker.isValue: Boolean
+ get() = asIr().isValue
+
+ override val RegularClassSymbolMarker.isFun: Boolean
+ get() = asIr().isFun
+
+ override val ClassLikeSymbolMarker.typeParameters: List
+ get() {
+ val parameters = processIr(
+ onClass = { it.typeParameters },
+ onTypeAlias = { it.typeParameters },
+ )
+ return parameters.map { it.symbol }
+ }
+
+ override val ClassLikeSymbolMarker.modality: Modality
+ get() = processIr(
+ onClass = {
+ // For some reason kotlin annotations in IR have open modality and java annotations have final modality
+ // But since it's legal to actualize kotlin annotation class with java annotation class
+ // and effectively all annotation classes have the same modality, it's ok to always return one
+ // modality for all annotation classes (doesn't matter final or open)
+ if (it.isAnnotationClass) Modality.OPEN else it.modality
+ },
+ onTypeAlias = { Modality.FINAL }
+ )
+ override val ClassLikeSymbolMarker.visibility: Visibility
+ get() = safeAsIr()!!.visibility.delegate
+
+ override val CallableSymbolMarker.modality: Modality?
+ get() = when (this) {
+ is IrConstructorSymbol -> Modality.FINAL
+ is IrSymbol -> (owner as? IrOverridableMember)?.modality
+ else -> shouldNotBeCalled()
+ }
+
+ override val CallableSymbolMarker.visibility: Visibility
+ get() = when (this) {
+ is IrEnumEntrySymbol -> Visibilities.Public
+ is IrSymbol -> (owner as IrDeclarationWithVisibility).visibility.delegate
+ else -> shouldNotBeCalled()
+ }
+
+ override val RegularClassSymbolMarker.superTypes: List
+ get() = asIr().superTypes
+
+ override val CallableSymbolMarker.isExpect: Boolean
+ get() = processIr(
+ onFunction = { it.isExpect },
+ onProperty = { it.isExpect },
+ onField = { false },
+ onValueParameter = { false },
+ onEnumEntry = { false }
+ )
+ override val CallableSymbolMarker.isInline: Boolean
+ get() = processIr(
+ onFunction = { it.isInline },
+ onProperty = { false }, // property can not be inline in IR. Its getter is inline instead
+ onField = { false },
+ onValueParameter = { false },
+ onEnumEntry = { false }
+ )
+
+ override val CallableSymbolMarker.isSuspend: Boolean
+ get() = processIr(
+ onFunction = { it.isSuspend },
+ onProperty = { false }, // property can not be suspend in IR. Its getter is suspend instead
+ onField = { false },
+ onValueParameter = { false },
+ onEnumEntry = { false }
+ )
+
+ override val CallableSymbolMarker.isExternal: Boolean
+ get() = safeAsIr()?.isExternal ?: false
+
+ override val CallableSymbolMarker.isInfix: Boolean
+ get() = safeAsIr()?.isInfix ?: false
+
+ override val CallableSymbolMarker.isOperator: Boolean
+ get() = safeAsIr()?.isOperator ?: false
+
+ override val CallableSymbolMarker.isTailrec: Boolean
+ get() = safeAsIr()?.isTailrec ?: false
+
+ override val PropertySymbolMarker.isVar: Boolean
+ get() = asIr().isVar
+
+ override val PropertySymbolMarker.isLateinit: Boolean
+ get() = asIr().isLateinit
+
+ override val PropertySymbolMarker.isConst: Boolean
+ get() = asIr().isConst
+
+ override val PropertySymbolMarker.setter: FunctionSymbolMarker?
+ get() = asIr().setter?.symbol
+
+ @OptIn(UnsafeCastFunction::class)
+ override fun createExpectActualTypeParameterSubstitutor(
+ expectTypeParameters: List,
+ actualTypeParameters: List,
+ parentSubstitutor: TypeSubstitutorMarker?,
+ ): TypeSubstitutorMarker {
+ val expectParameters = expectTypeParameters.castAll()
+ val actualParameters = actualTypeParameters.castAll()
+ val actualTypes = actualParameters.map { it.owner.defaultType }
+ val substitutor = IrTypeSubstitutor(expectParameters, actualTypes, typeContext.irBuiltIns, allowEmptySubstitution = true)
+ return when (parentSubstitutor) {
+ null -> substitutor
+ is AbstractIrTypeSubstitutor -> IrChainedSubstitutor(parentSubstitutor, substitutor)
+ else -> shouldNotBeCalled()
+ }
+ }
+
+ /*
+ * [isActualDeclaration] flag is needed to correctly determine scope for specific class
+ * In IR there are no scopes, all declarations are stored inside IrClass itself, so this flag
+ * has no sense in IR context
+ */
+ override fun RegularClassSymbolMarker.collectAllMembers(isActualDeclaration: Boolean): List {
+ return asIr().declarations.filterNot { it is IrAnonymousInitializer }.map { it.symbol }
+ }
+
+ override fun RegularClassSymbolMarker.getMembersForExpectClass(name: Name): List {
+ return asIr().declarations.filter { it.getNameWithAssert() == name }.map { it.symbol }
+ }
+
+ override fun RegularClassSymbolMarker.collectEnumEntryNames(): List {
+ return asIr().declarations.filterIsInstance().map { it.name }
+ }
+
+ override val CallableSymbolMarker.dispatchReceiverType: KotlinTypeMarker?
+ get() = (asIr().parent as? IrClass)?.defaultType
+
+ override val CallableSymbolMarker.extensionReceiverType: KotlinTypeMarker?
+ get() = safeAsIr()?.extensionReceiverParameter?.type
+
+ override val CallableSymbolMarker.returnType: KotlinTypeMarker
+ get() = processIr(
+ onFunction = { it.returnType },
+ onProperty = { it.getter?.returnType ?: it.backingField?.type ?: error("No type for property: $it") },
+ onField = { it.type },
+ onValueParameter = { it.type },
+ onEnumEntry = { it.parentAsClass.defaultType }
+ )
+
+ override val CallableSymbolMarker.typeParameters: List
+ get() = processIr(
+ onFunction = { it.typeParameters.map { parameter -> parameter.symbol } },
+ onProperty = { it.getter?.symbol?.typeParameters.orEmpty() },
+ onField = { emptyList() },
+ onValueParameter = { emptyList() },
+ onEnumEntry = { emptyList() }
+ )
+
+ override val FunctionSymbolMarker.valueParameters: List
+ get() = asIr().valueParameters.map { it.symbol }
+
+ override val ValueParameterSymbolMarker.isVararg: Boolean
+ get() = asIr().isVararg
+ override val ValueParameterSymbolMarker.isNoinline: Boolean
+ get() = asIr().isNoinline
+ override val ValueParameterSymbolMarker.isCrossinline: Boolean
+ get() = asIr().isCrossinline
+ override val ValueParameterSymbolMarker.hasDefaultValue: Boolean
+ get() = asIr().hasDefaultValue()
+
+ override fun CallableSymbolMarker.isAnnotationConstructor(): Boolean {
+ val irConstructor = safeAsIr() ?: return false
+ return irConstructor.constructedClass.isAnnotationClass
+ }
+
+ override val TypeParameterSymbolMarker.bounds: List
+ get() = asIr().superTypes
+ override val TypeParameterSymbolMarker.variance: Variance
+ get() = asIr().variance
+ override val TypeParameterSymbolMarker.isReified: Boolean
+ get() = asIr().isReified
+
+ override fun areCompatibleExpectActualTypes(expectType: KotlinTypeMarker?, actualType: KotlinTypeMarker?): Boolean {
+ if (expectType == null) return actualType == null
+ if (actualType == null) return false
+ /*
+ * Here we need to actualize both types, because of following situation:
+ *
+ * // MODULE: common
+ * expect fun foo(): S // (1)
+ * expect class S
+ *
+ * // MODULE: intermediate
+ * actual fun foo(): S = null!! // (2)
+ *
+ * // MODULE: platform
+ * actual typealias S = String
+ *
+ * When we match return types of (1) and (2) they both will have original type `S`, but from
+ * perspective of module `platform` it should be replaced with `String`
+ */
+ val actualizedExpectType = actualizingSubstitutor.substitute(expectType as IrType)
+ val actualizedActualType = actualizingSubstitutor.substitute(actualType as IrType)
+ return AbstractTypeChecker.equalTypes(
+ typeContext.newTypeCheckerState(errorTypesEqualToAnything = true, stubTypesEqualToAnything = false),
+ actualizedExpectType,
+ actualizedActualType
+ )
+ }
+
+ private val actualizingSubstitutor = ActualizingSubstitutor()
+
+ private inner class ActualizingSubstitutor : AbstractIrTypeSubstitutor() {
+ override fun substitute(type: IrType): IrType {
+ return substituteOrNull(type) ?: type
+ }
+
+ private fun substituteOrNull(type: IrType): IrType? {
+ if (type !is IrSimpleTypeImpl) return null
+ val newClassifier = (type.classifier.owner as? IrClass)?.let { expectToActualClassMap[it.classIdOrFail] }
+ val newArguments = ArrayList(type.arguments.size)
+ var argumentsChanged = false
+ for (argument in type.arguments) {
+ val newArgument = substituteArgumentOrNull(argument)
+ if (newArgument != null) {
+ newArguments += newArgument
+ argumentsChanged = true
+ } else {
+ newArguments += argument
+ }
+ }
+ if (newClassifier == null && !argumentsChanged) {
+ return null
+ }
+ return IrSimpleTypeImpl(
+ classifier = newClassifier ?: type.classifier,
+ type.nullability,
+ newArguments,
+ type.annotations,
+ type.abbreviation
+ )
+ }
+
+ private fun substituteArgumentOrNull(argument: IrTypeArgument): IrTypeArgument? {
+ return when (argument) {
+ is IrStarProjection -> null
+ is IrTypeProjection -> when (argument) {
+ is IrTypeProjectionImpl -> {
+ val newType = substituteOrNull(argument.type) ?: return null
+ makeTypeProjection(newType, argument.variance)
+ }
+ is IrTypeBase -> substituteOrNull(argument) as IrTypeBase?
+ else -> shouldNotBeCalled()
+ }
+ }
+ }
+ }
+
+ override fun RegularClassSymbolMarker.isNotSamInterface(): Boolean {
+ // TODO: is it correct for java classes?
+ return !asIr().isFun
+ }
+
+ override fun CallableSymbolMarker.shouldSkipMatching(containingExpectClass: RegularClassSymbolMarker): Boolean {
+ return false
+ }
+
+ override val CallableSymbolMarker.hasStableParameterNames: Boolean
+ get() = when (asIr().origin) {
+ IrDeclarationOrigin.IR_EXTERNAL_DECLARATION_STUB,
+ IrDeclarationOrigin.IR_EXTERNAL_JAVA_DECLARATION_STUB,
+ -> false
+ else -> true
+ }
+
+ override fun onMatchedMembers(expectSymbol: DeclarationSymbolMarker, actualSymbol: DeclarationSymbolMarker) {
+ require(expectSymbol is IrSymbol)
+ require(actualSymbol is IrSymbol)
+ when (expectSymbol) {
+ is IrClassSymbol -> {
+ val actualClassSymbol = when (actualSymbol) {
+ is IrClassSymbol -> actualSymbol
+ is IrTypeAliasSymbol -> actualSymbol.owner.expandedType.getClass()!!.symbol
+ else -> actualSymbol.unexpectedSymbolKind()
+ }
+ onMatchedClasses(expectSymbol, actualClassSymbol)
+ }
+ else -> onMatchedCallables(expectSymbol, actualSymbol)
+ }
+ }
+
+ abstract fun onMatchedClasses(expectClassSymbol: IrClassSymbol, actualClassSymbol: IrClassSymbol)
+ abstract fun onMatchedCallables(expectSymbol: IrSymbol, actualSymbol: IrSymbol)
+}
diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/symbols/IrSymbol.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/symbols/IrSymbol.kt
index c1efa0ebe70..5f5acc456bf 100644
--- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/symbols/IrSymbol.kt
+++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/symbols/IrSymbol.kt
@@ -25,6 +25,7 @@ import org.jetbrains.kotlin.ir.types.IrSimpleType
import org.jetbrains.kotlin.ir.types.IrTypeAbbreviation
import org.jetbrains.kotlin.ir.util.IdSignature
import org.jetbrains.kotlin.ir.util.SymbolTable
+import org.jetbrains.kotlin.mpp.*
import org.jetbrains.kotlin.types.model.TypeConstructorMarker
import org.jetbrains.kotlin.types.model.TypeParameterMarker
@@ -46,7 +47,7 @@ import org.jetbrains.kotlin.types.model.TypeParameterMarker
* @see IdSignature
* @see SymbolTable
*/
-interface IrSymbol {
+interface IrSymbol : DeclarationSymbolMarker {
/**
* The declaration that this symbol refers to if it's bound.
@@ -167,7 +168,7 @@ interface IrAnonymousInitializerSymbol : IrBindableSymbol
+interface IrEnumEntrySymbol : IrBindableSymbol, EnumEntrySymbolMarker
/**
* A symbol whose [owner] is [IrField].
@@ -175,7 +176,7 @@ interface IrEnumEntrySymbol : IrBindableSymbol
* @see IrGetField
* @see IrSetField
*/
-interface IrFieldSymbol : IrBindableSymbol
+interface IrFieldSymbol : IrBindableSymbol, FieldSymbolMarker
/**
* A symbol whose [owner] is [IrClass], [IrScript] or [IrTypeParameter].
@@ -195,7 +196,7 @@ sealed interface IrClassifierSymbol : IrSymbol, TypeConstructorMarker {
* @see IrCall.superQualifierSymbol
* @see IrFieldAccessExpression.superQualifierSymbol
*/
-interface IrClassSymbol : IrClassifierSymbol, IrBindableSymbol
+interface IrClassSymbol : IrClassifierSymbol, IrBindableSymbol, RegularClassSymbolMarker
/**
* A symbol whose [owner] is [IrScript].
@@ -205,7 +206,10 @@ interface IrScriptSymbol : IrClassifierSymbol, IrBindableSymbol, TypeParameterMarker
+interface IrTypeParameterSymbol : IrClassifierSymbol,
+ IrBindableSymbol,
+ TypeParameterMarker,
+ TypeParameterSymbolMarker
/**
* A symbol whose [owner] is [IrValueParameter] or [IrVariable].
@@ -223,7 +227,7 @@ sealed interface IrValueSymbol : IrSymbol {
/**
* A symbol whose [owner] is [IrValueParameter].
*/
-interface IrValueParameterSymbol : IrValueSymbol, IrBindableSymbol
+interface IrValueParameterSymbol : IrValueSymbol, IrBindableSymbol, ValueParameterSymbolMarker
/**
* A symbol whose [owner] is [IrVariable].
@@ -247,7 +251,7 @@ sealed interface IrReturnTargetSymbol : IrSymbol {
*
* @see IrFunctionReference
*/
-sealed interface IrFunctionSymbol : IrReturnTargetSymbol {
+sealed interface IrFunctionSymbol : IrReturnTargetSymbol, FunctionSymbolMarker {
override val owner: IrFunction
}
@@ -256,14 +260,14 @@ sealed interface IrFunctionSymbol : IrReturnTargetSymbol {
*
* @see IrConstructorCall
*/
-interface IrConstructorSymbol : IrFunctionSymbol, IrBindableSymbol
+interface IrConstructorSymbol : IrFunctionSymbol, IrBindableSymbol, ConstructorSymbolMarker
/**
* A symbol whose [owner] is [IrSimpleFunction].
*
* @see IrCall
*/
-interface IrSimpleFunctionSymbol : IrFunctionSymbol, IrBindableSymbol
+interface IrSimpleFunctionSymbol : IrFunctionSymbol, IrBindableSymbol, SimpleFunctionSymbolMarker
/**
* A symbol whose [owner] is [IrReturnableBlock].
@@ -273,7 +277,7 @@ interface IrReturnableBlockSymbol : IrReturnTargetSymbol, IrBindableSymbol
+interface IrPropertySymbol : IrBindableSymbol, PropertySymbolMarker
/**
* A symbol whose [owner] is [IrLocalDelegatedProperty].
@@ -285,4 +289,4 @@ interface IrLocalDelegatedPropertySymbol : IrBindableSymbol
+interface IrTypeAliasSymbol : IrBindableSymbol, TypeAliasSymbolMarker
diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/IrTypeSubstitutor.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/IrTypeSubstitutor.kt
index 61214c9e63b..aec1aa75d48 100644
--- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/IrTypeSubstitutor.kt
+++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/IrTypeSubstitutor.kt
@@ -13,8 +13,11 @@ import org.jetbrains.kotlin.types.Variance
import org.jetbrains.kotlin.types.model.TypeSubstitutorMarker
import org.jetbrains.kotlin.utils.memoryOptimizedMap
+abstract class AbstractIrTypeSubstitutor : TypeSubstitutorMarker {
+ abstract fun substitute(type: IrType): IrType
+}
-abstract class AbstractIrTypeSubstitutor(private val irBuiltIns: IrBuiltIns) : TypeSubstitutorMarker {
+abstract class BaseIrTypeSubstitutor(private val irBuiltIns: IrBuiltIns) : AbstractIrTypeSubstitutor() {
private fun IrType.typeParameterConstructor(): IrTypeParameterSymbol? {
return if (this is IrSimpleType) classifier as? IrTypeParameterSymbol
@@ -25,7 +28,7 @@ abstract class AbstractIrTypeSubstitutor(private val irBuiltIns: IrBuiltIns) : T
abstract fun isEmptySubstitution(): Boolean
- fun substitute(type: IrType): IrType {
+ final override fun substitute(type: IrType): IrType {
if (isEmptySubstitution()) return type
return substituteType(type)
}
@@ -63,8 +66,9 @@ abstract class AbstractIrTypeSubstitutor(private val irBuiltIns: IrBuiltIns) : T
class IrTypeSubstitutor(
typeParameters: List,
typeArguments: List,
- irBuiltIns: IrBuiltIns
-) : AbstractIrTypeSubstitutor(irBuiltIns) {
+ irBuiltIns: IrBuiltIns,
+ private val allowEmptySubstitution: Boolean = false
+) : BaseIrTypeSubstitutor(irBuiltIns) {
init {
assert(typeParameters.size == typeArguments.size) {
@@ -80,7 +84,8 @@ class IrTypeSubstitutor(
override fun getSubstitutionArgument(typeParameter: IrTypeParameterSymbol): IrTypeArgument =
substitution[typeParameter]
- ?: throw AssertionError("Unsubstituted type parameter: ${typeParameter.owner.render()}")
+ ?: typeParameter.takeIf { allowEmptySubstitution }?.owner?.defaultType
+ ?: error("Unsubstituted type parameter: ${typeParameter.owner.render()}")
override fun isEmptySubstitution(): Boolean = substitution.isEmpty()
}
@@ -90,7 +95,7 @@ class IrCapturedTypeSubstitutor(
typeArguments: List,
capturedTypes: List,
irBuiltIns: IrBuiltIns
-) : AbstractIrTypeSubstitutor(irBuiltIns) {
+) : BaseIrTypeSubstitutor(irBuiltIns) {
init {
assert(typeArguments.size == typeParameters.size)
@@ -108,3 +113,10 @@ class IrCapturedTypeSubstitutor(
override fun isEmptySubstitution(): Boolean = oldSubstitution.isEmpty()
}
+
+class IrChainedSubstitutor(val first: AbstractIrTypeSubstitutor, val second: AbstractIrTypeSubstitutor) : AbstractIrTypeSubstitutor() {
+ override fun substitute(type: IrType): IrType {
+ val firstResult = first.substitute(type)
+ return second.substitute(firstResult)
+ }
+}
diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/irTypes.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/irTypes.kt
index 16e07873514..48299012573 100644
--- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/irTypes.kt
+++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/irTypes.kt
@@ -169,7 +169,7 @@ val IrClassifierSymbol.defaultType: IrType
is IrScriptSymbol -> unexpectedSymbolKind()
}
-val IrTypeParameter.defaultType: IrType
+val IrTypeParameter.defaultType: IrSimpleType
get() = IrSimpleTypeImpl(
symbol,
SimpleTypeNullability.NOT_SPECIFIED,
diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/AdditionalIrUtils.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/AdditionalIrUtils.kt
index 8e090661e74..1c9fab0601f 100644
--- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/AdditionalIrUtils.kt
+++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/AdditionalIrUtils.kt
@@ -15,10 +15,7 @@ import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.kotlin.ir.symbols.impl.IrClassPublicSymbolImpl
-import org.jetbrains.kotlin.name.ClassId
-import org.jetbrains.kotlin.name.FqName
-import org.jetbrains.kotlin.name.Name
-import org.jetbrains.kotlin.name.SpecialNames
+import org.jetbrains.kotlin.name.*
import org.jetbrains.kotlin.resolve.descriptorUtil.module
import org.jetbrains.kotlin.utils.filterIsInstanceAnd
import java.io.File
@@ -57,12 +54,49 @@ val IrDeclarationParent.kotlinFqName: FqName
}
val IrClass.classId: ClassId?
+ get() = classIdImpl
+
+val IrTypeAlias.classId: ClassId?
+ get() = classIdImpl
+
+private val IrDeclarationWithName.classIdImpl: ClassId?
get() = when (val parent = this.parent) {
is IrClass -> parent.classId?.createNestedClassId(this.name)
is IrPackageFragment -> ClassId.topLevel(parent.packageFqName.child(this.name))
else -> null
}
+val IrClass.classIdOrFail: ClassId
+ get() = classIdOrFailImpl
+
+val IrTypeAlias.classIdOrFail: ClassId
+ get() = classIdOrFailImpl
+
+private val IrDeclarationWithName.classIdOrFailImpl: ClassId
+ get() = classIdImpl ?: error("No classId for $this")
+
+val IrFunction.callableId: CallableId
+ get() = callableIdImpl
+
+val IrProperty.callableId: CallableId
+ get() = callableIdImpl
+
+val IrField.callableId: CallableId
+ get() = callableIdImpl
+
+val IrEnumEntry.callableId: CallableId
+ get() = callableIdImpl
+
+private val IrDeclarationWithName.callableIdImpl: CallableId
+ get() {
+ if (this.symbol is IrClassifierSymbol) error("Classifiers can not have callableId. Got $this")
+ return when (val parent = this.parent) {
+ is IrClass -> parent.classId?.let { CallableId(it, name) }
+ is IrPackageFragment -> CallableId(parent.packageFqName, name)
+ else -> null
+ } ?: error("$this has no callableId")
+ }
+
@Suppress("unused")
@Deprecated(
"This function is deprecated because it has confusing name and behavior. " +
diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DeepCopyIrTreeWithSymbols.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DeepCopyIrTreeWithSymbols.kt
index 32175c74c5a..8412250ea9a 100644
--- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DeepCopyIrTreeWithSymbols.kt
+++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DeepCopyIrTreeWithSymbols.kt
@@ -802,7 +802,7 @@ open class DeepCopyIrTreeWithSymbols(
expression.value.transform()
).copyAttributes(expression)
- private fun SymbolRemapper.getReferencedReturnTarget(returnTarget: IrReturnTargetSymbol) =
+ private fun SymbolRemapper.getReferencedReturnTarget(returnTarget: IrReturnTargetSymbol): IrReturnTargetSymbol =
when (returnTarget) {
is IrFunctionSymbol -> getReferencedFunction(returnTarget)
is IrReturnableBlockSymbol -> getReferencedReturnableBlock(returnTarget)
diff --git a/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/mpp/AbstractExpectActualCompatibilityChecker.kt b/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/mpp/AbstractExpectActualCompatibilityChecker.kt
index f35c5403d5f..de69bfb6da6 100644
--- a/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/mpp/AbstractExpectActualCompatibilityChecker.kt
+++ b/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/mpp/AbstractExpectActualCompatibilityChecker.kt
@@ -29,7 +29,7 @@ object AbstractExpectActualCompatibilityChecker {
context: ExpectActualMatchingContext,
): ExpectActualCompatibility {
val result = with(context) {
- areCompatibleClassifiers(expectClassSymbol, actualClassLikeSymbol)
+ areCompatibleClassifiers(expectClassSymbol, actualClassLikeSymbol, parentSubstitutor = null)
}
@Suppress("UNCHECKED_CAST")
return result as ExpectActualCompatibility
@@ -50,11 +50,29 @@ object AbstractExpectActualCompatibilityChecker {
return result as ExpectActualCompatibility
}
+ fun matchSingleExpectTopLevelDeclarationAgainstPotentialActuals(
+ expectDeclaration: DeclarationSymbolMarker,
+ actualDeclarations: List,
+ context: ExpectActualMatchingContext,
+ ) {
+ with(context) {
+ matchSingleExpectAgainstPotentialActuals(
+ expectDeclaration,
+ actualDeclarations,
+ substitutor = null,
+ expectClassSymbol = null,
+ actualClassSymbol = null,
+ unfulfilled = null
+ )
+ }
+ }
+
context(ExpectActualMatchingContext<*>)
@Suppress("warnings")
private fun areCompatibleClassifiers(
expectClassSymbol: RegularClassSymbolMarker,
actualClassLikeSymbol: ClassLikeSymbolMarker,
+ parentSubstitutor: TypeSubstitutorMarker?
): ExpectActualCompatibility<*> {
// Can't check FQ names here because nested expected class may be implemented via actual typealias's expansion with the other FQ name
require(expectClassSymbol.name == actualClassLikeSymbol.name) {
@@ -95,7 +113,7 @@ object AbstractExpectActualCompatibilityChecker {
val substitutor = createExpectActualTypeParameterSubstitutor(
expectTypeParameterSymbols,
actualTypeParameterSymbols,
- parentSubstitutor = null
+ parentSubstitutor
)
areCompatibleTypeParameters(expectTypeParameterSymbols, actualTypeParameterSymbols, substitutor).let {
@@ -133,7 +151,7 @@ object AbstractExpectActualCompatibilityChecker {
actualClassSymbol: RegularClassSymbolMarker,
substitutor: TypeSubstitutorMarker,
): ExpectActualCompatibility<*> {
- val unfulfilled = arrayListOf, MutableCollection>>>()
+ val unfulfilled = arrayListOf, List>>>()
val actualMembersByName = actualClassSymbol.collectAllMembers(isActualDeclaration = true).groupBy { it.name }
@@ -145,31 +163,14 @@ object AbstractExpectActualCompatibilityChecker {
expectMember is RegularClassSymbolMarker && actualMember is RegularClassSymbolMarker
}.orEmpty()
- val mapping = actualMembers.keysToMap { actualMember ->
- when (expectMember) {
- is CallableSymbolMarker -> areCompatibleCallables(
- expectMember,
- actualMember as CallableSymbolMarker,
- substitutor,
- expectClassSymbol,
- actualClassSymbol
- )
-
- is RegularClassSymbolMarker -> areCompatibleClassifiers(expectMember, actualMember as RegularClassSymbolMarker)
- else -> error("Unsupported declaration: $expectMember ($actualMembers)")
- }
- }
- if (mapping.values.any { it == ExpectActualCompatibility.Compatible }) continue
-
- val incompatibilityMap = mutableMapOf, MutableCollection>()
- for ((declaration, compatibility) in mapping) {
- when (compatibility) {
- ExpectActualCompatibility.Compatible -> continue@outer
- is Incompatible -> incompatibilityMap.getOrPut(compatibility) { SmartList() }.add(declaration)
- }
- }
-
- unfulfilled.add(expectMember to incompatibilityMap)
+ matchSingleExpectAgainstPotentialActuals(
+ expectMember,
+ actualMembers,
+ substitutor,
+ expectClassSymbol,
+ actualClassSymbol,
+ unfulfilled
+ )
}
if (expectClassSymbol.classKind == ClassKind.ENUM_CLASS) {
@@ -186,6 +187,53 @@ object AbstractExpectActualCompatibilityChecker {
return Incompatible.ClassScopes(unfulfilled)
}
+ context(ExpectActualMatchingContext<*>)
+ private fun matchSingleExpectAgainstPotentialActuals(
+ expectMember: DeclarationSymbolMarker,
+ actualMembers: List,
+ substitutor: TypeSubstitutorMarker?,
+ expectClassSymbol: RegularClassSymbolMarker?,
+ actualClassSymbol: RegularClassSymbolMarker?,
+ unfulfilled: MutableList, List>>>?
+ ) {
+ val mapping = actualMembers.keysToMap { actualMember ->
+ when (expectMember) {
+ is CallableSymbolMarker -> areCompatibleCallables(
+ expectMember,
+ actualMember as CallableSymbolMarker,
+ substitutor,
+ expectClassSymbol,
+ actualClassSymbol
+ )
+
+ is RegularClassSymbolMarker -> {
+ val parentSubstitutor = substitutor?.takeIf { !innerClassesCapturesOuterTypeParameters }
+ areCompatibleClassifiers(
+ expectMember,
+ actualMember as ClassLikeSymbolMarker,
+ parentSubstitutor
+ )
+ }
+ else -> error("Unsupported declaration: $expectMember ($actualMembers)")
+ }
+ }
+
+ val incompatibilityMap = mutableMapOf, MutableList>()
+ for ((actualMember, compatibility) in mapping) {
+ when (compatibility) {
+ ExpectActualCompatibility.Compatible -> {
+ onMatchedMembers(expectMember, actualMember)
+ return
+ }
+
+ is Incompatible -> incompatibilityMap.getOrPut(compatibility) { SmartList() }.add(actualMember)
+ }
+ }
+
+ unfulfilled?.add(expectMember to incompatibilityMap)
+ onMismatchedMembersFromClassScope(expectMember, incompatibilityMap)
+ }
+
context(ExpectActualMatchingContext<*>)
private fun areCompatibleCallables(
expectDeclaration: CallableSymbolMarker,
@@ -307,6 +355,10 @@ object AbstractExpectActualCompatibilityChecker {
actualDeclaration
).let { if (it != ExpectActualCompatibility.Compatible) return it }
+ expectDeclaration is EnumEntrySymbolMarker && actualDeclaration is EnumEntrySymbolMarker -> {
+ // do nothing, entries are matched only by name
+ }
+
else -> error("Unsupported declarations: $expectDeclaration, $actualDeclaration")
}
diff --git a/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/mpp/ExpectActualMatchingContext.kt b/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/mpp/ExpectActualMatchingContext.kt
index 8319d710137..e2bf664601a 100644
--- a/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/mpp/ExpectActualMatchingContext.kt
+++ b/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/mpp/ExpectActualMatchingContext.kt
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.mpp.*
import org.jetbrains.kotlin.name.CallableId
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.Name
+import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualCompatibility
import org.jetbrains.kotlin.types.Variance
import org.jetbrains.kotlin.types.model.KotlinTypeMarker
import org.jetbrains.kotlin.types.model.TypeSubstitutorMarker
@@ -20,6 +21,21 @@ import org.jetbrains.kotlin.types.model.TypeSystemContext
interface ExpectActualMatchingContext : TypeSystemContext {
val shouldCheckReturnTypesOfCallables: Boolean
+ /*
+ * This flag indicates how are type parameters of inner classes stored in the specific implementation of RegularClassSymbolMarker
+ *
+ * class Outer {
+ * inner class Inner
+ * }
+ *
+ * If flag is set to `true` then `typeParameters` for class `Outer.Inner` contains both parameters: [U, R]
+ * Otherwise it contains only parameters of itself: [U]
+ *
+ * This flag is needed for proper calculation of substitutions for components of inner classes
+ */
+ val innerClassesCapturesOuterTypeParameters: Boolean
+ get() = true
+
val RegularClassSymbolMarker.classId: ClassId
val TypeAliasSymbolMarker.classId: ClassId
val CallableSymbolMarker.callableId: CallableId
@@ -100,10 +116,17 @@ interface ExpectActualMatchingContext : TypeSystemC
/*
* Determines should some declaration from expect class scope be checked
* - FE 1.0: skip fake overrides
- * - FIR: skip nothing
+ * - FIR: skip fake overrides
* - IR: skip nothing
*/
fun CallableSymbolMarker.shouldSkipMatching(containingExpectClass: RegularClassSymbolMarker): Boolean
val CallableSymbolMarker.hasStableParameterNames: Boolean
+
+ fun onMatchedMembers(expectSymbol: DeclarationSymbolMarker, actualSymbol: DeclarationSymbolMarker) {}
+
+ fun onMismatchedMembersFromClassScope(
+ expectSymbol: DeclarationSymbolMarker,
+ actualSymbolsByIncompatibility: Map, List>
+ ) {}
}
diff --git a/compiler/testData/codegen/box/multiplatform/callToJavaSuper.kt b/compiler/testData/codegen/box/multiplatform/callToJavaSuper.kt
index 4be5acd5a08..4cbc72a1000 100644
--- a/compiler/testData/codegen/box/multiplatform/callToJavaSuper.kt
+++ b/compiler/testData/codegen/box/multiplatform/callToJavaSuper.kt
@@ -1,5 +1,6 @@
// LANGUAGE: +MultiPlatformProjects
// WITH_STDLIB
+// FULL_JDK
// TARGET_BACKEND: JVM_IR
// IGNORE_BACKEND_K1: JVM_IR
// Ignore reason: expect/actual are not supported in K1 box tests
diff --git a/compiler/testData/diagnostics/tests/multiplatform/defaultArguments/methodDefaultArgsViaActualTypealias.fir.kt b/compiler/testData/diagnostics/tests/multiplatform/defaultArguments/methodDefaultArgsViaActualTypealias.fir.kt
new file mode 100644
index 00000000000..f0471169b53
--- /dev/null
+++ b/compiler/testData/diagnostics/tests/multiplatform/defaultArguments/methodDefaultArgsViaActualTypealias.fir.kt
@@ -0,0 +1,49 @@
+// !DIAGNOSTICS: -ACTUAL_WITHOUT_EXPECT
+// MODULE: m1-common
+// FILE: common.kt
+expect class A {
+ fun foo(p1: String = "common", p2: String = "common", p3: String)
+}
+
+expect class B {
+ fun foo(s: String)
+}
+
+interface I {
+ fun methodWithDefaultArg(s: String = "common")
+}
+
+expect class WithDefaultArgFromSuper : I {
+ override fun methodWithDefaultArg(s: String)
+}
+
+expect open class WithIncompatibility {
+ fun foo(p: String = "common")
+}
+
+// MODULE: m2-jvm()()(m1-common)
+// FILE: jvm.kt
+
+class AImpl {
+ fun foo(p1: String = "impl", p2: String = "impl", p3: String) {}
+}
+
+actual typealias A = AImpl
+
+class BImpl {
+ fun foo(s: String = "impl") {}
+}
+
+actual typealias B = BImpl
+
+class WithDefaultArgFromSuperImpl : I {
+ override fun methodWithDefaultArg(s: String) {}
+}
+
+actual typealias WithDefaultArgFromSuper = WithDefaultArgFromSuperImpl
+
+class WithIncompatibilityImpl {
+ fun foo(p: String) {}
+}
+
+actual typealias WithIncompatibility = WithIncompatibilityImpl
diff --git a/compiler/testData/diagnostics/tests/multiplatform/defaultArguments/methodDefaultArgsViaActualTypealias.kt b/compiler/testData/diagnostics/tests/multiplatform/defaultArguments/methodDefaultArgsViaActualTypealias.kt
index 03418a5a091..2aff9ad6a38 100644
--- a/compiler/testData/diagnostics/tests/multiplatform/defaultArguments/methodDefaultArgsViaActualTypealias.kt
+++ b/compiler/testData/diagnostics/tests/multiplatform/defaultArguments/methodDefaultArgsViaActualTypealias.kt
@@ -1,4 +1,3 @@
-// FIR_IDENTICAL
// !DIAGNOSTICS: -ACTUAL_WITHOUT_EXPECT
// MODULE: m1-common
// FILE: common.kt
diff --git a/compiler/testData/diagnostics/tests/multiplatform/enum/javaEnum.fir.kt b/compiler/testData/diagnostics/tests/multiplatform/enum/javaEnum.fir.kt
new file mode 100644
index 00000000000..3bb2c1601ea
--- /dev/null
+++ b/compiler/testData/diagnostics/tests/multiplatform/enum/javaEnum.fir.kt
@@ -0,0 +1,34 @@
+// MODULE: m1-common
+// FILE: common.kt
+
+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();
+}
diff --git a/compiler/testData/diagnostics/tests/multiplatform/enum/javaEnum.kt b/compiler/testData/diagnostics/tests/multiplatform/enum/javaEnum.kt
index ab192066c68..727c918af54 100644
--- a/compiler/testData/diagnostics/tests/multiplatform/enum/javaEnum.kt
+++ b/compiler/testData/diagnostics/tests/multiplatform/enum/javaEnum.kt
@@ -1,4 +1,3 @@
-// FIR_IDENTICAL
// MODULE: m1-common
// FILE: common.kt
diff --git a/compiler/testData/diagnostics/tests/multiplatform/enum/simpleEnum.fir.kt b/compiler/testData/diagnostics/tests/multiplatform/enum/simpleEnum.fir.kt
new file mode 100644
index 00000000000..eb4776a61fa
--- /dev/null
+++ b/compiler/testData/diagnostics/tests/multiplatform/enum/simpleEnum.fir.kt
@@ -0,0 +1,17 @@
+// MODULE: m1-common
+// FILE: common.kt
+
+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");
+}
diff --git a/compiler/testData/diagnostics/tests/multiplatform/enum/simpleEnum.kt b/compiler/testData/diagnostics/tests/multiplatform/enum/simpleEnum.kt
index e465c204f82..5261c676cf1 100644
--- a/compiler/testData/diagnostics/tests/multiplatform/enum/simpleEnum.kt
+++ b/compiler/testData/diagnostics/tests/multiplatform/enum/simpleEnum.kt
@@ -1,4 +1,3 @@
-// FIR_IDENTICAL
// MODULE: m1-common
// FILE: common.kt
diff --git a/compiler/testData/diagnostics/tests/multiplatform/expectInterfaceApplicability.fir.kt b/compiler/testData/diagnostics/tests/multiplatform/expectInterfaceApplicability.fir.kt
index 6b2ab5ced75..b43742bdc00 100644
--- a/compiler/testData/diagnostics/tests/multiplatform/expectInterfaceApplicability.fir.kt
+++ b/compiler/testData/diagnostics/tests/multiplatform/expectInterfaceApplicability.fir.kt
@@ -1,15 +1,15 @@
// MODULE: m1-common
// FILE: common.kt
// TODO: .fir.kt version is just a stub.
-expect interface My {
+expect interface My {
open fun openFunPositive()
- open fun openFunNegative()
+ open fun openFunNegative()
abstract fun abstractFun()
open val openValPositive: Int
- open val openValNegative: Int
+ open val openValNegative: Int
abstract val abstractVal: Int
-}
+}
// MODULE: m1-jvm()()(m1-common)
// FILE: jvm.kt
diff --git a/compiler/testData/diagnostics/tests/multiplatform/generic/typeParameterBoundsDifferentOrderActualMissing.fir.kt b/compiler/testData/diagnostics/tests/multiplatform/generic/typeParameterBoundsDifferentOrderActualMissing.fir.kt
index de2dfec1596..3be85a7a66f 100644
--- a/compiler/testData/diagnostics/tests/multiplatform/generic/typeParameterBoundsDifferentOrderActualMissing.fir.kt
+++ b/compiler/testData/diagnostics/tests/multiplatform/generic/typeParameterBoundsDifferentOrderActualMissing.fir.kt
@@ -4,7 +4,7 @@
interface A
interface B
-expect fun List.foo() where T : A, T : B
+expect fun List.foo() where T : A, T : B
// MODULE: m2-jvm()()(m1-common)
// FILE: jvm.kt
diff --git a/compiler/testData/diagnostics/tests/multiplatform/headerClass/actualClassWithDefaultValuesInAnnotationViaTypealias.fir.kt b/compiler/testData/diagnostics/tests/multiplatform/headerClass/actualClassWithDefaultValuesInAnnotationViaTypealias.fir.kt
index 119fd39e8bf..79722e91845 100644
--- a/compiler/testData/diagnostics/tests/multiplatform/headerClass/actualClassWithDefaultValuesInAnnotationViaTypealias.fir.kt
+++ b/compiler/testData/diagnostics/tests/multiplatform/headerClass/actualClassWithDefaultValuesInAnnotationViaTypealias.fir.kt
@@ -7,7 +7,7 @@ expect annotation class Foo3
expect annotation class Foo4
expect annotation class Foo5()
expect annotation class Foo6()
-expect annotation class Foo7()
+expect annotation class Foo7()
@Foo1
fun foo() {}
diff --git a/compiler/testData/diagnostics/tests/multiplatform/headerClass/actualClassWithDifferentConstructors.fir.kt b/compiler/testData/diagnostics/tests/multiplatform/headerClass/actualClassWithDifferentConstructors.fir.kt
index 649563e8234..3e0480365f3 100644
--- a/compiler/testData/diagnostics/tests/multiplatform/headerClass/actualClassWithDifferentConstructors.fir.kt
+++ b/compiler/testData/diagnostics/tests/multiplatform/headerClass/actualClassWithDifferentConstructors.fir.kt
@@ -5,9 +5,9 @@ expect class Foo1
expect class Foo2
expect class Foo3
-expect class Bar1()
-expect class Bar2()
-expect class Bar3()
+expect class Bar1()
+expect class Bar2()
+expect class Bar3()
expect class Bar4()
expect class Bar5()
expect class Bar6()
diff --git a/compiler/testData/diagnostics/tests/multiplatform/headerClass/expectDeclarationWithStrongIncompatibilities.fir.kt b/compiler/testData/diagnostics/tests/multiplatform/headerClass/expectDeclarationWithStrongIncompatibilities.fir.kt
index 81e53a1036a..98dd465a6bf 100644
--- a/compiler/testData/diagnostics/tests/multiplatform/headerClass/expectDeclarationWithStrongIncompatibilities.fir.kt
+++ b/compiler/testData/diagnostics/tests/multiplatform/headerClass/expectDeclarationWithStrongIncompatibilities.fir.kt
@@ -3,12 +3,12 @@
// FILE: common.kt
expect fun foo1(x: Int)
-expect fun foo2(x: Int)
+expect fun foo2(x: Int)
expect class NoArgConstructor()
-expect fun foo3(): Int
-expect fun foo4(): Int
+expect fun foo3(): Int
+expect fun foo4(): Int
// MODULE: m2-jvm()()(m1-common)
diff --git a/compiler/testData/diagnostics/tests/multiplatform/headerClass/expectFunInterface.fir.kt b/compiler/testData/diagnostics/tests/multiplatform/headerClass/expectFunInterface.fir.kt
index 8720243d056..c52d8a335f4 100644
--- a/compiler/testData/diagnostics/tests/multiplatform/headerClass/expectFunInterface.fir.kt
+++ b/compiler/testData/diagnostics/tests/multiplatform/headerClass/expectFunInterface.fir.kt
@@ -5,9 +5,9 @@ expect fun interface F1 {
fun run()
}
-expect fun interface F2 {
+expect fun interface F2 {
fun run()
-}
+}
expect fun interface F3 {
fun run()
@@ -21,9 +21,9 @@ expect fun interface F5 {
fun run()
}
-expect fun interface F6 {
+expect fun interface F6 {
fun run()
-}
+}
// MODULE: m2-jvm()()(m1-common)
diff --git a/compiler/testData/diagnostics/tests/multiplatform/headerClass/genericClassImplTypeAlias.fir.kt b/compiler/testData/diagnostics/tests/multiplatform/headerClass/genericClassImplTypeAlias.fir.kt
new file mode 100644
index 00000000000..3549d34fdac
--- /dev/null
+++ b/compiler/testData/diagnostics/tests/multiplatform/headerClass/genericClassImplTypeAlias.fir.kt
@@ -0,0 +1,37 @@
+// !DIAGNOSTICS: -ACTUAL_WITHOUT_EXPECT
+// MODULE: m1-common
+// FILE: common.kt
+
+expect class C1
+expect interface C2
+expect interface C3
+expect interface C4
+expect interface C5
+expect interface C6
+expect interface C7
+expect interface C8
+expect interface C9
+expect interface C10
+
+// MODULE: m2-jvm()()(m1-common)
+// FILE: jvm.kt
+
+class A>
+class B
+
+actual typealias C1 = String
+actual typealias C2 = List
+actual typealias C3 = List
+actual typealias C4 = MutableMap
+actual typealias C5 = MutableMap
+actual typealias C51 = MutableMap
+actual typealias C52 = MutableMap
+actual typealias C53 = A>
+actual typealias C54 = B>
+actual typealias C6 = MutableList
+actual typealias C7 = MutableList
+actual typealias C8 = MutableList<*>
+actual typealias C9 = MutableList
+
+typealias Tmp = MutableList
+actual typealias C10 = Tmp
diff --git a/compiler/testData/diagnostics/tests/multiplatform/headerClass/genericClassImplTypeAlias.kt b/compiler/testData/diagnostics/tests/multiplatform/headerClass/genericClassImplTypeAlias.kt
index 65153d15164..804c086a1ae 100644
--- a/compiler/testData/diagnostics/tests/multiplatform/headerClass/genericClassImplTypeAlias.kt
+++ b/compiler/testData/diagnostics/tests/multiplatform/headerClass/genericClassImplTypeAlias.kt
@@ -1,4 +1,3 @@
-// FIR_IDENTICAL
// !DIAGNOSTICS: -ACTUAL_WITHOUT_EXPECT
// MODULE: m1-common
// FILE: common.kt
diff --git a/compiler/testData/diagnostics/tests/multiplatform/headerClass/morePermissiveVisibilityOnActual.fir.kt b/compiler/testData/diagnostics/tests/multiplatform/headerClass/morePermissiveVisibilityOnActual.fir.kt
index f60649f095f..533880d54aa 100644
--- a/compiler/testData/diagnostics/tests/multiplatform/headerClass/morePermissiveVisibilityOnActual.fir.kt
+++ b/compiler/testData/diagnostics/tests/multiplatform/headerClass/morePermissiveVisibilityOnActual.fir.kt
@@ -2,20 +2,20 @@
// MODULE: m1-common
// FILE: common.kt
-expect open class Container {
+expect open class Container {
fun publicFun()
internal fun internalFun1()
internal fun internalFun2()
- internal fun internalFun3()
+ internal fun internalFun3()
protected fun protectedFun1()
protected fun protectedFun2()
- protected fun protectedFun3()
+ protected fun protectedFun3()
- open internal fun openInternalFun()
- open fun openPublicFun()
-}
+ open internal fun openInternalFun()
+ open fun openPublicFun()
+}
// MODULE: m2-jvm()()(m1-common)
diff --git a/compiler/testData/diagnostics/tests/multiplatform/headerClass/nestedClassesWithErrors.fir.kt b/compiler/testData/diagnostics/tests/multiplatform/headerClass/nestedClassesWithErrors.fir.kt
index e43fb12bdaf..9c44aaae50a 100644
--- a/compiler/testData/diagnostics/tests/multiplatform/headerClass/nestedClassesWithErrors.fir.kt
+++ b/compiler/testData/diagnostics/tests/multiplatform/headerClass/nestedClassesWithErrors.fir.kt
@@ -14,9 +14,9 @@ expect class C {
expect inner class I
}
-expect class D {
+expect class D {
class N
-}
+}
expect class E {
class N
diff --git a/compiler/testData/diagnostics/tests/multiplatform/headerClass/noImplKeywordOnMember.fir.kt b/compiler/testData/diagnostics/tests/multiplatform/headerClass/noImplKeywordOnMember.fir.kt
index bd34df5eb05..f25d953ab1d 100644
--- a/compiler/testData/diagnostics/tests/multiplatform/headerClass/noImplKeywordOnMember.fir.kt
+++ b/compiler/testData/diagnostics/tests/multiplatform/headerClass/noImplKeywordOnMember.fir.kt
@@ -1,10 +1,10 @@
// MODULE: m1-common
// FILE: common.kt
-expect class Foo {
+expect class Foo {
fun bar(): String
- fun bas(f: Int)
-}
+ fun bas(f: Int)
+}
// MODULE: m2-jvm()()(m1-common)
// FILE: jvm.kt
diff --git a/compiler/testData/diagnostics/tests/multiplatform/headerClass/superClass.fir.kt b/compiler/testData/diagnostics/tests/multiplatform/headerClass/superClass.fir.kt
index 3e1c7edda7f..1d82857c7a1 100644
--- a/compiler/testData/diagnostics/tests/multiplatform/headerClass/superClass.fir.kt
+++ b/compiler/testData/diagnostics/tests/multiplatform/headerClass/superClass.fir.kt
@@ -7,7 +7,7 @@ interface J
expect class Foo : I, C, J
-expect class Bar : C()
+expect class Bar : C()
// MODULE: m2-jvm()()(m1-common)
// FILE: jvm.kt
diff --git a/compiler/testData/diagnostics/tests/multiplatform/headerFunInNonHeaderClass.fir.kt b/compiler/testData/diagnostics/tests/multiplatform/headerFunInNonHeaderClass.fir.kt
index 14fd83841bc..5745558b1fb 100644
--- a/compiler/testData/diagnostics/tests/multiplatform/headerFunInNonHeaderClass.fir.kt
+++ b/compiler/testData/diagnostics/tests/multiplatform/headerFunInNonHeaderClass.fir.kt
@@ -2,7 +2,7 @@
// FILE: common.kt
class Foo {
- expect fun bar(): String
+ expect fun bar(): String
}
// MODULE: m1-jvm()()(m1-common)
diff --git a/compiler/testData/diagnostics/tests/multiplatform/hmpp/kt57320.fir.kt b/compiler/testData/diagnostics/tests/multiplatform/hmpp/kt57320.fir.kt
index cb24a89785e..2bdb9b24101 100644
--- a/compiler/testData/diagnostics/tests/multiplatform/hmpp/kt57320.fir.kt
+++ b/compiler/testData/diagnostics/tests/multiplatform/hmpp/kt57320.fir.kt
@@ -26,7 +26,7 @@ interface KotlinXStringDemoInterface {
val value: String
}
-expect fun StringDemoInterface.plusK(): String
+expect fun StringDemoInterface.plusK(): String
// MODULE: js()()(common, intermediate)
// TARGET_PLATFORM: JS
@@ -34,7 +34,7 @@ expect fun StringDemoInterface.plusK(): String
// FILE: StringDemoInterface.kt
actual typealias StringDemoInterface = KotlinXStringDemoInterface
-; The following declaration is incompatible: expect fun StringDemoInterface.plusK(): String")!>actual fun StringDemoInterface.plusK() = StringValue(value).plus("K").value
+; The following declaration is incompatible: expect fun StringDemoInterface.plusK(): String")!>actual fun StringDemoInterface.plusK() = StringValue(value).plus("K").value
// FILE: main.kt
class StringDemo(override val value: String) : StringDemoInterface
diff --git a/compiler/testData/diagnostics/tests/multiplatform/hmpp/multiplatformCompositeAnalysis/expectAndActualInTheSameModule.fir.kt b/compiler/testData/diagnostics/tests/multiplatform/hmpp/multiplatformCompositeAnalysis/expectAndActualInTheSameModule.fir.kt
index 35032665242..2835fe5ef79 100644
--- a/compiler/testData/diagnostics/tests/multiplatform/hmpp/multiplatformCompositeAnalysis/expectAndActualInTheSameModule.fir.kt
+++ b/compiler/testData/diagnostics/tests/multiplatform/hmpp/multiplatformCompositeAnalysis/expectAndActualInTheSameModule.fir.kt
@@ -3,10 +3,10 @@
// TARGET_PLATFORM: Common
expect class CommonClass {
- fun memberFun()
- val memberProp: Int
- class Nested
- inner class Inner
+ fun memberFun()
+ val memberProp: Int
+ class Nested
+ inner class Inner
}
actual class CommonClass {
actual fun memberFun() {}
diff --git a/compiler/testData/diagnostics/tests/multiplatform/hmpp/multiplatformCompositeAnalysis/expectAndActualInTheSameModuleIncompatibilities.fir.kt b/compiler/testData/diagnostics/tests/multiplatform/hmpp/multiplatformCompositeAnalysis/expectAndActualInTheSameModuleIncompatibilities.fir.kt
index 798233848b2..6a90ee7255a 100644
--- a/compiler/testData/diagnostics/tests/multiplatform/hmpp/multiplatformCompositeAnalysis/expectAndActualInTheSameModuleIncompatibilities.fir.kt
+++ b/compiler/testData/diagnostics/tests/multiplatform/hmpp/multiplatformCompositeAnalysis/expectAndActualInTheSameModuleIncompatibilities.fir.kt
@@ -13,8 +13,8 @@ val callableKind: Int = 1
expect fun typeParameterCount()
fun typeParameterCount() {}
-expect enum class EnumEntries {
- ONE, TWO;
+expect enum class EnumEntries {
+ ONE, TWO;
}
actual enum class EnumEntries {
ONE;
diff --git a/compiler/testData/diagnostics/tests/multiplatform/java/flexibleTypes.fir.kt b/compiler/testData/diagnostics/tests/multiplatform/java/flexibleTypes.fir.kt
deleted file mode 100644
index 9580ce80604..00000000000
--- a/compiler/testData/diagnostics/tests/multiplatform/java/flexibleTypes.fir.kt
+++ /dev/null
@@ -1,31 +0,0 @@
-// MODULE: m1-common
-// FILE: common.kt
-
-expect class Foo {
- constructor(p: Any)
-
- fun f1(s: String): Int
-
- fun f2(s: List?): MutableMap
-
- fun > f3(t: T): T?
-}
-
-// MODULE: m2-jvm()()(m1-common)
-// FILE: FooImpl.java
-
-import java.util.*;
-
-public class FooImpl {
- public FooImpl(Object p) {}
-
- public final int f1(String s) { return 0; }
-
- public final Map f2(List s) { return null; }
-
- public final > T f3(T t) { return null; }
-}
-
-// FILE: jvm.kt
-
-actual typealias Foo = FooImpl
diff --git a/compiler/testData/diagnostics/tests/multiplatform/java/flexibleTypes.kt b/compiler/testData/diagnostics/tests/multiplatform/java/flexibleTypes.kt
index 8c344f239ed..78871917df9 100644
--- a/compiler/testData/diagnostics/tests/multiplatform/java/flexibleTypes.kt
+++ b/compiler/testData/diagnostics/tests/multiplatform/java/flexibleTypes.kt
@@ -1,3 +1,4 @@
+// FIR_IDENTICAL
// MODULE: m1-common
// FILE: common.kt
diff --git a/compiler/testData/diagnostics/tests/multiplatform/kt54827.fir.kt b/compiler/testData/diagnostics/tests/multiplatform/kt54827.fir.kt
index 015fdeb55c7..34818d4ec5b 100644
--- a/compiler/testData/diagnostics/tests/multiplatform/kt54827.fir.kt
+++ b/compiler/testData/diagnostics/tests/multiplatform/kt54827.fir.kt
@@ -1,8 +1,8 @@
// MODULE: m1-common
// FILE: common.kt
-expect class SomeClass {
+expect class SomeClass {
fun foo()
-}
+}
// MODULE: m1-jvm()()(m1-common)
// FILE: jvm.kt
diff --git a/compiler/testData/diagnostics/tests/multiplatform/topLevelFun/inlineFun.fir.kt b/compiler/testData/diagnostics/tests/multiplatform/topLevelFun/inlineFun.fir.kt
index 94d0de397a4..b2975eb0e8c 100644
--- a/compiler/testData/diagnostics/tests/multiplatform/topLevelFun/inlineFun.fir.kt
+++ b/compiler/testData/diagnostics/tests/multiplatform/topLevelFun/inlineFun.fir.kt
@@ -1,7 +1,7 @@
// MODULE: m1-common
// FILE: common.kt
-inline expect fun inlineFun()
+inline expect fun inlineFun()
expect fun nonInlineFun()
// MODULE: m2-jvm()()(m1-common)
diff --git a/compiler/testData/diagnostics/tests/multiplatform/topLevelFun/valueParameterModifiers.fir.kt b/compiler/testData/diagnostics/tests/multiplatform/topLevelFun/valueParameterModifiers.fir.kt
index 37868b85876..0ccc96ccf1d 100644
--- a/compiler/testData/diagnostics/tests/multiplatform/topLevelFun/valueParameterModifiers.fir.kt
+++ b/compiler/testData/diagnostics/tests/multiplatform/topLevelFun/valueParameterModifiers.fir.kt
@@ -3,15 +3,15 @@
// FILE: common.kt
expect fun f1(s: () -> String)
-expect inline fun f2(s: () -> String)
+expect inline fun f2(s: () -> String)
expect inline fun f3(noinline s: () -> String)
expect fun f4(s: () -> String)
-expect inline fun f5(s: () -> String)
+expect inline fun f5(s: () -> String)
expect inline fun f6(crossinline s: () -> String)
-expect fun f7(x: Any)
-expect fun f8(vararg x: Any)
+expect fun f7(x: Any)
+expect fun f8(vararg x: Any)
// MODULE: m2-jvm()()(m1-common)
// FILE: jvm.kt
diff --git a/compiler/testData/diagnostics/tests/multiplatform/varSetterVisibility.fir.kt b/compiler/testData/diagnostics/tests/multiplatform/varSetterVisibility.fir.kt
index a574d3eeebd..99e67edb724 100644
--- a/compiler/testData/diagnostics/tests/multiplatform/varSetterVisibility.fir.kt
+++ b/compiler/testData/diagnostics/tests/multiplatform/varSetterVisibility.fir.kt
@@ -1,20 +1,20 @@
// MODULE: m1-common
// FILE: common.kt
-expect var v1: Boolean
+expect var v1: Boolean
expect var v2: Boolean
internal set
-expect var v3: Boolean
- internal set
+expect var v3: Boolean
+ internal set
-expect open class C {
- var foo: Boolean
-}
+expect open class C {
+ var foo: Boolean
+}
-expect open class C2 {
- var foo: Boolean
-}
+expect open class C2 {
+ var foo: Boolean
+}
// MODULE: m1-jvm()()(m1-common)
// FILE: jvm.kt
diff --git a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/backend/ir/ActualizerOnlyFacade.kt b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/backend/ir/ActualizerOnlyFacade.kt
index 77b140beb00..067f65e5449 100644
--- a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/backend/ir/ActualizerOnlyFacade.kt
+++ b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/backend/ir/ActualizerOnlyFacade.kt
@@ -6,8 +6,11 @@
package org.jetbrains.kotlin.test.backend.ir
import org.jetbrains.kotlin.backend.common.actualizer.IrActualizer
+import org.jetbrains.kotlin.backend.jvm.JvmIrTypeSystemContext
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.config.languageVersionSettings
+import org.jetbrains.kotlin.ir.types.IrTypeSystemContextImpl
+import org.jetbrains.kotlin.platform.jvm.isJvm
import org.jetbrains.kotlin.test.model.*
import org.jetbrains.kotlin.test.services.TestServices
import org.jetbrains.kotlin.test.services.compilerConfigurationProvider
@@ -17,10 +20,16 @@ class ActualizerOnlyFacade(
) : AbstractTestFacade() {
override fun transform(module: TestModule, inputArtifact: IrBackendInput): IrBackendInput {
if (module.useIrActualizer()) {
+ val builtins = inputArtifact.irModuleFragment.irBuiltins
+ val typeSystemContext = when (module.targetPlatform.isJvm()) {
+ true -> JvmIrTypeSystemContext(builtins)
+ false -> IrTypeSystemContextImpl(builtins)
+ }
IrActualizer.actualize(
inputArtifact.irModuleFragment,
inputArtifact.dependentIrModuleFragments,
inputArtifact.diagnosticReporter,
+ typeSystemContext,
testServices.compilerConfigurationProvider.getCompilerConfiguration(module).languageVersionSettings
)
}
@@ -35,4 +44,4 @@ class ActualizerOnlyFacade(
override val outputKind: TestArtifactKind = BackendKinds.IrBackend
override fun shouldRunAnalysis(module: TestModule): Boolean = true
-}
\ No newline at end of file
+}
diff --git a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/backend/ir/JvmIrBackendFacade.kt b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/backend/ir/JvmIrBackendFacade.kt
index e4f74da819e..b083947d9fc 100644
--- a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/backend/ir/JvmIrBackendFacade.kt
+++ b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/backend/ir/JvmIrBackendFacade.kt
@@ -8,12 +8,14 @@ package org.jetbrains.kotlin.test.backend.ir
import org.jetbrains.kotlin.KtPsiSourceFile
import org.jetbrains.kotlin.backend.common.BackendException
import org.jetbrains.kotlin.backend.common.actualizer.IrActualizer
+import org.jetbrains.kotlin.backend.jvm.JvmIrTypeSystemContext
import org.jetbrains.kotlin.backend.jvm.MultifileFacadeFileEntry
import org.jetbrains.kotlin.backend.jvm.lower.getFileClassInfoFromIrFile
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil
import org.jetbrains.kotlin.ir.PsiIrFileEntry
import org.jetbrains.kotlin.ir.declarations.IrFile
+import org.jetbrains.kotlin.ir.types.IrTypeSystemContextImpl
import org.jetbrains.kotlin.ir.util.NaiveSourceBasedFileEntryImpl
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.test.backend.classic.JavaCompilerFacade
@@ -40,6 +42,7 @@ class JvmIrBackendFacade(
inputArtifact.irModuleFragment,
inputArtifact.dependentIrModuleFragments,
inputArtifact.state.diagnosticReporter,
+ JvmIrTypeSystemContext(inputArtifact.irModuleFragment.irBuiltins),
inputArtifact.state.languageVersionSettings
)
}
diff --git a/core/compiler.common/src/org/jetbrains/kotlin/mpp/DeclarationSymbolMarkers.kt b/core/compiler.common/src/org/jetbrains/kotlin/mpp/DeclarationSymbolMarkers.kt
index 1b45d03ef79..801e090af17 100644
--- a/core/compiler.common/src/org/jetbrains/kotlin/mpp/DeclarationSymbolMarkers.kt
+++ b/core/compiler.common/src/org/jetbrains/kotlin/mpp/DeclarationSymbolMarkers.kt
@@ -17,6 +17,8 @@ interface ConstructorSymbolMarker : FunctionSymbolMarker
interface SimpleFunctionSymbolMarker : FunctionSymbolMarker
interface PropertySymbolMarker : CallableSymbolMarker
interface ValueParameterSymbolMarker : CallableSymbolMarker
+interface FieldSymbolMarker : CallableSymbolMarker
+interface EnumEntrySymbolMarker : CallableSymbolMarker
interface ClassifierSymbolMarker : DeclarationSymbolMarker
interface TypeParameterSymbolMarker : ClassifierSymbolMarker
diff --git a/core/compiler.common/src/org/jetbrains/kotlin/resolve/multiplatform/ExpectActualCompatibility.kt b/core/compiler.common/src/org/jetbrains/kotlin/resolve/multiplatform/ExpectActualCompatibility.kt
index 637aced0cfb..45aabd08d35 100644
--- a/core/compiler.common/src/org/jetbrains/kotlin/resolve/multiplatform/ExpectActualCompatibility.kt
+++ b/core/compiler.common/src/org/jetbrains/kotlin/resolve/multiplatform/ExpectActualCompatibility.kt
@@ -5,6 +5,9 @@
package org.jetbrains.kotlin.resolve.multiplatform
+import kotlin.contracts.ExperimentalContracts
+import kotlin.contracts.contract
+
sealed class ExpectActualCompatibility {
// For IncompatibilityKind.STRONG `actual` declaration is considered as overload and error reports on expected declaration
enum class IncompatibilityKind {
@@ -95,3 +98,11 @@ sealed class ExpectActualCompatibility {
val ExpectActualCompatibility<*>.compatible: Boolean
get() = this == ExpectActualCompatibility.Compatible
+
+@OptIn(ExperimentalContracts::class)
+fun ExpectActualCompatibility<*>.isIncompatible(): Boolean {
+ contract {
+ returns(true) implies (this@isIncompatible is ExpectActualCompatibility.Incompatible<*>)
+ }
+ return !compatible
+}
diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/converters/FirJsKlibBackendFacade.kt b/js/js.tests/test/org/jetbrains/kotlin/js/test/converters/FirJsKlibBackendFacade.kt
index a3a1db75061..1dbfaaf428e 100644
--- a/js/js.tests/test/org/jetbrains/kotlin/js/test/converters/FirJsKlibBackendFacade.kt
+++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/converters/FirJsKlibBackendFacade.kt
@@ -16,6 +16,7 @@ import org.jetbrains.kotlin.incremental.components.LookupTracker
import org.jetbrains.kotlin.ir.backend.js.JsFactories
import org.jetbrains.kotlin.ir.backend.js.resolverLogger
import org.jetbrains.kotlin.ir.backend.js.serializeModuleIntoKlib
+import org.jetbrains.kotlin.ir.types.IrTypeSystemContextImpl
import org.jetbrains.kotlin.ir.util.IrMessageLogger
import org.jetbrains.kotlin.js.test.utils.JsIrIncrementalDataProvider
import org.jetbrains.kotlin.js.test.utils.jsIrIncrementalDataProvider
@@ -71,6 +72,7 @@ class FirJsKlibBackendFacade(
inputArtifact.irModuleFragment,
inputArtifact.dependentIrModuleFragments,
diagnosticReporter,
+ IrTypeSystemContextImpl(inputArtifact.irModuleFragment.irBuiltins),
configuration.languageVersionSettings
)
} else {
@@ -124,4 +126,4 @@ class FirJsKlibBackendFacade(
return BinaryArtifacts.KLib(File(outputFile))
}
-}
\ No newline at end of file
+}
diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Fir2Ir.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Fir2Ir.kt
index 390a4810c49..5f400527a29 100644
--- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Fir2Ir.kt
+++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Fir2Ir.kt
@@ -31,6 +31,7 @@ import org.jetbrains.kotlin.fir.signaturer.Ir2FirManglerAdapter
import org.jetbrains.kotlin.incremental.components.LookupTracker
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
import org.jetbrains.kotlin.ir.declarations.IrExternalPackageFragment
+import org.jetbrains.kotlin.ir.types.IrTypeSystemContextImpl
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.visitors.acceptVoid
import org.jetbrains.kotlin.library.metadata.KlibMetadataFactories
@@ -87,6 +88,7 @@ internal fun PhaseContext.fir2Ir(
visibilityConverter = Fir2IrVisibilityConverter.Default,
diagnosticReporter = diagnosticsReporter,
kotlinBuiltIns = builtInsModule ?: DefaultBuiltIns.Instance,
+ actualizerTypeContextProvider = ::IrTypeSystemContextImpl,
fir2IrResultPostCompute = {
// it's important to compare manglers before actualization, since IR will be actualized, while FIR won't
irModuleFragment.acceptVoid(