diff --git a/lib/Sema/TypeCheckConcurrency.cpp b/lib/Sema/TypeCheckConcurrency.cpp index 52a8ee024f86e..3894ada9b60dc 100644 --- a/lib/Sema/TypeCheckConcurrency.cpp +++ b/lib/Sema/TypeCheckConcurrency.cpp @@ -2610,9 +2610,23 @@ namespace { return MacroWalking::Expansion; } + PreWalkResult walkToPatternPre(Pattern *pattern) override { + // Walking into patterns leads to nothing good because then we + // end up visiting the AccessorDecls of a top-level + // PatternBindingDecl twice. + return Action::SkipNode(pattern); + } + PreWalkAction walkToDeclPre(Decl *decl) override { + // Don't walk into local types because nothing in them can + // change the outcome of our analysis, and we don't want to + // assume things there have been type checked yet. + if (isa(decl)) { + return Action::SkipChildren(); + } + if (auto func = dyn_cast(decl)) { - if (func->isLocalContext()) { + if (func->getDeclContext()->isLocalContext()) { checkLocalCaptures(func); } @@ -5355,11 +5369,9 @@ DefaultInitializerIsolation::evaluate(Evaluator &evaluator, return ActorIsolation::forUnspecified(); auto i = pbd->getPatternEntryIndexForVarDecl(var); - if (!pbd->isInitializerChecked(i)) - TypeChecker::typeCheckPatternBinding(pbd, i); dc = cast(pbd->getInitContext(i)); - initExpr = pbd->getInit(i); + initExpr = pbd->getCheckedAndContextualizedInit(i); enclosingIsolation = getActorIsolation(var); } else if (auto *param = dyn_cast(var)) { // If this parameter corresponds to a stored property for a diff --git a/lib/Sema/TypeCheckDeclPrimary.cpp b/lib/Sema/TypeCheckDeclPrimary.cpp index d4bf26dba1aed..a9825b0e47e7d 100644 --- a/lib/Sema/TypeCheckDeclPrimary.cpp +++ b/lib/Sema/TypeCheckDeclPrimary.cpp @@ -2722,7 +2722,16 @@ class DeclChecker : public DeclVisitor { // Trigger a request that will complete typechecking for the // initializer. - (void)PBD->getCheckedAndContextualizedInit(i); + (void) PBD->getCheckedAndContextualizedInit(i); + + if (auto *var = PBD->getSingleVar()) { + if (var->hasAttachedPropertyWrapper()) + return; + } + + if (!PBD->getDeclContext()->isLocalContext()) { + (void) PBD->getInitializerIsolation(i); + } } } diff --git a/lib/Sema/TypeCheckStmt.cpp b/lib/Sema/TypeCheckStmt.cpp index 2f7ed04579e6d..01d0370e4415d 100644 --- a/lib/Sema/TypeCheckStmt.cpp +++ b/lib/Sema/TypeCheckStmt.cpp @@ -2994,12 +2994,10 @@ bool TypeChecker::typeCheckTapBody(TapExpr *expr, DeclContext *DC) { } void TypeChecker::typeCheckTopLevelCodeDecl(TopLevelCodeDecl *TLCD) { - // We intentionally use typeCheckStmt instead of typeCheckBody here - // because we want to contextualize all the TopLevelCode - // declarations simultaneously. BraceStmt *Body = TLCD->getBody(); - StmtChecker(TLCD).typeCheckStmt(Body); + StmtChecker(TLCD).typeCheckBody(Body); TLCD->setBody(Body); + checkTopLevelActorIsolation(TLCD); checkTopLevelEffects(TLCD); performTopLevelDeclDiagnostics(TLCD); diff --git a/lib/Sema/TypeCheckStorage.cpp b/lib/Sema/TypeCheckStorage.cpp index 251d07439c0e9..a222632c54351 100644 --- a/lib/Sema/TypeCheckStorage.cpp +++ b/lib/Sema/TypeCheckStorage.cpp @@ -617,7 +617,6 @@ static void checkAndContextualizePatternBindingInit(PatternBindingDecl *binding, if (auto *initContext = binding->getInitContext(i)) { auto *init = binding->getInit(i); TypeChecker::contextualizeInitializer(initContext, init); - (void)binding->getInitializerIsolation(i); TypeChecker::checkInitializerEffects(initContext, init); } } diff --git a/lib/Sema/TypeChecker.cpp b/lib/Sema/TypeChecker.cpp index 3609bd5449fba..d0550ae9f82e8 100644 --- a/lib/Sema/TypeChecker.cpp +++ b/lib/Sema/TypeChecker.cpp @@ -284,7 +284,6 @@ TypeCheckSourceFileRequest::evaluate(Evaluator &eval, SourceFile *SF) const { for (auto D : SF->getTopLevelDecls()) { if (auto *TLCD = dyn_cast(D)) { TypeChecker::typeCheckTopLevelCodeDecl(TLCD); - TypeChecker::contextualizeTopLevelCode(TLCD); } else { TypeChecker::typeCheckDecl(D); } diff --git a/test/Concurrency/sendable_checking_captures.swift b/test/Concurrency/sendable_checking_captures.swift new file mode 100644 index 0000000000000..3df34012421da --- /dev/null +++ b/test/Concurrency/sendable_checking_captures.swift @@ -0,0 +1,25 @@ +// RUN: %target-typecheck-verify-swift -swift-version 6 + +class NonSendable {} // expected-note 3{{class 'NonSendable' does not conform to the 'Sendable' protocol}} + +func callee(_: @Sendable () -> NonSendable) {} + +var testLocalCaptures: Int { + let ns = NonSendable() + + @Sendable func localFunc() -> NonSendable { + return ns // expected-error {{capture of 'ns' with non-sendable type 'NonSendable' in a `@Sendable` local function}} + } + + callee { return ns } // expected-error {{capture of 'ns' with non-sendable type 'NonSendable' in a `@Sendable` closure}} + + return 3 +} + +struct Bad { + var c: Int = { + let ns = NonSendable() + callee { return ns } // expected-error {{capture of 'ns' with non-sendable type 'NonSendable' in a `@Sendable` closure}} + return 3 + }() +} \ No newline at end of file