Skip to content

Commit 9a3d1b7

Browse files
committed
[TypeChecker] Warn if witness mismatches only on sendability until Swift 6 mode
This expands the downgrade for Objective-C requirements to all requirements until strict concurrency checking is enabled (either via a flag in Swift 5 language mode or by switching to Swift 6 language mode). Resolves: rdar://134503878
1 parent 00eee36 commit 9a3d1b7

File tree

4 files changed

+55
-13
lines changed

4 files changed

+55
-13
lines changed

lib/Sema/CSSimplify.cpp

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5616,16 +5616,16 @@ bool ConstraintSystem::repairFailures(
56165616
}
56175617

56185618
if (auto *VD = getAsDecl<ValueDecl>(anchor)) {
5619-
// Matching a witness to an ObjC protocol requirement.
5620-
if (VD->isObjC() &&
5621-
isa<ProtocolDecl>(VD->getDeclContext()) &&
5619+
// Matching a witness to an protocol requirement.
5620+
if (isa<ProtocolDecl>(VD->getDeclContext()) &&
56225621
VD->isProtocolRequirement() &&
56235622
path[0].is<LocatorPathElt::Witness>() &&
56245623
// Note that the condition below is very important,
56255624
// we need to wait until the very last moment to strip
5626-
// the concurrency annotations from the inner most type.
5625+
// the concurrency annotations from the innermost type.
56275626
conversionsOrFixes.empty()) {
5628-
// Allow requirements to introduce `swift_attr` annotations
5627+
// Allow requirements to introduce `swift_attr` and other
5628+
// concurrency related annotations (e.g. `& Sendable` or `@Sendable`)
56295629
// (note that `swift_attr` in type contexts weren't supported
56305630
// before) and for witnesses to adopt them gradually by matching
56315631
// with a warning in non-strict concurrency mode.
@@ -5637,11 +5637,15 @@ bool ConstraintSystem::repairFailures(
56375637
auto strippedRHS = rhs->stripConcurrency(/*recursive=*/true,
56385638
/*dropGlobalActor=*/true);
56395639

5640-
auto result = matchTypes(strippedLHS, strippedRHS, matchKind,
5641-
flags | TMF_ApplyingFix, locator);
5642-
if (!result.isFailure()) {
5643-
increaseScore(SK_MissingSynthesizableConformance, locator);
5644-
return true;
5640+
// If nothing got stripped there is no reason to re-match
5641+
// the types.
5642+
if (!strippedLHS->isEqual(lhs) || !strippedRHS->isEqual(rhs)) {
5643+
auto result = matchTypes(strippedLHS, strippedRHS, matchKind,
5644+
flags | TMF_ApplyingFix, locator);
5645+
if (!result.isFailure()) {
5646+
increaseScore(SK_MissingSynthesizableConformance, locator);
5647+
return true;
5648+
}
56455649
}
56465650
}
56475651
}

lib/Sema/TypeCheckProtocol.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1263,8 +1263,7 @@ swift::matchWitness(WitnessChecker::RequirementEnvironmentCache &reqEnvCache,
12631263
// missing Sendable conformances when matching ObjC requirements.
12641264
// This is not an error until Swift 6 because `swift_attr` wasn't
12651265
// allowed in type contexts initially.
1266-
return req->isObjC() &&
1267-
solution->getFixedScore()
1266+
return solution->getFixedScore()
12681267
.Data[SK_MissingSynthesizableConformance] > 0;
12691268
}();
12701269

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
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+
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+
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+
}

test/decl/protocol/conforms/isolated_any.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %target-swift-frontend -typecheck -verify %s
1+
// RUN: %target-swift-frontend -typecheck -verify -swift-version 6 %s
22

33
struct A<T> {
44
// expected-note @+1 {{candidate has non-matching type}}

0 commit comments

Comments
 (0)