Skip to content

Commit b8ca381

Browse files
authored
Merge pull request #72546 from gottesmm/eliminate-rest-of-the-named-variants
[region-isolation] Add named variants to the rest of the diagnostics
2 parents f46e58a + 4f957fc commit b8ca381

8 files changed

+240
-145
lines changed

include/swift/AST/DiagnosticsSIL.def

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -949,7 +949,7 @@ ERROR(regionbasedisolation_isolated_capture_yields_race, none,
949949
"%1 closure captures value of non-Sendable type %0 from %2 context; later accesses to value could race",
950950
(Type, ActorIsolation, ActorIsolation))
951951
ERROR(regionbasedisolation_transfer_yields_race_stronglytransferred_binding, none,
952-
"binding of non-Sendable type %0 accessed after being transferred; later accesses could race",
952+
"value of non-Sendable type %0 accessed after being transferred; later accesses could race",
953953
(Type))
954954
ERROR(regionbasedisolation_arg_transferred, none,
955955
"%0 value of type %1 transferred to %2 context; later accesses to value could race",
@@ -981,6 +981,12 @@ NOTE(regionbasedisolation_named_transfer_into_transferring_param, none,
981981
NOTE(regionbasedisolation_named_notransfer_transfer_into_result, none,
982982
"%0 %1 cannot be a transferring result. %0 uses may race with caller uses",
983983
(StringRef, Identifier))
984+
NOTE(regionbasedisolation_named_stronglytransferred_binding, none,
985+
"%0 used after being passed as a transferring parameter; Later uses could race",
986+
(Identifier))
987+
NOTE(regionbasedisolation_named_isolated_closure_yields_race, none,
988+
"%0 %1 is captured by %2 closure. %2 uses in closure may race against later %3 uses",
989+
(StringRef, Identifier, ActorIsolation, ActorIsolation))
984990

985991
// Misc Error.
986992
ERROR(regionbasedisolation_task_or_actor_isolated_transferred, none,

lib/SILOptimizer/Mandatory/TransferNonSendable.cpp

Lines changed: 88 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -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

622662
public:
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

686735
void 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

test/ClangImporter/transferring.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,11 @@ func funcTestTransferringResult() async {
2828
let x2 = NonSendableCStruct()
2929
let y2 = returnUserDefinedFromGlobalFunction(x2)
3030
await transferToMain(x2) // expected-error {{transferring value of non-Sendable type 'NonSendableCStruct' from nonisolated context to main actor-isolated context}}
31-
useValue(y2) // expected-note {{access here could race}}
31+
useValue(y2) // expected-note {{use here could race}}
3232
}
3333

3434
func funcTestTransferringArg() async {
3535
let x = NonSendableCStruct()
36-
transferUserDefinedIntoGlobalFunction(x) // expected-error {{binding of non-Sendable type 'NonSendableCStruct' accessed after being transferred}}
37-
useValue(x) // expected-note {{access here could race}}
36+
transferUserDefinedIntoGlobalFunction(x) // expected-error {{value of non-Sendable type 'NonSendableCStruct' accessed after being transferred; later accesses could race}}
37+
useValue(x) // expected-note {{use here could race}}
3838
}

test/ClangImporter/transferring_objc.swift

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,9 @@ func methodTestTransferringResult() async {
2525
func methodTestTransferringArg() async {
2626
let x = MyType()
2727
let s = NSObject()
28-
let _ = x.getResultWithTransferringArgument(s) // expected-error {{binding of non-Sendable type 'NSObject' accessed after being transferred}}
29-
useValue(s) // expected-note {{access here could race}}
28+
let _ = x.getResultWithTransferringArgument(s) // expected-error {{transferring 's' may cause a race}}
29+
// expected-note @-1 {{'s' used after being passed as a transferring parameter; Later uses could race}}
30+
useValue(s) // expected-note {{use here could race}}
3031
}
3132

3233
// Make sure we just ignore the swift_attr if it is applied to something like a
@@ -46,11 +47,12 @@ func funcTestTransferringResult() async {
4647
let y2 = returnNSObjectFromGlobalFunction(x2)
4748
await transferToMain(x2) // expected-error {{transferring 'x2' may cause a race}}
4849
// expected-note @-1 {{transferring disconnected 'x2' to main actor-isolated callee could cause races in between callee main actor-isolated and local nonisolated uses}}
49-
useValue(y2) // expected-note {{access here could race}}
50+
useValue(y2) // expected-note {{use here could race}}
5051
}
5152

5253
func funcTestTransferringArg() async {
5354
let x = NSObject()
54-
transferNSObjectToGlobalFunction(x) // expected-error {{binding of non-Sendable type 'NSObject' accessed after being transferred}}
55-
useValue(x) // expected-note {{access here could race}}
55+
transferNSObjectToGlobalFunction(x) // expected-error {{transferring 'x' may cause a race}}
56+
// expected-note @-1 {{'x' used after being passed as a transferring parameter; Later uses could race}}
57+
useValue(x) // expected-note {{use here could race}}
5658
}

0 commit comments

Comments
 (0)