Skip to content

Commit 61157cd

Browse files
authored
Merge pull request #83165 from xedin/nonisolated-nonseding-with-special-decls-6.2
[6.2][Concurrency] NonisolatedNonsendingByDefault: Infer `nonisolated(nonsending)` on declaration with special special semantics
2 parents 6516d94 + fb0daaa commit 61157cd

File tree

3 files changed

+94
-0
lines changed

3 files changed

+94
-0
lines changed

lib/Sema/TypeCheckConcurrency.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3543,6 +3543,28 @@ namespace {
35433543
if (auto isolationExpr = dyn_cast<CurrentContextIsolationExpr>(expr))
35443544
recordCurrentContextIsolation(isolationExpr);
35453545

3546+
// `withoutActuallyEscaping` parameter types are set to be
3547+
// `nonisolated(nonsending)` when the `NonisolatedNonsendingByDefault`
3548+
// feature is enabled, which means that we need to make the argument
3549+
// as `nonisolated(nonsending)` if it's a closure. This cannot be done
3550+
// sooner because we need to make sure that closure is definitely
3551+
// nonisolated and due to how AST is structured we cannot do this in
3552+
// `determineClosureIsolation`.
3553+
if (ctx.LangOpts.hasFeature(Feature::NonisolatedNonsendingByDefault)) {
3554+
if (auto *MTEE = dyn_cast<MakeTemporarilyEscapableExpr>(expr)) {
3555+
if (auto *call = dyn_cast<CallExpr>(MTEE->getSubExpr())) {
3556+
if (auto *closure = dyn_cast<ClosureExpr>(call->getFn())) {
3557+
if (auto closureTy = closure->getType()->getAs<FunctionType>()) {
3558+
if (closureTy->isAsync() &&
3559+
closure->getActorIsolation().isNonisolated())
3560+
closure->setActorIsolation(
3561+
ActorIsolation::forCallerIsolationInheriting());
3562+
}
3563+
}
3564+
}
3565+
}
3566+
}
3567+
35463568
return Action::Continue(expr);
35473569
}
35483570

lib/Sema/TypeOfReference.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2322,9 +2322,17 @@ static DeclReferenceType getTypeOfReferenceWithSpecialTypeCheckingSemantics(
23222322
CS.getConstraintLocator(locator, ConstraintLocator::ThrownErrorType),
23232323
0);
23242324
FunctionType::Param arg(escapeClosure);
2325+
2326+
auto bodyParamIsolation = FunctionTypeIsolation::forNonIsolated();
2327+
if (CS.getASTContext().LangOpts.hasFeature(
2328+
Feature::NonisolatedNonsendingByDefault)) {
2329+
bodyParamIsolation = FunctionTypeIsolation::forNonIsolatedCaller();
2330+
}
2331+
23252332
auto bodyClosure = FunctionType::get(arg, result,
23262333
FunctionType::ExtInfoBuilder()
23272334
.withNoEscape(true)
2335+
.withIsolation(bodyParamIsolation)
23282336
.withAsync(true)
23292337
.withThrows(true, thrownError)
23302338
.build());
@@ -2333,9 +2341,16 @@ static DeclReferenceType getTypeOfReferenceWithSpecialTypeCheckingSemantics(
23332341
FunctionType::Param(bodyClosure, CS.getASTContext().getIdentifier("do")),
23342342
};
23352343

2344+
auto withoutEscapingIsolation = FunctionTypeIsolation::forNonIsolated();
2345+
if (CS.getASTContext().LangOpts.hasFeature(
2346+
Feature::NonisolatedNonsendingByDefault)) {
2347+
withoutEscapingIsolation = FunctionTypeIsolation::forNonIsolatedCaller();
2348+
}
2349+
23362350
auto refType = FunctionType::get(args, result,
23372351
FunctionType::ExtInfoBuilder()
23382352
.withNoEscape(false)
2353+
.withIsolation(withoutEscapingIsolation)
23392354
.withAsync(true)
23402355
.withThrows(true, thrownError)
23412356
.build());
@@ -2359,20 +2374,36 @@ static DeclReferenceType getTypeOfReferenceWithSpecialTypeCheckingSemantics(
23592374
CS.getConstraintLocator(locator, ConstraintLocator::ThrownErrorType),
23602375
0);
23612376
FunctionType::Param bodyArgs[] = {FunctionType::Param(openedTy)};
2377+
2378+
auto bodyParamIsolation = FunctionTypeIsolation::forNonIsolated();
2379+
if (CS.getASTContext().LangOpts.hasFeature(
2380+
Feature::NonisolatedNonsendingByDefault)) {
2381+
bodyParamIsolation = FunctionTypeIsolation::forNonIsolatedCaller();
2382+
}
2383+
23622384
auto bodyClosure = FunctionType::get(bodyArgs, result,
23632385
FunctionType::ExtInfoBuilder()
23642386
.withNoEscape(true)
23652387
.withThrows(true, thrownError)
2388+
.withIsolation(bodyParamIsolation)
23662389
.withAsync(true)
23672390
.build());
23682391
FunctionType::Param args[] = {
23692392
FunctionType::Param(existentialTy),
23702393
FunctionType::Param(bodyClosure, CS.getASTContext().getIdentifier("do")),
23712394
};
2395+
2396+
auto openExistentialIsolation = FunctionTypeIsolation::forNonIsolated();
2397+
if (CS.getASTContext().LangOpts.hasFeature(
2398+
Feature::NonisolatedNonsendingByDefault)) {
2399+
openExistentialIsolation = FunctionTypeIsolation::forNonIsolatedCaller();
2400+
}
2401+
23722402
auto refType = FunctionType::get(args, result,
23732403
FunctionType::ExtInfoBuilder()
23742404
.withNoEscape(false)
23752405
.withThrows(true, thrownError)
2406+
.withIsolation(openExistentialIsolation)
23762407
.withAsync(true)
23772408
.build());
23782409
return {refType, refType, refType, refType, Type()};

test/Concurrency/attr_execution/attr_execution.swift

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,3 +80,44 @@ func testClosure() {
8080
takesClosure {
8181
}
8282
}
83+
84+
protocol P {
85+
}
86+
87+
func open<T: P>(_: T) async {}
88+
89+
// CHECK-LABEL: sil hidden [ossa] @$s14attr_execution19testOpenExistential11existentialyAA1P_p_tYaF : $@convention(thin) @async (@sil_isolated @sil_implicit_leading_param @guaranteed Optional<any Actor>, @in_guaranteed any P) -> ()
90+
// CHECK: bb0([[ISOLATION:%.*]] : @guaranteed $Optional<any Actor>, [[EXISTENTIAL:%.*]] : $*any P):
91+
// CHECK: [[OPEN_REF:%.*]] = function_ref @$s14attr_execution4openyyxYaAA1PRzlF
92+
// CHECK: apply [[OPEN_REF]]<@opened("{{.*}}", any P) Self>([[ISOLATION]], {{.*}})
93+
// CHECK: } // end sil function '$s14attr_execution19testOpenExistential11existentialyAA1P_p_tYaF'
94+
func testOpenExistential(existential: any P) async {
95+
await _openExistential(existential, do: open)
96+
}
97+
98+
func testWithoutActuallyEscaping(_ f: () async -> ()) async {
99+
// CHECK-LABEL: // closure #1 in testWithoutActuallyEscaping(_:)
100+
// CHECK-NEXT: // Isolation: caller_isolation_inheriting
101+
await withoutActuallyEscaping(f) {
102+
await $0()
103+
}
104+
105+
// CHECK-LABEL: // closure #2 in testWithoutActuallyEscaping(_:)
106+
// CHECK-NEXT: // Isolation: global_actor. type: MainActor
107+
await withoutActuallyEscaping(f) { @MainActor in
108+
await $0()
109+
}
110+
111+
actor Test {
112+
// CHECK-LABEL: // closure #1 in testActorIsolatedCapture() in Test #1 in testWithoutActuallyEscaping(_:)
113+
// CHECK-NEXT: // Isolation: actor_instance. name: 'self'
114+
func testActorIsolatedCapture() async {
115+
await withoutActuallyEscaping(compute) {
116+
_ = self
117+
await $0()
118+
}
119+
}
120+
121+
func compute() async {}
122+
}
123+
}

0 commit comments

Comments
 (0)