@@ -1921,39 +1921,6 @@ static FuncDecl *findAnnotatableFunction(DeclContext *dc) {
19211921 return fn;
19221922}
19231923
1924- // / Note when the enclosing context could be put on a global actor.
1925- // FIXME: This should handle closures too.
1926- static void noteGlobalActorOnContext (DeclContext *dc, Type globalActor) {
1927- // If we are in a synchronous function on the global actor,
1928- // suggest annotating with the global actor itself.
1929- if (auto fn = findAnnotatableFunction (dc)) {
1930- // Suppress this for accessories because you can't change the
1931- // actor isolation of an individual accessor. Arguably we could
1932- // add this to the entire storage declaration, though.
1933- // Suppress this for async functions out of caution; but don't
1934- // suppress it if we looked through a defer.
1935- if (!isa<AccessorDecl>(fn) &&
1936- (!fn->isAsyncContext () || fn != dc)) {
1937- switch (getActorIsolation (fn)) {
1938- case ActorIsolation::ActorInstance:
1939- case ActorIsolation::GlobalActor:
1940- case ActorIsolation::GlobalActorUnsafe:
1941- case ActorIsolation::Nonisolated:
1942- case ActorIsolation::NonisolatedUnsafe:
1943- return ;
1944-
1945- case ActorIsolation::Unspecified:
1946- fn->diagnose (diag::note_add_globalactor_to_function,
1947- globalActor->getWithoutParens ().getString (),
1948- fn, globalActor)
1949- .fixItInsert (fn->getAttributeInsertionLoc (false ),
1950- diag::insert_globalactor_attr, globalActor);
1951- return ;
1952- }
1953- }
1954- }
1955- }
1956-
19571924bool swift::diagnoseApplyArgSendability (ApplyExpr *apply, const DeclContext *declContext) {
19581925 auto isolationCrossing = apply->getIsolationCrossing ();
19591926 if (!isolationCrossing.has_value ())
@@ -2036,6 +2003,12 @@ namespace {
20362003 // / an expression or function.
20372004 llvm::SmallDenseMap<const DeclContext *, ActorIsolation> requiredIsolation;
20382005
2006+ using IsolationPair = std::pair<ReferencedActor::Kind, ActorIsolation>;
2007+
2008+ using DiagnosticList = std::vector<IsolationError>;
2009+
2010+ llvm::DenseMap<IsolationPair, DiagnosticList> isoErrors;
2011+
20392012 // / Keeps track of the capture context of variables that have been
20402013 // / explicitly captured in closures.
20412014 llvm::SmallDenseMap<VarDecl *, TinyPtrVector<const DeclContext *>>
@@ -2054,6 +2027,70 @@ namespace {
20542027 return applyStack.back ().dyn_cast <ApplyExpr *>();
20552028 }
20562029
2030+ // / Note when the enclosing context could be put on a global actor.
2031+ // FIXME: This should handle closures too.
2032+ static bool missingGlobalActorOnContext (DeclContext *dc, Type globalActor) {
2033+ // If we are in a synchronous function on the global actor,
2034+ // suggest annotating with the global actor itself.
2035+ if (auto fn = findAnnotatableFunction (dc)) {
2036+ // Suppress this for accessories because you can't change the
2037+ // actor isolation of an individual accessor. Arguably we could
2038+ // add this to the entire storage declaration, though.
2039+ // Suppress this for async functions out of caution; but don't
2040+ // suppress it if we looked through a defer.
2041+ if (!isa<AccessorDecl>(fn) &&
2042+ (!fn->isAsyncContext () || fn != dc)) {
2043+ switch (getActorIsolation (fn)) {
2044+ case ActorIsolation::ActorInstance:
2045+ case ActorIsolation::GlobalActor:
2046+ case ActorIsolation::GlobalActorUnsafe:
2047+ case ActorIsolation::Nonisolated:
2048+ case ActorIsolation::NonisolatedUnsafe:
2049+ return false ;
2050+
2051+ case ActorIsolation::Unspecified:
2052+ fn->diagnose (diag::add_globalactor_to_function,
2053+ globalActor->getWithoutParens ().getString (),
2054+ fn, globalActor)
2055+ .fixItInsert (fn->getAttributeInsertionLoc (false ),
2056+ diag::insert_globalactor_attr, globalActor);
2057+ return true ;
2058+ }
2059+ }
2060+ }
2061+ return false ;
2062+ }
2063+
2064+ public:
2065+ bool diagnoseIsolationErrors () {
2066+ bool diagnosedError = false ;
2067+
2068+ for (auto list : isoErrors) {
2069+ IsolationPair key = list.getFirst ();
2070+ DiagnosticList errors = list.getSecond ();
2071+ ActorIsolation isolation = key.second ;
2072+
2073+ auto behavior = DiagnosticBehavior::Error;
2074+
2075+ // Add Fix-it for missing @SomeActor annotation
2076+ if (isolation.isGlobalActor ()) {
2077+ if (missingGlobalActorOnContext (
2078+ const_cast <DeclContext*>(getDeclContext ()), isolation.getGlobalActor ())) {
2079+ behavior= DiagnosticBehavior::Note;
2080+ }
2081+ }
2082+
2083+ for (IsolationError error : errors) {
2084+ // Diagnose actor_isolated_non_self_reference as note
2085+ // if we provide fix-it in missingGlobalActorOnContext
2086+ ctx.Diags .diagnose (error.loc , error.diag )
2087+ .limitBehavior (behavior);
2088+ }
2089+ }
2090+ return diagnosedError;
2091+ }
2092+
2093+ private:
20572094 const PatternBindingDecl *getTopPatternBindingDecl () const {
20582095 return patternBindingStack.empty () ? nullptr : patternBindingStack.back ();
20592096 }
@@ -2385,6 +2422,8 @@ namespace {
23852422 requiredIsolationLoc = expr->getLoc ();
23862423
23872424 expr->walk (*this );
2425+ // print all diagnostics here :)
2426+ // diagnoseIsolationErrors(getDeclContext(), isoErrors);
23882427 requiredIsolationLoc = SourceLoc ();
23892428 return requiredIsolation[getDeclContext ()];
23902429 }
@@ -3203,11 +3242,11 @@ namespace {
32033242 .warnUntilSwiftVersionIf (getContextIsolation ().preconcurrency (), 6 );
32043243 }
32053244
3206- if (unsatisfiedIsolation->isGlobalActor ()) {
3207- noteGlobalActorOnContext (
3208- const_cast <DeclContext *>(getDeclContext ()),
3209- unsatisfiedIsolation->getGlobalActor ());
3210- }
3245+ // if (unsatisfiedIsolation->isGlobalActor()) {
3246+ // noteGlobalActorOnContext(
3247+ // const_cast<DeclContext *>(getDeclContext()),
3248+ // unsatisfiedIsolation->getGlobalActor());
3249+ // }
32113250
32123251 return true ;
32133252 }
@@ -3576,22 +3615,38 @@ namespace {
35763615 bool preconcurrencyContext =
35773616 result.options .contains (ActorReferenceResult::Flags::Preconcurrency);
35783617
3579- ctx.Diags .diagnose (
3580- loc, diag::actor_isolated_non_self_reference,
3581- decl,
3582- useKind,
3583- refKind + 1 , refGlobalActor,
3584- result.isolation )
3585- .warnUntilSwiftVersionIf (preconcurrencyContext, 6 );
3586-
3587- noteIsolatedActorMember (decl, context);
3588-
3589- if (result.isolation .isGlobalActor ()) {
3590- noteGlobalActorOnContext (
3591- const_cast <DeclContext *>(getDeclContext ()),
3592- result.isolation .getGlobalActor ());
3593- }
3618+ if (ctx.LangOpts .hasFeature (Feature::GroupActorErrors)) {
3619+ IsolationError isoMismatch = IsolationError (loc, Diagnostic (diag::actor_isolated_non_self_reference,
3620+ decl,
3621+ useKind,
3622+ refKind + 1 , refGlobalActor,
3623+ result.isolation ));
35943624
3625+ auto iter = isoErrors.find (std::make_pair (refKind,result.isolation ));
3626+ if (iter != isoErrors.end ()){
3627+ iter->second .push_back (isoMismatch);
3628+ } else {
3629+ DiagnosticList list;
3630+ list.push_back (isoMismatch);
3631+ auto keyPair = std::make_pair (refKind,result.isolation );
3632+ isoErrors.insert (std::make_pair (keyPair, list));
3633+ }
3634+ } else {
3635+ ctx.Diags .diagnose (
3636+ loc, diag::actor_isolated_non_self_reference,
3637+ decl,
3638+ useKind,
3639+ refKind + 1 , refGlobalActor,
3640+ result.isolation )
3641+ .warnUntilSwiftVersionIf (preconcurrencyContext, 6 );
3642+
3643+ noteIsolatedActorMember (decl, context);
3644+ if (result.isolation .isGlobalActor ()) {
3645+ missingGlobalActorOnContext (
3646+ const_cast <DeclContext *>(getDeclContext ()),
3647+ result.isolation .getGlobalActor ());
3648+ }
3649+ }
35953650 return true ;
35963651 }
35973652 }
@@ -3733,9 +3788,11 @@ void swift::checkFunctionActorIsolation(AbstractFunctionDecl *decl) {
37333788 if (decl->getAttrs ().hasAttribute <LLDBDebuggerFunctionAttr>())
37343789 return ;
37353790
3791+ auto &ctx = decl->getASTContext ();
37363792 ActorIsolationChecker checker (decl);
37373793 if (auto body = decl->getBody ()) {
37383794 body->walk (checker);
3795+ if (ctx.LangOpts .hasFeature (Feature::GroupActorErrors)){ checker.diagnoseIsolationErrors (); }
37393796 }
37403797 if (auto ctor = dyn_cast<ConstructorDecl>(decl)) {
37413798 if (auto superInit = ctor->getSuperInitCall ())
0 commit comments