Skip to content

Commit c069e6a

Browse files
authored
Merge pull request #76268 from xedin/rdar-134504519
[TypeChecker] Warn if witness mismatches only on sendability until Sw…
2 parents c04736f + 6c1fc03 commit c069e6a

File tree

3 files changed

+75
-13
lines changed

3 files changed

+75
-13
lines changed

lib/Sema/CSSimplify.cpp

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5470,16 +5470,17 @@ bool ConstraintSystem::repairFailures(
54705470
}
54715471

54725472
if (auto *VD = getAsDecl<ValueDecl>(anchor)) {
5473-
// Matching a witness to an ObjC protocol requirement.
5474-
if (VD->isObjC() &&
5475-
isa<ProtocolDecl>(VD->getDeclContext()) &&
5473+
// Matching a witness to an protocol requirement.
5474+
if (isa<ProtocolDecl>(VD->getDeclContext()) &&
54765475
VD->isProtocolRequirement() &&
5476+
VD->preconcurrency() &&
54775477
path[0].is<LocatorPathElt::Witness>() &&
54785478
// Note that the condition below is very important,
54795479
// we need to wait until the very last moment to strip
5480-
// the concurrency annotations from the inner most type.
5480+
// the concurrency annotations from the innermost type.
54815481
conversionsOrFixes.empty()) {
5482-
// Allow requirements to introduce `swift_attr` annotations
5482+
// Allow requirements to introduce `swift_attr` and other
5483+
// concurrency related annotations (e.g. `& Sendable` or `@Sendable`)
54835484
// (note that `swift_attr` in type contexts weren't supported
54845485
// before) and for witnesses to adopt them gradually by matching
54855486
// with a warning in non-strict concurrency mode.
@@ -5491,11 +5492,15 @@ bool ConstraintSystem::repairFailures(
54915492
auto strippedRHS = rhs->stripConcurrency(/*recursive=*/true,
54925493
/*dropGlobalActor=*/true);
54935494

5494-
auto result = matchTypes(strippedLHS, strippedRHS, matchKind,
5495-
flags | TMF_ApplyingFix, locator);
5496-
if (!result.isFailure()) {
5497-
increaseScore(SK_MissingSynthesizableConformance, locator);
5498-
return true;
5495+
// If nothing got stripped there is no reason to re-match
5496+
// the types.
5497+
if (!strippedLHS->isEqual(lhs) || !strippedRHS->isEqual(rhs)) {
5498+
auto result = matchTypes(strippedLHS, strippedRHS, matchKind,
5499+
flags | TMF_ApplyingFix, locator);
5500+
if (!result.isFailure()) {
5501+
increaseScore(SK_MissingSynthesizableConformance, locator);
5502+
return true;
5503+
}
54995504
}
55005505
}
55015506
}

lib/Sema/TypeCheckProtocol.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1260,9 +1260,11 @@ swift::matchWitness(WitnessChecker::RequirementEnvironmentCache &reqEnvCache,
12601260

12611261
// If there are no other issues, let's check whether this are
12621262
// missing Sendable conformances when matching ObjC requirements.
1263-
// This is not an error until Swift 6 because `swift_attr` wasn't
1264-
// allowed in type contexts initially.
1265-
return req->isObjC() &&
1263+
// This is not an error until Swift 6 because i.e. `swift_attr` wasn't
1264+
// allowed in type contexts initially and introducing new concurrency
1265+
// attributes shouldn't break witnesses without strict concurrency
1266+
// enabled.
1267+
return req->preconcurrency() &&
12661268
solution->getFixedScore()
12671269
.Data[SK_MissingSynthesizableConformance] > 0;
12681270
}();
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
// RUN: %target-typecheck-verify-swift -swift-version 5 -verify-additional-prefix swift5-
2+
// RUN: %target-typecheck-verify-swift -swift-version 5 -strict-concurrency=complete -verify-additional-prefix swift6-
3+
// RUN: %target-typecheck-verify-swift -swift-version 6 -verify-additional-prefix swift6-
4+
5+
protocol P {
6+
@preconcurrency var prop: [String: any Sendable] { get set }
7+
// expected-swift5-note@-1 3 {{expected sendability to match requirement here}}
8+
// expected-swift6-note@-2 3 {{protocol requires property 'prop' with type '[String : any Sendable]'}}
9+
@preconcurrency func reqFn(_: [String: any Sendable], _: @Sendable ((any Sendable)?) -> Void)
10+
// expected-swift5-note@-1 2 {{expected sendability to match requirement here}}
11+
// expected-swift6-note@-2 2 {{protocol requires function 'reqFn' with type '([String : any Sendable], @Sendable ((any Sendable)?) -> Void) -> ()'}}
12+
}
13+
14+
struct S1 : P { // expected-swift6-error {{type 'S1' does not conform to protocol 'P'}} expected-swift6-note {{add stubs for conformance}}
15+
var prop: [String: Any] = [:]
16+
// expected-swift5-warning@-1 {{sendability of function types in property 'prop' does not match requirement in protocol 'P'; this is an error in the Swift 6 language mode}}
17+
// expected-swift6-note@-2 {{candidate has non-matching type '[String : Any]'}}
18+
func reqFn(_: [String: Any], _: (Any?) -> Void) {}
19+
// expected-swift5-warning@-1 {{sendability of function types in instance method 'reqFn' does not match requirement in protocol 'P'; this is an error in the Swift 6 language mode}}
20+
// expected-swift6-note@-2 {{candidate has non-matching type '([String : Any], (Any?) -> Void) -> ()'}}
21+
}
22+
23+
struct S2 : P { // expected-swift6-error {{type 'S2' does not conform to protocol 'P'}} expected-swift6-note {{add stubs for conformance}}
24+
var prop: [String: Any] = [:]
25+
// expected-swift5-warning@-1 {{sendability of function types in property 'prop' does not match requirement in protocol 'P'; this is an error in the Swift 6 language mode}}
26+
// expected-swift6-note@-2 {{candidate has non-matching type '[String : Any]'}}
27+
28+
func reqFn(_: [String: Any], _: ((any Sendable)?) -> Void) {}
29+
// expected-swift5-warning@-1 {{sendability of function types in instance method 'reqFn' does not match requirement in protocol 'P'; this is an error in the Swift 6 language mode}}
30+
// expected-swift6-note@-2 {{candidate has non-matching type '([String : Any], ((any Sendable)?) -> Void) -> ()'}}
31+
}
32+
33+
struct S3 : P { // expected-swift6-error {{type 'S3' does not conform to protocol 'P'}} expected-swift6-note {{add stubs for conformance}}
34+
var prop: [String: Any] = [:]
35+
// expected-swift5-warning@-1 {{sendability of function types in property 'prop' does not match requirement in protocol 'P'; this is an error in the Swift 6 language mode}}
36+
// expected-swift6-note@-2 {{candidate has non-matching type '[String : Any]'}}
37+
38+
func reqFn(_: [String: any Sendable], _: ((any Sendable)?) -> Void) {} // Ok
39+
}
40+
41+
protocol Q {
42+
var prop: [String: [String: any Sendable]] { get set }
43+
// expected-note@-1 {{protocol requires property 'prop' with type '[String : [String : any Sendable]]'}}
44+
45+
func test(_: [() -> (any Sendable)?])
46+
// expected-note@-1 {{protocol requires function 'test' with type '([() -> (any Sendable)?]) -> ()'}}
47+
}
48+
49+
struct S4 : Q { // expected-error {{type 'S4' does not conform to protocol 'Q'}} expected-note {{add stubs for conformance}}
50+
var prop: [String: [String: Any]] = [:]
51+
// expected-note@-1 {{candidate has non-matching type '[String : [String : Any]]'}}
52+
53+
func test(_: [() -> Any?]) {}
54+
// expected-note@-1 {{candidate has non-matching type '([() -> Any?]) -> ()'}}
55+
}

0 commit comments

Comments
 (0)