Skip to content

Commit f025657

Browse files
authored
Merge pull request #72435 from gottesmm/pr-89ce065b7f50a41a58d8fb358d0145913d8b53a3
[region-isolation] Convert more diagnostics from type isolation form to named variable form
2 parents bd1b99b + 29e3069 commit f025657

16 files changed

+417
-163
lines changed

lib/SILOptimizer/Mandatory/TransferNonSendable.cpp

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -479,9 +479,6 @@ class UseAfterTransferDiagnosticEmitter {
479479
diag::regionbasedisolation_named_info_transfer_yields_race,
480480
name, isolationCrossing.getCallerIsolation(),
481481
isolationCrossing.getCalleeIsolation());
482-
// Then emit the note about where the variable is defined.
483-
diagnoseNote(variableDefinedLoc, diag::variable_defined_here,
484-
false /*variable*/);
485482
emitRequireInstDiagnostics();
486483
}
487484

lib/SILOptimizer/Utils/VariableNameUtils.cpp

Lines changed: 73 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,11 @@ findRootValueForNonTupleTempAllocation(AllocationInst *allocInst,
5151
}
5252
}
5353

54+
if (auto *sbi = dyn_cast<StoreBorrowInst>(&inst)) {
55+
if (sbi->getDest() == allocInst)
56+
return sbi->getSrc();
57+
}
58+
5459
// If we do not identify the write... return SILValue(). We weren't able
5560
// to understand the write.
5661
break;
@@ -128,6 +133,57 @@ static SILValue findRootValueForTupleTempAllocation(AllocationInst *allocInst,
128133

129134
if (auto *si = dyn_cast<StoreInst>(&inst)) {
130135
if (si->getOwnershipQualifier() != StoreOwnershipQualifier::Assign) {
136+
// Check if we are updating the entire tuple value.
137+
if (si->getDest() == allocInst) {
138+
// If we already found a root address (meaning we were processing
139+
// tuple_elt_addr), bail. We have some sort of unhandled mix of
140+
// copy_addr and store.
141+
if (foundRootAddress)
142+
return SILValue();
143+
144+
// If we already found a destructure, return SILValue(). We are
145+
// initializing twice.
146+
if (foundDestructure)
147+
return SILValue();
148+
149+
// We are looking for a pattern where we construct a tuple from
150+
// destructured parts.
151+
if (auto *ti = dyn_cast<TupleInst>(si->getSrc())) {
152+
for (auto p : llvm::enumerate(ti->getOperandValues())) {
153+
SILValue value = lookThroughOwnershipInsts(p.value());
154+
if (auto *dti = dyn_cast_or_null<DestructureTupleInst>(
155+
value->getDefiningInstruction())) {
156+
// We should always go through the same dti.
157+
if (foundDestructure && foundDestructure != dti)
158+
return SILValue();
159+
if (!foundDestructure)
160+
foundDestructure = dti;
161+
162+
// If we have a mixmatch of indices, we cannot look through.
163+
if (p.index() != dti->getIndexOfResult(value))
164+
return SILValue();
165+
if (tupleValues[p.index()])
166+
return SILValue();
167+
tupleValues[p.index()] = value;
168+
169+
// If we have completely covered the tuple, break.
170+
--numEltsLeft;
171+
if (!numEltsLeft)
172+
break;
173+
}
174+
}
175+
176+
// If we haven't completely covered the tuple, return SILValue(). We
177+
// should completely cover the tuple.
178+
if (numEltsLeft)
179+
return SILValue();
180+
181+
// Otherwise, break since we are done.
182+
break;
183+
}
184+
}
185+
186+
// If we store to a tuple_element_addr, update for a single value.
131187
if (auto *tei = dyn_cast<TupleElementAddrInst>(si->getDest())) {
132188
if (tei->getOperand() == allocInst) {
133189
unsigned i = tei->getFieldIndex();
@@ -183,7 +239,7 @@ static SILValue findRootValueForTupleTempAllocation(AllocationInst *allocInst,
183239

184240
SILValue VariableNameInferrer::getRootValueForTemporaryAllocation(
185241
AllocationInst *allocInst) {
186-
struct AddressWalker : public TransitiveAddressWalker<AddressWalker> {
242+
struct AddressWalker final : public TransitiveAddressWalker<AddressWalker> {
187243
AddressWalkerState &state;
188244

189245
AddressWalker(AddressWalkerState &state) : state(state) {}
@@ -194,6 +250,12 @@ SILValue VariableNameInferrer::getRootValueForTemporaryAllocation(
194250
return true;
195251
}
196252

253+
TransitiveUseVisitation visitTransitiveUseAsEndPointUse(Operand *use) {
254+
if (auto *sbi = dyn_cast<StoreBorrowInst>(use->getUser()))
255+
return TransitiveUseVisitation::OnlyUser;
256+
return TransitiveUseVisitation::OnlyUses;
257+
}
258+
197259
void onError(Operand *use) { state.foundError = true; }
198260
};
199261

@@ -288,6 +350,13 @@ SILValue VariableNameInferrer::findDebugInfoProvidingValueHelper(
288350
return allocInst;
289351
}
290352

353+
// If we have a store_borrow, always look at the dest. We are going to see
354+
// if we can determine if dest is a temporary alloc_stack.
355+
if (auto *sbi = dyn_cast<StoreBorrowInst>(searchValue)) {
356+
searchValue = sbi->getDest();
357+
continue;
358+
}
359+
291360
if (auto *globalAddrInst = dyn_cast<GlobalAddrInst>(searchValue)) {
292361
variableNamePath.push_back(globalAddrInst);
293362
return globalAddrInst;
@@ -487,7 +556,9 @@ SILValue VariableNameInferrer::findDebugInfoProvidingValueHelper(
487556
isa<ConvertFunctionInst>(searchValue) ||
488557
isa<MarkUninitializedInst>(searchValue) ||
489558
isa<CopyableToMoveOnlyWrapperAddrInst>(searchValue) ||
490-
isa<MoveOnlyWrapperToCopyableAddrInst>(searchValue)) {
559+
isa<MoveOnlyWrapperToCopyableAddrInst>(searchValue) ||
560+
isa<MoveOnlyWrapperToCopyableValueInst>(searchValue) ||
561+
isa<CopyableToMoveOnlyWrapperValueInst>(searchValue)) {
491562
searchValue = cast<SingleValueInstruction>(searchValue)->getOperand(0);
492563
continue;
493564
}

test/Concurrency/experimental_feature_strictconcurrency.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ struct Test2: TestProtocol { // expected-warning{{conformance of 'C2' to 'Sendab
2727

2828
@MainActor
2929
func iterate(stream: AsyncStream<Int>) async {
30-
nonisolated(unsafe) var it = stream.makeAsyncIterator() // expected-region-isolation-note {{variable defined here}}
30+
nonisolated(unsafe) var it = stream.makeAsyncIterator()
3131
// FIXME: Region isolation should consider a value from a 'nonisolated(unsafe)'
3232
// declaration to be in a disconnected region
3333

test/Concurrency/sendable_checking.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -274,7 +274,7 @@ final class NonSendable {
274274

275275
@available(SwiftStdlib 5.1, *)
276276
func testNonSendableBaseArg() async {
277-
let t = NonSendable() // expected-tns-note {{variable defined here}}
277+
let t = NonSendable()
278278
await t.update()
279279
// expected-targeted-and-complete-warning @-1 {{passing argument of non-sendable type 'NonSendable' into main actor-isolated context may introduce data races}}
280280
// expected-tns-warning @-2 {{transferring 't' may cause a race}}

0 commit comments

Comments
 (0)