Skip to content

Commit 427a555

Browse files
committed
[move-only-address] When emitting a simple assignment, make sure to consume the move only type.
This was an oversight since I thought that `let _ = x` and `_ = x` were codegened in the same way. rdar://102491017
1 parent 20aa5b5 commit 427a555

File tree

3 files changed

+37
-5
lines changed

3 files changed

+37
-5
lines changed

lib/SILGen/SILGenExpr.cpp

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4758,7 +4758,19 @@ static void emitSimpleAssignment(SILGenFunction &SGF, SILLocation loc,
47584758
FormalEvaluationScope writeback(SGF);
47594759
auto srcLV = SGF.emitLValue(srcLoad->getSubExpr(),
47604760
SGFAccessKind::IgnoredRead);
4761-
(void) SGF.emitLoadOfLValue(loc, std::move(srcLV), SGFContext());
4761+
RValue rv = SGF.emitLoadOfLValue(loc, std::move(srcLV), SGFContext());
4762+
// If we have a move only type, we need to implode and perform a move to
4763+
// ensure we consume our argument as part of the assignment. Otherwise,
4764+
// we don't do anything.
4765+
if (rv.getLoweredType(SGF).isMoveOnly()) {
4766+
ManagedValue value = std::move(rv).getAsSingleValue(SGF, loc);
4767+
// If we have an address, then ensure plus one will create a temporary
4768+
// copy which will act as a consume of the address value. If we have
4769+
// an object, we need to insert our own move though.
4770+
value = value.ensurePlusOne(SGF, loc);
4771+
if (value.getType().isObject())
4772+
value = SGF.B.createMoveValue(loc, value);
4773+
}
47624774
return;
47634775
}
47644776

test/SILOptimizer/moveonly_addresschecker_diagnostics.swift

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2067,24 +2067,41 @@ public func closureAndClosureCaptureClassArgUseAfterConsume(_ x2: inout Klass) {
20672067
/////////////////////////////
20682068

20692069
func moveOperatorTest(_ k: __owned Klass) {
2070-
var k2 = k // expected-error {{'k2' consumed more than once}}
2070+
var k2 = k
2071+
// expected-error @-1 {{'k2' consumed more than once}}
2072+
// expected-error @-2 {{'k2' consumed more than once}}
2073+
// expected-error @-3 {{'k2' consumed more than once}}
20712074
k2 = Klass()
20722075
let k3 = _move k2 // expected-note {{consuming use}}
20732076
let _ = _move k2 // expected-note {{consuming use}}
2077+
_ = k2 // expected-note {{consuming use}}
2078+
let _ = k2
2079+
// expected-note @-1 {{consuming use}}
2080+
// expected-note @-2 {{consuming use}}
2081+
// expected-note @-3 {{consuming use}}
20742082
let _ = k3
20752083
}
20762084

20772085
/////////////////////////////////////////
20782086
// Black hole initialization test case//
20792087
/////////////////////////////////////////
20802088

2081-
func blackHoleTestCase(_ k: __owned Klass) {
2082-
var k2 = k // expected-error {{'k2' consumed more than once}}
2089+
func blackHoleKlassTestCase(_ k: __owned Klass) {
2090+
var k2 = k
20832091
// expected-error @-1 {{'k2' consumed more than once}}
2092+
// expected-error @-2 {{'k2' consumed more than once}}
2093+
// expected-error @-3 {{'k2' consumed more than once}}
2094+
// expected-error @-4 {{'k2' consumed more than once}}
20842095
let _ = k2 // expected-note {{consuming use}}
20852096
let _ = k2 // expected-note {{consuming use}}
20862097

20872098
k2 = Klass()
20882099
var _ = k2 // expected-note {{consuming use}}
20892100
var _ = k2 // expected-note {{consuming use}}
2101+
2102+
_ = k2 // expected-note {{consuming use}}
2103+
_ = k2
2104+
// expected-note @-1 {{consuming use}}
2105+
// expected-note @-2 {{consuming use}}
2106+
// expected-note @-3 {{consuming use}}
20902107
}

test/SILOptimizer/moveonly_deinits.swift

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,14 @@ struct MoveOnlyStruct {
1212
deinit { // expected-error {{'self' consumed more than once}}
1313
let x = self // expected-note {{consuming use}}
1414
_ = x
15-
var y = MoveOnlyStruct()
15+
var y = MoveOnlyStruct() // expected-error {{'y' consumed more than once}}
1616
y = self // expected-note {{consuming use}}
1717
// We get an infinite recursion since we are going to call our own
1818
// deinit here. We are just testing diagnostics here though.
1919
_ = y // expected-warning {{function call causes an infinite recursion}}
20+
// expected-note @-1 {{consuming use}}
21+
let z = y // expected-note {{consuming use}}
22+
let _ = z
2023
globalMoveOnlyStruct = self // expected-note {{consuming use}}
2124
} // expected-note {{consuming use}}
2225
}

0 commit comments

Comments
 (0)