@@ -1921,39 +1921,6 @@ static FuncDecl *findAnnotatableFunction(DeclContext *dc) {
1921
1921
return fn;
1922
1922
}
1923
1923
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
-
1957
1924
bool swift::diagnoseApplyArgSendability (ApplyExpr *apply, const DeclContext *declContext) {
1958
1925
auto isolationCrossing = apply->getIsolationCrossing ();
1959
1926
if (!isolationCrossing.has_value ())
@@ -2036,6 +2003,12 @@ namespace {
2036
2003
// / an expression or function.
2037
2004
llvm::SmallDenseMap<const DeclContext *, ActorIsolation> requiredIsolation;
2038
2005
2006
+ using IsolationPair = std::pair<ReferencedActor::Kind, ActorIsolation>;
2007
+
2008
+ using DiagnosticList = std::vector<IsolationError>;
2009
+
2010
+ llvm::DenseMap<IsolationPair, DiagnosticList> isoErrors;
2011
+
2039
2012
// / Keeps track of the capture context of variables that have been
2040
2013
// / explicitly captured in closures.
2041
2014
llvm::SmallDenseMap<VarDecl *, TinyPtrVector<const DeclContext *>>
@@ -2054,6 +2027,70 @@ namespace {
2054
2027
return applyStack.back ().dyn_cast <ApplyExpr *>();
2055
2028
}
2056
2029
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:
2057
2094
const PatternBindingDecl *getTopPatternBindingDecl () const {
2058
2095
return patternBindingStack.empty () ? nullptr : patternBindingStack.back ();
2059
2096
}
@@ -2385,6 +2422,8 @@ namespace {
2385
2422
requiredIsolationLoc = expr->getLoc ();
2386
2423
2387
2424
expr->walk (*this );
2425
+ // print all diagnostics here :)
2426
+ // diagnoseIsolationErrors(getDeclContext(), isoErrors);
2388
2427
requiredIsolationLoc = SourceLoc ();
2389
2428
return requiredIsolation[getDeclContext ()];
2390
2429
}
@@ -3203,11 +3242,11 @@ namespace {
3203
3242
.warnUntilSwiftVersionIf (getContextIsolation ().preconcurrency (), 6 );
3204
3243
}
3205
3244
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
+ // }
3211
3250
3212
3251
return true ;
3213
3252
}
@@ -3576,22 +3615,38 @@ namespace {
3576
3615
bool preconcurrencyContext =
3577
3616
result.options .contains (ActorReferenceResult::Flags::Preconcurrency);
3578
3617
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 ));
3594
3624
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
+ }
3595
3650
return true ;
3596
3651
}
3597
3652
}
@@ -3733,9 +3788,11 @@ void swift::checkFunctionActorIsolation(AbstractFunctionDecl *decl) {
3733
3788
if (decl->getAttrs ().hasAttribute <LLDBDebuggerFunctionAttr>())
3734
3789
return ;
3735
3790
3791
+ auto &ctx = decl->getASTContext ();
3736
3792
ActorIsolationChecker checker (decl);
3737
3793
if (auto body = decl->getBody ()) {
3738
3794
body->walk (checker);
3795
+ if (ctx.LangOpts .hasFeature (Feature::GroupActorErrors)){ checker.diagnoseIsolationErrors (); }
3739
3796
}
3740
3797
if (auto ctor = dyn_cast<ConstructorDecl>(decl)) {
3741
3798
if (auto superInit = ctor->getSuperInitCall ())
0 commit comments