Skip to content

Commit 4be3990

Browse files
authored
Merge pull request #77434 from xedin/rdar-134503878-other-way-around
[Concurrency] Allow witnesses to adopt concurrency before requirements
2 parents fc90551 + 73d658a commit 4be3990

File tree

2 files changed

+47
-29
lines changed

2 files changed

+47
-29
lines changed

lib/Sema/CSSimplify.cpp

Lines changed: 32 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -5412,35 +5412,38 @@ bool ConstraintSystem::repairFailures(
54125412

54135413
if (auto *VD = getAsDecl<ValueDecl>(anchor)) {
54145414
// Matching a witness to an protocol requirement.
5415-
if (isa<ProtocolDecl>(VD->getDeclContext()) &&
5416-
VD->isProtocolRequirement() &&
5417-
VD->preconcurrency() &&
5418-
path[0].is<LocatorPathElt::Witness>() &&
5419-
// Note that the condition below is very important,
5420-
// we need to wait until the very last moment to strip
5421-
// the concurrency annotations from the innermost type.
5422-
conversionsOrFixes.empty()) {
5423-
// Allow requirements to introduce `swift_attr` and other
5424-
// concurrency related annotations (e.g. `& Sendable` or `@Sendable`)
5425-
// (note that `swift_attr` in type contexts weren't supported
5426-
// before) and for witnesses to adopt them gradually by matching
5427-
// with a warning in non-strict concurrency mode.
5428-
if (!(Context.isSwiftVersionAtLeast(6) ||
5429-
Context.LangOpts.StrictConcurrencyLevel ==
5430-
StrictConcurrency::Complete)) {
5431-
auto strippedLHS = lhs->stripConcurrency(/*recursive=*/true,
5432-
/*dropGlobalActor=*/true);
5433-
auto strippedRHS = rhs->stripConcurrency(/*recursive=*/true,
5434-
/*dropGlobalActor=*/true);
5435-
5436-
// If nothing got stripped there is no reason to re-match
5437-
// the types.
5438-
if (!strippedLHS->isEqual(lhs) || !strippedRHS->isEqual(rhs)) {
5439-
auto result = matchTypes(strippedLHS, strippedRHS, matchKind,
5440-
flags | TMF_ApplyingFix, locator);
5441-
if (!result.isFailure()) {
5442-
increaseScore(SK_MissingSynthesizableConformance, locator);
5443-
return true;
5415+
if (auto witnessElt = path[0].getAs<LocatorPathElt::Witness>()) {
5416+
if (isa<ProtocolDecl>(VD->getDeclContext()) &&
5417+
VD->isProtocolRequirement()) {
5418+
auto *witness = witnessElt->getDecl();
5419+
if ((VD->preconcurrency() || witness->preconcurrency()) &&
5420+
// Note that the condition below is very important,
5421+
// we need to wait until the very last moment to strip
5422+
// the concurrency annotations from the innermost type.
5423+
conversionsOrFixes.empty()) {
5424+
// Allow requirements/witnesses to introduce `swift_attr` and other
5425+
// concurrency related annotations (e.g. `& Sendable` or `@Sendable`)
5426+
// (note that `swift_attr` in type contexts weren't supported
5427+
// before) and for witnesses to adopt them gradually by matching
5428+
// with a warning in non-strict concurrency mode.
5429+
if (!(Context.isSwiftVersionAtLeast(6) ||
5430+
Context.LangOpts.StrictConcurrencyLevel ==
5431+
StrictConcurrency::Complete)) {
5432+
auto strippedLHS = lhs->stripConcurrency(/*recursive=*/true,
5433+
/*dropGlobalActor=*/true);
5434+
auto strippedRHS = rhs->stripConcurrency(/*recursive=*/true,
5435+
/*dropGlobalActor=*/true);
5436+
5437+
// If nothing got stripped there is no reason to re-match
5438+
// the types.
5439+
if (!strippedLHS->isEqual(lhs) || !strippedRHS->isEqual(rhs)) {
5440+
auto result = matchTypes(strippedLHS, strippedRHS, matchKind,
5441+
flags | TMF_ApplyingFix, locator);
5442+
if (!result.isFailure()) {
5443+
increaseScore(SK_MissingSynthesizableConformance, locator);
5444+
return true;
5445+
}
5446+
}
54445447
}
54455448
}
54465449
}

test/Concurrency/witness_matching_with_sendable.swift

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,3 +53,18 @@ struct S4 : Q { // expected-error {{type 'S4' does not conform to protocol 'Q'}}
5353
func test(_: [() -> Any?]) {}
5454
// expected-note@-1 {{candidate has non-matching type '([() -> Any?]) -> ()'}}
5555
}
56+
57+
// Test that client is allowed to adopt concurrency first.
58+
protocol PreConcurrency {
59+
var prop: [String: Any] { get } // expected-swift6-note {{protocol requires property 'prop' with type '[String : Any]'}}
60+
func req(_: [String: Any], _: ((Any)?) -> Void) // expected-swift6-note {{protocol requires function 'req' with type '([String : Any], (Any?) -> Void) -> ()'}}
61+
}
62+
63+
class Adopter {
64+
@preconcurrency var prop: [String: any Sendable] = [:] // expected-swift6-note {{candidate has non-matching type '[String : any Sendable]'}}
65+
}
66+
67+
extension Adopter : PreConcurrency { // expected-swift6-error {{type 'Adopter' does not conform to protocol 'PreConcurrency'}} expected-swift6-note {{add stubs for conformance}}
68+
@preconcurrency func req(_: [String: any Sendable], _: ((any Sendable)?) -> Void) {}
69+
// expected-swift6-note@-1 {{candidate has non-matching type '([String : any Sendable], ((any Sendable)?) -> Void) -> ()'}}
70+
}

0 commit comments

Comments
 (0)