@@ -575,6 +575,19 @@ class UseAfterTransferDiagnosticEmitter {
575575 emitRequireInstDiagnostics ();
576576 }
577577
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+
578591 void emitTypedIsolationCrossing (SILLocation loc, Type inferredType,
579592 ApplyIsolationCrossing isolationCrossing) {
580593 diagnoseError (
@@ -665,6 +678,11 @@ class UseAfterTransferDiagnosticEmitter {
665678 }
666679
667680 void emitUnknownPatternError () {
681+ if (AbortOnUnknownPatternMatchError) {
682+ llvm::report_fatal_error (
683+ " RegionIsolation: Aborting on unknown pattern match error" );
684+ }
685+
668686 diagnoseError (transferOp->getUser (),
669687 diag::regionbasedisolation_unknown_pattern)
670688 .limitBehaviorIf (getBehaviorLimit ());
@@ -839,7 +857,7 @@ struct UseAfterTransferDiagnosticInferrer::AutoClosureWalker : ASTWalker {
839857 : foundTypeInfo(foundTypeInfo), targetDecl(targetDecl),
840858 targetDeclIsolationInfo (targetDeclIsolationInfo) {}
841859
842- Expr *lookThroughExpr (Expr *expr) {
860+ Expr *lookThroughArgExpr (Expr *expr) {
843861 while (true ) {
844862 if (auto *memberRefExpr = dyn_cast<MemberRefExpr>(expr)) {
845863 expr = memberRefExpr->getBase ();
@@ -867,67 +885,85 @@ struct UseAfterTransferDiagnosticInferrer::AutoClosureWalker : ASTWalker {
867885
868886 PreWalkResult<Expr *> walkToExprPre (Expr *expr) override {
869887 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 .
872890 if (!visitedCallExprDeclRefExprs.count (declRef)) {
873891 if (declRef->getDecl () == targetDecl) {
874- visitedCallExprDeclRefExprs.insert (declRef);
875892 foundTypeInfo.diagnosticEmitter
876- .emitTypedRaceWithUnknownIsolationCrossing (
877- foundTypeInfo.baseLoc , declRef-> findOriginalType ());
893+ .emitNamedAsyncLetNoIsolationCrossingError (
894+ foundTypeInfo.baseLoc , targetDecl-> getBaseIdentifier ());
878895 return Action::Continue (expr);
879896 }
880897 }
881898 }
882899
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.
883902 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 ;
930960 }
961+
962+ // Otherwise default back to the "callee" error.
963+ foundTypeInfo.diagnosticEmitter .emitNamedIsolationCrossingError (
964+ foundTypeInfo.baseLoc , targetDecl->getBaseIdentifier (),
965+ targetDeclIsolationInfo, *isolationCrossing);
966+ continue ;
931967 }
932968 }
933969 }
@@ -1059,6 +1095,11 @@ void TransferNonSendableImpl::emitUseAfterTransferDiagnostics() {
10591095 // tells the user to file a bug. This importantly ensures that we can
10601096 // guarantee that we always find the require if we successfully compile.
10611097 if (!didEmitRequireNote) {
1098+ if (AbortOnUnknownPatternMatchError) {
1099+ llvm::report_fatal_error (
1100+ " RegionIsolation: Aborting on unknown pattern match error" );
1101+ }
1102+
10621103 diagnoseError (transferOp, diag::regionbasedisolation_unknown_pattern);
10631104 continue ;
10641105 }
@@ -1117,6 +1158,11 @@ class TransferNonTransferrableDiagnosticEmitter {
11171158 }
11181159
11191160 void emitUnknownPatternError () {
1161+ if (AbortOnUnknownPatternMatchError) {
1162+ llvm::report_fatal_error (
1163+ " RegionIsolation: Aborting on unknown pattern match error" );
1164+ }
1165+
11201166 diagnoseError (getOperand ()->getUser (),
11211167 diag::regionbasedisolation_unknown_pattern)
11221168 .limitBehaviorIf (getBehaviorLimit ());
@@ -1602,6 +1648,11 @@ struct DiagnosticEvaluator final
16021648 }
16031649
16041650 void handleUnknownCodePattern (const PartitionOp &op) const {
1651+ if (AbortOnUnknownPatternMatchError) {
1652+ llvm::report_fatal_error (
1653+ " RegionIsolation: Aborting on unknown pattern match error" );
1654+ }
1655+
16051656 diagnoseError (op.getSourceInst (),
16061657 diag::regionbasedisolation_unknown_pattern);
16071658 }
0 commit comments