Skip to content

Commit fd287d2

Browse files
authored
Rollup merge of rust-lang#120773 - Enselic:copy-vs-move, r=oli-obk
large_assignments: Allow moves into functions Moves into functions are typically implemented with pointer passing rather than memcpy's at the llvm-ir level, so allow moves into functions. Part of the "Differentiate between Operand::Move and Operand::Copy" step of rust-lang#83518. r? `@oli-obk` (who I think is still E-mentor?)
2 parents e525bc9 + a4fbd01 commit fd287d2

9 files changed

+147
-38
lines changed

compiler/rustc_monomorphize/src/collector.rs

+9-1
Original file line numberDiff line numberDiff line change
@@ -666,7 +666,15 @@ impl<'a, 'tcx> MirUsedCollector<'a, 'tcx> {
666666
debug!(?def_id, ?fn_span);
667667

668668
for arg in args {
669-
if let Some(too_large_size) = self.operand_size_if_too_large(limit, &arg.node) {
669+
// Moving args into functions is typically implemented with pointer
670+
// passing at the llvm-ir level and not by memcpy's. So always allow
671+
// moving args into functions.
672+
let operand: &mir::Operand<'tcx> = &arg.node;
673+
if let mir::Operand::Move(_) = operand {
674+
continue;
675+
}
676+
677+
if let Some(too_large_size) = self.operand_size_if_too_large(limit, operand) {
670678
self.lint_large_assignment(limit.0, too_large_size, location, arg.span);
671679
};
672680
}

tests/ui/lint/large_assignments/box_rc_arc_allowed.rs

-29
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
#![deny(large_assignments)]
2+
#![feature(large_assignments)]
3+
#![move_size_limit = "1000"]
4+
// build-fail
5+
// only-64bit
6+
7+
// edition:2018
8+
// compile-flags: -Zmir-opt-level=1
9+
10+
use std::{sync::Arc, rc::Rc};
11+
12+
fn main() {
13+
let data = [0; 9999];
14+
15+
// Looking at --emit mir, we can see that all parameters below are passed by
16+
// copy. But it requires at least mir-opt-level=1.
17+
let _ = Arc::new(data); // OK!
18+
let _ = Box::new(data); // OK!
19+
let _ = Rc::new(data); // OK!
20+
21+
// Looking at --emit llvm-ir, we can see that a memcpy is involved in the
22+
// parameter passing. So we want the lint to trigger here.
23+
let _ = NotBox::new(data); //~ ERROR large_assignments
24+
}
25+
26+
struct NotBox {
27+
data: [u8; 9999],
28+
}
29+
30+
impl NotBox {
31+
fn new(data: [u8; 9999]) -> Self {
32+
// Looking at --emit llvm-ir, we can see that a memcpy is involved.
33+
// So we want the lint to trigger here.
34+
Self { //~ ERROR large_assignments
35+
data,
36+
}
37+
}
38+
}

tests/ui/lint/large_assignments/box_rc_arc_allowed.stderr renamed to tests/ui/lint/large_assignments/copy_into_box_rc_arc.stderr

+9-7
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,23 @@
11
error: moving 9999 bytes
2-
--> $DIR/box_rc_arc_allowed.rs:16:25
2+
--> $DIR/copy_into_box_rc_arc.rs:23:25
33
|
4-
LL | let _ = NotBox::new([0; 9999]);
5-
| ^^^^^^^^^ value moved from here
4+
LL | let _ = NotBox::new(data);
5+
| ^^^^ value moved from here
66
|
77
= note: The current maximum size is 1000, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]`
88
note: the lint level is defined here
9-
--> $DIR/box_rc_arc_allowed.rs:1:9
9+
--> $DIR/copy_into_box_rc_arc.rs:1:9
1010
|
1111
LL | #![deny(large_assignments)]
1212
| ^^^^^^^^^^^^^^^^^
1313

1414
error: moving 9999 bytes
15-
--> $DIR/box_rc_arc_allowed.rs:26:13
15+
--> $DIR/copy_into_box_rc_arc.rs:34:9
1616
|
17-
LL | data,
18-
| ^^^^ value moved from here
17+
LL | / Self {
18+
LL | | data,
19+
LL | | }
20+
| |_________^ value moved from here
1921
|
2022
= note: The current maximum size is 1000, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]`
2123

tests/ui/lint/large_assignments/large_future.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
#![cfg_attr(attribute, feature(large_assignments))]
33
#![cfg_attr(attribute, move_size_limit = "1000")]
44
// build-fail
5-
// only-x86_64
5+
// only-64bit
66
// revisions: attribute option
77
// [option]compile-flags: -Zmove-size-limit=1000
88

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
#![deny(large_assignments)]
2+
#![feature(large_assignments)]
3+
#![move_size_limit = "1000"]
4+
// build-fail
5+
// only-64bit
6+
7+
// edition:2018
8+
// compile-flags: -Zmir-opt-level=0
9+
10+
use std::{sync::Arc, rc::Rc};
11+
12+
fn main() {
13+
// Looking at --emit mir, we can see that all parameters below are passed
14+
// by move.
15+
let _ = Arc::new([0; 9999]); // OK!
16+
let _ = Box::new([0; 9999]); // OK!
17+
let _ = Rc::new([0; 9999]); // OK!
18+
19+
// Looking at --emit llvm-ir, we can see that no memcpy is involved in the
20+
// parameter passing. Instead, a pointer is passed. This is typically what
21+
// we get when moving parameter into functions. So we don't want the lint to
22+
// trigger here.
23+
let _ = NotBox::new([0; 9999]); // OK (compare with copy_into_box_rc_arc.rs)
24+
}
25+
26+
struct NotBox {
27+
data: [u8; 9999],
28+
}
29+
30+
impl NotBox {
31+
fn new(data: [u8; 9999]) -> Self {
32+
Self {
33+
// Looking at --emit llvm-ir, we can see that a memcpy is involved.
34+
// So we want the lint to trigger here.
35+
data, //~ ERROR large_assignments
36+
}
37+
}
38+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
error: moving 9999 bytes
2+
--> $DIR/move_into_box_rc_arc.rs:35:13
3+
|
4+
LL | data,
5+
| ^^^^ value moved from here
6+
|
7+
= note: The current maximum size is 1000, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]`
8+
note: the lint level is defined here
9+
--> $DIR/move_into_box_rc_arc.rs:1:9
10+
|
11+
LL | #![deny(large_assignments)]
12+
| ^^^^^^^^^^^^^^^^^
13+
14+
error: aborting due to 1 previous error
15+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// build-fail
2+
3+
#![feature(large_assignments)]
4+
#![move_size_limit = "1000"]
5+
#![deny(large_assignments)]
6+
#![allow(unused)]
7+
8+
// Note: This type does not implement Copy.
9+
struct Data([u8; 9999]);
10+
11+
fn main() {
12+
// Looking at llvm-ir output, we can see a memcpy'd into Data, so we want
13+
// the lint to trigger here.
14+
let data = Data([100; 9999]); //~ ERROR large_assignments
15+
16+
// Looking at llvm-ir output, we can see that there is no memcpy involved in
17+
// this function call. Instead, just a pointer is passed to the function. So
18+
// the lint shall not trigger here.
19+
take_data(data);
20+
}
21+
22+
fn take_data(data: Data) {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
error: moving 9999 bytes
2+
--> $DIR/move_into_fn.rs:14:16
3+
|
4+
LL | let data = Data([100; 9999]);
5+
| ^^^^^^^^^^^^^^^^^ value moved from here
6+
|
7+
= note: The current maximum size is 1000, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]`
8+
note: the lint level is defined here
9+
--> $DIR/move_into_fn.rs:5:9
10+
|
11+
LL | #![deny(large_assignments)]
12+
| ^^^^^^^^^^^^^^^^^
13+
14+
error: aborting due to 1 previous error
15+

0 commit comments

Comments
 (0)