Skip to content

Commit 2cd7a45

Browse files
authored
Merge pull request #79149 from jckarter/borrow-to-destructure-interior-pointer-order-of-operations
BorrowToDestructureTransform: Fix order of operations when placing borrows around InteriorPointerOperands.
2 parents 7ee5c15 + 1e37b67 commit 2cd7a45

File tree

3 files changed

+50
-13
lines changed

3 files changed

+50
-13
lines changed

include/swift/SIL/OwnershipUtils.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -893,9 +893,6 @@ class InteriorPointerOperandKind {
893893
/// object with guaranteed ownership. All transitive address uses of the
894894
/// interior pointer must be within the lifetime of the guaranteed lifetime. As
895895
/// such, these must be treated as implicit uses of the parent guaranteed value.
896-
///
897-
/// FIXME: This should probably also handle project_box once we support
898-
/// borrowing a box.
899896
struct InteriorPointerOperand {
900897
Operand *operand;
901898
InteriorPointerOperandKind kind;

lib/SILOptimizer/Mandatory/MoveOnlyBorrowToDestructureUtils.cpp

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1190,7 +1190,7 @@ void Implementation::rewriteUses(InstructionDeleter *deleter) {
11901190
LLVM_DEBUG(llvm::dbgs() << " Computed available values for block bb"
11911191
<< block->getDebugID() << '\n';
11921192
availableValues.print(llvm::dbgs(), " "));
1193-
// Then walk from the top to the bottom of the block rewriting as we go.
1193+
// Then walk from the beginning to the end of the block, rewriting as we go.
11941194
for (auto ii = block->begin(), ie = block->end(); ii != ie;) {
11951195
auto *inst = &*ii;
11961196
++ii;
@@ -1336,13 +1336,6 @@ void Implementation::rewriteUses(InstructionDeleter *deleter) {
13361336
borrowBuilder.createGuaranteedMoveOnlyWrapperToCopyableValue(
13371337
loc, value);
13381338
}
1339-
// NOTE: oldInst may be nullptr if our operand is a SILArgument
1340-
// which can happen with switch_enum.
1341-
auto *oldInst = operand.get()->getDefiningInstruction();
1342-
operand.set(value);
1343-
if (oldInst && deleter)
1344-
deleter->forceTrackAsDead(oldInst);
1345-
13461339
// If we have a terminator that is a trivial use (e.x.: we
13471340
// struct_extract a trivial value). Just put the end_borrow before the
13481341
// terminator.
@@ -1351,19 +1344,31 @@ void Implementation::rewriteUses(InstructionDeleter *deleter) {
13511344
operand.getOperandOwnership() == OperandOwnership::TrivialUse) {
13521345
SILBuilderWithScope endBuilder(inst);
13531346
endBuilder.createEndBorrow(getSafeLoc(inst), borrow);
1354-
continue;
1347+
goto update_operand;
13551348
} else {
13561349
// Otherwise, put the end_borrow.
13571350
for (auto *succBlock : ti->getSuccessorBlocks()) {
13581351
auto *nextInst = &succBlock->front();
13591352
SILBuilderWithScope endBuilder(nextInst);
13601353
endBuilder.createEndBorrow(getSafeLoc(nextInst), borrow);
13611354
}
1362-
continue;
1355+
goto update_operand;
13631356
}
13641357
}
13651358

13661359
insertEndBorrowsForNonConsumingUse(&operand, borrow);
1360+
update_operand:
1361+
// We update the operand after placing end_borrows, since we might
1362+
// need the original operand's lifetime to correctly delineate the
1363+
// new lifetime, such as if there is an InteriorPointerOperand.
1364+
1365+
// NOTE: oldInst may be nullptr if our operand is a SILArgument
1366+
// which can happen with switch_enum.
1367+
auto *oldInst = operand.get()->getDefiningInstruction();
1368+
operand.set(value);
1369+
if (oldInst && deleter)
1370+
deleter->forceTrackAsDead(oldInst);
1371+
13671372
continue;
13681373
}
13691374

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// rdar://133333278
2+
3+
// RUN: %target-swift-frontend -emit-sil -verify %s
4+
5+
public final class List<Element> where Element: ~Copyable {
6+
public private(set) var count: Int
7+
8+
@inlinable
9+
public var capacity: Int {
10+
return buffer.count
11+
}
12+
13+
@inlinable
14+
public static var defaultCapacity: Int { 2 }
15+
16+
@_alwaysEmitIntoClient
17+
private var buffer: UnsafeMutableBufferPointer<Element>
18+
19+
public init(emptyWithCapacity initialCapacity: Int = defaultCapacity) {
20+
precondition(initialCapacity >= 0)
21+
self.count = 0
22+
self.buffer = .allocate(capacity: initialCapacity)
23+
}
24+
}
25+
26+
private struct ListProcessor: ~Copyable {
27+
fileprivate struct ListElement {
28+
}
29+
30+
fileprivate var tasks: List<ListElement>
31+
fileprivate func process() {
32+
for _ in 0..<tasks.count {
33+
}
34+
}
35+
}

0 commit comments

Comments
 (0)