diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 74493186ea647..af73d0e907220 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -5875,7 +5875,7 @@ ASTContext::getOpenedExistentialSignature(Type type, GenericSignature parentSig) return found->second; auto genericParam = OpenedArchetypeType::getSelfInterfaceTypeFromContext( - canParentSig, type->getASTContext()) + canParentSig, *this) ->castTo(); Requirement requirement(RequirementKind::Conformance, genericParam, constraint); diff --git a/lib/AST/ASTDumper.cpp b/lib/AST/ASTDumper.cpp index e37496562f17e..e94b2e3df072e 100644 --- a/lib/AST/ASTDumper.cpp +++ b/lib/AST/ASTDumper.cpp @@ -1402,6 +1402,7 @@ namespace { printField(PD->getDefaultArgumentKind(), "default_arg"); } if (PD->hasDefaultExpr() && + PD->getDefaultArgumentCaptureInfo().hasBeenComputed() && !PD->getDefaultArgumentCaptureInfo().isTrivial()) { printFieldRaw([&](raw_ostream &OS) { PD->getDefaultArgumentCaptureInfo().print(OS); @@ -1488,7 +1489,8 @@ namespace { void printCommonAFD(AbstractFunctionDecl *D, const char *Type, StringRef Label) { printCommon(D, Type, Label, FuncColor); - if (!D->getCaptureInfo().isTrivial()) { + if (D->getCaptureInfo().hasBeenComputed() && + !D->getCaptureInfo().isTrivial()) { printFlagRaw([&](raw_ostream &OS) { D->getCaptureInfo().print(OS); }); @@ -2826,7 +2828,8 @@ class PrintExpr : public ExprVisitor, break; } - if (!E->getCaptureInfo().isTrivial()) { + if (E->getCaptureInfo().hasBeenComputed() && + !E->getCaptureInfo().isTrivial()) { printFieldRaw([&](raw_ostream &OS) { E->getCaptureInfo().print(OS); }, "", CapturesColor); diff --git a/lib/AST/ASTPrinter.cpp b/lib/AST/ASTPrinter.cpp index e692a86383e75..ae03dc01730f1 100644 --- a/lib/AST/ASTPrinter.cpp +++ b/lib/AST/ASTPrinter.cpp @@ -1683,14 +1683,11 @@ void PrintAST::printGenericSignature(GenericSignature genericSig, static void eraseInvertibleProtocolConformances( SmallVectorImpl &requirements) { llvm::erase_if(requirements, [&](Requirement req) { - if (req.getKind() == RequirementKind::Conformance) { - if (auto protoType = req.getSecondType()->getAs()) { - auto proto = protoType->getDecl(); - return proto->getInvertibleProtocolKind().has_value(); - } - } + if (req.getKind() != RequirementKind::Conformance) + return false; - return false; + return req.getProtocolDecl() + ->getInvertibleProtocolKind().has_value(); }); } diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index c28e4ef646fd4..a0f89a263d01c 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -954,7 +954,7 @@ Type TypeBase::stripConcurrency(bool recurse, bool dropGlobalActor) { // If it's a Sendable requirement, skip it. const auto &req = requirements[reqIdx]; if (req.getKind() == RequirementKind::Conformance && - req.getSecondType()->castTo()->getDecl() + req.getProtocolDecl() ->isSpecificProtocol(KnownProtocolKind::Sendable)) continue; diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp index 57d630445e162..ad420272dfcf8 100644 --- a/lib/Sema/CSSimplify.cpp +++ b/lib/Sema/CSSimplify.cpp @@ -10256,13 +10256,9 @@ performMemberLookup(ConstraintKind constraintKind, DeclNameRef memberName, if (req.getKind() != RequirementKind::Conformance) return false; - if (auto protocolTy = - req.getSecondType()->template getAs()) { - return req.getFirstType()->hasTypeVariable() && - protocolTy->getDecl()->isSpecificProtocol( - KnownProtocolKind::Sendable); - } - return false; + return (req.getFirstType()->hasTypeVariable() && + req.getProtocolDecl()->isSpecificProtocol( + KnownProtocolKind::Sendable)); })) { result.OverallResult = MemberLookupResult::Unsolved; return result; diff --git a/lib/Sema/TypeCheckConcurrency.cpp b/lib/Sema/TypeCheckConcurrency.cpp index 76d766810fd8b..fc78a38abc141 100644 --- a/lib/Sema/TypeCheckConcurrency.cpp +++ b/lib/Sema/TypeCheckConcurrency.cpp @@ -2624,9 +2624,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); } @@ -4249,7 +4263,9 @@ void swift::checkFunctionActorIsolation(AbstractFunctionDecl *decl) { ActorIsolationChecker checker(decl); if (auto body = decl->getBody()) { body->walk(checker); - if(ctx.LangOpts.hasFeature(Feature::GroupActorErrors)){ checker.diagnoseIsolationErrors(); } + if (ctx.LangOpts.hasFeature(Feature::GroupActorErrors)) { + checker.diagnoseIsolationErrors(); + } } if (auto ctor = dyn_cast(decl)) { if (auto superInit = ctor->getSuperInitCall()) @@ -5375,11 +5391,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/lib/Serialization/Deserialization.cpp b/lib/Serialization/Deserialization.cpp index f70be9efc28c9..976ca2461314e 100644 --- a/lib/Serialization/Deserialization.cpp +++ b/lib/Serialization/Deserialization.cpp @@ -987,7 +987,7 @@ ProtocolConformanceDeserializer::readNormalProtocolConformance( assert(!isa(dc->getModuleScopeContext()) && "should not have serialized a conformance from a clang module"); - Type conformingType = dc->getDeclaredInterfaceType(); + Type conformingType = dc->getSelfInterfaceType(); PrettyStackTraceType trace(ctx, "reading conformance for", conformingType); auto protoOrError = MF.getDeclChecked(protoID); 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