Skip to content

Commit d5ca8ee

Browse files
authored
Merge pull request #72137 from kavon/ncgenerics-conditional-conformances
GenProto: drop conditional Copyable reqs from protocol conformance descriptors
2 parents 8ddbc8b + 49fdf19 commit d5ca8ee

File tree

2 files changed

+86
-5
lines changed

2 files changed

+86
-5
lines changed

lib/IRGen/GenProto.cpp

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2113,17 +2113,28 @@ namespace {
21132113
if (!normal)
21142114
return;
21152115

2116-
std::optional<Requirement> scratchRequirement;
2117-
auto condReqs = normal->getConditionalRequirements();
2116+
SmallVector<Requirement, 2> condReqs;
2117+
{
2118+
// FIXME(kavon): probably need to emit the inverse requirements in the
2119+
// metadata so the runtime knows not to check for Copyable? For now
2120+
// filter them out.
2121+
auto origCondReqs = normal->getConditionalRequirements();
2122+
for (auto req : origCondReqs) {
2123+
if (req.getKind() == RequirementKind::Conformance &&
2124+
req.getProtocolDecl()->getInvertibleProtocolKind())
2125+
continue;
2126+
condReqs.push_back(req);
2127+
}
2128+
}
2129+
21182130
if (condReqs.empty()) {
21192131
// For a protocol P that conforms to another protocol, introduce a
21202132
// conditional requirement for that P's Self: P. This aligns with
21212133
// SILWitnessTable::enumerateWitnessTableConditionalConformances().
21222134
if (auto selfProto = normal->getDeclContext()->getSelfProtocolDecl()) {
21232135
auto selfType = selfProto->getSelfInterfaceType()->getCanonicalType();
2124-
scratchRequirement.emplace(RequirementKind::Conformance, selfType,
2125-
selfProto->getDeclaredInterfaceType());
2126-
condReqs = *scratchRequirement;
2136+
condReqs.emplace_back(RequirementKind::Conformance, selfType,
2137+
selfProto->getDeclaredInterfaceType());
21272138
}
21282139

21292140
if (condReqs.empty())
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
// RUN: %target-run-simple-swift(-Xfrontend -sil-verify-all -enable-experimental-feature NoncopyableGenerics) | %FileCheck %s
2+
// RUN: %target-run-simple-swift(-O -Xfrontend -sil-verify-all -enable-experimental-feature NoncopyableGenerics) | %FileCheck %s
3+
4+
protocol P {
5+
func speak()
6+
}
7+
8+
extension P {
9+
func speak() { print("hello") }
10+
}
11+
12+
struct Noncopyable: ~Copyable {}
13+
struct Ordinary {}
14+
15+
struct Dog<T: ~Copyable>: Copyable {}
16+
extension Dog: P where T: Copyable {}
17+
18+
enum Cat<Left: ~Copyable, Right: ~Copyable>: Copyable {
19+
case meows
20+
init() { self = .meows }
21+
}
22+
extension Cat: P where Left: Copyable {}
23+
24+
func attemptCall(_ a: Any) {
25+
if let value = a as? P {
26+
value.speak()
27+
return
28+
}
29+
print("failed to cast (attemptCall)")
30+
}
31+
32+
defer { main() }
33+
func main() {
34+
// CHECK: hello
35+
attemptCall(Dog<Ordinary>())
36+
37+
// FIXME: this is NOT suppose to succeed! (rdar://123466649)
38+
// CHECK: hello
39+
attemptCall(Dog<Noncopyable>())
40+
41+
// CHECK: hello
42+
attemptCall(Cat<Ordinary, Noncopyable>())
43+
44+
// FIXME: this is NOT suppose to succeed! (rdar://123466649)
45+
// CHECK: hello
46+
attemptCall(Cat<Noncopyable, Ordinary>())
47+
48+
// FIXME: this should succeeed!!
49+
// CHECK: failed to cast (test_radar124171788)
50+
test_radar124171788(.nothing)
51+
}
52+
53+
// coverage for rdar://124171788
54+
enum Maybe<Wrapped: ~Copyable>: ~Copyable {
55+
case just(Wrapped)
56+
case nothing
57+
}
58+
extension Maybe: Copyable {}
59+
extension Maybe: CustomStringConvertible {
60+
var description: String {
61+
"cast succeeded"
62+
}
63+
}
64+
func test_radar124171788(_ v: Maybe<Int>) {
65+
if let foo = v as? CustomDebugStringConvertible {
66+
print("\(foo.debugDescription)")
67+
return
68+
}
69+
print("failed to cast (test_radar124171788)")
70+
}

0 commit comments

Comments
 (0)