From a2f217902675d8ad29ecb79a8c153b485d85cb7b Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 26 Mar 2021 16:28:52 +0000 Subject: [PATCH] Add an attribute to be able to configure the limit --- compiler/rustc_feature/src/active.rs | 3 +++ compiler/rustc_feature/src/builtin_attrs.rs | 4 ++++ compiler/rustc_lint_defs/src/builtin.rs | 2 +- compiler/rustc_middle/src/middle/limits.rs | 15 ++++++++++----- compiler/rustc_mir/src/monomorphize/collector.rs | 7 ++++++- compiler/rustc_session/src/session.rs | 16 ++++++++++++++++ compiler/rustc_span/src/symbol.rs | 2 ++ src/test/ui/async-await/large_moves.rs | 2 ++ src/test/ui/async-await/large_moves.stderr | 8 ++++---- .../feature-gate-large-assignments.rs | 5 +++++ .../feature-gate-large-assignments.stderr | 12 ++++++++++++ 11 files changed, 65 insertions(+), 11 deletions(-) create mode 100644 src/test/ui/feature-gates/feature-gate-large-assignments.rs create mode 100644 src/test/ui/feature-gates/feature-gate-large-assignments.stderr diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index a410826d3fda..eb143e5bac22 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -633,6 +633,9 @@ declare_features! ( /// Allows associated types in inherent impls. (active, inherent_associated_types, "1.52.0", Some(8995), None), + // Allows setting the threshold for the `large_assignments` lint. + (active, large_assignments, "1.52.0", Some(83518), None), + /// Allows `extern "C-unwind" fn` to enable unwinding across ABI boundaries. (active, c_unwind, "1.52.0", Some(74990), None), diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index 43054f5bf5e7..8dfc4572a848 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -241,6 +241,10 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ const_eval_limit, CrateLevel, template!(NameValueStr: "N"), const_eval_limit, experimental!(const_eval_limit) ), + gated!( + move_size_limit, CrateLevel, template!(NameValueStr: "N"), large_assignments, + experimental!(move_size_limit) + ), // Entry point: ungated!(main, Normal, template!(Word)), diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index e29005c0c897..2edb8b717fd5 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -2906,7 +2906,7 @@ declare_lint! { /// This lint will trigger on all sites of large moves and thus allow the /// user to resolve them in code. pub LARGE_ASSIGNMENTS, - Allow, + Warn, "detects large moves or copies", } diff --git a/compiler/rustc_middle/src/middle/limits.rs b/compiler/rustc_middle/src/middle/limits.rs index 61f850c2fc16..601198fd0de0 100644 --- a/compiler/rustc_middle/src/middle/limits.rs +++ b/compiler/rustc_middle/src/middle/limits.rs @@ -1,4 +1,8 @@ -//! Registering limits, recursion_limit, type_length_limit and const_eval_limit +//! Registering limits: +//! * recursion_limit, +//! * move_size_limit, +//! * type_length_limit, and +//! * const_eval_limit //! //! There are various parts of the compiler that must impose arbitrary limits //! on how deeply they recurse to prevent stack overflow. Users can override @@ -8,13 +12,14 @@ use crate::bug; use rustc_ast as ast; use rustc_data_structures::sync::OnceCell; -use rustc_session::{Limit, Session}; +use rustc_session::Session; use rustc_span::symbol::{sym, Symbol}; use std::num::IntErrorKind; pub fn update_limits(sess: &Session, krate: &ast::Crate) { update_limit(sess, krate, &sess.recursion_limit, sym::recursion_limit, 128); + update_limit(sess, krate, &sess.move_size_limit, sym::move_size_limit, 0); update_limit(sess, krate, &sess.type_length_limit, sym::type_length_limit, 1048576); update_limit(sess, krate, &sess.const_eval_limit, sym::const_eval_limit, 1_000_000); } @@ -22,7 +27,7 @@ pub fn update_limits(sess: &Session, krate: &ast::Crate) { fn update_limit( sess: &Session, krate: &ast::Crate, - limit: &OnceCell, + limit: &OnceCell + std::fmt::Debug>, name: Symbol, default: usize, ) { @@ -34,7 +39,7 @@ fn update_limit( if let Some(s) = attr.value_str() { match s.as_str().parse() { Ok(n) => { - limit.set(Limit::new(n)).unwrap(); + limit.set(From::from(n)).unwrap(); return; } Err(e) => { @@ -63,5 +68,5 @@ fn update_limit( } } } - limit.set(Limit::new(default)).unwrap(); + limit.set(From::from(default)).unwrap(); } diff --git a/compiler/rustc_mir/src/monomorphize/collector.rs b/compiler/rustc_mir/src/monomorphize/collector.rs index 8ff3edac65fb..e621bc9167d8 100644 --- a/compiler/rustc_mir/src/monomorphize/collector.rs +++ b/compiler/rustc_mir/src/monomorphize/collector.rs @@ -757,11 +757,16 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> { fn visit_operand(&mut self, operand: &mir::Operand<'tcx>, location: Location) { self.super_operand(operand, location); + let limit = self.tcx.sess.move_size_limit(); + if limit == 0 { + return; + } + let limit = Size::from_bytes(limit); let ty = operand.ty(self.body, self.tcx); let ty = self.monomorphize(ty); let layout = self.tcx.layout_of(ty::ParamEnv::reveal_all().and(ty)); if let Ok(layout) = layout { - if layout.size > Size::from_bytes(1000) { + if layout.size > limit { debug!(?layout); let source_info = self.body.source_info(location); debug!(?source_info); diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index cc2583be9447..7bff634fb2dd 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -83,6 +83,12 @@ impl Limit { } } +impl From for Limit { + fn from(value: usize) -> Self { + Self::new(value) + } +} + impl fmt::Display for Limit { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{}", self.0) @@ -143,6 +149,10 @@ pub struct Session { /// operations such as auto-dereference and monomorphization. pub recursion_limit: OnceCell, + /// The size at which the `large_assignments` lint starts + /// being emitted. + pub move_size_limit: OnceCell, + /// The maximum length of types during monomorphization. pub type_length_limit: OnceCell, @@ -352,6 +362,11 @@ impl Session { self.recursion_limit.get().copied().unwrap() } + #[inline] + pub fn move_size_limit(&self) -> usize { + self.move_size_limit.get().copied().unwrap() + } + #[inline] pub fn type_length_limit(&self) -> Limit { self.type_length_limit.get().copied().unwrap() @@ -1414,6 +1429,7 @@ pub fn build_session( features: OnceCell::new(), lint_store: OnceCell::new(), recursion_limit: OnceCell::new(), + move_size_limit: OnceCell::new(), type_length_limit: OnceCell::new(), const_eval_limit: OnceCell::new(), incr_comp_session: OneThread::new(RefCell::new(IncrCompSession::NotInitialized)), diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 52270f0e6277..5c46e7d9af90 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -669,6 +669,7 @@ symbols! { label_break_value, lang, lang_items, + large_assignments, lateout, lazy_normalization_consts, le, @@ -749,6 +750,7 @@ symbols! { more_struct_aliases, movbe_target_feature, move_ref_pattern, + move_size_limit, mul, mul_assign, mul_with_overflow, diff --git a/src/test/ui/async-await/large_moves.rs b/src/test/ui/async-await/large_moves.rs index 7e6819d6d139..fff23db3351e 100644 --- a/src/test/ui/async-await/large_moves.rs +++ b/src/test/ui/async-await/large_moves.rs @@ -1,4 +1,6 @@ #![deny(large_assignments)] +#![feature(large_assignments)] +#![move_size_limit = "1000"] // build-fail // edition:2018 diff --git a/src/test/ui/async-await/large_moves.stderr b/src/test/ui/async-await/large_moves.stderr index d395d2ae8696..476f5875beb3 100644 --- a/src/test/ui/async-await/large_moves.stderr +++ b/src/test/ui/async-await/large_moves.stderr @@ -1,5 +1,5 @@ error: moving 10024 bytes - --> $DIR/large_moves.rs:7:13 + --> $DIR/large_moves.rs:9:13 | LL | let x = async { | _____________^ @@ -17,19 +17,19 @@ LL | #![deny(large_assignments)] | ^^^^^^^^^^^^^^^^^ error: moving 10024 bytes - --> $DIR/large_moves.rs:13:14 + --> $DIR/large_moves.rs:15:14 | LL | let z = (x, 42); | ^ value moved from here error: moving 10024 bytes - --> $DIR/large_moves.rs:13:13 + --> $DIR/large_moves.rs:15:13 | LL | let z = (x, 42); | ^^^^^^^ value moved from here error: moving 10024 bytes - --> $DIR/large_moves.rs:15:13 + --> $DIR/large_moves.rs:17:13 | LL | let a = z.0; | ^^^ value moved from here diff --git a/src/test/ui/feature-gates/feature-gate-large-assignments.rs b/src/test/ui/feature-gates/feature-gate-large-assignments.rs new file mode 100644 index 000000000000..7e9e574bfa08 --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-large-assignments.rs @@ -0,0 +1,5 @@ +// check that `move_size_limit is feature-gated + +#![move_size_limit = "42"] //~ ERROR the `#[move_size_limit]` attribute is an experimental feature + +fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-large-assignments.stderr b/src/test/ui/feature-gates/feature-gate-large-assignments.stderr new file mode 100644 index 000000000000..8ddc3043e966 --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-large-assignments.stderr @@ -0,0 +1,12 @@ +error[E0658]: the `#[move_size_limit]` attribute is an experimental feature + --> $DIR/feature-gate-large-assignments.rs:3:1 + | +LL | #![move_size_limit = "42"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #83518 for more information + = help: add `#![feature(large_assignments)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`.