Skip to content

Commit f93d1b4

Browse files
committed
Bail out NRVO if _0 is mutated after the candidate assignement.
1 parent ee64f66 commit f93d1b4

File tree

4 files changed

+42
-7
lines changed

4 files changed

+42
-7
lines changed

Diff for: compiler/rustc_mir_transform/src/nrvo.rs

+12-4
Original file line numberDiff line numberDiff line change
@@ -147,15 +147,20 @@ fn find_local_assigned_to_return_place(start: BasicBlock, body: &mut Body<'_>) -
147147
if vis.seen_indirect {
148148
discard_borrowed_locals(&mut assigned_locals);
149149
}
150+
if assigned_locals.contains(RETURN_PLACE) {
151+
return None;
152+
}
150153

151154
for (statement_index, stmt) in bbdata.statements.iter().enumerate().rev() {
152155
if let StatementKind::Assign(box (lhs, ref rhs)) = stmt.kind
153156
&& lhs.as_local() == Some(RETURN_PLACE)
154-
&& let Rvalue::Use(rhs) = rhs
155-
&& let Some(rhs) = rhs.place()
156-
&& let Some(rhs) = rhs.as_local()
157-
&& !assigned_locals.contains(rhs)
158157
{
158+
let Rvalue::Use(rhs) = rhs else { return None };
159+
let rhs = rhs.place()?;
160+
let rhs = rhs.as_local()?;
161+
if assigned_locals.contains(rhs) {
162+
return None;
163+
}
159164
return Some(rhs);
160165
}
161166

@@ -165,6 +170,9 @@ fn find_local_assigned_to_return_place(start: BasicBlock, body: &mut Body<'_>) -
165170
if vis.seen_indirect {
166171
discard_borrowed_locals(&mut assigned_locals);
167172
}
173+
if assigned_locals.contains(RETURN_PLACE) {
174+
return None;
175+
}
168176
}
169177

170178
match body.basic_blocks.predecessors()[block].as_slice() {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
- // MIR for `constant` before RenameReturnPlace
2+
+ // MIR for `constant` after RenameReturnPlace
3+
4+
fn constant(_1: char) -> char {
5+
let mut _0: char;
6+
let mut _2: char;
7+
8+
bb0: {
9+
- _2 = _1;
10+
+ _0 = _1;
11+
_0 = const 'b';
12+
- _0 = _2;
13+
return;
14+
}
15+
}
16+

Diff for: tests/mir-opt/nrvo_miscompile_111005.multiple.RenameReturnPlace.diff

+2-3
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,8 @@
88

99
bb0: {
1010
_2 = _1;
11-
- _3 = _1;
12-
- _0 = _3;
13-
+ _0 = _1;
11+
_3 = _1;
12+
_0 = _3;
1413
_0 = _2;
1514
_2 = const 'b';
1615
return;

Diff for: tests/mir-opt/nrvo_miscompile_111005.rs

+12
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,17 @@ pub fn multiple(arg: char) -> char {
5454
})
5555
}
5656

57+
// EMIT_MIR nrvo_miscompile_111005.constant.RenameReturnPlace.diff
58+
#[custom_mir(dialect = "runtime", phase = "initial")]
59+
pub fn constant(arg: char) -> char {
60+
mir!({
61+
let temp = arg;
62+
RET = 'b';
63+
RET = temp;
64+
Return()
65+
})
66+
}
67+
5768
// EMIT_MIR nrvo_miscompile_111005.projection.RenameReturnPlace.diff
5869
#[custom_mir(dialect = "runtime", phase = "initial")]
5970
pub fn projection(arg: char) -> (char, u8) {
@@ -143,6 +154,7 @@ fn main() {
143154
assert_eq!(indirect('a'), 'a');
144155
assert_eq!(moved('a'), 'a');
145156
assert_eq!(multiple('a'), 'a');
157+
assert_eq!(constant('a'), 'a');
146158
assert_eq!(call('a'), 'a');
147159
assert_eq!(call_ok('a'), 'a');
148160
assert_eq!(multiple_return('a', true), 'z');

0 commit comments

Comments
 (0)