Skip to content

Commit e2d59bd

Browse files
Merge pull request #81044 from nate-chandler/rdar141279635
6.2: [MoveOnly] Fix consumption of opened existentials.
2 parents ccefa62 + 875e67a commit e2d59bd

File tree

6 files changed

+42
-16
lines changed

6 files changed

+42
-16
lines changed

include/swift/SIL/SILInstruction.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7821,6 +7821,7 @@ class OpenExistentialAddrInst
78217821
}
78227822

78237823
OpenedExistentialAccess getAccessKind() const { return ForAccess; }
7824+
void setAccessKind(OpenedExistentialAccess kind) { ForAccess = kind; }
78247825

78257826
CanExistentialArchetypeType getDefinedOpenedArchetype() const {
78267827
const auto archetype = getOpenedArchetypeOf(getType().getASTType());

lib/SILOptimizer/Mandatory/MoveOnlyAddressCheckerUtils.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1899,7 +1899,7 @@ shouldEmitPartialMutationError(UseState &useState, PartialMutation::Kind kind,
18991899
// Otherwise, walk one level towards our child type. We unconditionally
19001900
// unwrap since we should never fail here due to earlier checking.
19011901
std::tie(iterPair, iterType) =
1902-
*pair.walkOneLevelTowardsChild(iterPair, iterType, fn);
1902+
*pair.walkOneLevelTowardsChild(iterPair, iterType, targetType, fn);
19031903
}
19041904

19051905
return {};
@@ -3431,6 +3431,10 @@ void MoveOnlyAddressCheckerPImpl::rewriteUses(
34313431
auto accessPath = AccessPathWithBase::computeInScope(copy->getSrc());
34323432
if (auto *access = dyn_cast_or_null<BeginAccessInst>(accessPath.base))
34333433
access->setAccessKind(SILAccessKind::Modify);
3434+
if (auto *oeai =
3435+
dyn_cast_or_null<OpenExistentialAddrInst>(copy->getSrc())) {
3436+
oeai->setAccessKind(OpenedExistentialAccess::Mutable);
3437+
}
34343438
copy->setIsTakeOfSrc(IsTake);
34353439
continue;
34363440
}

lib/SILOptimizer/Mandatory/MoveOnlyBorrowToDestructureUtils.cpp

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -877,7 +877,6 @@ AvailableValues &Implementation::computeAvailableValues(SILBasicBlock *block) {
877877
llvm::dbgs()
878878
<< " Destructuring available values in preds to smallest size for bb"
879879
<< block->getDebugID() << '\n');
880-
auto *fn = block->getFunction();
881880
IntervalMapAllocator::Map typeSpanToValue(getAllocator());
882881
for (auto *predBlock : predsSkippingBackEdges) {
883882
SWIFT_DEFER { typeSpanToValue.clear(); };
@@ -930,20 +929,10 @@ AvailableValues &Implementation::computeAvailableValues(SILBasicBlock *block) {
930929
// smallest offset size could result in further destructuring that an
931930
// earlier value required. Instead, we do a final loop afterwards using
932931
// the interval map to update each available value.
933-
auto iterType = iterValue->getType();
934932
auto loc = getSafeLoc(predBlock->getTerminator());
935933
SILBuilderWithScope builder(predBlock->getTerminator());
936934

937935
while (smallestOffsetSize->first.size < iterOffsetSize.size) {
938-
TypeOffsetSizePair childOffsetSize;
939-
SILType childType;
940-
941-
// We are returned an optional here and should never fail... so use a
942-
// force unwrap.
943-
std::tie(childOffsetSize, childType) =
944-
*iterOffsetSize.walkOneLevelTowardsChild(iterOffsetSize, iterType,
945-
fn);
946-
947936
// Before we destructure ourselves, erase our entire value from the
948937
// map. We do not need to consider the possibility of there being holes
949938
// in our range since we always store values whole to their entire
@@ -1401,8 +1390,8 @@ void Implementation::rewriteUses(InstructionDeleter *deleter) {
14011390

14021391
// Then walk one level towards our target type.
14031392
std::tie(iterOffsetSize, iterType) =
1404-
*useOffsetSize.walkOneLevelTowardsChild(parentOffsetSize,
1405-
iterType, fn);
1393+
*useOffsetSize.walkOneLevelTowardsChild(
1394+
parentOffsetSize, iterType, unwrappedOperandType, fn);
14061395

14071396
unsigned start = parentOffsetSize.startOffset;
14081397
consumeBuilder.emitDestructureValueOperation(

lib/SILOptimizer/Mandatory/MoveOnlyTypeUtils.cpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ static StructDecl *getFullyReferenceableStruct(SILType ktypeTy) {
2626
std::optional<std::pair<TypeOffsetSizePair, SILType>>
2727
TypeOffsetSizePair::walkOneLevelTowardsChild(
2828
TypeOffsetSizePair ancestorOffsetSize, SILType ancestorType,
29-
SILFunction *fn) const {
29+
SILType childType, SILFunction *fn) const {
3030
assert(ancestorOffsetSize.size >= size &&
3131
"Too large to be a child of ancestorType");
3232
assert((ancestorOffsetSize.startOffset <= startOffset &&
@@ -127,6 +127,16 @@ TypeOffsetSizePair::walkOneLevelTowardsChild(
127127
llvm_unreachable("Not a child of this enum?!");
128128
}
129129

130+
if (ancestorType.isExistentialType()) {
131+
assert(childType);
132+
auto childArchetypeType =
133+
childType.getASTType()->getAs<ExistentialArchetypeType>();
134+
assert(childArchetypeType);
135+
assert(childArchetypeType->getExistentialType()->getCanonicalType() ==
136+
ancestorType.getASTType());
137+
return {{ancestorOffsetSize, childType}};
138+
}
139+
130140
llvm_unreachable("Hit a leaf type?! Should have handled it earlier");
131141
}
132142

lib/SILOptimizer/Mandatory/MoveOnlyTypeUtils.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,8 @@ struct TypeOffsetSizePair {
6464
/// be a child type of \p ancestorType.
6565
std::optional<std::pair<TypeOffsetSizePair, SILType>>
6666
walkOneLevelTowardsChild(TypeOffsetSizePair ancestorOffsetSize,
67-
SILType ancestorType, SILFunction *fn) const;
67+
SILType ancestorType, SILType childType,
68+
SILFunction *fn) const;
6869

6970
/// Given an ancestor offset \p ancestorOffset and a type called \p
7071
/// ancestorType, walk one level towards this current type inserting on value,
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// RUN: %target-build-swift %s
2+
3+
protocol P: ~Copyable {
4+
var property: Bool { get }
5+
consuming func function()
6+
}
7+
8+
struct S: P, ~Copyable {
9+
var property: Bool { false }
10+
consuming func function() {}
11+
}
12+
13+
func g(s: consuming any P & ~Copyable) {
14+
let s = s
15+
s.function()
16+
}
17+
18+
func f() {
19+
let s = S()
20+
g(s: s)
21+
}

0 commit comments

Comments
 (0)