Skip to content

Commit cf1c177

Browse files
committed
Sema: Relax check around implied conditional conformance
Fixes rdar://123933687.
1 parent a781ca2 commit cf1c177

File tree

2 files changed

+31
-1
lines changed

2 files changed

+31
-1
lines changed

lib/Sema/TypeCheckProtocol.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2424,8 +2424,16 @@ checkIndividualConformance(NormalProtocolConformance *conformance) {
24242424
implyingConf = implyingConf->getImplyingConformance();
24252425
}
24262426

2427+
// If the conditional requirements all have the form `T : Copyable`, then
2428+
// we accept the implied conformance with the same conditional requirements.
24272429
auto implyingCondReqs = implyingConf->getConditionalRequirements();
2428-
if (!implyingCondReqs.empty()) {
2430+
bool allCondReqsInvertible = llvm::all_of(implyingCondReqs,
2431+
[&](Requirement req) {
2432+
return (req.getKind() == RequirementKind::Conformance &&
2433+
req.getProtocolDecl()->getInvertibleProtocolKind());
2434+
});
2435+
2436+
if (!allCondReqsInvertible) {
24292437
// FIXME:
24302438
// We shouldn't suggest including witnesses for the conformance, because
24312439
// those suggestions will go in the current DeclContext, but really they
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// RUN: %target-typecheck-verify-swift -enable-experimental-feature NoncopyableGenerics
2+
3+
struct G<T: ~Copyable>: ~Copyable {}
4+
5+
extension G: Copyable {}
6+
7+
protocol Base {}
8+
protocol Derived: Base {}
9+
10+
// Normally we would require the conditional conformance 'G: Base' to be
11+
// explicitly declared, but that would break source compatibility if G
12+
// used to be unconditionally Copyable.
13+
14+
extension G: Derived {} // expected-note {{requirement from conditional conformance of 'G<NotCopyable>' to 'Base'}}
15+
16+
struct NotCopyable: ~Copyable {}
17+
struct IsCopyable {}
18+
19+
func f<T: Base>(_: T.Type) {}
20+
21+
f(G<NotCopyable>.self) // expected-error {{global function 'f' requires that 'NotCopyable' conform to 'Copyable'}}
22+
f(G<IsCopyable>.self) // accepted

0 commit comments

Comments
 (0)