Skip to content

Commit 2f44b0a

Browse files
authored
Merge pull request #72641 from rjmccall/isolated-any-witness-mismatch
Allow @isolated(any) mismatches in witness matching.
2 parents 644c933 + b773c49 commit 2f44b0a

File tree

3 files changed

+64
-8
lines changed

3 files changed

+64
-8
lines changed

lib/Sema/CSSimplify.cpp

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3041,6 +3041,13 @@ matchFunctionThrowing(ConstraintSystem &cs,
30413041
}
30423042
}
30433043

3044+
static bool isWitnessMatching(ConstraintLocatorBuilder locator) {
3045+
SmallVector<LocatorPathElt, 4> path;
3046+
(void) locator.getLocatorParts(path);
3047+
return (path.size() == 1 &&
3048+
path[0].is<LocatorPathElt::Witness>());
3049+
}
3050+
30443051
bool
30453052
ConstraintSystem::matchFunctionIsolations(FunctionType *func1,
30463053
FunctionType *func2,
@@ -3054,8 +3061,11 @@ ConstraintSystem::matchFunctionIsolations(FunctionType *func1,
30543061
// function-conversion score to make sure this solution is worse than
30553062
// an exact match.
30563063
// FIXME: there may be a better way. see https://github.com/apple/swift/pull/62514
3057-
auto matchIfConversion = [&]() -> bool {
3058-
if (kind < ConstraintKind::Subtype)
3064+
auto matchIfConversion = [&](bool isErasure = false) -> bool {
3065+
// We generally require a conversion here, but allow some lassitude
3066+
// if we're doing witness-matching.
3067+
if (kind < ConstraintKind::Subtype &&
3068+
!(isErasure && isWitnessMatching(locator)))
30593069
return false;
30603070
increaseScore(SK_FunctionConversion, locator);
30613071
return true;
@@ -3154,7 +3164,7 @@ ConstraintSystem::matchFunctionIsolations(FunctionType *func1,
31543164
// isolation as a conversion.
31553165
case FunctionTypeIsolation::Kind::NonIsolated:
31563166
case FunctionTypeIsolation::Kind::GlobalActor:
3157-
return matchIfConversion();
3167+
return matchIfConversion(/*erasure*/ true);
31583168

31593169
// Parameter isolation is value-dependent and can't be erased in the
31603170
// abstract, though. We need to be able to recover the isolation from
@@ -5579,9 +5589,11 @@ bool ConstraintSystem::repairFailures(
55795589
}
55805590

55815591
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>() &&
5592+
// Matching a witness to an ObjC protocol requirement.
5593+
if (VD->isObjC() &&
5594+
isa<ProtocolDecl>(VD->getDeclContext()) &&
5595+
VD->isProtocolRequirement() &&
5596+
path[0].is<LocatorPathElt::Witness>() &&
55855597
// Note that the condition below is very important,
55865598
// we need to wait until the very last moment to strip
55875599
// the concurrency annotations from the inner most type.
@@ -5593,10 +5605,11 @@ bool ConstraintSystem::repairFailures(
55935605
if (!(Context.isSwiftVersionAtLeast(6) ||
55945606
Context.LangOpts.StrictConcurrencyLevel ==
55955607
StrictConcurrency::Complete)) {
5596-
auto strippedLHS = lhs->stripConcurrency(/*resursive=*/true,
5608+
auto strippedLHS = lhs->stripConcurrency(/*recursive=*/true,
55975609
/*dropGlobalActor=*/true);
5598-
auto strippedRHS = rhs->stripConcurrency(/*resursive=*/true,
5610+
auto strippedRHS = rhs->stripConcurrency(/*recursive=*/true,
55995611
/*dropGlobalActor=*/true);
5612+
56005613
auto result = matchTypes(strippedLHS, strippedRHS, matchKind,
56015614
flags | TMF_ApplyingFix, locator);
56025615
if (!result.isFailure()) {
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
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]])
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// RUN: %target-swift-frontend -typecheck -enable-experimental-feature IsolatedAny -verify %s
2+
3+
struct A<T> {
4+
// expected-note @+1 {{candidate has non-matching type}}
5+
func enqueue(operation: @escaping @Sendable () async -> T) {}
6+
}
7+
8+
protocol AnnotatedEnqueuer {
9+
associatedtype Result
10+
11+
// expected-note @+1 {{protocol requires function}}
12+
func enqueue(operation: @escaping @isolated(any) () async -> Result)
13+
}
14+
15+
// expected-error @+1 {{type 'A<T>' does not conform to protocol 'AnnotatedEnqueuer'}}
16+
extension A : AnnotatedEnqueuer {}

0 commit comments

Comments
 (0)