@@ -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 (
@@ -844,7 +857,7 @@ struct UseAfterTransferDiagnosticInferrer::AutoClosureWalker : ASTWalker {
844857 : foundTypeInfo(foundTypeInfo), targetDecl(targetDecl),
845858 targetDeclIsolationInfo (targetDeclIsolationInfo) {}
846859
847- Expr *lookThroughExpr (Expr *expr) {
860+ Expr *lookThroughArgExpr (Expr *expr) {
848861 while (true ) {
849862 if (auto *memberRefExpr = dyn_cast<MemberRefExpr>(expr)) {
850863 expr = memberRefExpr->getBase ();
@@ -872,67 +885,85 @@ struct UseAfterTransferDiagnosticInferrer::AutoClosureWalker : ASTWalker {
872885
873886 PreWalkResult<Expr *> walkToExprPre (Expr *expr) override {
874887 if (auto *declRef = dyn_cast<DeclRefExpr>(expr)) {
875- // If this decl ref expr was not visited as part of a callExpr, add it as
876- // 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 .
877890 if (!visitedCallExprDeclRefExprs.count (declRef)) {
878891 if (declRef->getDecl () == targetDecl) {
879- visitedCallExprDeclRefExprs.insert (declRef);
880892 foundTypeInfo.diagnosticEmitter
881- .emitTypedRaceWithUnknownIsolationCrossing (
882- foundTypeInfo.baseLoc , declRef-> findOriginalType ());
893+ .emitNamedAsyncLetNoIsolationCrossingError (
894+ foundTypeInfo.baseLoc , targetDecl-> getBaseIdentifier ());
883895 return Action::Continue (expr);
884896 }
885897 }
886898 }
887899
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.
888902 if (auto *callExpr = dyn_cast<CallExpr>(expr)) {
889- if (auto isolationCrossing = callExpr->getIsolationCrossing ()) {
890- // Search callExpr's arguments to see if we have our targetDecl.
891- auto *argList = callExpr->getArgs ();
892- for (auto pair : llvm::enumerate (argList->getArgExprs ())) {
893- auto *arg = lookThroughExpr (pair.value ());
894- if (auto *declRef = dyn_cast<DeclRefExpr>(arg)) {
895- if (declRef->getDecl () == targetDecl) {
896- // Found our target!
897- visitedCallExprDeclRefExprs.insert (declRef);
898-
899- // See if we can find a valueDecl/name for our callee so we can
900- // emit a nicer error.
901- ConcreteDeclRef concreteDecl =
902- callExpr->getDirectCallee ()->getReferencedDecl ();
903-
904- // If we do not find a direct one, see if we are calling a method
905- // on a nominal type.
906- if (!concreteDecl) {
907- if (auto *dot = dyn_cast<DotSyntaxCallExpr>(
908- callExpr->getDirectCallee ())) {
909- concreteDecl = dot->getSemanticFn ()->getReferencedDecl ();
910- }
911- }
912-
913- if (concreteDecl) {
914- auto *valueDecl = concreteDecl.getDecl ();
915- assert (valueDecl &&
916- " Should be non-null if concreteDecl is valid" );
917- if (valueDecl->hasName ()) {
918- foundTypeInfo.diagnosticEmitter
919- .emitNamedIsolationCrossingError (
920- foundTypeInfo.baseLoc ,
921- targetDecl->getBaseIdentifier (),
922- targetDeclIsolationInfo, *isolationCrossing,
923- valueDecl->getName (),
924- valueDecl->getDescriptiveKind ());
925- return Action::Continue (expr);
926- }
927- }
928-
929- // Otherwise default back to the "callee" error.
930- foundTypeInfo.diagnosticEmitter .emitNamedIsolationCrossingError (
931- foundTypeInfo.baseLoc , targetDecl->getBaseIdentifier (),
932- targetDeclIsolationInfo, *isolationCrossing);
933- return Action::Continue (expr);
934- }
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 ;
935960 }
961+
962+ // Otherwise default back to the "callee" error.
963+ foundTypeInfo.diagnosticEmitter .emitNamedIsolationCrossingError (
964+ foundTypeInfo.baseLoc , targetDecl->getBaseIdentifier (),
965+ targetDeclIsolationInfo, *isolationCrossing);
966+ continue ;
936967 }
937968 }
938969 }
0 commit comments