[K/N] Forbid calling sealed class constructor from objc

This commit is contained in:
Pavel Kunyavskiy
2021-09-22 11:49:47 +03:00
committed by Space
parent 669965d56c
commit 68445deae8
5 changed files with 144 additions and 14 deletions
@@ -6,7 +6,6 @@
package org.jetbrains.kotlin.backend.konan.objcexport
import org.jetbrains.kotlin.backend.common.descriptors.allParameters
import org.jetbrains.kotlin.backend.common.descriptors.isSuspend
import org.jetbrains.kotlin.backend.konan.*
import org.jetbrains.kotlin.backend.konan.descriptors.allOverriddenDescriptors
import org.jetbrains.kotlin.backend.konan.descriptors.isArray
@@ -71,10 +70,12 @@ internal fun ObjCExportMapper.getClassIfCategory(extensionReceiverType: KotlinTy
}
}
private fun isSealedClassConstructor(descriptor: ConstructorDescriptor) = descriptor.constructedClass.isSealed()
// Note: partially duplicated in ObjCExportLazyImpl.translateTopLevels.
internal fun ObjCExportMapper.shouldBeExposed(descriptor: CallableMemberDescriptor): Boolean =
descriptor.isEffectivelyPublicApi && !descriptor.isExpect &&
!isHiddenByDeprecation(descriptor)
!isHiddenByDeprecation(descriptor) && !(descriptor is ConstructorDescriptor && isSealedClassConstructor(descriptor))
internal fun ObjCExportMapper.shouldBeExposed(descriptor: ClassDescriptor): Boolean =
shouldBeVisible(descriptor) && !isSpecialMapped(descriptor) && !descriptor.defaultType.isObjCObjectType()
@@ -1113,6 +1113,56 @@ __attribute__((swift_name("OverrideMethodsOfAnyKt")))
+ (BOOL)testObj:(id)obj other:(id)other swift:(BOOL)swift error:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("test(obj:other:swift:)")));
@end;
__attribute__((swift_name("Person")))
@interface KtPerson : KtBase
@end;
__attribute__((objc_subclassing_restricted))
__attribute__((swift_name("Person.User")))
@interface KtPersonUser : KtPerson
- (instancetype)initWithId:(int32_t)id __attribute__((swift_name("init(id:)"))) __attribute__((objc_designated_initializer));
- (BOOL)isEqual:(id _Nullable)other __attribute__((swift_name("isEqual(_:)")));
- (NSUInteger)hash __attribute__((swift_name("hash()")));
- (NSString *)description __attribute__((swift_name("description()")));
- (int32_t)component1 __attribute__((swift_name("component1()")));
- (KtPersonUser *)doCopyId:(int32_t)id __attribute__((swift_name("doCopy(id:)")));
@property (readonly) int32_t id __attribute__((swift_name("id")));
@end;
__attribute__((swift_name("Person.Worker")))
@interface KtPersonWorker : KtBase
- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer));
+ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead")));
@end;
__attribute__((objc_subclassing_restricted))
__attribute__((swift_name("Person.WorkerEmployee")))
@interface KtPersonWorkerEmployee : KtPersonWorker
- (instancetype)initWithId:(int32_t)id __attribute__((swift_name("init(id:)"))) __attribute__((objc_designated_initializer));
- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)) __attribute__((unavailable));
+ (instancetype)new __attribute__((unavailable));
- (BOOL)isEqual:(id _Nullable)other __attribute__((swift_name("isEqual(_:)")));
- (NSUInteger)hash __attribute__((swift_name("hash()")));
- (NSString *)description __attribute__((swift_name("description()")));
- (int32_t)component1 __attribute__((swift_name("component1()")));
- (KtPersonWorkerEmployee *)doCopyId:(int32_t)id __attribute__((swift_name("doCopy(id:)")));
@property (readonly) int32_t id __attribute__((swift_name("id")));
@end;
__attribute__((objc_subclassing_restricted))
__attribute__((swift_name("Person.WorkerContractor")))
@interface KtPersonWorkerContractor : KtPersonWorker
- (instancetype)initWithId:(int32_t)id __attribute__((swift_name("init(id:)"))) __attribute__((objc_designated_initializer));
- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)) __attribute__((unavailable));
+ (instancetype)new __attribute__((unavailable));
- (BOOL)isEqual:(id _Nullable)other __attribute__((swift_name("isEqual(_:)")));
- (NSUInteger)hash __attribute__((swift_name("hash()")));
- (NSString *)description __attribute__((swift_name("description()")));
- (int32_t)component1 __attribute__((swift_name("component1()")));
- (KtPersonWorkerContractor *)doCopyId:(int32_t)id __attribute__((swift_name("doCopy(id:)")));
@property (readonly) int32_t id __attribute__((swift_name("id")));
@end;
__attribute__((objc_subclassing_restricted))
__attribute__((swift_name("ThrowableAsError")))
@interface KtThrowableAsError : KtKotlinThrowable
@@ -2633,8 +2683,6 @@ __attribute__((swift_name("ValuesKt")))
__attribute__((swift_name("InvariantSuper")))
@interface KtInvariantSuper<T> : KtBase
- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer));
+ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead")));
@end;
__attribute__((objc_subclassing_restricted))
@@ -2646,8 +2694,6 @@ __attribute__((swift_name("Invariant")))
__attribute__((swift_name("OutVariantSuper")))
@interface KtOutVariantSuper<__covariant T> : KtBase
- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer));
+ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead")));
@end;
__attribute__((objc_subclassing_restricted))
@@ -2659,8 +2705,6 @@ __attribute__((swift_name("OutVariant")))
__attribute__((swift_name("InVariantSuper")))
@interface KtInVariantSuper<__contravariant T> : KtBase
- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer));
+ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead")));
@end;
__attribute__((objc_subclassing_restricted))
@@ -1055,6 +1055,56 @@ __attribute__((swift_name("OverrideMethodsOfAnyKt")))
+ (BOOL)testObj:(id)obj other:(id)other swift:(BOOL)swift error:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("test(obj:other:swift:)")));
@end;
__attribute__((swift_name("Person")))
@interface KtPerson : KtBase
@end;
__attribute__((objc_subclassing_restricted))
__attribute__((swift_name("Person.User")))
@interface KtPersonUser : KtPerson
- (instancetype)initWithId:(int32_t)id __attribute__((swift_name("init(id:)"))) __attribute__((objc_designated_initializer));
- (BOOL)isEqual:(id _Nullable)other __attribute__((swift_name("isEqual(_:)")));
- (NSUInteger)hash __attribute__((swift_name("hash()")));
- (NSString *)description __attribute__((swift_name("description()")));
- (int32_t)component1 __attribute__((swift_name("component1()")));
- (KtPersonUser *)doCopyId:(int32_t)id __attribute__((swift_name("doCopy(id:)")));
@property (readonly) int32_t id __attribute__((swift_name("id")));
@end;
__attribute__((swift_name("Person.Worker")))
@interface KtPersonWorker : KtBase
- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer));
+ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead")));
@end;
__attribute__((objc_subclassing_restricted))
__attribute__((swift_name("Person.WorkerEmployee")))
@interface KtPersonWorkerEmployee : KtPersonWorker
- (instancetype)initWithId:(int32_t)id __attribute__((swift_name("init(id:)"))) __attribute__((objc_designated_initializer));
- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)) __attribute__((unavailable));
+ (instancetype)new __attribute__((unavailable));
- (BOOL)isEqual:(id _Nullable)other __attribute__((swift_name("isEqual(_:)")));
- (NSUInteger)hash __attribute__((swift_name("hash()")));
- (NSString *)description __attribute__((swift_name("description()")));
- (int32_t)component1 __attribute__((swift_name("component1()")));
- (KtPersonWorkerEmployee *)doCopyId:(int32_t)id __attribute__((swift_name("doCopy(id:)")));
@property (readonly) int32_t id __attribute__((swift_name("id")));
@end;
__attribute__((objc_subclassing_restricted))
__attribute__((swift_name("Person.WorkerContractor")))
@interface KtPersonWorkerContractor : KtPersonWorker
- (instancetype)initWithId:(int32_t)id __attribute__((swift_name("init(id:)"))) __attribute__((objc_designated_initializer));
- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)) __attribute__((unavailable));
+ (instancetype)new __attribute__((unavailable));
- (BOOL)isEqual:(id _Nullable)other __attribute__((swift_name("isEqual(_:)")));
- (NSUInteger)hash __attribute__((swift_name("hash()")));
- (NSString *)description __attribute__((swift_name("description()")));
- (int32_t)component1 __attribute__((swift_name("component1()")));
- (KtPersonWorkerContractor *)doCopyId:(int32_t)id __attribute__((swift_name("doCopy(id:)")));
@property (readonly) int32_t id __attribute__((swift_name("id")));
@end;
__attribute__((objc_subclassing_restricted))
__attribute__((swift_name("ThrowableAsError")))
@interface KtThrowableAsError : KtKotlinThrowable
@@ -2575,8 +2625,6 @@ __attribute__((swift_name("ValuesKt")))
__attribute__((swift_name("InvariantSuper")))
@interface KtInvariantSuper : KtBase
- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer));
+ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead")));
@end;
__attribute__((objc_subclassing_restricted))
@@ -2588,8 +2636,6 @@ __attribute__((swift_name("Invariant")))
__attribute__((swift_name("OutVariantSuper")))
@interface KtOutVariantSuper : KtBase
- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer));
+ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead")));
@end;
__attribute__((objc_subclassing_restricted))
@@ -2601,8 +2647,6 @@ __attribute__((swift_name("OutVariant")))
__attribute__((swift_name("InVariantSuper")))
@interface KtInVariantSuper : KtBase
- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer));
+ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead")));
@end;
__attribute__((objc_subclassing_restricted))
@@ -0,0 +1,15 @@
/*
* Copyright 2010-2021 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 sealedClass
sealed class Person() {
data class User(val id: Int) : Person()
abstract class Worker() {
data class Employee(val id: Int) : Worker()
data class Contractor(val id: Int) : Worker()
}
}
@@ -0,0 +1,26 @@
import Kt
private func test1() throws {
let user = Person.User(id: 1)
let worker = Person.Worker()
let employee = Person.WorkerEmployee(id: 2)
let contractor = Person.WorkerContractor(id: 3)
let userAsPerson: Person = user
let employeeAsWorker: Person.Worker = employee
let contractorAsWorker: Person.Worker = contractor
try assertEquals(actual: user.id, expected: 1)
try assertEquals(actual: (userAsPerson as! Person.User).id, expected: 1)
try assertEquals(actual: employee.id, expected: 2)
try assertEquals(actual: (employeeAsWorker as! Person.WorkerEmployee).id, expected: 2)
try assertEquals(actual: contractor.id, expected: 3)
try assertEquals(actual: (contractorAsWorker as! Person.WorkerContractor).id, expected: 3)
}
class SealedClassTests : SimpleTestProvider {
override init() {
super.init()
test("Test1", test1)
}
}