@@ -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 (
@@ -664,6 +677,11 @@ class UseAfterTransferDiagnosticEmitter {
664
677
}
665
678
666
679
void emitUnknownPatternError () {
680
+ if (shouldAbortOnUnknownPatternMatchError ()) {
681
+ llvm::report_fatal_error (
682
+ " RegionIsolation: Aborting on unknown pattern match error" );
683
+ }
684
+
667
685
diagnoseError (transferOp->getUser (),
668
686
diag::regionbasedisolation_unknown_pattern)
669
687
.limitBehaviorIf (getBehaviorLimit ());
@@ -838,7 +856,7 @@ struct UseAfterTransferDiagnosticInferrer::AutoClosureWalker : ASTWalker {
838
856
: foundTypeInfo(foundTypeInfo), targetDecl(targetDecl),
839
857
targetDeclIsolationInfo (targetDeclIsolationInfo) {}
840
858
841
- Expr *lookThroughExpr (Expr *expr) {
859
+ Expr *lookThroughArgExpr (Expr *expr) {
842
860
while (true ) {
843
861
if (auto *memberRefExpr = dyn_cast<MemberRefExpr>(expr)) {
844
862
expr = memberRefExpr->getBase ();
@@ -866,67 +884,85 @@ struct UseAfterTransferDiagnosticInferrer::AutoClosureWalker : ASTWalker {
866
884
867
885
PreWalkResult<Expr *> walkToExprPre (Expr *expr) override {
868
886
if (auto *declRef = dyn_cast<DeclRefExpr>(expr)) {
869
- // If this decl ref expr was not visited as part of a callExpr, add it as
870
- // 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 .
871
889
if (!visitedCallExprDeclRefExprs.count (declRef)) {
872
890
if (declRef->getDecl () == targetDecl) {
873
- visitedCallExprDeclRefExprs.insert (declRef);
874
891
foundTypeInfo.diagnosticEmitter
875
- .emitTypedRaceWithUnknownIsolationCrossing (
876
- foundTypeInfo.baseLoc , declRef-> findOriginalType ());
892
+ .emitNamedAsyncLetNoIsolationCrossingError (
893
+ foundTypeInfo.baseLoc , targetDecl-> getBaseIdentifier ());
877
894
return Action::Continue (expr);
878
895
}
879
896
}
880
897
}
881
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.
882
901
if (auto *callExpr = dyn_cast<CallExpr>(expr)) {
883
- if (auto isolationCrossing = callExpr->getIsolationCrossing ()) {
884
- // Search callExpr's arguments to see if we have our targetDecl.
885
- auto *argList = callExpr->getArgs ();
886
- for (auto pair : llvm::enumerate (argList->getArgExprs ())) {
887
- auto *arg = lookThroughExpr (pair.value ());
888
- if (auto *declRef = dyn_cast<DeclRefExpr>(arg)) {
889
- if (declRef->getDecl () == targetDecl) {
890
- // Found our target!
891
- visitedCallExprDeclRefExprs.insert (declRef);
892
-
893
- // See if we can find a valueDecl/name for our callee so we can
894
- // emit a nicer error.
895
- ConcreteDeclRef concreteDecl =
896
- callExpr->getDirectCallee ()->getReferencedDecl ();
897
-
898
- // If we do not find a direct one, see if we are calling a method
899
- // on a nominal type.
900
- if (!concreteDecl) {
901
- if (auto *dot = dyn_cast<DotSyntaxCallExpr>(
902
- callExpr->getDirectCallee ())) {
903
- concreteDecl = dot->getSemanticFn ()->getReferencedDecl ();
904
- }
905
- }
906
-
907
- if (concreteDecl) {
908
- auto *valueDecl = concreteDecl.getDecl ();
909
- assert (valueDecl &&
910
- " Should be non-null if concreteDecl is valid" );
911
- if (valueDecl->hasName ()) {
912
- foundTypeInfo.diagnosticEmitter
913
- .emitNamedIsolationCrossingError (
914
- foundTypeInfo.baseLoc ,
915
- targetDecl->getBaseIdentifier (),
916
- targetDeclIsolationInfo, *isolationCrossing,
917
- valueDecl->getName (),
918
- valueDecl->getDescriptiveKind ());
919
- return Action::Continue (expr);
920
- }
921
- }
922
-
923
- // Otherwise default back to the "callee" error.
924
- foundTypeInfo.diagnosticEmitter .emitNamedIsolationCrossingError (
925
- foundTypeInfo.baseLoc , targetDecl->getBaseIdentifier (),
926
- targetDeclIsolationInfo, *isolationCrossing);
927
- return Action::Continue (expr);
928
- }
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 ;
929
959
}
960
+
961
+ // Otherwise default back to the "callee" error.
962
+ foundTypeInfo.diagnosticEmitter .emitNamedIsolationCrossingError (
963
+ foundTypeInfo.baseLoc , targetDecl->getBaseIdentifier (),
964
+ targetDeclIsolationInfo, *isolationCrossing);
965
+ continue ;
930
966
}
931
967
}
932
968
}
@@ -1058,6 +1094,11 @@ void TransferNonSendableImpl::emitUseAfterTransferDiagnostics() {
1058
1094
// tells the user to file a bug. This importantly ensures that we can
1059
1095
// guarantee that we always find the require if we successfully compile.
1060
1096
if (!didEmitRequireNote) {
1097
+ if (shouldAbortOnUnknownPatternMatchError ()) {
1098
+ llvm::report_fatal_error (
1099
+ " RegionIsolation: Aborting on unknown pattern match error" );
1100
+ }
1101
+
1061
1102
diagnoseError (transferOp, diag::regionbasedisolation_unknown_pattern);
1062
1103
continue ;
1063
1104
}
@@ -1116,6 +1157,11 @@ class TransferNonTransferrableDiagnosticEmitter {
1116
1157
}
1117
1158
1118
1159
void emitUnknownPatternError () {
1160
+ if (shouldAbortOnUnknownPatternMatchError ()) {
1161
+ llvm::report_fatal_error (
1162
+ " RegionIsolation: Aborting on unknown pattern match error" );
1163
+ }
1164
+
1119
1165
diagnoseError (getOperand ()->getUser (),
1120
1166
diag::regionbasedisolation_unknown_pattern)
1121
1167
.limitBehaviorIf (getBehaviorLimit ());
@@ -1601,6 +1647,11 @@ struct DiagnosticEvaluator final
1601
1647
}
1602
1648
1603
1649
void handleUnknownCodePattern (const PartitionOp &op) const {
1650
+ if (shouldAbortOnUnknownPatternMatchError ()) {
1651
+ llvm::report_fatal_error (
1652
+ " RegionIsolation: Aborting on unknown pattern match error" );
1653
+ }
1654
+
1604
1655
diagnoseError (op.getSourceInst (),
1605
1656
diag::regionbasedisolation_unknown_pattern);
1606
1657
}
0 commit comments