@@ -904,45 +904,58 @@ namespace {
904
904
return false ;
905
905
906
906
Expr *subArg = arg->getSubExpr ();
907
+ ValueDecl *valueDecl = nullptr ;
907
908
if (LookupExpr *baseArg = dyn_cast<LookupExpr>(subArg)) {
908
909
while (LookupExpr *nextLayer = dyn_cast<LookupExpr>(baseArg->getBase ()))
909
910
baseArg = nextLayer;
910
911
// subArg: the actual property being passed inout
911
912
// baseArg: the property in the actor who's property is being passed
912
913
// inout
913
914
914
- auto memberDecl = baseArg->getMember ().getDecl ();
915
- auto isolation = ActorIsolationRestriction::forDeclaration (memberDecl);
916
- switch (isolation) {
917
- case ActorIsolationRestriction::Unrestricted:
918
- case ActorIsolationRestriction::LocalCapture:
919
- case ActorIsolationRestriction::Unsafe:
920
- case ActorIsolationRestriction::GlobalActor: // TODO: handle global
921
- // actors
922
- break ;
923
- case ActorIsolationRestriction::ActorSelf: {
924
- if (isPartialApply) {
925
- // The partially applied InoutArg is a property of actor. This can
926
- // really only happen when the property is a struct with a mutating
927
- // async method.
928
- if (auto partialApply = dyn_cast<ApplyExpr>(call->getFn ())) {
929
- ValueDecl *fnDecl =
930
- cast<DeclRefExpr>(partialApply->getFn ())->getDecl ();
931
- ctx.Diags .diagnose (
932
- call->getLoc (), diag::actor_isolated_mutating_func,
933
- fnDecl->getName (), memberDecl->getDescriptiveKind (),
934
- memberDecl->getName ());
935
- return true ;
936
- }
937
- } else {
915
+ valueDecl = baseArg->getMember ().getDecl ();
916
+ } else if (DeclRefExpr *declExpr = dyn_cast<DeclRefExpr>(subArg)) {
917
+ valueDecl = declExpr->getDecl ();
918
+ } else {
919
+ llvm_unreachable (" Inout argument is neither a lookup nor decl." );
920
+ }
921
+ assert (valueDecl != nullptr && " valueDecl was never set!" );
922
+ auto isolation = ActorIsolationRestriction::forDeclaration (valueDecl);
923
+ switch (isolation) {
924
+ case ActorIsolationRestriction::Unrestricted:
925
+ case ActorIsolationRestriction::LocalCapture:
926
+ case ActorIsolationRestriction::Unsafe:
927
+ break ;
928
+ case ActorIsolationRestriction::GlobalActor: {
929
+ ctx.Diags .diagnose (call->getLoc (),
930
+ diag::actor_isolated_inout_state,
931
+ valueDecl->getDescriptiveKind (),
932
+ valueDecl->getName (),
933
+ call->implicitlyAsync ());
934
+ valueDecl->diagnose (diag::kind_declared_here,
935
+ valueDecl->getDescriptiveKind ());
936
+ return true ;
937
+ }
938
+ case ActorIsolationRestriction::ActorSelf: {
939
+ if (isPartialApply) {
940
+ // The partially applied InoutArg is a property of actor. This can
941
+ // really only happen when the property is a struct with a mutating
942
+ // async method.
943
+ if (auto partialApply = dyn_cast<ApplyExpr>(call->getFn ())) {
944
+ ValueDecl *fnDecl =
945
+ cast<DeclRefExpr>(partialApply->getFn ())->getDecl ();
938
946
ctx.Diags .diagnose (
939
- subArg ->getLoc (), diag::actor_isolated_inout_state ,
940
- memberDecl-> getDescriptiveKind (), memberDecl-> getName (),
941
- call-> implicitlyAsync ());
947
+ call ->getLoc (), diag::actor_isolated_mutating_func ,
948
+ fnDecl-> getName (), valueDecl-> getDescriptiveKind (),
949
+ valueDecl-> getName ());
942
950
return true ;
943
951
}
952
+ } else {
953
+ ctx.Diags .diagnose (
954
+ subArg->getLoc (), diag::actor_isolated_inout_state,
955
+ valueDecl->getDescriptiveKind (), valueDecl->getName (), call->implicitlyAsync ());
956
+ return true ;
944
957
}
945
- }
958
+ }
946
959
}
947
960
return false ;
948
961
}
0 commit comments