[K/N] Implement objc overridablity condition for IR
^KT-61511
This commit is contained in:
committed by
Space Team
parent
202f30f910
commit
156c341eeb
+14
-3
@@ -26,11 +26,15 @@ import org.jetbrains.kotlin.fir.backend.*
|
||||
import org.jetbrains.kotlin.fir.backend.native.FirNativeKotlinMangler
|
||||
import org.jetbrains.kotlin.fir.descriptors.FirModuleDescriptor
|
||||
import org.jetbrains.kotlin.fir.pipeline.convertToIrAndActualize
|
||||
import org.jetbrains.kotlin.fir.references.FirReference
|
||||
import org.jetbrains.kotlin.fir.signaturer.Ir2FirManglerAdapter
|
||||
import org.jetbrains.kotlin.incremental.components.LookupTracker
|
||||
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
|
||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
|
||||
import org.jetbrains.kotlin.ir.declarations.IrExternalPackageFragment
|
||||
import org.jetbrains.kotlin.ir.declarations.IrMemberWithContainerSource
|
||||
import org.jetbrains.kotlin.ir.objcinterop.IrObjCOverridabilityCondition
|
||||
import org.jetbrains.kotlin.ir.types.IrTypeSystemContextImpl
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.ir.visitors.acceptVoid
|
||||
@@ -40,11 +44,18 @@ import org.jetbrains.kotlin.storage.LockBasedStorageManager
|
||||
|
||||
internal val KlibFactories = KlibMetadataFactories(::KonanBuiltIns, DynamicTypeDeserializer)
|
||||
|
||||
internal object NativeFir2IrExtensions : Fir2IrExtensions {
|
||||
override val irNeedsDeserialization = false
|
||||
override val externalOverridabilityConditions = listOf(IrObjCOverridabilityCondition)
|
||||
override fun generateOrGetFacadeClass(declaration: IrMemberWithContainerSource, components: Fir2IrComponents) = null
|
||||
override fun deserializeToplevelClass(irClass: IrClass, components: Fir2IrComponents) = false
|
||||
override fun registerDeclarations(symbolTable: SymbolTable) {}
|
||||
override fun findInjectedValue(calleeReference: FirReference, conversionScope: Fir2IrConversionScope) = null
|
||||
}
|
||||
|
||||
internal fun PhaseContext.fir2Ir(
|
||||
input: FirOutput.Full,
|
||||
): Fir2IrOutput {
|
||||
val fir2IrExtensions = Fir2IrExtensions.Default
|
||||
|
||||
var builtInsModule: KotlinBuiltIns? = null
|
||||
|
||||
val resolvedLibraries = config.resolvedLibraries.getFullResolvedList()
|
||||
@@ -85,7 +96,7 @@ internal fun PhaseContext.fir2Ir(
|
||||
useIrFakeOverrideBuilder = configuration.getBoolean(CommonConfigurationKeys.USE_IR_FAKE_OVERRIDE_BUILDER),
|
||||
)
|
||||
val (irModuleFragment, components, pluginContext, irActualizedResult) = input.firResult.convertToIrAndActualize(
|
||||
fir2IrExtensions,
|
||||
NativeFir2IrExtensions,
|
||||
fir2IrConfiguration,
|
||||
IrGenerationExtension.getInstances(config.project),
|
||||
signatureComposer = DescriptorSignatureComposerStub(KonanManglerDesc),
|
||||
|
||||
+1
@@ -172,6 +172,7 @@ class KonanDriver(
|
||||
copy(BinaryOptions.objcExportDisableSwiftMemberNameMangling)
|
||||
copy(BinaryOptions.objcExportIgnoreInterfaceMethodCollisions)
|
||||
copy(KonanConfigKeys.OBJC_GENERICS)
|
||||
copy(CommonConfigurationKeys.USE_IR_FAKE_OVERRIDE_BUILDER)
|
||||
}
|
||||
|
||||
// For the second stage, remove already compiled source files from the configuration.
|
||||
|
||||
+3
-1
@@ -27,6 +27,7 @@ import org.jetbrains.kotlin.ir.builders.TranslationPluginContext
|
||||
import org.jetbrains.kotlin.ir.declarations.DescriptorMetadataSource
|
||||
import org.jetbrains.kotlin.ir.linkage.IrDeserializer
|
||||
import org.jetbrains.kotlin.ir.linkage.partial.partialLinkageConfig
|
||||
import org.jetbrains.kotlin.ir.objcinterop.IrObjCOverridabilityCondition
|
||||
import org.jetbrains.kotlin.ir.symbols.IrSymbol
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.ir.visitors.acceptVoid
|
||||
@@ -154,7 +155,8 @@ internal fun PsiToIrContext.psiToIr(
|
||||
cachedLibraries = config.cachedLibraries,
|
||||
lazyIrForCaches = config.lazyIrForCaches,
|
||||
libraryBeingCached = config.libraryToCache,
|
||||
userVisibleIrModulesSupport = config.userVisibleIrModulesSupport
|
||||
userVisibleIrModulesSupport = config.userVisibleIrModulesSupport,
|
||||
externalOverridabilityConditions = listOf(IrObjCOverridabilityCondition)
|
||||
).also { linker ->
|
||||
|
||||
// context.config.librariesWithDependencies could change at each iteration.
|
||||
|
||||
+5
-2
@@ -39,6 +39,7 @@ import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
|
||||
import org.jetbrains.kotlin.ir.builders.TranslationPluginContext
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.declarations.lazy.IrLazyClass
|
||||
import org.jetbrains.kotlin.ir.overrides.IrExternalOverridabilityCondition
|
||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrPublicSymbolBase
|
||||
import org.jetbrains.kotlin.ir.types.IrTypeSystemContextImpl
|
||||
@@ -306,7 +307,8 @@ internal class KonanIrLinker(
|
||||
private val cachedLibraries: CachedLibraries,
|
||||
private val lazyIrForCaches: Boolean,
|
||||
private val libraryBeingCached: PartialCacheInfo?,
|
||||
override val userVisibleIrModulesSupport: UserVisibleIrModulesSupport
|
||||
override val userVisibleIrModulesSupport: UserVisibleIrModulesSupport,
|
||||
externalOverridabilityConditions: List<IrExternalOverridabilityCondition>,
|
||||
) : KotlinIrLinker(currentModule, messageLogger, builtIns, symbolTable, exportedDependencies) {
|
||||
override fun isBuiltInModule(moduleDescriptor: ModuleDescriptor): Boolean = moduleDescriptor.isNativeStdlib()
|
||||
|
||||
@@ -321,7 +323,8 @@ internal class KonanIrLinker(
|
||||
typeSystem = IrTypeSystemContextImpl(builtIns),
|
||||
friendModules = friendModules,
|
||||
partialLinkageSupport = partialLinkageSupport,
|
||||
platformSpecificClassFilter = KonanFakeOverrideClassFilter
|
||||
platformSpecificClassFilter = KonanFakeOverrideClassFilter,
|
||||
externalOverridabilityConditions = externalOverridabilityConditions,
|
||||
)
|
||||
|
||||
val moduleDeserializers = mutableMapOf<ModuleDescriptor, KonanPartialModuleDeserializer>()
|
||||
|
||||
@@ -4101,6 +4101,11 @@ if (PlatformInfo.isAppleTarget(project)) {
|
||||
createInterop("kt59167") {
|
||||
it.defFile 'interop/kt59167/kt59167.def'
|
||||
}
|
||||
createInterop("overridabilityCondition") {
|
||||
it.defFile 'interop/objc/overridabilityCondition/lib.def'
|
||||
it.headers "$projectDir/interop/objc/overridabilityCondition/lib.h"
|
||||
it.extraOpts "-Xcompile-source", "$projectDir/interop/objc/overridabilityCondition/lib.m"
|
||||
}
|
||||
}
|
||||
|
||||
createInterop("withSpaces") {
|
||||
@@ -4673,6 +4678,12 @@ if (PlatformInfo.isAppleTarget(project)) {
|
||||
interop = "objcDirect"
|
||||
}
|
||||
|
||||
interopTest("interop_objc_overridabilityCondition") {
|
||||
interop = "overridabilityCondition"
|
||||
source = "interop/objc/overridabilityCondition/main.kt"
|
||||
flags = [ "-Xuse-ir-fake-override-builder" ]
|
||||
}
|
||||
|
||||
interopTest("interop_objc_foreignException") {
|
||||
source = "interop/objc/foreignException/objc_wrap.kt"
|
||||
interop = 'foreignException'
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
language = Objective-C
|
||||
headersFilter = **/lib.h
|
||||
@@ -0,0 +1,10 @@
|
||||
#import <Foundation/NSObject.h>
|
||||
#import <Foundation/NSDate.h>
|
||||
#import <Foundation/NSUUID.h>
|
||||
|
||||
@interface ObjCClass : NSObject
|
||||
- (NSString*)fooWithArg:(int)arg arg2:(NSString*)arg2;
|
||||
- (NSString*)fooWithArg:(int)ohNoOtherName name2:(NSString*)name2;
|
||||
- (NSString*)fooWithArg:(int)arg name3:(NSString*)name3;
|
||||
@end
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
#import "lib.h"
|
||||
|
||||
@implementation ObjCClass {
|
||||
}
|
||||
|
||||
- (NSString*)fooWithArg:(int)arg arg2:(NSString*)arg2 {
|
||||
return @"A";
|
||||
}
|
||||
|
||||
- (NSString*)fooWithArg:(int)ohNoOtherName name2:(NSString*)name2 {
|
||||
return @"B";
|
||||
}
|
||||
|
||||
- (NSString*)fooWithArg:(int)arg name3:(NSString*)name3 {
|
||||
return @"C";
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,54 @@
|
||||
@file:OptIn(kotlinx.cinterop.ExperimentalForeignApi::class)
|
||||
|
||||
import lib.ObjCClass
|
||||
|
||||
@Suppress("CONFLICTING_OVERLOADS")
|
||||
class OverrideAll : ObjCClass() {
|
||||
override fun fooWithArg(arg: Int, arg2: String?) = "D"
|
||||
override fun fooWithArg(ohNoOtherName: Int, name2: String?) = "E"
|
||||
override fun fooWithArg(arg: Int, name3: String?) = "F"
|
||||
}
|
||||
|
||||
@Suppress("CONFLICTING_OVERLOADS")
|
||||
class OverrideNone : ObjCClass() {
|
||||
}
|
||||
|
||||
@Suppress("CONFLICTING_OVERLOADS")
|
||||
class OverrideOne : ObjCClass() {
|
||||
override fun fooWithArg(arg: Int, arg2: String?) = "G"
|
||||
}
|
||||
|
||||
@Suppress("CONFLICTING_OVERLOADS")
|
||||
class OverrideWithDifferentFirstArgName : ObjCClass() {
|
||||
override fun fooWithArg(a: Int, arg2: String?) = "H"
|
||||
override fun fooWithArg(b: Int, name2: String?) = "I"
|
||||
override fun fooWithArg(c: Int, name3: String?) = "J"
|
||||
}
|
||||
|
||||
fun test(x: ObjCClass, expected: String) {
|
||||
val res = x.fooWithArg(arg = 0, arg2 = "") +
|
||||
x.fooWithArg(ohNoOtherName = 0, name2="") +
|
||||
x.fooWithArg(arg = 0, name3 = "")
|
||||
if (res != expected) throw IllegalStateException("Fail ${x::class}: ${res} instead of $expected")
|
||||
}
|
||||
|
||||
fun main() {
|
||||
test(ObjCClass(), "ABC")
|
||||
test(OverrideAll(), "DEF")
|
||||
test(OverrideNone(), "ABC")
|
||||
test(OverrideOne(), "GBC")
|
||||
test(OverrideWithDifferentFirstArgName(), "HIJ")
|
||||
|
||||
// Also test non-virtual calls
|
||||
val x1 = OverrideAll()
|
||||
val res1 = x1.fooWithArg(arg = 0, arg2 = "") +
|
||||
x1.fooWithArg(ohNoOtherName = 0, name2="") +
|
||||
x1.fooWithArg(arg = 0, name3 = "")
|
||||
if (res1 != "DEF") throw IllegalStateException("Fail OverrideAll non-virtual: ${res1} instead of DEF")
|
||||
|
||||
val x2 = OverrideNone()
|
||||
val res2 = x2.fooWithArg(arg = 0, arg2 = "") +
|
||||
x2.fooWithArg(ohNoOtherName = 0, name2="") +
|
||||
x2.fooWithArg(arg = 0, name3 = "")
|
||||
if (res2 != "ABC") throw IllegalStateException("Fail OverrideNone non-virtual: ${res2} instead of ABC")
|
||||
}
|
||||
Reference in New Issue
Block a user