| // TARGET_BACKEND: NATIVE |
| // DISABLE_NATIVE: isAppleTarget=false |
| // IGNORE_KLIB_RUNTIME_ERRORS_WITH_CUSTOM_FIRST_STAGE: Native:1.9,2.0,2.1,2.2,2.3,2.4 |
| // IGNORE_KLIB_RUNTIME_ERRORS_WITH_CUSTOM_SECOND_STAGE: Native:1.9,2.0,2.1,2.2,2.3,2.4 |
| // ^^^KT-77446 is fixed in 2.4.20-Beta1 |
| |
| // KT-77446: a Kotlin class subclassing an Objective-C class whose -init is declared unavailable |
| // must not crash when constructed via another initializer that internally dispatches through |
| // [self init]. AVPlayerItem.initWithAsset:automaticallyLoadedAssetKeys: is one real-world case; |
| // this test reproduces the same shape with a local ObjC base class so the test does not depend |
| // on AVFoundation host behavior. |
| |
| // MODULE: objclib |
| // FILE: objclib.def |
| language = Objective-C |
| headers = objclib.h |
| headerFilter = objclib.h |
| |
| // FILE: objclib.h |
| #import <Foundation/Foundation.h> |
| |
| @interface ObjCBase : NSObject |
| - (instancetype)init __attribute__((unavailable)); |
| - (instancetype)initWithValue:(int)value; |
| @property (nonatomic, readonly) int storedValue; |
| @end |
| |
| // FILE: objclib.m |
| #import "objclib.h" |
| |
| @implementation ObjCBase { |
| int _storedValue; |
| } |
| |
| - (instancetype)init { |
| return [super init]; |
| } |
| |
| - (instancetype)initWithValue:(int)value { |
| self = [self init]; // This is the path that hit MissingInitImp before KT-77446 was fixed. |
| if (self) { |
| _storedValue = value; |
| } |
| return self; |
| } |
| |
| - (int)storedValue { |
| return _storedValue; |
| } |
| |
| @end |
| |
| // MODULE: main(objclib) |
| // FILE: main.kt |
| @file:OptIn(kotlinx.cinterop.BetaInteropApi::class, kotlinx.cinterop.ExperimentalForeignApi::class) |
| |
| import kotlinx.cinterop.ObjCObjectBase.OverrideInit |
| import objclib.ObjCBase |
| |
| class KotlinSubclass : ObjCBase { |
| @OverrideInit |
| constructor(value: Int) : super(value = value) |
| } |
| |
| fun box(): String { |
| val obj = KotlinSubclass(value = 42) |
| if (obj.storedValue() != 42) return "FAIL: storedValue=${obj.storedValue()}" |
| return "OK" |
| } |