Simplify calling primitive and nullable @Throws from Swift

Prefer Swift code simplicity over following Obj-C conventions
This commit is contained in:
Svyatoslav Scherbina
2020-02-06 16:37:09 +03:00
committed by SvyatoslavScherbina
parent cd9812b504
commit 537188fce8
7 changed files with 67 additions and 84 deletions
@@ -755,8 +755,6 @@ private fun ObjCExportCodeGenerator.generateObjCImp(
} }
var errorOutPtr: LLVMValueRef? = null var errorOutPtr: LLVMValueRef? = null
var kotlinResultOutPtr: LLVMValueRef? = null
lateinit var kotlinResultOutBridge: TypeBridge
val kotlinArgs = methodBridge.paramBridges.mapIndexedNotNull { index, paramBridge -> val kotlinArgs = methodBridge.paramBridges.mapIndexedNotNull { index, paramBridge ->
val parameter = param(index) val parameter = param(index)
@@ -774,13 +772,6 @@ private fun ObjCExportCodeGenerator.generateObjCImp(
errorOutPtr = parameter errorOutPtr = parameter
null null
} }
is MethodBridgeValueParameter.KotlinResultOutParameter -> {
assert(kotlinResultOutPtr == null)
kotlinResultOutPtr = parameter
kotlinResultOutBridge = paramBridge.bridge
null
}
} }
} }
@@ -803,12 +794,12 @@ private fun ObjCExportCodeGenerator.generateObjCImp(
MethodBridge.ReturnValue.WithError.Success -> Int8(0).llvm // false MethodBridge.ReturnValue.WithError.Success -> Int8(0).llvm // false
is MethodBridge.ReturnValue.WithError.RefOrNull -> { is MethodBridge.ReturnValue.WithError.ZeroForError -> {
if (returnType.successBridge == MethodBridge.ReturnValue.Instance.InitResult) { if (returnType.successBridge == MethodBridge.ReturnValue.Instance.InitResult) {
// Release init receiver, as required by convention. // Release init receiver, as required by convention.
callFromBridge(objcRelease, listOf(param(0))) callFromBridge(objcRelease, listOf(param(0)))
} }
kNullInt8Ptr Zero(returnType.objCType(context)).llvm
} }
} }
@@ -818,13 +809,6 @@ private fun ObjCExportCodeGenerator.generateObjCImp(
val targetResult = callKotlin(kotlinArgs, Lifetime.ARGUMENT, exceptionHandler) val targetResult = callKotlin(kotlinArgs, Lifetime.ARGUMENT, exceptionHandler)
kotlinResultOutPtr?.let {
ifThen(icmpNe(it, LLVMConstNull(it.type)!!)) {
val objCResult = kotlinToObjC(targetResult!!, kotlinResultOutBridge)
store(objCResult, it)
}
}
tailrec fun genReturnValueOnSuccess(returnBridge: MethodBridge.ReturnValue): LLVMValueRef? = when (returnBridge) { tailrec fun genReturnValueOnSuccess(returnBridge: MethodBridge.ReturnValue): LLVMValueRef? = when (returnBridge) {
MethodBridge.ReturnValue.Void -> null MethodBridge.ReturnValue.Void -> null
MethodBridge.ReturnValue.HashCode -> { MethodBridge.ReturnValue.HashCode -> {
@@ -833,7 +817,7 @@ private fun ObjCExportCodeGenerator.generateObjCImp(
} }
is MethodBridge.ReturnValue.Mapped -> kotlinToObjC(targetResult!!, returnBridge.bridge) is MethodBridge.ReturnValue.Mapped -> kotlinToObjC(targetResult!!, returnBridge.bridge)
MethodBridge.ReturnValue.WithError.Success -> Int8(1).llvm // true MethodBridge.ReturnValue.WithError.Success -> Int8(1).llvm // true
is MethodBridge.ReturnValue.WithError.RefOrNull -> genReturnValueOnSuccess(returnBridge.successBridge) is MethodBridge.ReturnValue.WithError.ZeroForError -> genReturnValueOnSuccess(returnBridge.successBridge)
MethodBridge.ReturnValue.Instance.InitResult -> param(0) MethodBridge.ReturnValue.Instance.InitResult -> param(0)
MethodBridge.ReturnValue.Instance.FactoryResult -> kotlinReferenceToObjC(targetResult!!) // provided by [callKotlin] MethodBridge.ReturnValue.Instance.FactoryResult -> kotlinReferenceToObjC(targetResult!!) // provided by [callKotlin]
} }
@@ -904,8 +888,6 @@ private fun ObjCExportCodeGenerator.generateKotlinToObjCBridge(
val result = generateFunction(codegen, functionType, "kotlin2objc") { val result = generateFunction(codegen, functionType, "kotlin2objc") {
var errorOutPtr: LLVMValueRef? = null var errorOutPtr: LLVMValueRef? = null
var kotlinResultOutPtr: LLVMValueRef? = null
lateinit var kotlinResultOutBridge: TypeBridge
val parameters = irFunction.allParameters.mapIndexed { index, parameterDescriptor -> val parameters = irFunction.allParameters.mapIndexed { index, parameterDescriptor ->
parameterDescriptor to param(index) parameterDescriptor to param(index)
@@ -937,12 +919,9 @@ private fun ObjCExportCodeGenerator.generateKotlinToObjCBridge(
error("Method is not instance and thus can't have bridge for overriding: $baseMethod") error("Method is not instance and thus can't have bridge for overriding: $baseMethod")
MethodBridgeValueParameter.ErrorOutParameter -> MethodBridgeValueParameter.ErrorOutParameter ->
alloca(int8TypePtr).also { errorOutPtr = it } alloca(int8TypePtr).also {
store(kNullInt8Ptr, it)
is MethodBridgeValueParameter.KotlinResultOutParameter -> errorOutPtr = it
alloca(bridge.bridge.objCType).also {
kotlinResultOutPtr = it
kotlinResultOutBridge = bridge.bridge
} }
} }
} }
@@ -981,17 +960,20 @@ private fun ObjCExportCodeGenerator.generateKotlinToObjCBridge(
ifThen(icmpEq(targetResult, Int8(0).llvm)) { ifThen(icmpEq(targetResult, Int8(0).llvm)) {
rethrow() rethrow()
} }
null
kotlinResultOutPtr?.let {
objCToKotlin(load(it), kotlinResultOutBridge, lifetime)
}
} }
is MethodBridge.ReturnValue.WithError.RefOrNull -> { is MethodBridge.ReturnValue.WithError.ZeroForError -> {
ifThen(icmpEq(targetResult, kNullInt8Ptr)) { if (returnBridge.successMayBeZero) {
rethrow() val error = load(errorOutPtr!!)
ifThen(icmpNe(error, kNullInt8Ptr)) {
rethrow()
}
} else {
ifThen(icmpEq(targetResult, kNullInt8Ptr)) {
rethrow()
}
} }
assert(kotlinResultOutPtr == null)
genKotlinBaseMethodResult(lifetime, returnBridge.successBridge) genKotlinBaseMethodResult(lifetime, returnBridge.successBridge)
} }
@@ -1446,7 +1428,6 @@ private val MethodBridgeParameter.objCType: LLVMTypeRef get() = when (this) {
is MethodBridgeReceiver -> ReferenceBridge.objCType is MethodBridgeReceiver -> ReferenceBridge.objCType
MethodBridgeSelector -> int8TypePtr MethodBridgeSelector -> int8TypePtr
MethodBridgeValueParameter.ErrorOutParameter -> pointerType(ReferenceBridge.objCType) MethodBridgeValueParameter.ErrorOutParameter -> pointerType(ReferenceBridge.objCType)
is MethodBridgeValueParameter.KotlinResultOutParameter -> pointerType(this.bridge.objCType)
} }
private fun MethodBridge.ReturnValue.objCType(context: Context): LLVMTypeRef { private fun MethodBridge.ReturnValue.objCType(context: Context): LLVMTypeRef {
@@ -1457,8 +1438,8 @@ private fun MethodBridge.ReturnValue.objCType(context: Context): LLVMTypeRef {
MethodBridge.ReturnValue.WithError.Success -> ObjCValueType.BOOL.llvmType MethodBridge.ReturnValue.WithError.Success -> ObjCValueType.BOOL.llvmType
MethodBridge.ReturnValue.Instance.InitResult, MethodBridge.ReturnValue.Instance.InitResult,
MethodBridge.ReturnValue.Instance.FactoryResult, MethodBridge.ReturnValue.Instance.FactoryResult -> ReferenceBridge.objCType
is MethodBridge.ReturnValue.WithError.RefOrNull -> ReferenceBridge.objCType is MethodBridge.ReturnValue.WithError.ZeroForError -> this.successBridge.objCType(context)
} }
} }
@@ -1503,8 +1484,8 @@ private fun MethodBridge.ReturnValue.getObjCEncoding(targetFamily: Family): Stri
MethodBridge.ReturnValue.WithError.Success -> ObjCValueType.BOOL.encoding MethodBridge.ReturnValue.WithError.Success -> ObjCValueType.BOOL.encoding
MethodBridge.ReturnValue.Instance.InitResult, MethodBridge.ReturnValue.Instance.InitResult,
MethodBridge.ReturnValue.Instance.FactoryResult, MethodBridge.ReturnValue.Instance.FactoryResult -> ReferenceBridge.objCEncoding
is MethodBridge.ReturnValue.WithError.RefOrNull -> ReferenceBridge.objCEncoding is MethodBridge.ReturnValue.WithError.ZeroForError -> this.successBridge.getObjCEncoding(targetFamily)
} }
private val MethodBridgeParameter.objCEncoding: String get() = when (this) { private val MethodBridgeParameter.objCEncoding: String get() = when (this) {
@@ -1512,7 +1493,6 @@ private val MethodBridgeParameter.objCEncoding: String get() = when (this) {
is MethodBridgeReceiver -> ReferenceBridge.objCEncoding is MethodBridgeReceiver -> ReferenceBridge.objCEncoding
MethodBridgeSelector -> ":" MethodBridgeSelector -> ":"
MethodBridgeValueParameter.ErrorOutParameter -> "^${ReferenceBridge.objCEncoding}" MethodBridgeValueParameter.ErrorOutParameter -> "^${ReferenceBridge.objCEncoding}"
is MethodBridgeValueParameter.KotlinResultOutParameter -> "^${this.bridge.objCEncoding}"
} }
private val TypeBridge.objCEncoding: String get() = when (this) { private val TypeBridge.objCEncoding: String get() = when (this) {
@@ -35,7 +35,6 @@ internal object MethodBridgeSelector : MethodBridgeParameter()
internal sealed class MethodBridgeValueParameter : MethodBridgeParameter() { internal sealed class MethodBridgeValueParameter : MethodBridgeParameter() {
data class Mapped(val bridge: TypeBridge) : MethodBridgeValueParameter() data class Mapped(val bridge: TypeBridge) : MethodBridgeValueParameter()
object ErrorOutParameter : MethodBridgeValueParameter() object ErrorOutParameter : MethodBridgeValueParameter()
data class KotlinResultOutParameter(val bridge: TypeBridge) : MethodBridgeValueParameter()
} }
internal data class MethodBridge( internal data class MethodBridge(
@@ -55,7 +54,7 @@ internal data class MethodBridge(
sealed class WithError : ReturnValue() { sealed class WithError : ReturnValue() {
object Success : WithError() object Success : WithError()
data class RefOrNull(val successBridge: ReturnValue) : WithError() data class ZeroForError(val successBridge: ReturnValue, val successMayBeZero: Boolean) : WithError()
} }
} }
@@ -87,8 +86,7 @@ internal fun MethodBridge.valueParametersAssociated(
when (it) { when (it) {
is MethodBridgeValueParameter.Mapped -> it to kotlinParameters.next() is MethodBridgeValueParameter.Mapped -> it to kotlinParameters.next()
is MethodBridgeValueParameter.ErrorOutParameter, is MethodBridgeValueParameter.ErrorOutParameter -> it to null
is MethodBridgeValueParameter.KotlinResultOutParameter -> it to null
} }
}.also { assert(!kotlinParameters.hasNext()) } }.also { assert(!kotlinParameters.hasNext()) }
} }
@@ -103,8 +101,7 @@ internal fun MethodBridge.parametersAssociated(
is MethodBridgeValueParameter.Mapped, MethodBridgeReceiver.Instance -> is MethodBridgeValueParameter.Mapped, MethodBridgeReceiver.Instance ->
it to kotlinParameters.next() it to kotlinParameters.next()
MethodBridgeReceiver.Static, MethodBridgeSelector, MethodBridgeValueParameter.ErrorOutParameter, MethodBridgeReceiver.Static, MethodBridgeSelector, MethodBridgeValueParameter.ErrorOutParameter ->
is MethodBridgeValueParameter.KotlinResultOutParameter ->
it to null it to null
MethodBridgeReceiver.Factory -> { MethodBridgeReceiver.Factory -> {
@@ -15,7 +15,6 @@ import org.jetbrains.kotlin.builtins.getReturnTypeFromFunctionType
import org.jetbrains.kotlin.builtins.getValueParameterTypesFromFunctionType import org.jetbrains.kotlin.builtins.getValueParameterTypesFromFunctionType
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.resolve.constants.ArrayValue import org.jetbrains.kotlin.resolve.constants.ArrayValue
import org.jetbrains.kotlin.resolve.constants.KClassValue import org.jetbrains.kotlin.resolve.constants.KClassValue
import org.jetbrains.kotlin.resolve.deprecation.Deprecation import org.jetbrains.kotlin.resolve.deprecation.Deprecation
@@ -582,7 +581,6 @@ internal class ObjCExportTranslatorImpl(
} }
} }
MethodBridgeValueParameter.ErrorOutParameter -> "error" MethodBridgeValueParameter.ErrorOutParameter -> "error"
is MethodBridgeValueParameter.KotlinResultOutParameter -> "result"
} }
val uniqueName = unifyName(candidateName, usedNames) val uniqueName = unifyName(candidateName, usedNames)
@@ -592,15 +590,6 @@ internal class ObjCExportTranslatorImpl(
is MethodBridgeValueParameter.Mapped -> mapType(p!!.type, bridge.bridge, objCExportScope) is MethodBridgeValueParameter.Mapped -> mapType(p!!.type, bridge.bridge, objCExportScope)
MethodBridgeValueParameter.ErrorOutParameter -> MethodBridgeValueParameter.ErrorOutParameter ->
ObjCPointerType(ObjCNullableReferenceType(ObjCClassType("NSError")), nullable = true) ObjCPointerType(ObjCNullableReferenceType(ObjCClassType("NSError")), nullable = true)
is MethodBridgeValueParameter.KotlinResultOutParameter -> {
val resultType = mapType(method.returnType!!, bridge.bridge, objCExportScope)
// Note: non-nullable reference or pointer type is unusable here
// when passing reference to local variable from Swift because it
// would require a non-null initializer then.
val pointeeType = resultType.makeNullableIfReferenceOrPointer()
ObjCPointerType(pointeeType, nullable = true)
}
} }
parameters += ObjCParameter(uniqueName, p, type) parameters += ObjCParameter(uniqueName, p, type)
@@ -621,6 +610,14 @@ internal class ObjCExportTranslatorImpl(
val attributes = mutableListOf<String>() val attributes = mutableListOf<String>()
attributes += swiftNameAttribute(swiftName) attributes += swiftNameAttribute(swiftName)
if (baseMethodBridge.returnBridge is MethodBridge.ReturnValue.WithError.ZeroForError
&& baseMethodBridge.returnBridge.successMayBeZero) {
// Method may return zero on success, but
// standard Objective-C convention doesn't suppose this happening.
// Add non-standard convention hint for Swift:
attributes += "swift_error(nonnull_error)" // Means "failure <=> (error != nil)".
}
if (method is ConstructorDescriptor && !method.constructedClass.isArray) { // TODO: check methodBridge instead. if (method is ConstructorDescriptor && !method.constructedClass.isArray) { // TODO: check methodBridge instead.
attributes += "objc_designated_initializer" attributes += "objc_designated_initializer"
@@ -659,11 +656,17 @@ internal class ObjCExportTranslatorImpl(
MethodBridge.ReturnValue.HashCode -> ObjCPrimitiveType.NSUInteger MethodBridge.ReturnValue.HashCode -> ObjCPrimitiveType.NSUInteger
is MethodBridge.ReturnValue.Mapped -> mapType(method.returnType!!, returnBridge.bridge, objCExportScope) is MethodBridge.ReturnValue.Mapped -> mapType(method.returnType!!, returnBridge.bridge, objCExportScope)
MethodBridge.ReturnValue.WithError.Success -> ObjCPrimitiveType.BOOL MethodBridge.ReturnValue.WithError.Success -> ObjCPrimitiveType.BOOL
is MethodBridge.ReturnValue.WithError.RefOrNull -> { is MethodBridge.ReturnValue.WithError.ZeroForError -> {
val successReturnType = mapReturnType(returnBridge.successBridge, method, objCExportScope) as? ObjCNonNullReferenceType val successReturnType = mapReturnType(returnBridge.successBridge, method, objCExportScope)
?: error("Function is expected to have non-null return type: $method")
ObjCNullableReferenceType(successReturnType) if (!returnBridge.successMayBeZero) {
check(successReturnType is ObjCNonNullReferenceType
|| (successReturnType is ObjCPointerType && !successReturnType.nullable)) {
"Unexpected return type: $successReturnType in $method"
}
}
successReturnType.makeNullableIfReferenceOrPointer()
} }
MethodBridge.ReturnValue.Instance.InitResult, MethodBridge.ReturnValue.Instance.InitResult,
@@ -237,7 +237,6 @@ private fun ObjCExportMapper.bridgeParameter(parameter: ParameterDescriptor): Me
private fun ObjCExportMapper.bridgeReturnType( private fun ObjCExportMapper.bridgeReturnType(
descriptor: FunctionDescriptor, descriptor: FunctionDescriptor,
valueParameters: MutableList<MethodBridgeValueParameter>,
convertExceptionsToErrors: Boolean convertExceptionsToErrors: Boolean
): MethodBridge.ReturnValue { ): MethodBridge.ReturnValue {
val returnType = descriptor.returnType!! val returnType = descriptor.returnType!!
@@ -247,7 +246,11 @@ private fun ObjCExportMapper.bridgeReturnType(
} else { } else {
MethodBridge.ReturnValue.Instance.InitResult MethodBridge.ReturnValue.Instance.InitResult
}.let { }.let {
if (convertExceptionsToErrors) MethodBridge.ReturnValue.WithError.RefOrNull(it) else it if (convertExceptionsToErrors) {
MethodBridge.ReturnValue.WithError.ZeroForError(it, successMayBeZero = false)
} else {
it
}
} }
descriptor.containingDeclaration == descriptor.builtIns.any && descriptor.name.asString() == "hashCode" -> { descriptor.containingDeclaration == descriptor.builtIns.any && descriptor.name.asString() == "hashCode" -> {
@@ -268,20 +271,25 @@ private fun ObjCExportMapper.bridgeReturnType(
else -> { else -> {
val returnTypeBridge = bridgeType(returnType) val returnTypeBridge = bridgeType(returnType)
val successReturnValueBridge = MethodBridge.ReturnValue.Mapped(returnTypeBridge)
if (convertExceptionsToErrors) { if (convertExceptionsToErrors) {
if (returnTypeBridge is ReferenceBridge && !TypeUtils.isNullableType(returnType)) { val canReturnZero = !returnTypeBridge.isReferenceOrPointer() || TypeUtils.isNullableType(returnType)
MethodBridge.ReturnValue.WithError.RefOrNull(MethodBridge.ReturnValue.Mapped(returnTypeBridge)) MethodBridge.ReturnValue.WithError.ZeroForError(
} else { successReturnValueBridge,
valueParameters += MethodBridgeValueParameter.KotlinResultOutParameter(returnTypeBridge) successMayBeZero = canReturnZero
MethodBridge.ReturnValue.WithError.Success )
}
} else { } else {
MethodBridge.ReturnValue.Mapped(returnTypeBridge) successReturnValueBridge
} }
} }
} }
} }
private fun TypeBridge.isReferenceOrPointer(): Boolean = when (this) {
ReferenceBridge, is BlockPointerBridge -> true
is ValueTypeBridge -> this.objCValueType == ObjCValueType.POINTER
}
private fun ObjCExportMapper.bridgeMethodImpl(descriptor: FunctionDescriptor): MethodBridge { private fun ObjCExportMapper.bridgeMethodImpl(descriptor: FunctionDescriptor): MethodBridge {
assert(isBaseMethod(descriptor)) assert(isBaseMethod(descriptor))
@@ -306,7 +314,7 @@ private fun ObjCExportMapper.bridgeMethodImpl(descriptor: FunctionDescriptor): M
valueParameters += bridgeParameter(it) valueParameters += bridgeParameter(it)
} }
val returnBridge = bridgeReturnType(descriptor, valueParameters, convertExceptionsToErrors) val returnBridge = bridgeReturnType(descriptor, convertExceptionsToErrors)
if (convertExceptionsToErrors) { if (convertExceptionsToErrors) {
valueParameters += MethodBridgeValueParameter.ErrorOutParameter valueParameters += MethodBridgeValueParameter.ErrorOutParameter
} }
@@ -453,13 +453,11 @@ internal class ObjCExportNamerImpl(
else -> it!!.name.asString().toIdentifier() else -> it!!.name.asString().toIdentifier()
} }
MethodBridgeValueParameter.ErrorOutParameter -> "error" MethodBridgeValueParameter.ErrorOutParameter -> "error"
is MethodBridgeValueParameter.KotlinResultOutParameter -> "result"
} }
if (index == 0) { if (index == 0) {
append(when { append(when {
bridge is MethodBridgeValueParameter.ErrorOutParameter || bridge is MethodBridgeValueParameter.ErrorOutParameter -> "AndReturn"
bridge is MethodBridgeValueParameter.KotlinResultOutParameter -> "AndReturn"
method is ConstructorDescriptor -> "With" method is ConstructorDescriptor -> "With"
else -> "" else -> ""
@@ -504,7 +502,6 @@ internal class ObjCExportNamerImpl(
else -> it!!.name.asString().toIdentifier() else -> it!!.name.asString().toIdentifier()
} }
MethodBridgeValueParameter.ErrorOutParameter -> continue@parameters MethodBridgeValueParameter.ErrorOutParameter -> continue@parameters
is MethodBridgeValueParameter.KotlinResultOutParameter -> "result"
} }
append(label) append(label)
@@ -270,9 +270,9 @@ __attribute__((swift_name("BridgeBase")))
- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); - (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer));
+ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); + (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead")));
- (id _Nullable)foo1AndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("foo1()"))); - (id _Nullable)foo1AndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("foo1()")));
- (BOOL)foo2AndReturnResult:(int32_t * _Nullable)result error:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("foo2(result:)"))); - (int32_t)foo2AndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("foo2()"))) __attribute__((swift_error(nonnull_error)));
- (BOOL)foo3AndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("foo3()"))); - (BOOL)foo3AndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("foo3()")));
- (BOOL)foo4AndReturnResult:(ValuesKotlinNothing * _Nullable * _Nullable)result error:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("foo4(result:)"))); - (ValuesKotlinNothing * _Nullable)foo4AndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("foo4()"))) __attribute__((swift_error(nonnull_error)));
@end; @end;
__attribute__((objc_subclassing_restricted)) __attribute__((objc_subclassing_restricted))
@@ -281,9 +281,9 @@ __attribute__((swift_name("Bridge")))
- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); - (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer));
+ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); + (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead")));
- (ValuesKotlinNothing * _Nullable)foo1AndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("foo1()"))); - (ValuesKotlinNothing * _Nullable)foo1AndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("foo1()")));
- (BOOL)foo2AndReturnResult:(int32_t * _Nullable)result error:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("foo2(result:)"))); - (int32_t)foo2AndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("foo2()"))) __attribute__((swift_error(nonnull_error)));
- (BOOL)foo3AndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("foo3()"))); - (BOOL)foo3AndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("foo3()")));
- (BOOL)foo4AndReturnResult:(ValuesKotlinNothing * _Nullable * _Nullable)result error:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("foo4(result:)"))); - (ValuesKotlinNothing *)foo4AndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("foo4()"))) __attribute__((swift_error(nonnull_error)));
@end; @end;
__attribute__((objc_subclassing_restricted)) __attribute__((objc_subclassing_restricted))
@@ -291,8 +291,7 @@ func testExceptions() throws {
try assertTrue(error.kotlinException is MyException) try assertTrue(error.kotlinException is MyException)
} }
do { do {
var result: Int32 = 0 try bridge.foo2()
try bridge.foo2(result: &result)
} catch let error as NSError { } catch let error as NSError {
try assertTrue(error.kotlinException is MyException) try assertTrue(error.kotlinException is MyException)
} }
@@ -302,8 +301,7 @@ func testExceptions() throws {
try assertTrue(error.kotlinException is MyException) try assertTrue(error.kotlinException is MyException)
} }
do { do {
var result: KotlinNothing? = nil try bridge.foo4()
try bridge.foo4(result: &result)
} catch let error as NSError { } catch let error as NSError {
try assertTrue(error.kotlinException is MyException) try assertTrue(error.kotlinException is MyException)
} }