mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[Concurrency] Allow witnesses to adopt concurrency before requirements
Allow witnesses to introduce `any Sendable` types into their interface before requirements (predicated on presence of `@preconcurrency` and Swift 5 language mode) as a pathway for concurrency adoption. Resolves: rdar://134503878
This commit is contained in:
@@ -5412,35 +5412,38 @@ bool ConstraintSystem::repairFailures(
|
||||
|
||||
if (auto *VD = getAsDecl<ValueDecl>(anchor)) {
|
||||
// Matching a witness to an protocol requirement.
|
||||
if (isa<ProtocolDecl>(VD->getDeclContext()) &&
|
||||
VD->isProtocolRequirement() &&
|
||||
VD->preconcurrency() &&
|
||||
path[0].is<LocatorPathElt::Witness>() &&
|
||||
// Note that the condition below is very important,
|
||||
// we need to wait until the very last moment to strip
|
||||
// the concurrency annotations from the innermost type.
|
||||
conversionsOrFixes.empty()) {
|
||||
// Allow requirements to introduce `swift_attr` and other
|
||||
// concurrency related annotations (e.g. `& Sendable` or `@Sendable`)
|
||||
// (note that `swift_attr` in type contexts weren't supported
|
||||
// before) and for witnesses to adopt them gradually by matching
|
||||
// with a warning in non-strict concurrency mode.
|
||||
if (!(Context.isSwiftVersionAtLeast(6) ||
|
||||
Context.LangOpts.StrictConcurrencyLevel ==
|
||||
StrictConcurrency::Complete)) {
|
||||
auto strippedLHS = lhs->stripConcurrency(/*recursive=*/true,
|
||||
/*dropGlobalActor=*/true);
|
||||
auto strippedRHS = rhs->stripConcurrency(/*recursive=*/true,
|
||||
/*dropGlobalActor=*/true);
|
||||
if (auto witnessElt = path[0].getAs<LocatorPathElt::Witness>()) {
|
||||
if (isa<ProtocolDecl>(VD->getDeclContext()) &&
|
||||
VD->isProtocolRequirement()) {
|
||||
auto *witness = witnessElt->getDecl();
|
||||
if ((VD->preconcurrency() || witness->preconcurrency()) &&
|
||||
// Note that the condition below is very important,
|
||||
// we need to wait until the very last moment to strip
|
||||
// the concurrency annotations from the innermost type.
|
||||
conversionsOrFixes.empty()) {
|
||||
// Allow requirements/witnesses to introduce `swift_attr` and other
|
||||
// concurrency related annotations (e.g. `& Sendable` or `@Sendable`)
|
||||
// (note that `swift_attr` in type contexts weren't supported
|
||||
// before) and for witnesses to adopt them gradually by matching
|
||||
// with a warning in non-strict concurrency mode.
|
||||
if (!(Context.isSwiftVersionAtLeast(6) ||
|
||||
Context.LangOpts.StrictConcurrencyLevel ==
|
||||
StrictConcurrency::Complete)) {
|
||||
auto strippedLHS = lhs->stripConcurrency(/*recursive=*/true,
|
||||
/*dropGlobalActor=*/true);
|
||||
auto strippedRHS = rhs->stripConcurrency(/*recursive=*/true,
|
||||
/*dropGlobalActor=*/true);
|
||||
|
||||
// If nothing got stripped there is no reason to re-match
|
||||
// the types.
|
||||
if (!strippedLHS->isEqual(lhs) || !strippedRHS->isEqual(rhs)) {
|
||||
auto result = matchTypes(strippedLHS, strippedRHS, matchKind,
|
||||
flags | TMF_ApplyingFix, locator);
|
||||
if (!result.isFailure()) {
|
||||
increaseScore(SK_MissingSynthesizableConformance, locator);
|
||||
return true;
|
||||
// If nothing got stripped there is no reason to re-match
|
||||
// the types.
|
||||
if (!strippedLHS->isEqual(lhs) || !strippedRHS->isEqual(rhs)) {
|
||||
auto result = matchTypes(strippedLHS, strippedRHS, matchKind,
|
||||
flags | TMF_ApplyingFix, locator);
|
||||
if (!result.isFailure()) {
|
||||
increaseScore(SK_MissingSynthesizableConformance, locator);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,3 +53,18 @@ struct S4 : Q { // expected-error {{type 'S4' does not conform to protocol 'Q'}}
|
||||
func test(_: [() -> Any?]) {}
|
||||
// expected-note@-1 {{candidate has non-matching type '([() -> Any?]) -> ()'}}
|
||||
}
|
||||
|
||||
// Test that client is allowed to adopt concurrency first.
|
||||
protocol PreConcurrency {
|
||||
var prop: [String: Any] { get } // expected-swift6-note {{protocol requires property 'prop' with type '[String : Any]'}}
|
||||
func req(_: [String: Any], _: ((Any)?) -> Void) // expected-swift6-note {{protocol requires function 'req' with type '([String : Any], (Any?) -> Void) -> ()'}}
|
||||
}
|
||||
|
||||
class Adopter {
|
||||
@preconcurrency var prop: [String: any Sendable] = [:] // expected-swift6-note {{candidate has non-matching type '[String : any Sendable]'}}
|
||||
}
|
||||
|
||||
extension Adopter : PreConcurrency { // expected-swift6-error {{type 'Adopter' does not conform to protocol 'PreConcurrency'}} expected-swift6-note {{add stubs for conformance}}
|
||||
@preconcurrency func req(_: [String: any Sendable], _: ((any Sendable)?) -> Void) {}
|
||||
// expected-swift6-note@-1 {{candidate has non-matching type '([String : any Sendable], ((any Sendable)?) -> Void) -> ()'}}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user