@@ -662,7 +662,8 @@ void UseAfterTransferDiagnosticInferrer::init(const Operand *op) {
662
662
663
663
auto *autoClosureExpr = loc.getAsASTNode <AutoClosureExpr>();
664
664
if (!autoClosureExpr) {
665
- llvm::report_fatal_error (" Transfer error emission missing a case?!" );
665
+ diagnoseError (op->getUser (), diag::regionbasedisolation_unknown_pattern);
666
+ return ;
666
667
}
667
668
668
669
auto *i = const_cast <SILInstruction *>(op->getUser ());
@@ -710,6 +711,10 @@ class TransferNonTransferrableDiagnosticInferrer {
710
711
711
712
// / Used if we have a function argument that is transferred into an closure.
712
713
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 ,
713
718
};
714
719
715
720
struct UseDiagnosticInfo {
@@ -730,6 +735,11 @@ class TransferNonTransferrableDiagnosticInferrer {
730
735
return {UseDiagnosticInfoKind::FunctionArgumentClosure, isolation};
731
736
}
732
737
738
+ static UseDiagnosticInfo forFunctionArgumentApplyStronglyTransferred () {
739
+ return {UseDiagnosticInfoKind::FunctionArgumentApplyStronglyTransferred,
740
+ {}};
741
+ }
742
+
733
743
private:
734
744
UseDiagnosticInfo (UseDiagnosticInfoKind kind,
735
745
std::optional<ActorIsolation> isolation)
@@ -747,7 +757,11 @@ class TransferNonTransferrableDiagnosticInferrer {
747
757
: info(info),
748
758
loc (info.transferredOperand->getUser ()->getLoc().getSourceLoc()) {}
749
759
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 ();
751
765
752
766
UseDiagnosticInfo getDiagnostic () const { return diagnosticInfo.value (); }
753
767
SourceLoc getLoc () const { return loc; }
@@ -779,27 +793,55 @@ bool TransferNonTransferrableDiagnosticInferrer::initForIsolatedPartialApply(
779
793
return false ;
780
794
}
781
795
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
+ }
786
801
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 ();
792
804
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 ;
797
821
}
798
822
}
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
+ }
799
840
}
800
841
}
801
842
802
843
diagnosticInfo = UseDiagnosticInfo::forMiscUse ();
844
+ return true ;
803
845
}
804
846
805
847
// ===----------------------------------------------------------------------===//
@@ -941,6 +983,8 @@ void TransferNonSendableImpl::runDiagnosticEvaluator() {
941
983
workingPartition.print (llvm::dbgs ()));
942
984
}
943
985
986
+ LLVM_DEBUG (llvm::dbgs () << " Finished walking blocks for diagnostics.\n " );
987
+
944
988
// Now that we have found all of our transferInsts/Requires emit errors.
945
989
transferOpToRequireInstMultiMap.setFrozen ();
946
990
}
@@ -1065,18 +1109,21 @@ void TransferNonSendableImpl::emitTransferredNonTransferrableDiagnostics() {
1065
1109
if (transferredNonTransferrable.empty ())
1066
1110
return ;
1067
1111
1112
+ LLVM_DEBUG (
1113
+ llvm::dbgs () << " Emitting transfer non transferrable diagnostics.\n " );
1114
+
1068
1115
using UseDiagnosticInfoKind =
1069
1116
TransferNonTransferrableDiagnosticInferrer::UseDiagnosticInfoKind;
1070
1117
1071
1118
auto &astContext = regionInfo->getFunction ()->getASTContext ();
1072
1119
for (auto info : transferredNonTransferrable) {
1073
1120
auto *op = info.transferredOperand ;
1074
1121
TransferNonTransferrableDiagnosticInferrer diagnosticInferrer (info);
1075
- diagnosticInferrer.run ();
1122
+ if (!diagnosticInferrer.run ())
1123
+ continue ;
1076
1124
1077
1125
auto diagnosticInfo = diagnosticInferrer.getDiagnostic ();
1078
1126
auto loc = diagnosticInferrer.getLoc ();
1079
-
1080
1127
switch (diagnosticInfo.kind ) {
1081
1128
case UseDiagnosticInfoKind::Invalid:
1082
1129
llvm_unreachable (" Should never see this" );
@@ -1120,6 +1167,15 @@ void TransferNonSendableImpl::emitTransferredNonTransferrableDiagnostics() {
1120
1167
astContext, fArg ->getDecl ()->getLoc (),
1121
1168
diag::regionbasedisolation_isolated_since_in_same_region_basename,
1122
1169
" 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 ;
1123
1179
}
1124
1180
}
1125
1181
}
0 commit comments