Skip to content

Commit 97be86b

Browse files
committed
Runtime: Don't try to register class stubs on older objc runtimes
This will allow us to emit class stubs unconditionally, rather than checking the -enable-resilient-objc-class-stubs flag. Part of <rdar://problem/49090631>.
1 parent 075b918 commit 97be86b

File tree

2 files changed

+27
-24
lines changed

2 files changed

+27
-24
lines changed

stdlib/public/runtime/Metadata.cpp

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2711,16 +2711,23 @@ _swift_initClassMetadataImpl(ClassMetadata *self,
27112711
// globals. Note that the field offset vector is *not* updated;
27122712
// however we should not be using it for anything in a non-generic
27132713
// class.
2714-
if (auto *stub = description->getObjCResilientClassStub()) {
2715-
if (_objc_realizeClassFromSwift == nullptr ||
2716-
objc_loadClassref == nullptr) {
2717-
fatalError(0, "class %s requires missing Objective-C runtime feature; "
2718-
"the deployment target was newer than this OS\n",
2719-
self->getDescription()->Name.get());
2720-
}
2714+
auto *stub = description->getObjCResilientClassStub();
2715+
2716+
// On a new enough runtime, register the class as a replacement for
2717+
// its stub if we have one, which attaches any categories referencing
2718+
// the stub.
2719+
//
2720+
// On older runtimes, just register the class via the usual mechanism.
2721+
// The compiler enforces that @objc methods in extensions of classes
2722+
// with resilient ancestry have the correct availability, so it should
2723+
// be safe to ignore the stub in this case.
2724+
if (stub != nullptr &&
2725+
objc_loadClassref != nullptr &&
2726+
_objc_realizeClassFromSwift != nullptr) {
27212727
_objc_realizeClassFromSwift((Class) self, const_cast<void *>(stub));
2722-
} else
2728+
} else {
27232729
swift_instantiateObjCClass(self);
2730+
}
27242731
}
27252732
#else
27262733
assert(!description->hasObjCResilientClassStub());

test/Interpreter/objc_class_resilience_stubs.swift

Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,18 @@ var ResilientClassTestSuite = TestSuite("ResilientClass")
2828

2929
class ResilientNSObjectSubclass : ResilientNSObjectOutsideParent {}
3030

31+
@_optimize(none) func blackHole<T>(_: T) {}
32+
33+
@_optimize(none) func forceMetadata() {
34+
blackHole(ResilientNSObjectSubclass())
35+
}
36+
37+
// This should not crash on older runtimes because we check before
38+
// attempting to register the class stub.
39+
ResilientClassTestSuite.test("RealizeResilientClass") {
40+
forceMetadata()
41+
}
42+
3143
@objc protocol MyProtocol {
3244
func myMethod() -> Int
3345
}
@@ -61,20 +73,4 @@ ResilientClassTestSuite.test("category on other class")
6173
expectEqual(69, (o as AnotherProtocol).anotherMethod())
6274
}
6375

64-
@_optimize(none) func blackHole<T>(_: T) {}
65-
66-
@_optimize(none) func forceMetadata() {
67-
blackHole(ResilientNSObjectSubclass())
68-
}
69-
70-
if loadClassrefMissing {
71-
ResilientClassTestSuite.test("RealizeResilientClass")
72-
.crashOutputMatches("class ResilientNSObjectSubclass requires missing Objective-C runtime feature")
73-
.code {
74-
expectCrashLater()
75-
print("About to crash...")
76-
forceMetadata()
77-
}
78-
}
79-
8076
runAllTests()

0 commit comments

Comments
 (0)