Skip to content

Commit

Permalink
Rollup merge of #115492 - Enselic:large-box-move, r=oli-obk
Browse files Browse the repository at this point in the history
Allow `large_assignments` for Box/Arc/Rc initialization

Does the `stop linting in box/arc initialization` task of #83518.

r? `@oli-obk` who is E-mentor.
  • Loading branch information
matthiaskrgr authored Sep 5, 2023
2 parents e9d15ec + 789451b commit 6f180ea
Show file tree
Hide file tree
Showing 4 changed files with 147 additions and 16 deletions.
101 changes: 91 additions & 10 deletions compiler/rustc_monomorphize/src/collector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -179,15 +179,16 @@ use rustc_middle::query::TyCtxtAt;
use rustc_middle::ty::adjustment::{CustomCoerceUnsized, PointerCoercion};
use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_middle::ty::{
self, GenericParamDefKind, Instance, InstanceDef, Ty, TyCtxt, TypeFoldable, TypeVisitableExt,
VtblEntry,
self, AssocKind, GenericParamDefKind, Instance, InstanceDef, Ty, TyCtxt, TypeFoldable,
TypeVisitableExt, VtblEntry,
};
use rustc_middle::ty::{GenericArgKind, GenericArgs};
use rustc_middle::{middle::codegen_fn_attrs::CodegenFnAttrFlags, mir::visit::TyContext};
use rustc_session::config::EntryFnType;
use rustc_session::lint::builtin::LARGE_ASSIGNMENTS;
use rustc_session::Limit;
use rustc_span::source_map::{dummy_spanned, respan, Span, Spanned, DUMMY_SP};
use rustc_span::symbol::{sym, Ident};
use rustc_target::abi::Size;
use std::path::PathBuf;

Expand Down Expand Up @@ -432,7 +433,7 @@ fn collect_items_rec<'tcx>(
hir::InlineAsmOperand::SymFn { anon_const } => {
let fn_ty =
tcx.typeck_body(anon_const.body).node_type(anon_const.hir_id);
visit_fn_use(tcx, fn_ty, false, *op_sp, &mut used_items);
visit_fn_use(tcx, fn_ty, false, *op_sp, &mut used_items, &[]);
}
hir::InlineAsmOperand::SymStatic { path: _, def_id } => {
let instance = Instance::mono(tcx, *def_id);
Expand Down Expand Up @@ -593,6 +594,11 @@ struct MirUsedCollector<'a, 'tcx> {
instance: Instance<'tcx>,
/// Spans for move size lints already emitted. Helps avoid duplicate lints.
move_size_spans: Vec<Span>,
/// If true, we should temporarily skip move size checks, because we are
/// processing an operand to a `skip_move_check_fns` function call.
skip_move_size_check: bool,
/// Set of functions for which it is OK to move large data into.
skip_move_check_fns: Vec<DefId>,
}

impl<'a, 'tcx> MirUsedCollector<'a, 'tcx> {
Expand Down Expand Up @@ -691,7 +697,14 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> {
) => {
let fn_ty = operand.ty(self.body, self.tcx);
let fn_ty = self.monomorphize(fn_ty);
visit_fn_use(self.tcx, fn_ty, false, span, &mut self.output);
visit_fn_use(
self.tcx,
fn_ty,
false,
span,
&mut self.output,
&self.skip_move_check_fns,
);
}
mir::Rvalue::Cast(
mir::CastKind::PointerCoercion(PointerCoercion::ClosureFnPointer(_)),
Expand Down Expand Up @@ -790,7 +803,14 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> {
mir::TerminatorKind::Call { ref func, .. } => {
let callee_ty = func.ty(self.body, tcx);
let callee_ty = self.monomorphize(callee_ty);
visit_fn_use(self.tcx, callee_ty, true, source, &mut self.output)
self.skip_move_size_check = visit_fn_use(
self.tcx,
callee_ty,
true,
source,
&mut self.output,
&self.skip_move_check_fns,
)
}
mir::TerminatorKind::Drop { ref place, .. } => {
let ty = place.ty(self.body, self.tcx).ty;
Expand All @@ -802,7 +822,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> {
match *op {
mir::InlineAsmOperand::SymFn { ref value } => {
let fn_ty = self.monomorphize(value.literal.ty());
visit_fn_use(self.tcx, fn_ty, false, source, &mut self.output);
visit_fn_use(self.tcx, fn_ty, false, source, &mut self.output, &[]);
}
mir::InlineAsmOperand::SymStatic { def_id } => {
let instance = Instance::mono(self.tcx, def_id);
Expand Down Expand Up @@ -841,12 +861,13 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> {
}

self.super_terminator(terminator, location);
self.skip_move_size_check = false;
}

fn visit_operand(&mut self, operand: &mir::Operand<'tcx>, location: Location) {
self.super_operand(operand, location);
let move_size_limit = self.tcx.move_size_limit().0;
if move_size_limit > 0 {
if move_size_limit > 0 && !self.skip_move_size_check {
self.check_move_size(move_size_limit, operand, location);
}
}
Expand Down Expand Up @@ -877,8 +898,11 @@ fn visit_fn_use<'tcx>(
is_direct_call: bool,
source: Span,
output: &mut MonoItems<'tcx>,
) {
skip_move_check_fns: &[DefId],
) -> bool {
let mut skip_move_size_check = false;
if let ty::FnDef(def_id, args) = *ty.kind() {
skip_move_size_check = skip_move_check_fns.contains(&def_id);
let instance = if is_direct_call {
ty::Instance::expect_resolve(tcx, ty::ParamEnv::reveal_all(), def_id, args)
} else {
Expand All @@ -889,6 +913,7 @@ fn visit_fn_use<'tcx>(
};
visit_instance_use(tcx, instance, is_direct_call, source, output);
}
skip_move_size_check
}

fn visit_instance_use<'tcx>(
Expand Down Expand Up @@ -1369,6 +1394,31 @@ fn collect_alloc<'tcx>(tcx: TyCtxt<'tcx>, alloc_id: AllocId, output: &mut MonoIt
}
}

fn add_assoc_fn<'tcx>(
tcx: TyCtxt<'tcx>,
def_id: Option<DefId>,
fn_ident: Ident,
skip_move_check_fns: &mut Vec<DefId>,
) {
if let Some(def_id) = def_id.and_then(|def_id| assoc_fn_of_type(tcx, def_id, fn_ident)) {
skip_move_check_fns.push(def_id);
}
}

fn assoc_fn_of_type<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, fn_ident: Ident) -> Option<DefId> {
for impl_def_id in tcx.inherent_impls(def_id) {
if let Some(new) = tcx.associated_items(impl_def_id).find_by_name_and_kind(
tcx,
fn_ident,
AssocKind::Fn,
def_id,
) {
return Some(new.def_id);
}
}
return None;
}

/// Scans the MIR in order to find function calls, closures, and drop-glue.
#[instrument(skip(tcx, output), level = "debug")]
fn collect_used_items<'tcx>(
Expand All @@ -1377,8 +1427,39 @@ fn collect_used_items<'tcx>(
output: &mut MonoItems<'tcx>,
) {
let body = tcx.instance_mir(instance.def);
MirUsedCollector { tcx, body: &body, output, instance, move_size_spans: vec![] }
.visit_body(&body);

let mut skip_move_check_fns = vec![];
if tcx.move_size_limit().0 > 0 {
add_assoc_fn(
tcx,
tcx.lang_items().owned_box(),
Ident::from_str("new"),
&mut skip_move_check_fns,
);
add_assoc_fn(
tcx,
tcx.get_diagnostic_item(sym::Arc),
Ident::from_str("new"),
&mut skip_move_check_fns,
);
add_assoc_fn(
tcx,
tcx.get_diagnostic_item(sym::Rc),
Ident::from_str("new"),
&mut skip_move_check_fns,
);
}

MirUsedCollector {
tcx,
body: &body,
output,
instance,
move_size_spans: vec![],
skip_move_size_check: false,
skip_move_check_fns,
}
.visit_body(&body);
}

#[instrument(skip(tcx, output), level = "debug")]
Expand Down
22 changes: 19 additions & 3 deletions tests/ui/async-await/large_moves.attribute.stderr
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
error: moving 10024 bytes
--> $DIR/large_moves.rs:19:14
--> $DIR/large_moves.rs:21:14
|
LL | let z = (x, 42);
| ^ value moved from here
Expand All @@ -12,12 +12,28 @@ LL | #![deny(large_assignments)]
| ^^^^^^^^^^^^^^^^^

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

error: aborting due to 2 previous errors
error: moving 9999 bytes
--> $DIR/large_moves.rs:27:13
|
LL | let _ = NotBox::new([0; 9999]);
| ^^^^^^^^^^^^^^^^^^^^^^ value moved from here
|
= note: The current maximum size is 1000, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]`

error: moving 9999 bytes
--> $DIR/large_moves.rs:41:13
|
LL | data,
| ^^^^ value moved from here
|
= note: The current maximum size is 1000, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]`

error: aborting due to 4 previous errors

22 changes: 19 additions & 3 deletions tests/ui/async-await/large_moves.option.stderr
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
error: moving 10024 bytes
--> $DIR/large_moves.rs:19:14
--> $DIR/large_moves.rs:21:14
|
LL | let z = (x, 42);
| ^ value moved from here
Expand All @@ -12,12 +12,28 @@ LL | #![deny(large_assignments)]
| ^^^^^^^^^^^^^^^^^

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

error: aborting due to 2 previous errors
error: moving 9999 bytes
--> $DIR/large_moves.rs:27:13
|
LL | let _ = NotBox::new([0; 9999]);
| ^^^^^^^^^^^^^^^^^^^^^^ value moved from here
|
= note: The current maximum size is 1000, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]`

error: moving 9999 bytes
--> $DIR/large_moves.rs:41:13
|
LL | data,
| ^^^^ value moved from here
|
= note: The current maximum size is 1000, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]`

error: aborting due to 4 previous errors

18 changes: 18 additions & 0 deletions tests/ui/async-await/large_moves.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
// edition:2018
// compile-flags: -Zmir-opt-level=0

use std::{sync::Arc, rc::Rc};

fn main() {
let x = async {
let y = [0; 9999];
Expand All @@ -19,8 +21,24 @@ fn main() {
let z = (x, 42); //~ ERROR large_assignments
let a = z.0; //~ ERROR large_assignments
let b = z.1;
let _ = Arc::new([0; 9999]); // OK!
let _ = Box::new([0; 9999]); // OK!
let _ = Rc::new([0; 9999]); // OK!
let _ = NotBox::new([0; 9999]); //~ ERROR large_assignments
}

async fn thing(y: &[u8]) {
dbg!(y);
}

struct NotBox {
data: [u8; 9999],
}

impl NotBox {
fn new(data: [u8; 9999]) -> Self {
Self {
data, //~ ERROR large_assignments
}
}
}

0 comments on commit 6f180ea

Please sign in to comment.