@@ -574,6 +574,19 @@ class UseAfterTransferDiagnosticEmitter {
574574 emitRequireInstDiagnostics ();
575575 }
576576
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+
577590 void emitTypedIsolationCrossing (SILLocation loc, Type inferredType,
578591 ApplyIsolationCrossing isolationCrossing) {
579592 diagnoseError (
@@ -664,6 +677,11 @@ class UseAfterTransferDiagnosticEmitter {
664677 }
665678
666679 void emitUnknownPatternError () {
680+ if (shouldAbortOnUnknownPatternMatchError ()) {
681+ llvm::report_fatal_error (
682+ " RegionIsolation: Aborting on unknown pattern match error" );
683+ }
684+
667685 diagnoseError (transferOp->getUser (),
668686 diag::regionbasedisolation_unknown_pattern)
669687 .limitBehaviorIf (getBehaviorLimit ());
@@ -838,7 +856,7 @@ struct UseAfterTransferDiagnosticInferrer::AutoClosureWalker : ASTWalker {
838856 : foundTypeInfo(foundTypeInfo), targetDecl(targetDecl),
839857 targetDeclIsolationInfo (targetDeclIsolationInfo) {}
840858
841- Expr *lookThroughExpr (Expr *expr) {
859+ Expr *lookThroughArgExpr (Expr *expr) {
842860 while (true ) {
843861 if (auto *memberRefExpr = dyn_cast<MemberRefExpr>(expr)) {
844862 expr = memberRefExpr->getBase ();
@@ -866,67 +884,85 @@ struct UseAfterTransferDiagnosticInferrer::AutoClosureWalker : ASTWalker {
866884
867885 PreWalkResult<Expr *> walkToExprPre (Expr *expr) override {
868886 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 .
871889 if (!visitedCallExprDeclRefExprs.count (declRef)) {
872890 if (declRef->getDecl () == targetDecl) {
873- visitedCallExprDeclRefExprs.insert (declRef);
874891 foundTypeInfo.diagnosticEmitter
875- .emitTypedRaceWithUnknownIsolationCrossing (
876- foundTypeInfo.baseLoc , declRef-> findOriginalType ());
892+ .emitNamedAsyncLetNoIsolationCrossingError (
893+ foundTypeInfo.baseLoc , targetDecl-> getBaseIdentifier ());
877894 return Action::Continue (expr);
878895 }
879896 }
880897 }
881898
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.
882901 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 ;
929959 }
960+
961+ // Otherwise default back to the "callee" error.
962+ foundTypeInfo.diagnosticEmitter .emitNamedIsolationCrossingError (
963+ foundTypeInfo.baseLoc , targetDecl->getBaseIdentifier (),
964+ targetDeclIsolationInfo, *isolationCrossing);
965+ continue ;
930966 }
931967 }
932968 }
@@ -1058,6 +1094,11 @@ void TransferNonSendableImpl::emitUseAfterTransferDiagnostics() {
10581094 // tells the user to file a bug. This importantly ensures that we can
10591095 // guarantee that we always find the require if we successfully compile.
10601096 if (!didEmitRequireNote) {
1097+ if (shouldAbortOnUnknownPatternMatchError ()) {
1098+ llvm::report_fatal_error (
1099+ " RegionIsolation: Aborting on unknown pattern match error" );
1100+ }
1101+
10611102 diagnoseError (transferOp, diag::regionbasedisolation_unknown_pattern);
10621103 continue ;
10631104 }
@@ -1116,6 +1157,11 @@ class TransferNonTransferrableDiagnosticEmitter {
11161157 }
11171158
11181159 void emitUnknownPatternError () {
1160+ if (shouldAbortOnUnknownPatternMatchError ()) {
1161+ llvm::report_fatal_error (
1162+ " RegionIsolation: Aborting on unknown pattern match error" );
1163+ }
1164+
11191165 diagnoseError (getOperand ()->getUser (),
11201166 diag::regionbasedisolation_unknown_pattern)
11211167 .limitBehaviorIf (getBehaviorLimit ());
@@ -1601,6 +1647,11 @@ struct DiagnosticEvaluator final
16011647 }
16021648
16031649 void handleUnknownCodePattern (const PartitionOp &op) const {
1650+ if (shouldAbortOnUnknownPatternMatchError ()) {
1651+ llvm::report_fatal_error (
1652+ " RegionIsolation: Aborting on unknown pattern match error" );
1653+ }
1654+
16041655 diagnoseError (op.getSourceInst (),
16051656 diag::regionbasedisolation_unknown_pattern);
16061657 }
0 commit comments