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