@@ -662,7 +662,8 @@ void UseAfterTransferDiagnosticInferrer::init(const Operand *op) {
662662
663663 auto *autoClosureExpr = loc.getAsASTNode <AutoClosureExpr>();
664664 if (!autoClosureExpr) {
665- llvm::report_fatal_error (" Transfer error emission missing a case?!" );
665+ diagnoseError (op->getUser (), diag::regionbasedisolation_unknown_pattern);
666+ return ;
666667 }
667668
668669 auto *i = const_cast <SILInstruction *>(op->getUser ());
@@ -710,6 +711,10 @@ class TransferNonTransferrableDiagnosticInferrer {
710711
711712 // / Used if we have a function argument that is transferred into an closure.
712713 FunctionArgumentClosure = 3 ,
714+
715+ // / Used if we have a function argument passed as an explicitly strongly
716+ // / transferring argument to a function.
717+ FunctionArgumentApplyStronglyTransferred = 4 ,
713718 };
714719
715720 struct UseDiagnosticInfo {
@@ -730,6 +735,11 @@ class TransferNonTransferrableDiagnosticInferrer {
730735 return {UseDiagnosticInfoKind::FunctionArgumentClosure, isolation};
731736 }
732737
738+ static UseDiagnosticInfo forFunctionArgumentApplyStronglyTransferred () {
739+ return {UseDiagnosticInfoKind::FunctionArgumentApplyStronglyTransferred,
740+ {}};
741+ }
742+
733743 private:
734744 UseDiagnosticInfo (UseDiagnosticInfoKind kind,
735745 std::optional<ActorIsolation> isolation)
@@ -747,7 +757,11 @@ class TransferNonTransferrableDiagnosticInferrer {
747757 : info(info),
748758 loc (info.transferredOperand->getUser ()->getLoc().getSourceLoc()) {}
749759
750- void run ();
760+ // / Gathers diagnostics. Returns false if we emitted a "I don't understand
761+ // / error". If we emit such an error, we should bail without emitting any
762+ // / further diagnostics, since we may not have any diagnostics or be in an
763+ // / inconcistent state.
764+ bool run ();
751765
752766 UseDiagnosticInfo getDiagnostic () const { return diagnosticInfo.value (); }
753767 SourceLoc getLoc () const { return loc; }
@@ -779,27 +793,55 @@ bool TransferNonTransferrableDiagnosticInferrer::initForIsolatedPartialApply(
779793 return false ;
780794}
781795
782- void TransferNonTransferrableDiagnosticInferrer::run () {
783- if (isa<SILFunctionArgument>(info.nonTransferrableValue )) {
784- // We need to find the isolation info.
785- auto loc = info.transferredOperand ->getUser ()->getLoc ();
796+ bool TransferNonTransferrableDiagnosticInferrer::run () {
797+ if (!isa<SILFunctionArgument>(info.nonTransferrableValue )) {
798+ diagnosticInfo = UseDiagnosticInfo::forMiscUse ();
799+ return true ;
800+ }
786801
787- if (auto *sourceApply = loc.getAsASTNode <ApplyExpr>()) {
788- diagnosticInfo = UseDiagnosticInfo::forFunctionArgumentApply (
789- sourceApply->getIsolationCrossing ().value ().getCalleeIsolation ());
790- return ;
791- }
802+ // We need to find the isolation info.
803+ auto loc = info.transferredOperand ->getUser ()->getLoc ();
792804
793- if (auto *ace = loc.getAsASTNode <AbstractClosureExpr>()) {
794- if (ace->getActorIsolation ().isActorIsolated ()) {
795- if (initForIsolatedPartialApply (info.transferredOperand , ace)) {
796- return ;
805+ if (auto *sourceApply = loc.getAsASTNode <ApplyExpr>()) {
806+ std::optional<ActorIsolation> isolation = {};
807+
808+ // First try to get the apply from the isolation crossing.
809+ if (auto value = sourceApply->getIsolationCrossing ())
810+ isolation = value->getCalleeIsolation ();
811+
812+ // If we could not infer an isolation...
813+ if (!isolation) {
814+ // First see if we have a transferring argument.
815+ if (auto fas = FullApplySite::isa (info.transferredOperand ->getUser ())) {
816+ if (fas.getArgumentParameterInfo (*info.transferredOperand )
817+ .hasOption (SILParameterInfo::Transferring)) {
818+ diagnosticInfo =
819+ UseDiagnosticInfo::forFunctionArgumentApplyStronglyTransferred ();
820+ return true ;
797821 }
798822 }
823+
824+ // Otherwise, emit a "we don't know error" that tells the user to file a
825+ // bug.
826+ diagnoseError (info.transferredOperand ->getUser (),
827+ diag::regionbasedisolation_unknown_pattern);
828+ return false ;
829+ }
830+
831+ diagnosticInfo = UseDiagnosticInfo::forFunctionArgumentApply (*isolation);
832+ return true ;
833+ }
834+
835+ if (auto *ace = loc.getAsASTNode <AbstractClosureExpr>()) {
836+ if (ace->getActorIsolation ().isActorIsolated ()) {
837+ if (initForIsolatedPartialApply (info.transferredOperand , ace)) {
838+ return true ;
839+ }
799840 }
800841 }
801842
802843 diagnosticInfo = UseDiagnosticInfo::forMiscUse ();
844+ return true ;
803845}
804846
805847// ===----------------------------------------------------------------------===//
@@ -941,6 +983,8 @@ void TransferNonSendableImpl::runDiagnosticEvaluator() {
941983 workingPartition.print (llvm::dbgs ()));
942984 }
943985
986+ LLVM_DEBUG (llvm::dbgs () << " Finished walking blocks for diagnostics.\n " );
987+
944988 // Now that we have found all of our transferInsts/Requires emit errors.
945989 transferOpToRequireInstMultiMap.setFrozen ();
946990}
@@ -1065,18 +1109,21 @@ void TransferNonSendableImpl::emitTransferredNonTransferrableDiagnostics() {
10651109 if (transferredNonTransferrable.empty ())
10661110 return ;
10671111
1112+ LLVM_DEBUG (
1113+ llvm::dbgs () << " Emitting transfer non transferrable diagnostics.\n " );
1114+
10681115 using UseDiagnosticInfoKind =
10691116 TransferNonTransferrableDiagnosticInferrer::UseDiagnosticInfoKind;
10701117
10711118 auto &astContext = regionInfo->getFunction ()->getASTContext ();
10721119 for (auto info : transferredNonTransferrable) {
10731120 auto *op = info.transferredOperand ;
10741121 TransferNonTransferrableDiagnosticInferrer diagnosticInferrer (info);
1075- diagnosticInferrer.run ();
1122+ if (!diagnosticInferrer.run ())
1123+ continue ;
10761124
10771125 auto diagnosticInfo = diagnosticInferrer.getDiagnostic ();
10781126 auto loc = diagnosticInferrer.getLoc ();
1079-
10801127 switch (diagnosticInfo.kind ) {
10811128 case UseDiagnosticInfoKind::Invalid:
10821129 llvm_unreachable (" Should never see this" );
@@ -1120,6 +1167,15 @@ void TransferNonSendableImpl::emitTransferredNonTransferrableDiagnostics() {
11201167 astContext, fArg ->getDecl ()->getLoc (),
11211168 diag::regionbasedisolation_isolated_since_in_same_region_basename,
11221169 " task isolated" , fArg ->getDecl ()->getBaseName ());
1170+ break ;
1171+ }
1172+ case UseDiagnosticInfoKind::FunctionArgumentApplyStronglyTransferred: {
1173+ diagnoseError (
1174+ astContext, loc,
1175+ diag::regionbasedisolation_arg_passed_to_strongly_transferred_param,
1176+ op->get ()->getType ().getASTType ())
1177+ .highlight (op->getUser ()->getLoc ().getSourceRange ());
1178+ break ;
11231179 }
11241180 }
11251181 }
0 commit comments