Skip to content

Commit 9025f17

Browse files
committed
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.
1 parent 1a0200e commit 9025f17

File tree

8 files changed

+63
-17
lines changed

8 files changed

+63
-17
lines changed

compiler/rustc_monomorphize/src/collector.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -630,7 +630,7 @@ impl<'a, 'tcx> MirUsedCollector<'a, 'tcx> {
630630
let source_info = self.body.source_info(location);
631631
debug!(?source_info);
632632

633-
if let Some(too_large_size) = self.operand_size_if_too_large(limit, operand) {
633+
if let Some(too_large_size) = self.operand_size_if_too_large(limit, operand, false) {
634634
self.lint_large_assignment(limit.0, too_large_size, location, source_info.span);
635635
};
636636
}
@@ -666,7 +666,7 @@ 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+
if let Some(too_large_size) = self.operand_size_if_too_large(limit, &arg.node, true) {
670670
self.lint_large_assignment(limit.0, too_large_size, location, arg.span);
671671
};
672672
}
@@ -676,7 +676,11 @@ impl<'a, 'tcx> MirUsedCollector<'a, 'tcx> {
676676
&mut self,
677677
limit: Limit,
678678
operand: &mir::Operand<'tcx>,
679+
allow_move: bool,
679680
) -> Option<Size> {
681+
if allow_move && let mir::Operand::Move(_) = operand {
682+
return None;
683+
}
680684
let ty = operand.ty(self.body, self.tcx);
681685
let ty = self.monomorphize(ty);
682686
let Ok(layout) = self.tcx.layout_of(ty::ParamEnv::reveal_all().and(ty)) else {

compiler/rustc_monomorphize/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#![feature(array_windows)]
22
#![feature(is_sorted)]
3+
#![feature(let_chains)]
34
#![allow(rustc::potential_query_instability)]
45
#![deny(rustc::untranslatable_diagnostic)]
56
#![deny(rustc::diagnostic_outside_of_impl)]

tests/ui/lint/large_assignments/copy_into_box_rc_arc.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ fn main() {
1717
let _ = Arc::new(data); // OK!
1818
let _ = Box::new(data); // OK!
1919
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.
2023
let _ = NotBox::new(data); //~ ERROR large_assignments
2124
}
2225

@@ -26,6 +29,8 @@ struct NotBox {
2629

2730
impl NotBox {
2831
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.
2934
Self { //~ ERROR large_assignments
3035
data,
3136
}

tests/ui/lint/large_assignments/copy_into_box_rc_arc.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error: moving 9999 bytes
2-
--> $DIR/copy_into_box_rc_arc.rs:20:25
2+
--> $DIR/copy_into_box_rc_arc.rs:23:25
33
|
44
LL | let _ = NotBox::new(data);
55
| ^^^^ value moved from here
@@ -12,7 +12,7 @@ LL | #![deny(large_assignments)]
1212
| ^^^^^^^^^^^^^^^^^
1313

1414
error: moving 9999 bytes
15-
--> $DIR/copy_into_box_rc_arc.rs:29:9
15+
--> $DIR/copy_into_box_rc_arc.rs:34:9
1616
|
1717
LL | / Self {
1818
LL | | data,

tests/ui/lint/large_assignments/move_into_box_rc_arc.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,12 @@ fn main() {
1515
let _ = Arc::new([0; 9999]); // OK!
1616
let _ = Box::new([0; 9999]); // OK!
1717
let _ = Rc::new([0; 9999]); // OK!
18-
let _ = NotBox::new([0; 9999]); //~ ERROR large_assignments
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)
1924
}
2025

2126
struct NotBox {
@@ -25,6 +30,8 @@ struct NotBox {
2530
impl NotBox {
2631
fn new(data: [u8; 9999]) -> Self {
2732
Self {
33+
// Looking at --emit llvm-ir, we can see that a memcpy is involved.
34+
// So we want the lint to trigger here.
2835
data, //~ ERROR large_assignments
2936
}
3037
}
Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
error: moving 9999 bytes
2-
--> $DIR/move_into_box_rc_arc.rs:18:25
2+
--> $DIR/move_into_box_rc_arc.rs:35:13
33
|
4-
LL | let _ = NotBox::new([0; 9999]);
5-
| ^^^^^^^^^ value moved from here
4+
LL | 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
@@ -11,13 +11,5 @@ note: the lint level is defined here
1111
LL | #![deny(large_assignments)]
1212
| ^^^^^^^^^^^^^^^^^
1313

14-
error: moving 9999 bytes
15-
--> $DIR/move_into_box_rc_arc.rs:28:13
16-
|
17-
LL | data,
18-
| ^^^^ value moved from here
19-
|
20-
= note: The current maximum size is 1000, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]`
21-
22-
error: aborting due to 2 previous errors
14+
error: aborting due to 1 previous error
2315

Lines changed: 22 additions & 0 deletions
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) {}
Lines changed: 15 additions & 0 deletions
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)