@@ -491,10 +491,10 @@ class UseAfterTransferDiagnosticEmitter {
491491 emitUnknownPatternError ();
492492 }
493493
494- void emitNamedIsolationCrossingError (SILLocation loc, Identifier name,
495- SILIsolationInfo namesIsolationInfo ,
496- ApplyIsolationCrossing isolationCrossing ,
497- SILLocation variableDefinedLoc ) {
494+ void
495+ emitNamedIsolationCrossingError (SILLocation loc, Identifier name ,
496+ SILIsolationInfo namedValuesIsolationInfo ,
497+ ApplyIsolationCrossing isolationCrossing ) {
498498 // Emit the short error.
499499 diagnoseError (loc, diag::regionbasedisolation_named_transfer_yields_race,
500500 name)
@@ -504,7 +504,7 @@ class UseAfterTransferDiagnosticEmitter {
504504 SmallString<64 > descriptiveKindStr;
505505 {
506506 llvm::raw_svector_ostream os (descriptiveKindStr);
507- namesIsolationInfo .printForDiagnostics (os);
507+ namedValuesIsolationInfo .printForDiagnostics (os);
508508 }
509509 diagnoseNote (
510510 loc, diag::regionbasedisolation_named_info_transfer_yields_race, name,
@@ -523,7 +523,24 @@ class UseAfterTransferDiagnosticEmitter {
523523 emitRequireInstDiagnostics ();
524524 }
525525
526- void emitUseOfStronglyTransferredValue (SILLocation loc, Type inferredType) {
526+ void emitNamedUseOfStronglyTransferredValue (SILLocation loc,
527+ Identifier name) {
528+ // Emit the short error.
529+ diagnoseError (loc, diag::regionbasedisolation_named_transfer_yields_race,
530+ name)
531+ .highlight (loc.getSourceRange ());
532+
533+ // Then emit the note with greater context.
534+ diagnoseNote (
535+ loc, diag::regionbasedisolation_named_stronglytransferred_binding, name)
536+ .highlight (loc.getSourceRange ());
537+
538+ // Finally the require points.
539+ emitRequireInstDiagnostics ();
540+ }
541+
542+ void emitTypedUseOfStronglyTransferredValue (SILLocation loc,
543+ Type inferredType) {
527544 diagnoseError (
528545 loc,
529546 diag::
@@ -542,6 +559,29 @@ class UseAfterTransferDiagnosticEmitter {
542559 emitRequireInstDiagnostics ();
543560 }
544561
562+ void emitNamedIsolationCrossingDueToCapture (
563+ SILLocation loc, Identifier name,
564+ SILIsolationInfo namedValuesIsolationInfo,
565+ ApplyIsolationCrossing isolationCrossing) {
566+ // Emit the short error.
567+ diagnoseError (loc, diag::regionbasedisolation_named_transfer_yields_race,
568+ name)
569+ .highlight (loc.getSourceRange ());
570+
571+ SmallString<64 > descriptiveKindStr;
572+ {
573+ llvm::raw_svector_ostream os (descriptiveKindStr);
574+ namedValuesIsolationInfo.printForDiagnostics (os);
575+ }
576+
577+ diagnoseNote (
578+ loc, diag::regionbasedisolation_named_isolated_closure_yields_race,
579+ descriptiveKindStr, name, isolationCrossing.getCalleeIsolation (),
580+ isolationCrossing.getCallerIsolation ())
581+ .highlight (loc.getSourceRange ());
582+ emitRequireInstDiagnostics ();
583+ }
584+
545585 void emitTypedIsolationCrossingDueToCapture (
546586 SILLocation loc, Type inferredType,
547587 ApplyIsolationCrossing isolationCrossing) {
@@ -617,7 +657,7 @@ class UseAfterTransferDiagnosticInferrer {
617657 SILLocation baseLoc = SILLocation::invalid();
618658 Type baseInferredType;
619659
620- struct Walker ;
660+ struct AutoClosureWalker ;
621661
622662public:
623663 UseAfterTransferDiagnosticInferrer (
@@ -671,16 +711,25 @@ bool UseAfterTransferDiagnosticInferrer::initForIsolatedPartialApply(
671711 return false ;
672712
673713 unsigned opIndex = ApplySite (op->getUser ()).getAppliedArgIndex (*op);
714+ bool emittedDiagnostic = false ;
674715 for (auto &p : foundCapturedIsolationCrossing) {
675- if (std::get<1 >(p) == opIndex) {
676- diagnosticEmitter.emitTypedIsolationCrossingDueToCapture (
677- RegularLocation (std::get<0 >(p).getLoc ()), baseInferredType,
678- std::get<2 >(p));
679- return true ;
716+ if (std::get<1 >(p) != opIndex)
717+ continue ;
718+ emittedDiagnostic = true ;
719+
720+ if (auto rootValueAndName = inferNameAndRootFromValue (transferOp->get ())) {
721+ diagnosticEmitter.emitNamedIsolationCrossingDueToCapture (
722+ RegularLocation (std::get<0 >(p).getLoc ()), rootValueAndName->first ,
723+ transferOp->getIsolationInfo (), std::get<2 >(p));
724+ continue ;
680725 }
726+
727+ diagnosticEmitter.emitTypedIsolationCrossingDueToCapture (
728+ RegularLocation (std::get<0 >(p).getLoc ()), baseInferredType,
729+ std::get<2 >(p));
681730 }
682731
683- return false ;
732+ return emittedDiagnostic ;
684733}
685734
686735void UseAfterTransferDiagnosticInferrer::initForApply (Operand *op,
@@ -701,14 +750,19 @@ void UseAfterTransferDiagnosticInferrer::initForApply(Operand *op,
701750 isolationCrossing);
702751}
703752
704- struct UseAfterTransferDiagnosticInferrer ::Walker : ASTWalker {
753+ // / This walker visits an AutoClosureExpr and looks for uses of a specific
754+ // / captured value. We want to error on the uses in the autoclosure.
755+ struct UseAfterTransferDiagnosticInferrer ::AutoClosureWalker : ASTWalker {
705756 UseAfterTransferDiagnosticInferrer &foundTypeInfo;
706757 ValueDecl *targetDecl;
758+ SILIsolationInfo targetDeclIsolationInfo;
707759 SmallPtrSet<Expr *, 8 > visitedCallExprDeclRefExprs;
708760
709- Walker (UseAfterTransferDiagnosticInferrer &foundTypeInfo,
710- ValueDecl *targetDecl)
711- : foundTypeInfo(foundTypeInfo), targetDecl(targetDecl) {}
761+ AutoClosureWalker (UseAfterTransferDiagnosticInferrer &foundTypeInfo,
762+ ValueDecl *targetDecl,
763+ SILIsolationInfo targetDeclIsolationInfo)
764+ : foundTypeInfo(foundTypeInfo), targetDecl(targetDecl),
765+ targetDeclIsolationInfo (targetDeclIsolationInfo) {}
712766
713767 Expr *lookThroughExpr (Expr *expr) {
714768 while (true ) {
@@ -761,9 +815,9 @@ struct UseAfterTransferDiagnosticInferrer::Walker : ASTWalker {
761815 if (declRef->getDecl () == targetDecl) {
762816 // Found our target!
763817 visitedCallExprDeclRefExprs.insert (declRef);
764- foundTypeInfo.diagnosticEmitter .emitTypedIsolationCrossing (
765- foundTypeInfo.baseLoc , declRef-> findOriginalType (),
766- *isolationCrossing);
818+ foundTypeInfo.diagnosticEmitter .emitNamedIsolationCrossingError (
819+ foundTypeInfo.baseLoc , targetDecl-> getBaseIdentifier (),
820+ targetDeclIsolationInfo, *isolationCrossing);
767821 return Action::Continue (expr);
768822 }
769823 }
@@ -783,7 +837,16 @@ void UseAfterTransferDiagnosticInferrer::infer() {
783837 " We should never transfer an indirect out parameter" );
784838 if (fas.getArgumentParameterInfo (*transferOp->getOperand ())
785839 .hasOption (SILParameterInfo::Transferring)) {
786- return diagnosticEmitter.emitUseOfStronglyTransferredValue (
840+
841+ // First try to do the named diagnostic if we can find a name.
842+ if (auto rootValueAndName =
843+ inferNameAndRootFromValue (transferOp->get ())) {
844+ return diagnosticEmitter.emitNamedUseOfStronglyTransferredValue (
845+ baseLoc, rootValueAndName->first );
846+ }
847+
848+ // Otherwise, emit the typed diagnostic.
849+ return diagnosticEmitter.emitTypedUseOfStronglyTransferredValue (
787850 baseLoc, baseInferredType);
788851 }
789852 }
@@ -804,20 +867,9 @@ void UseAfterTransferDiagnosticInferrer::infer() {
804867 // Before we do anything further, see if we can find a name and emit a name
805868 // error.
806869 if (auto rootValueAndName = inferNameAndRootFromValue (transferOp->get ())) {
807- if (auto *svi =
808- dyn_cast<SingleValueInstruction>(rootValueAndName->second )) {
809- return diagnosticEmitter.emitNamedIsolationCrossingError (
810- baseLoc, rootValueAndName->first , transferOp->getIsolationInfo (),
811- *sourceApply->getIsolationCrossing (), svi->getLoc ());
812- }
813-
814- if (auto *fArg =
815- dyn_cast<SILFunctionArgument>(rootValueAndName->second )) {
816- return diagnosticEmitter.emitNamedIsolationCrossingError (
817- baseLoc, rootValueAndName->first , transferOp->getIsolationInfo (),
818- *sourceApply->getIsolationCrossing (),
819- RegularLocation (fArg ->getDecl ()->getLoc ()));
820- }
870+ return diagnosticEmitter.emitNamedIsolationCrossingError (
871+ baseLoc, rootValueAndName->first , transferOp->getIsolationInfo (),
872+ *sourceApply->getIsolationCrossing ());
821873 }
822874
823875 // Otherwise, try to infer from the ApplyExpr.
@@ -843,7 +895,7 @@ void UseAfterTransferDiagnosticInferrer::infer() {
843895 auto captureInfo =
844896 autoClosureExpr->getCaptureInfo ().getCaptures ()[captureIndex];
845897 auto *captureDecl = captureInfo.getDecl ();
846- Walker walker (*this , captureDecl);
898+ AutoClosureWalker walker (*this , captureDecl, transferOp-> getIsolationInfo () );
847899 autoClosureExpr->walk (walker);
848900}
849901
0 commit comments