Skip to content

Commit 8c2c1a0

Browse files
committed
Allow @isolated(any) mismatches in witness matching.
Fixes rdar://125394096
1 parent a5c659b commit 8c2c1a0

File tree

2 files changed

+80
-12
lines changed

2 files changed

+80
-12
lines changed

lib/Sema/CSSimplify.cpp

Lines changed: 34 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5578,25 +5578,47 @@ bool ConstraintSystem::repairFailures(
55785578
return false;
55795579
}
55805580

5581+
// Be a little lax in protocol requirement matching.
55815582
if (auto *VD = getAsDecl<ValueDecl>(anchor)) {
5582-
// Matching a witness to a ObjC protocol requirement.
5583-
if (VD->isObjC() && VD->isProtocolRequirement() &&
5584-
path[0].is<LocatorPathElt::Witness>() &&
5583+
if (VD->isProtocolRequirement() &&
5584+
path[0].is<LocatorPathElt::Witness>() &&
55855585
// Note that the condition below is very important,
55865586
// we need to wait until the very last moment to strip
55875587
// the concurrency annotations from the inner most type.
55885588
conversionsOrFixes.empty()) {
5589-
// Allow requirements to introduce `swift_attr` annotations
5590-
// (note that `swift_attr` in type contexts weren't supported
5591-
// before) and for witnesses to adopt them gradually by matching
5592-
// with a warning in non-strict concurrency mode.
5593-
if (!(Context.isSwiftVersionAtLeast(6) ||
5589+
bool hasAdjustments = false;
5590+
Type strippedLHS = lhs;
5591+
Type strippedRHS = rhs;
5592+
5593+
// When matching to an ObjC protocol requirement, allow requirements
5594+
// to introduce `swift_attr` annotations (note that `swift_attr` in
5595+
// type contexts weren't supported before) and for witnesses to
5596+
// adopt them gradually by matching with a warning in non-strict
5597+
// concurrency mode.
5598+
if (VD->isObjC() &&
5599+
!(Context.isSwiftVersionAtLeast(6) ||
55945600
Context.LangOpts.StrictConcurrencyLevel ==
55955601
StrictConcurrency::Complete)) {
5596-
auto strippedLHS = lhs->stripConcurrency(/*resursive=*/true,
5597-
/*dropGlobalActor=*/true);
5598-
auto strippedRHS = rhs->stripConcurrency(/*resursive=*/true,
5599-
/*dropGlobalActor=*/true);
5602+
strippedLHS = lhs->stripConcurrency(/*recursive=*/true,
5603+
/*dropGlobalActor=*/true);
5604+
strippedRHS = rhs->stripConcurrency(/*recursive=*/true,
5605+
/*dropGlobalActor=*/true);
5606+
hasAdjustments = true;
5607+
}
5608+
5609+
// Always allow @isolated(any) mismatches.
5610+
auto maybeRemoveIsolatedAny = [&](Type &ty) {
5611+
if (auto fnType = ty->getAs<AnyFunctionType>();
5612+
fnType && fnType->getIsolation().isErased()) {
5613+
ty = fnType->withExtInfo(fnType->getExtInfo()
5614+
.withIsolation(FunctionTypeIsolation::forNonIsolated()));
5615+
hasAdjustments = true;
5616+
}
5617+
};
5618+
maybeRemoveIsolatedAny(strippedLHS);
5619+
maybeRemoveIsolatedAny(strippedRHS);
5620+
5621+
if (hasAdjustments) {
56005622
auto result = matchTypes(strippedLHS, strippedRHS, matchKind,
56015623
flags | TMF_ApplyingFix, locator);
56025624
if (!result.isFailure()) {
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
// RUN: %target-swift-frontend -emit-silgen -enable-experimental-feature IsolatedAny %s -module-name test -swift-version 6 -disable-availability-checking | %FileCheck %s
2+
// REQUIRES: concurrency
3+
// REQUIRES: asserts
4+
5+
// rdar://125394096. This was a source compatibility failure in which adding
6+
// @isolated(any) to TaskGroup.addTask caused problems with a project that
7+
// introduced a protocol for different task group types.
8+
9+
struct A<T> {
10+
func enqueue(operation: @escaping @isolated(any) () async -> T) {}
11+
}
12+
13+
protocol Enqueuer {
14+
associatedtype Result
15+
func enqueue(operation: @escaping @Sendable () async -> Result)
16+
}
17+
18+
extension A : Enqueuer {}
19+
20+
// CHECK-LABEL: sil private [transparent] [thunk] [ossa] @$s4test1AVyxGAA8EnqueuerA2aEP7enqueue9operationy6ResultQzyYaYbc_tFTW :
21+
// CHECK: bb0(%0 : @guaranteed $@Sendable @async @callee_guaranteed @substituted <τ_0_0> () -> @out τ_0_0 for <τ_0_0>, %1 : $*A<τ_0_0>):
22+
// CHECK-NEXT: [[CONVERTED_FN:%.*]] = convert_function %0 : $@Sendable @async @callee_guaranteed @substituted <τ_0_0> () -> @out τ_0_0 for <τ_0_0> to $@Sendable @async @callee_guaranteed () -> @out τ_0_0
23+
// CHECK-NEXT: [[ISOLATION:%.*]] = enum $Optional<any Actor>, #Optional.none
24+
// CHECK-NEXT: [[FN_COPY:%.*]] = copy_value [[CONVERTED_FN]] : $@Sendable @async @callee_guaranteed () -> @out τ_0_0
25+
// CHECK-NEXT: // function_ref
26+
// CHECK-NEXT: [[THUNK:%.*]] = function_ref @$sxIeghHr_xIeAghHr_lTR
27+
// CHECK-NEXT: partial_apply [callee_guaranteed] [isolated_any] [[THUNK]]<τ_0_0>([[ISOLATION]], [[FN_COPY]])
28+
29+
// For completeness, test that we allow mismatches in the opposite
30+
// direction as well.
31+
32+
struct B<T> {
33+
func enqueue(operation: @escaping @Sendable () async -> T) {}
34+
}
35+
36+
protocol AnnotatedEnqueuer {
37+
associatedtype Result
38+
func enqueue(operation: @escaping @isolated(any) () async -> Result)
39+
}
40+
41+
extension B : AnnotatedEnqueuer {}
42+
43+
// CHECK-LABEL: sil private [transparent] [thunk] [ossa] @$s4test1BVyxGAA17AnnotatedEnqueuerA2aEP7enqueue9operationy6ResultQzyYaYbYAc_tFTW
44+
// CHECK: bb0(%0 : @guaranteed $@isolated(any) @Sendable @async @callee_guaranteed @substituted <τ_0_0> () -> @out τ_0_0 for <τ_0_0>, %1 : $*B<τ_0_0>):
45+
// CHECK-NEXT: [[FN_COPY:%.*]] = copy_value %0
46+
// CHECK-NEXT: convert_function [[FN_COPY]] : $@isolated(any) @Sendable @async @callee_guaranteed @substituted <τ_0_0> () -> @out τ_0_0 for <τ_0_0> to $@Sendable @async @callee_guaranteed @substituted <τ_0_0> () -> @out τ_0_0 for <τ_0_0>

0 commit comments

Comments
 (0)