Skip to content

Commit 789451b

Browse files
committed
Allow large_assignments for Box/Arc/Rc initialization
Does the `stop linting in box/arc initialization` task of 83518.
1 parent bb90f81 commit 789451b

File tree

4 files changed

+147
-16
lines changed

4 files changed

+147
-16
lines changed

compiler/rustc_monomorphize/src/collector.rs

+91-10
Original file line numberDiff line numberDiff line change
@@ -179,15 +179,16 @@ use rustc_middle::query::TyCtxtAt;
179179
use rustc_middle::ty::adjustment::{CustomCoerceUnsized, PointerCoercion};
180180
use rustc_middle::ty::print::with_no_trimmed_paths;
181181
use rustc_middle::ty::{
182-
self, GenericParamDefKind, Instance, InstanceDef, Ty, TyCtxt, TypeFoldable, TypeVisitableExt,
183-
VtblEntry,
182+
self, AssocKind, GenericParamDefKind, Instance, InstanceDef, Ty, TyCtxt, TypeFoldable,
183+
TypeVisitableExt, VtblEntry,
184184
};
185185
use rustc_middle::ty::{GenericArgKind, GenericArgs};
186186
use rustc_middle::{middle::codegen_fn_attrs::CodegenFnAttrFlags, mir::visit::TyContext};
187187
use rustc_session::config::EntryFnType;
188188
use rustc_session::lint::builtin::LARGE_ASSIGNMENTS;
189189
use rustc_session::Limit;
190190
use rustc_span::source_map::{dummy_spanned, respan, Span, Spanned, DUMMY_SP};
191+
use rustc_span::symbol::{sym, Ident};
191192
use rustc_target::abi::Size;
192193
use std::path::PathBuf;
193194

@@ -431,7 +432,7 @@ fn collect_items_rec<'tcx>(
431432
hir::InlineAsmOperand::SymFn { anon_const } => {
432433
let fn_ty =
433434
tcx.typeck_body(anon_const.body).node_type(anon_const.hir_id);
434-
visit_fn_use(tcx, fn_ty, false, *op_sp, &mut used_items);
435+
visit_fn_use(tcx, fn_ty, false, *op_sp, &mut used_items, &[]);
435436
}
436437
hir::InlineAsmOperand::SymStatic { path: _, def_id } => {
437438
let instance = Instance::mono(tcx, *def_id);
@@ -592,6 +593,11 @@ struct MirUsedCollector<'a, 'tcx> {
592593
instance: Instance<'tcx>,
593594
/// Spans for move size lints already emitted. Helps avoid duplicate lints.
594595
move_size_spans: Vec<Span>,
596+
/// If true, we should temporarily skip move size checks, because we are
597+
/// processing an operand to a `skip_move_check_fns` function call.
598+
skip_move_size_check: bool,
599+
/// Set of functions for which it is OK to move large data into.
600+
skip_move_check_fns: Vec<DefId>,
595601
}
596602

597603
impl<'a, 'tcx> MirUsedCollector<'a, 'tcx> {
@@ -690,7 +696,14 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> {
690696
) => {
691697
let fn_ty = operand.ty(self.body, self.tcx);
692698
let fn_ty = self.monomorphize(fn_ty);
693-
visit_fn_use(self.tcx, fn_ty, false, span, &mut self.output);
699+
visit_fn_use(
700+
self.tcx,
701+
fn_ty,
702+
false,
703+
span,
704+
&mut self.output,
705+
&self.skip_move_check_fns,
706+
);
694707
}
695708
mir::Rvalue::Cast(
696709
mir::CastKind::PointerCoercion(PointerCoercion::ClosureFnPointer(_)),
@@ -789,7 +802,14 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> {
789802
mir::TerminatorKind::Call { ref func, .. } => {
790803
let callee_ty = func.ty(self.body, tcx);
791804
let callee_ty = self.monomorphize(callee_ty);
792-
visit_fn_use(self.tcx, callee_ty, true, source, &mut self.output)
805+
self.skip_move_size_check = visit_fn_use(
806+
self.tcx,
807+
callee_ty,
808+
true,
809+
source,
810+
&mut self.output,
811+
&self.skip_move_check_fns,
812+
)
793813
}
794814
mir::TerminatorKind::Drop { ref place, .. } => {
795815
let ty = place.ty(self.body, self.tcx).ty;
@@ -801,7 +821,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> {
801821
match *op {
802822
mir::InlineAsmOperand::SymFn { ref value } => {
803823
let fn_ty = self.monomorphize(value.literal.ty());
804-
visit_fn_use(self.tcx, fn_ty, false, source, &mut self.output);
824+
visit_fn_use(self.tcx, fn_ty, false, source, &mut self.output, &[]);
805825
}
806826
mir::InlineAsmOperand::SymStatic { def_id } => {
807827
let instance = Instance::mono(self.tcx, def_id);
@@ -840,12 +860,13 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> {
840860
}
841861

842862
self.super_terminator(terminator, location);
863+
self.skip_move_size_check = false;
843864
}
844865

845866
fn visit_operand(&mut self, operand: &mir::Operand<'tcx>, location: Location) {
846867
self.super_operand(operand, location);
847868
let move_size_limit = self.tcx.move_size_limit().0;
848-
if move_size_limit > 0 {
869+
if move_size_limit > 0 && !self.skip_move_size_check {
849870
self.check_move_size(move_size_limit, operand, location);
850871
}
851872
}
@@ -876,8 +897,11 @@ fn visit_fn_use<'tcx>(
876897
is_direct_call: bool,
877898
source: Span,
878899
output: &mut MonoItems<'tcx>,
879-
) {
900+
skip_move_check_fns: &[DefId],
901+
) -> bool {
902+
let mut skip_move_size_check = false;
880903
if let ty::FnDef(def_id, args) = *ty.kind() {
904+
skip_move_size_check = skip_move_check_fns.contains(&def_id);
881905
let instance = if is_direct_call {
882906
ty::Instance::expect_resolve(tcx, ty::ParamEnv::reveal_all(), def_id, args)
883907
} else {
@@ -888,6 +912,7 @@ fn visit_fn_use<'tcx>(
888912
};
889913
visit_instance_use(tcx, instance, is_direct_call, source, output);
890914
}
915+
skip_move_size_check
891916
}
892917

893918
fn visit_instance_use<'tcx>(
@@ -1365,6 +1390,31 @@ fn collect_alloc<'tcx>(tcx: TyCtxt<'tcx>, alloc_id: AllocId, output: &mut MonoIt
13651390
}
13661391
}
13671392

1393+
fn add_assoc_fn<'tcx>(
1394+
tcx: TyCtxt<'tcx>,
1395+
def_id: Option<DefId>,
1396+
fn_ident: Ident,
1397+
skip_move_check_fns: &mut Vec<DefId>,
1398+
) {
1399+
if let Some(def_id) = def_id.and_then(|def_id| assoc_fn_of_type(tcx, def_id, fn_ident)) {
1400+
skip_move_check_fns.push(def_id);
1401+
}
1402+
}
1403+
1404+
fn assoc_fn_of_type<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, fn_ident: Ident) -> Option<DefId> {
1405+
for impl_def_id in tcx.inherent_impls(def_id) {
1406+
if let Some(new) = tcx.associated_items(impl_def_id).find_by_name_and_kind(
1407+
tcx,
1408+
fn_ident,
1409+
AssocKind::Fn,
1410+
def_id,
1411+
) {
1412+
return Some(new.def_id);
1413+
}
1414+
}
1415+
return None;
1416+
}
1417+
13681418
/// Scans the MIR in order to find function calls, closures, and drop-glue.
13691419
#[instrument(skip(tcx, output), level = "debug")]
13701420
fn collect_used_items<'tcx>(
@@ -1373,8 +1423,39 @@ fn collect_used_items<'tcx>(
13731423
output: &mut MonoItems<'tcx>,
13741424
) {
13751425
let body = tcx.instance_mir(instance.def);
1376-
MirUsedCollector { tcx, body: &body, output, instance, move_size_spans: vec![] }
1377-
.visit_body(&body);
1426+
1427+
let mut skip_move_check_fns = vec![];
1428+
if tcx.move_size_limit().0 > 0 {
1429+
add_assoc_fn(
1430+
tcx,
1431+
tcx.lang_items().owned_box(),
1432+
Ident::from_str("new"),
1433+
&mut skip_move_check_fns,
1434+
);
1435+
add_assoc_fn(
1436+
tcx,
1437+
tcx.get_diagnostic_item(sym::Arc),
1438+
Ident::from_str("new"),
1439+
&mut skip_move_check_fns,
1440+
);
1441+
add_assoc_fn(
1442+
tcx,
1443+
tcx.get_diagnostic_item(sym::Rc),
1444+
Ident::from_str("new"),
1445+
&mut skip_move_check_fns,
1446+
);
1447+
}
1448+
1449+
MirUsedCollector {
1450+
tcx,
1451+
body: &body,
1452+
output,
1453+
instance,
1454+
move_size_spans: vec![],
1455+
skip_move_size_check: false,
1456+
skip_move_check_fns,
1457+
}
1458+
.visit_body(&body);
13781459
}
13791460

13801461
#[instrument(skip(tcx, output), level = "debug")]

tests/ui/async-await/large_moves.attribute.stderr

+19-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error: moving 10024 bytes
2-
--> $DIR/large_moves.rs:19:14
2+
--> $DIR/large_moves.rs:21:14
33
|
44
LL | let z = (x, 42);
55
| ^ value moved from here
@@ -12,12 +12,28 @@ LL | #![deny(large_assignments)]
1212
| ^^^^^^^^^^^^^^^^^
1313

1414
error: moving 10024 bytes
15-
--> $DIR/large_moves.rs:20:13
15+
--> $DIR/large_moves.rs:22:13
1616
|
1717
LL | let a = z.0;
1818
| ^^^ value moved from here
1919
|
2020
= note: The current maximum size is 1000, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]`
2121

22-
error: aborting due to 2 previous errors
22+
error: moving 9999 bytes
23+
--> $DIR/large_moves.rs:27:13
24+
|
25+
LL | let _ = NotBox::new([0; 9999]);
26+
| ^^^^^^^^^^^^^^^^^^^^^^ value moved from here
27+
|
28+
= note: The current maximum size is 1000, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]`
29+
30+
error: moving 9999 bytes
31+
--> $DIR/large_moves.rs:41:13
32+
|
33+
LL | data,
34+
| ^^^^ value moved from here
35+
|
36+
= note: The current maximum size is 1000, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]`
37+
38+
error: aborting due to 4 previous errors
2339

tests/ui/async-await/large_moves.option.stderr

+19-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error: moving 10024 bytes
2-
--> $DIR/large_moves.rs:19:14
2+
--> $DIR/large_moves.rs:21:14
33
|
44
LL | let z = (x, 42);
55
| ^ value moved from here
@@ -12,12 +12,28 @@ LL | #![deny(large_assignments)]
1212
| ^^^^^^^^^^^^^^^^^
1313

1414
error: moving 10024 bytes
15-
--> $DIR/large_moves.rs:20:13
15+
--> $DIR/large_moves.rs:22:13
1616
|
1717
LL | let a = z.0;
1818
| ^^^ value moved from here
1919
|
2020
= note: The current maximum size is 1000, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]`
2121

22-
error: aborting due to 2 previous errors
22+
error: moving 9999 bytes
23+
--> $DIR/large_moves.rs:27:13
24+
|
25+
LL | let _ = NotBox::new([0; 9999]);
26+
| ^^^^^^^^^^^^^^^^^^^^^^ value moved from here
27+
|
28+
= note: The current maximum size is 1000, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]`
29+
30+
error: moving 9999 bytes
31+
--> $DIR/large_moves.rs:41:13
32+
|
33+
LL | data,
34+
| ^^^^ value moved from here
35+
|
36+
= note: The current maximum size is 1000, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]`
37+
38+
error: aborting due to 4 previous errors
2339

tests/ui/async-await/large_moves.rs

+18
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
// edition:2018
1010
// compile-flags: -Zmir-opt-level=0
1111

12+
use std::{sync::Arc, rc::Rc};
13+
1214
fn main() {
1315
let x = async {
1416
let y = [0; 9999];
@@ -19,8 +21,24 @@ fn main() {
1921
let z = (x, 42); //~ ERROR large_assignments
2022
let a = z.0; //~ ERROR large_assignments
2123
let b = z.1;
24+
let _ = Arc::new([0; 9999]); // OK!
25+
let _ = Box::new([0; 9999]); // OK!
26+
let _ = Rc::new([0; 9999]); // OK!
27+
let _ = NotBox::new([0; 9999]); //~ ERROR large_assignments
2228
}
2329

2430
async fn thing(y: &[u8]) {
2531
dbg!(y);
2632
}
33+
34+
struct NotBox {
35+
data: [u8; 9999],
36+
}
37+
38+
impl NotBox {
39+
fn new(data: [u8; 9999]) -> Self {
40+
Self {
41+
data, //~ ERROR large_assignments
42+
}
43+
}
44+
}

0 commit comments

Comments
 (0)