1515#include " swift/AST/ASTWalker.h"
1616#include " swift/AST/DiagnosticsSIL.h"
1717#include " swift/AST/Expr.h"
18+ #include " swift/AST/ProtocolConformance.h"
19+ #include " swift/AST/SourceFile.h"
1820#include " swift/AST/Type.h"
1921#include " swift/Basic/FrozenMultiMap.h"
2022#include " swift/Basic/ImmutablePointerSet.h"
3537#include " swift/SILOptimizer/PassManager/Transforms.h"
3638#include " swift/SILOptimizer/Utils/PartitionUtils.h"
3739#include " swift/SILOptimizer/Utils/VariableNameUtils.h"
40+ #include " swift/Sema/Concurrency.h"
3841#include " llvm/ADT/DenseMap.h"
3942#include " llvm/Support/Debug.h"
4043
@@ -55,6 +58,33 @@ using Region = PartitionPrimitives::Region;
5558// MARK: Utilities
5659// ===----------------------------------------------------------------------===//
5760
61+ static std::optional<DiagnosticBehavior>
62+ getDiagnosticBehaviorLimitForValue (SILValue value) {
63+ auto *nom = value->getType ().getNominalOrBoundGenericNominal ();
64+ if (!nom)
65+ return {};
66+
67+ auto declRef = value->getFunction ()->getDeclRef ();
68+ if (!declRef)
69+ return {};
70+
71+ auto *fromDC = declRef.getInnermostDeclContext ();
72+ auto attributedImport = nom->findImport (fromDC);
73+ if (!attributedImport ||
74+ !attributedImport->options .contains (ImportFlags::Preconcurrency))
75+ return {};
76+
77+ if (auto *sourceFile = fromDC->getParentSourceFile ())
78+ sourceFile->setImportUsedPreconcurrency (*attributedImport);
79+
80+ if (hasExplicitSendableConformance (nom))
81+ return DiagnosticBehavior::Warning;
82+
83+ return attributedImport->module .importedModule ->isConcurrencyChecked ()
84+ ? DiagnosticBehavior::Warning
85+ : DiagnosticBehavior::Ignore;
86+ }
87+
5888static Expr *inferArgumentExprFromApplyExpr (ApplyExpr *sourceApply,
5989 FullApplySite fai,
6090 const Operand *op) {
@@ -438,14 +468,19 @@ class UseAfterTransferDiagnosticEmitter {
438468 emitUnknownPatternError ();
439469 }
440470
471+ std::optional<DiagnosticBehavior> getBehaviorLimit () const {
472+ return getDiagnosticBehaviorLimitForValue (transferOp->get ());
473+ }
474+
441475 void
442476 emitNamedIsolationCrossingError (SILLocation loc, Identifier name,
443477 SILIsolationInfo namedValuesIsolationInfo,
444478 ApplyIsolationCrossing isolationCrossing) {
445479 // Emit the short error.
446480 diagnoseError (loc, diag::regionbasedisolation_named_transfer_yields_race,
447481 name)
448- .highlight (loc.getSourceRange ());
482+ .highlight (loc.getSourceRange ())
483+ .limitBehaviorIf (getBehaviorLimit ());
449484
450485 // Then emit the note with greater context.
451486 SmallString<64 > descriptiveKindStr;
@@ -466,7 +501,8 @@ class UseAfterTransferDiagnosticEmitter {
466501 loc, diag::regionbasedisolation_transfer_yields_race_with_isolation,
467502 inferredType, isolationCrossing.getCallerIsolation (),
468503 isolationCrossing.getCalleeIsolation ())
469- .highlight (loc.getSourceRange ());
504+ .highlight (loc.getSourceRange ())
505+ .limitBehaviorIf (getBehaviorLimit ());
470506 emitRequireInstDiagnostics ();
471507 }
472508
@@ -475,7 +511,8 @@ class UseAfterTransferDiagnosticEmitter {
475511 // Emit the short error.
476512 diagnoseError (loc, diag::regionbasedisolation_named_transfer_yields_race,
477513 name)
478- .highlight (loc.getSourceRange ());
514+ .highlight (loc.getSourceRange ())
515+ .limitBehaviorIf (getBehaviorLimit ());
479516
480517 // Then emit the note with greater context.
481518 diagnoseNote (
@@ -493,7 +530,8 @@ class UseAfterTransferDiagnosticEmitter {
493530 diag::
494531 regionbasedisolation_transfer_yields_race_stronglytransferred_binding,
495532 inferredType)
496- .highlight (loc.getSourceRange ());
533+ .highlight (loc.getSourceRange ())
534+ .limitBehaviorIf (getBehaviorLimit ());
497535 emitRequireInstDiagnostics ();
498536 }
499537
@@ -502,7 +540,8 @@ class UseAfterTransferDiagnosticEmitter {
502540 diagnoseError (loc,
503541 diag::regionbasedisolation_transfer_yields_race_no_isolation,
504542 inferredType)
505- .highlight (loc.getSourceRange ());
543+ .highlight (loc.getSourceRange ())
544+ .limitBehaviorIf (getBehaviorLimit ());
506545 emitRequireInstDiagnostics ();
507546 }
508547
@@ -513,7 +552,8 @@ class UseAfterTransferDiagnosticEmitter {
513552 // Emit the short error.
514553 diagnoseError (loc, diag::regionbasedisolation_named_transfer_yields_race,
515554 name)
516- .highlight (loc.getSourceRange ());
555+ .highlight (loc.getSourceRange ())
556+ .limitBehaviorIf (getBehaviorLimit ());
517557
518558 SmallString<64 > descriptiveKindStr;
519559 {
@@ -535,13 +575,15 @@ class UseAfterTransferDiagnosticEmitter {
535575 diagnoseError (loc, diag::regionbasedisolation_isolated_capture_yields_race,
536576 inferredType, isolationCrossing.getCalleeIsolation (),
537577 isolationCrossing.getCallerIsolation ())
538- .highlight (loc.getSourceRange ());
578+ .highlight (loc.getSourceRange ())
579+ .limitBehaviorIf (getBehaviorLimit ());
539580 emitRequireInstDiagnostics ();
540581 }
541582
542583 void emitUnknownPatternError () {
543584 diagnoseError (transferOp->getUser (),
544- diag::regionbasedisolation_unknown_pattern);
585+ diag::regionbasedisolation_unknown_pattern)
586+ .limitBehaviorIf (getBehaviorLimit ());
545587 }
546588
547589private:
@@ -941,20 +983,26 @@ class TransferNonTransferrableDiagnosticEmitter {
941983 return info.nonTransferrable .dyn_cast <SILInstruction *>();
942984 }
943985
986+ std::optional<DiagnosticBehavior> getBehaviorLimit () const {
987+ return getDiagnosticBehaviorLimitForValue (info.transferredOperand ->get ());
988+ }
989+
944990 // / Return the isolation region info for \p getNonTransferrableValue().
945991 SILIsolationInfo getIsolationRegionInfo () const {
946992 return info.isolationRegionInfo ;
947993 }
948994
949995 void emitUnknownPatternError () {
950996 diagnoseError (getOperand ()->getUser (),
951- diag::regionbasedisolation_unknown_pattern);
997+ diag::regionbasedisolation_unknown_pattern)
998+ .limitBehaviorIf (getBehaviorLimit ());
952999 }
9531000
9541001 void emitUnknownUse (SILLocation loc) {
9551002 // TODO: This will eventually be an unknown pattern error.
956- diagnoseError (
957- loc, diag::regionbasedisolation_task_or_actor_isolated_transferred);
1003+ diagnoseError (loc,
1004+ diag::regionbasedisolation_task_or_actor_isolated_transferred)
1005+ .limitBehaviorIf (getBehaviorLimit ());
9581006 }
9591007
9601008 void emitFunctionArgumentApply (SILLocation loc, Type type,
@@ -967,7 +1015,8 @@ class TransferNonTransferrableDiagnosticEmitter {
9671015 diagnoseError (loc, diag::regionbasedisolation_arg_transferred,
9681016 StringRef (descriptiveKindStr), type,
9691017 crossing.getCalleeIsolation ())
970- .highlight (getOperand ()->getUser ()->getLoc ().getSourceRange ());
1018+ .highlight (getOperand ()->getUser ()->getLoc ().getSourceRange ())
1019+ .limitBehaviorIf (getBehaviorLimit ());
9711020 }
9721021
9731022 void emitNamedFunctionArgumentClosure (SILLocation loc, Identifier name,
@@ -995,13 +1044,15 @@ class TransferNonTransferrableDiagnosticEmitter {
9951044 auto diag =
9961045 diag::regionbasedisolation_arg_passed_to_strongly_transferred_param;
9971046 diagnoseError (loc, diag, descriptiveKindStr, type)
998- .highlight (getOperand ()->getUser ()->getLoc ().getSourceRange ());
1047+ .highlight (getOperand ()->getUser ()->getLoc ().getSourceRange ())
1048+ .limitBehaviorIf (getBehaviorLimit ());
9991049 }
10001050
10011051 void emitNamedOnlyError (SILLocation loc, Identifier name) {
10021052 diagnoseError (loc, diag::regionbasedisolation_named_transfer_yields_race,
10031053 name)
1004- .highlight (getOperand ()->getUser ()->getLoc ().getSourceRange ());
1054+ .highlight (getOperand ()->getUser ()->getLoc ().getSourceRange ())
1055+ .limitBehaviorIf (getBehaviorLimit ());
10051056 }
10061057
10071058 void emitNamedIsolation (SILLocation loc, Identifier name,
@@ -1176,7 +1227,7 @@ bool TransferNonTransferrableDiagnosticInferrer::run() {
11761227 if (!isolation) {
11771228 // Otherwise, emit a "we don't know error" that tells the user to file a
11781229 // bug.
1179- diagnoseError (op-> getUser (), diag::regionbasedisolation_unknown_pattern );
1230+ diagnosticEmitter. emitUnknownPatternError ( );
11801231 return false ;
11811232 }
11821233 assert (isolation && " Expected non-null" );
0 commit comments