@@ -575,6 +575,19 @@ class UseAfterTransferDiagnosticEmitter {
575
575
emitRequireInstDiagnostics ();
576
576
}
577
577
578
+ void emitNamedAsyncLetNoIsolationCrossingError (SILLocation loc,
579
+ Identifier name) {
580
+ // Emit the short error.
581
+ diagnoseError (loc, diag::regionbasedisolation_named_transfer_yields_race,
582
+ name)
583
+ .highlight (loc.getSourceRange ())
584
+ .limitBehaviorIf (getBehaviorLimit ());
585
+
586
+ diagnoseNote (
587
+ loc, diag::regionbasedisolation_named_nonisolated_asynclet_name, name);
588
+ emitRequireInstDiagnostics ();
589
+ }
590
+
578
591
void emitTypedIsolationCrossing (SILLocation loc, Type inferredType,
579
592
ApplyIsolationCrossing isolationCrossing) {
580
593
diagnoseError (
@@ -844,7 +857,7 @@ struct UseAfterTransferDiagnosticInferrer::AutoClosureWalker : ASTWalker {
844
857
: foundTypeInfo(foundTypeInfo), targetDecl(targetDecl),
845
858
targetDeclIsolationInfo (targetDeclIsolationInfo) {}
846
859
847
- Expr *lookThroughExpr (Expr *expr) {
860
+ Expr *lookThroughArgExpr (Expr *expr) {
848
861
while (true ) {
849
862
if (auto *memberRefExpr = dyn_cast<MemberRefExpr>(expr)) {
850
863
expr = memberRefExpr->getBase ();
@@ -872,67 +885,85 @@ struct UseAfterTransferDiagnosticInferrer::AutoClosureWalker : ASTWalker {
872
885
873
886
PreWalkResult<Expr *> walkToExprPre (Expr *expr) override {
874
887
if (auto *declRef = dyn_cast<DeclRefExpr>(expr)) {
875
- // If this decl ref expr was not visited as part of a callExpr, add it as
876
- // something without isolation crossing .
888
+ // If this decl ref expr was not visited as part of a callExpr and is our
889
+ // target decl... emit a simple async let error .
877
890
if (!visitedCallExprDeclRefExprs.count (declRef)) {
878
891
if (declRef->getDecl () == targetDecl) {
879
- visitedCallExprDeclRefExprs.insert (declRef);
880
892
foundTypeInfo.diagnosticEmitter
881
- .emitTypedRaceWithUnknownIsolationCrossing (
882
- foundTypeInfo.baseLoc , declRef-> findOriginalType ());
893
+ .emitNamedAsyncLetNoIsolationCrossingError (
894
+ foundTypeInfo.baseLoc , targetDecl-> getBaseIdentifier ());
883
895
return Action::Continue (expr);
884
896
}
885
897
}
886
898
}
887
899
900
+ // If we have a call expr, see if any of its arguments will cause our sent
901
+ // value to be transferred into another isolation domain.
888
902
if (auto *callExpr = dyn_cast<CallExpr>(expr)) {
889
- if (auto isolationCrossing = callExpr->getIsolationCrossing ()) {
890
- // Search callExpr's arguments to see if we have our targetDecl.
891
- auto *argList = callExpr->getArgs ();
892
- for (auto pair : llvm::enumerate (argList->getArgExprs ())) {
893
- auto *arg = lookThroughExpr (pair.value ());
894
- if (auto *declRef = dyn_cast<DeclRefExpr>(arg)) {
895
- if (declRef->getDecl () == targetDecl) {
896
- // Found our target!
897
- visitedCallExprDeclRefExprs.insert (declRef);
898
-
899
- // See if we can find a valueDecl/name for our callee so we can
900
- // emit a nicer error.
901
- ConcreteDeclRef concreteDecl =
902
- callExpr->getDirectCallee ()->getReferencedDecl ();
903
-
904
- // If we do not find a direct one, see if we are calling a method
905
- // on a nominal type.
906
- if (!concreteDecl) {
907
- if (auto *dot = dyn_cast<DotSyntaxCallExpr>(
908
- callExpr->getDirectCallee ())) {
909
- concreteDecl = dot->getSemanticFn ()->getReferencedDecl ();
910
- }
911
- }
912
-
913
- if (concreteDecl) {
914
- auto *valueDecl = concreteDecl.getDecl ();
915
- assert (valueDecl &&
916
- " Should be non-null if concreteDecl is valid" );
917
- if (valueDecl->hasName ()) {
918
- foundTypeInfo.diagnosticEmitter
919
- .emitNamedIsolationCrossingError (
920
- foundTypeInfo.baseLoc ,
921
- targetDecl->getBaseIdentifier (),
922
- targetDeclIsolationInfo, *isolationCrossing,
923
- valueDecl->getName (),
924
- valueDecl->getDescriptiveKind ());
925
- return Action::Continue (expr);
926
- }
927
- }
928
-
929
- // Otherwise default back to the "callee" error.
930
- foundTypeInfo.diagnosticEmitter .emitNamedIsolationCrossingError (
931
- foundTypeInfo.baseLoc , targetDecl->getBaseIdentifier (),
932
- targetDeclIsolationInfo, *isolationCrossing);
933
- return Action::Continue (expr);
934
- }
903
+ // Search callExpr's arguments to see if we have our targetDecl.
904
+ auto *argList = callExpr->getArgs ();
905
+ for (auto pair : llvm::enumerate (argList->getArgExprs ())) {
906
+ auto *arg = lookThroughArgExpr (pair.value ());
907
+ auto *declRef = dyn_cast<DeclRefExpr>(arg);
908
+ if (!declRef)
909
+ continue ;
910
+
911
+ if (declRef->getDecl () != targetDecl)
912
+ continue ;
913
+
914
+ // Found our target!
915
+ visitedCallExprDeclRefExprs.insert (declRef);
916
+
917
+ auto isolationCrossing = callExpr->getIsolationCrossing ();
918
+
919
+ // If we do not have an isolation crossing, then we must be just sending
920
+ // a value in a nonisolated fashion into an async let. So emit the
921
+ // simple async let error.
922
+ if (!isolationCrossing) {
923
+ foundTypeInfo.diagnosticEmitter
924
+ .emitNamedAsyncLetNoIsolationCrossingError (
925
+ foundTypeInfo.baseLoc , targetDecl->getBaseIdentifier ());
926
+ continue ;
927
+ }
928
+
929
+ // Otherwise, we are calling an actor isolated function in the async
930
+ // let. Emit a better error.
931
+
932
+ // See if we can find a valueDecl/name for our callee so we can
933
+ // emit a nicer error.
934
+ ConcreteDeclRef concreteDecl =
935
+ callExpr->getDirectCallee ()->getReferencedDecl ();
936
+
937
+ // If we do not find a direct one, see if we are calling a method
938
+ // on a nominal type.
939
+ if (!concreteDecl) {
940
+ if (auto *dot =
941
+ dyn_cast<DotSyntaxCallExpr>(callExpr->getDirectCallee ())) {
942
+ concreteDecl = dot->getSemanticFn ()->getReferencedDecl ();
943
+ }
944
+ }
945
+
946
+ if (!concreteDecl)
947
+ continue ;
948
+
949
+ auto *valueDecl = concreteDecl.getDecl ();
950
+ assert (valueDecl && " Should be non-null if concreteDecl is valid" );
951
+
952
+ if (auto isolationCrossing = callExpr->getIsolationCrossing ()) {
953
+ // If we have an isolation crossing, use that information.
954
+ if (valueDecl->hasName ()) {
955
+ foundTypeInfo.diagnosticEmitter .emitNamedIsolationCrossingError (
956
+ foundTypeInfo.baseLoc , targetDecl->getBaseIdentifier (),
957
+ targetDeclIsolationInfo, *isolationCrossing,
958
+ valueDecl->getName (), valueDecl->getDescriptiveKind ());
959
+ continue ;
935
960
}
961
+
962
+ // Otherwise default back to the "callee" error.
963
+ foundTypeInfo.diagnosticEmitter .emitNamedIsolationCrossingError (
964
+ foundTypeInfo.baseLoc , targetDecl->getBaseIdentifier (),
965
+ targetDeclIsolationInfo, *isolationCrossing);
966
+ continue ;
936
967
}
937
968
}
938
969
}
0 commit comments