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