Skip to content

Commit 5712175

Browse files
committed
Concurrency: Contextualize initializers before checking actor isolation
Otherwise, we'll miss captures inside closures inside stored property initializer expressions.
1 parent ff89c71 commit 5712175

File tree

5 files changed

+36
-22
lines changed

5 files changed

+36
-22
lines changed

lib/Sema/TypeCheckConcurrency.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5369,11 +5369,9 @@ DefaultInitializerIsolation::evaluate(Evaluator &evaluator,
53695369
return ActorIsolation::forUnspecified();
53705370

53715371
auto i = pbd->getPatternEntryIndexForVarDecl(var);
5372-
if (!pbd->isInitializerChecked(i))
5373-
TypeChecker::typeCheckPatternBinding(pbd, i);
53745372

53755373
dc = cast<Initializer>(pbd->getInitContext(i));
5376-
initExpr = pbd->getInit(i);
5374+
initExpr = pbd->getCheckedAndContextualizedInit(i);
53775375
enclosingIsolation = getActorIsolation(var);
53785376
} else if (auto *param = dyn_cast<ParamDecl>(var)) {
53795377
// If this parameter corresponds to a stored property for a

lib/Sema/TypeCheckDeclPrimary.cpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2722,7 +2722,16 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
27222722

27232723
// Trigger a request that will complete typechecking for the
27242724
// initializer.
2725-
(void)PBD->getCheckedAndContextualizedInit(i);
2725+
(void) PBD->getCheckedAndContextualizedInit(i);
2726+
2727+
if (auto *var = PBD->getSingleVar()) {
2728+
if (var->hasAttachedPropertyWrapper())
2729+
return;
2730+
}
2731+
2732+
if (!PBD->getDeclContext()->isLocalContext()) {
2733+
(void) PBD->getInitializerIsolation(i);
2734+
}
27262735
}
27272736
}
27282737

lib/Sema/TypeCheckStorage.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -617,7 +617,6 @@ static void checkAndContextualizePatternBindingInit(PatternBindingDecl *binding,
617617
if (auto *initContext = binding->getInitContext(i)) {
618618
auto *init = binding->getInit(i);
619619
TypeChecker::contextualizeInitializer(initContext, init);
620-
(void)binding->getInitializerIsolation(i);
621620
TypeChecker::checkInitializerEffects(initContext, init);
622621
}
623622
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// RUN: %target-typecheck-verify-swift -swift-version 6
2+
3+
class NonSendable {} // expected-note 3{{class 'NonSendable' does not conform to the 'Sendable' protocol}}
4+
5+
func callee(_: @Sendable () -> NonSendable) {}
6+
7+
var testLocalCaptures: Int {
8+
let ns = NonSendable()
9+
10+
@Sendable func localFunc() -> NonSendable {
11+
return ns // expected-error {{capture of 'ns' with non-sendable type 'NonSendable' in a `@Sendable` local function}}
12+
}
13+
14+
callee { return ns } // expected-error {{capture of 'ns' with non-sendable type 'NonSendable' in a `@Sendable` closure}}
15+
16+
return 3
17+
}
18+
19+
struct Bad {
20+
var c: Int = {
21+
let ns = NonSendable()
22+
callee { return ns } // expected-error {{capture of 'ns' with non-sendable type 'NonSendable' in a `@Sendable` closure}}
23+
return 3
24+
}()
25+
}

test/Concurrency/sendable_checking_script_mode.swift

Lines changed: 0 additions & 17 deletions
This file was deleted.

0 commit comments

Comments
 (0)