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