Skip to content

Commit ca525fc

Browse files
committed
[Runtime] Let existential types satisfy superclass requirements.
Previously, when an attempt was made to instantiate a generic metadata whose argument was constrained to subclass a superclass Super with an existential type E that had a superclass constraint to a subclass Sub of that same superclass Super, the instantiation would fail at runtime, despite the fact that the generic instantiation was allowed to type-check. The result was a runtime failure to instantiate generic metadata resulting eventually in a crash. Here, handling for that situation is added. When checking generic requirements at runtime, when a superclass requirement is encountered, an existential type is checked for. If that existential type has a superclass constraint and if that superclass constraint is a subclass of the superclass requirement, the check is determined to be satisfactory. rdar://problem/64672291
1 parent eed09ea commit ca525fc

File tree

2 files changed

+33
-0
lines changed

2 files changed

+33
-0
lines changed

stdlib/public/runtime/ProtocolConformance.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -869,6 +869,15 @@ bool swift::_checkGenericRequirements(
869869
substGenericParam, substWitnessTable).getMetadata();
870870
if (!baseType) return true;
871871

872+
// If the type which is constrained to a base class is an existential
873+
// type, and if that existential type includes a superclass constraint,
874+
// just require that the superclass by which the existential is
875+
// constrained is a subclass of the base class.
876+
if (auto *existential = dyn_cast<ExistentialTypeMetadata>(subjectType)) {
877+
if (auto *superclassConstraint = existential->getSuperclassConstraint())
878+
subjectType = superclassConstraint;
879+
}
880+
872881
if (!isSubclass(subjectType, baseType))
873882
return true;
874883

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// RUN: %target-run-simple-swift
2+
// REQUIRES: objc_interop
3+
4+
import Foundation
5+
6+
final class Storage<T: NSObject> {
7+
weak var object: T?
8+
init(object: T) {
9+
self.object = object
10+
}
11+
}
12+
13+
14+
@objc protocol MyProtocol {}
15+
typealias MyStorage = Storage<NSObject & MyProtocol>
16+
17+
class Gadget: NSObject, MyProtocol {
18+
func testit() {
19+
_ = MyStorage(object: self)
20+
}
21+
}
22+
23+
let gadget = Gadget()
24+
gadget.testit()

0 commit comments

Comments
 (0)