Skip to content

Commit 9e6d68e

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 b871528 commit 9e6d68e

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
@@ -841,6 +841,15 @@ bool swift::_checkGenericRequirements(
841841
substGenericParam, substWitnessTable).getMetadata();
842842
if (!baseType) return true;
843843

844+
// If the type which is constrained to a base class is an existential
845+
// type, and if that existential type includes a superclass constraint,
846+
// just require that the superclass by which the existential is
847+
// constrained is a subclass of the base class.
848+
if (auto *existential = dyn_cast<ExistentialTypeMetadata>(subjectType)) {
849+
if (auto *superclassConstraint = existential->getSuperclassConstraint())
850+
subjectType = superclassConstraint;
851+
}
852+
844853
if (!isSubclass(subjectType, baseType))
845854
return true;
846855

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)