Skip to content

Commit 70d120b

Browse files
committed
[IRGen] Accommodate ObjC generic classes better
Classes using the type-erased Objective-C generics model are represented in parts of IRGen as UnboundGenericTypes, which is a problem because a number of code paths expect all generic types to be bound. Update some of these that are involved in extensions on ObjC generic types.
1 parent 14f48dc commit 70d120b

File tree

4 files changed

+45
-5
lines changed

4 files changed

+45
-5
lines changed

lib/IRGen/GenDecl.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ llvm::cl::opt<bool> UseBasicDynamicReplacement(
8585
llvm::cl::desc("Basic implementation of dynamic replacement"));
8686

8787
namespace {
88-
88+
8989
/// Add methods, properties, and protocol conformances from a JITed extension
9090
/// to an ObjC class using the ObjC runtime.
9191
///
@@ -119,8 +119,8 @@ class CategoryInitializerVisitor
119119
/*allow uninitialized*/ false);
120120
classMetadata = Builder.CreateBitCast(classMetadata, IGM.ObjCClassPtrTy);
121121
metaclassMetadata = IGM.getAddrOfMetaclassObject(
122-
origTy.getClassOrBoundGenericClass(),
123-
NotForDefinition);
122+
dyn_cast_or_null<ClassDecl>(origTy->getAnyNominal()),
123+
NotForDefinition);
124124
metaclassMetadata = llvm::ConstantExpr::getBitCast(metaclassMetadata,
125125
IGM.ObjCClassPtrTy);
126126

lib/IRGen/MetadataRequest.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3411,7 +3411,7 @@ llvm::Value *irgen::emitClassHeapMetadataRef(IRGenFunction &IGF, CanType type,
34113411
bool allowUninitialized) {
34123412
assert(request.canResponseStatusBeIgnored() &&
34133413
"emitClassHeapMetadataRef only supports satisfied requests");
3414-
assert(type->mayHaveSuperclass());
3414+
assert(type->mayHaveSuperclass() || type->isTypeErasedGenericClassType());
34153415

34163416
// Archetypes may or may not be ObjC classes and need unwrapping to get at
34173417
// the class object.
@@ -3426,7 +3426,7 @@ llvm::Value *irgen::emitClassHeapMetadataRef(IRGenFunction &IGF, CanType type,
34263426
return classPtr;
34273427
}
34283428

3429-
if (ClassDecl *theClass = type->getClassOrBoundGenericClass()) {
3429+
if (ClassDecl *theClass = dyn_cast_or_null<ClassDecl>(type->getAnyNominal())) {
34303430
if (!hasKnownSwiftMetadata(IGF.IGM, theClass)) {
34313431
llvm::Value *result =
34323432
emitObjCHeapMetadataRef(IGF, theClass, allowUninitialized);

test/IRGen/objc_extensions_jit.swift

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -enable-objc-interop %s -emit-ir -disable-objc-attr-requires-foundation-module -use-jit | %FileCheck %s
2+
3+
import Foundation
4+
import objc_generics
5+
6+
extension NSString {
7+
func fn() {}
8+
}
9+
10+
extension GenericClass {
11+
@objc func fn() {}
12+
}
13+
14+
// CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} private void @runtime_registration
15+
// CHECK-NOT: @__swift_instantiateConcreteTypeFromMangledName
16+
// CHECK: ret void

test/Interpreter/objc_extensions.swift

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,3 +62,27 @@ let z: AnyObject = NSObject()
6262

6363
// CHECK: 123
6464
print(z.sillyMethod())
65+
66+
// Category on an ObjC generic class using a type-pinning parameter, including
67+
// a cast to an existential metatype
68+
@objc protocol CacheNameDefaulting {
69+
static var defaultCacheName: String { get }
70+
}
71+
extension OuterClass.InnerClass: CacheNameDefaulting {
72+
static var defaultCacheName: String { "InnerClasses" }
73+
}
74+
75+
extension NSCache {
76+
@objc convenience init(ofObjects objectTy: ObjectType.Type, forKeys keyTy: KeyType.Type) {
77+
self.init()
78+
79+
if let defaultNameTy = objectTy as? CacheNameDefaulting.Type {
80+
self.name = defaultNameTy.defaultCacheName
81+
}
82+
}
83+
}
84+
85+
let cache = NSCache(ofObjects: OuterClass.InnerClass.self, forKeys: NSString.self)
86+
87+
// CHECK: InnerClasses
88+
print(cache.name)

0 commit comments

Comments
 (0)