Add an attribute to be able to configure the limit
This commit is contained in:
parent
e9696c8b62
commit
a2f2179026
11 changed files with 65 additions and 11 deletions
|
@ -633,6 +633,9 @@ declare_features! (
|
||||||
/// Allows associated types in inherent impls.
|
/// Allows associated types in inherent impls.
|
||||||
(active, inherent_associated_types, "1.52.0", Some(8995), None),
|
(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.
|
/// Allows `extern "C-unwind" fn` to enable unwinding across ABI boundaries.
|
||||||
(active, c_unwind, "1.52.0", Some(74990), None),
|
(active, c_unwind, "1.52.0", Some(74990), None),
|
||||||
|
|
||||||
|
|
|
@ -241,6 +241,10 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
|
||||||
const_eval_limit, CrateLevel, template!(NameValueStr: "N"), const_eval_limit,
|
const_eval_limit, CrateLevel, template!(NameValueStr: "N"), const_eval_limit,
|
||||||
experimental!(const_eval_limit)
|
experimental!(const_eval_limit)
|
||||||
),
|
),
|
||||||
|
gated!(
|
||||||
|
move_size_limit, CrateLevel, template!(NameValueStr: "N"), large_assignments,
|
||||||
|
experimental!(move_size_limit)
|
||||||
|
),
|
||||||
|
|
||||||
// Entry point:
|
// Entry point:
|
||||||
ungated!(main, Normal, template!(Word)),
|
ungated!(main, Normal, template!(Word)),
|
||||||
|
|
|
@ -2906,7 +2906,7 @@ declare_lint! {
|
||||||
/// This lint will trigger on all sites of large moves and thus allow the
|
/// This lint will trigger on all sites of large moves and thus allow the
|
||||||
/// user to resolve them in code.
|
/// user to resolve them in code.
|
||||||
pub LARGE_ASSIGNMENTS,
|
pub LARGE_ASSIGNMENTS,
|
||||||
Allow,
|
Warn,
|
||||||
"detects large moves or copies",
|
"detects large moves or copies",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
//! There are various parts of the compiler that must impose arbitrary limits
|
||||||
//! on how deeply they recurse to prevent stack overflow. Users can override
|
//! on how deeply they recurse to prevent stack overflow. Users can override
|
||||||
|
@ -8,13 +12,14 @@
|
||||||
use crate::bug;
|
use crate::bug;
|
||||||
use rustc_ast as ast;
|
use rustc_ast as ast;
|
||||||
use rustc_data_structures::sync::OnceCell;
|
use rustc_data_structures::sync::OnceCell;
|
||||||
use rustc_session::{Limit, Session};
|
use rustc_session::Session;
|
||||||
use rustc_span::symbol::{sym, Symbol};
|
use rustc_span::symbol::{sym, Symbol};
|
||||||
|
|
||||||
use std::num::IntErrorKind;
|
use std::num::IntErrorKind;
|
||||||
|
|
||||||
pub fn update_limits(sess: &Session, krate: &ast::Crate) {
|
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.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.type_length_limit, sym::type_length_limit, 1048576);
|
||||||
update_limit(sess, krate, &sess.const_eval_limit, sym::const_eval_limit, 1_000_000);
|
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(
|
fn update_limit(
|
||||||
sess: &Session,
|
sess: &Session,
|
||||||
krate: &ast::Crate,
|
krate: &ast::Crate,
|
||||||
limit: &OnceCell<Limit>,
|
limit: &OnceCell<impl From<usize> + std::fmt::Debug>,
|
||||||
name: Symbol,
|
name: Symbol,
|
||||||
default: usize,
|
default: usize,
|
||||||
) {
|
) {
|
||||||
|
@ -34,7 +39,7 @@ fn update_limit(
|
||||||
if let Some(s) = attr.value_str() {
|
if let Some(s) = attr.value_str() {
|
||||||
match s.as_str().parse() {
|
match s.as_str().parse() {
|
||||||
Ok(n) => {
|
Ok(n) => {
|
||||||
limit.set(Limit::new(n)).unwrap();
|
limit.set(From::from(n)).unwrap();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
|
@ -63,5 +68,5 @@ fn update_limit(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
limit.set(Limit::new(default)).unwrap();
|
limit.set(From::from(default)).unwrap();
|
||||||
}
|
}
|
||||||
|
|
|
@ -757,11 +757,16 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
|
||||||
|
|
||||||
fn visit_operand(&mut self, operand: &mir::Operand<'tcx>, location: Location) {
|
fn visit_operand(&mut self, operand: &mir::Operand<'tcx>, location: Location) {
|
||||||
self.super_operand(operand, 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 = operand.ty(self.body, self.tcx);
|
||||||
let ty = self.monomorphize(ty);
|
let ty = self.monomorphize(ty);
|
||||||
let layout = self.tcx.layout_of(ty::ParamEnv::reveal_all().and(ty));
|
let layout = self.tcx.layout_of(ty::ParamEnv::reveal_all().and(ty));
|
||||||
if let Ok(layout) = layout {
|
if let Ok(layout) = layout {
|
||||||
if layout.size > Size::from_bytes(1000) {
|
if layout.size > limit {
|
||||||
debug!(?layout);
|
debug!(?layout);
|
||||||
let source_info = self.body.source_info(location);
|
let source_info = self.body.source_info(location);
|
||||||
debug!(?source_info);
|
debug!(?source_info);
|
||||||
|
|
|
@ -83,6 +83,12 @@ impl Limit {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<usize> for Limit {
|
||||||
|
fn from(value: usize) -> Self {
|
||||||
|
Self::new(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl fmt::Display for Limit {
|
impl fmt::Display for Limit {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
write!(f, "{}", self.0)
|
write!(f, "{}", self.0)
|
||||||
|
@ -143,6 +149,10 @@ pub struct Session {
|
||||||
/// operations such as auto-dereference and monomorphization.
|
/// operations such as auto-dereference and monomorphization.
|
||||||
pub recursion_limit: OnceCell<Limit>,
|
pub recursion_limit: OnceCell<Limit>,
|
||||||
|
|
||||||
|
/// The size at which the `large_assignments` lint starts
|
||||||
|
/// being emitted.
|
||||||
|
pub move_size_limit: OnceCell<usize>,
|
||||||
|
|
||||||
/// The maximum length of types during monomorphization.
|
/// The maximum length of types during monomorphization.
|
||||||
pub type_length_limit: OnceCell<Limit>,
|
pub type_length_limit: OnceCell<Limit>,
|
||||||
|
|
||||||
|
@ -352,6 +362,11 @@ impl Session {
|
||||||
self.recursion_limit.get().copied().unwrap()
|
self.recursion_limit.get().copied().unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn move_size_limit(&self) -> usize {
|
||||||
|
self.move_size_limit.get().copied().unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn type_length_limit(&self) -> Limit {
|
pub fn type_length_limit(&self) -> Limit {
|
||||||
self.type_length_limit.get().copied().unwrap()
|
self.type_length_limit.get().copied().unwrap()
|
||||||
|
@ -1414,6 +1429,7 @@ pub fn build_session(
|
||||||
features: OnceCell::new(),
|
features: OnceCell::new(),
|
||||||
lint_store: OnceCell::new(),
|
lint_store: OnceCell::new(),
|
||||||
recursion_limit: OnceCell::new(),
|
recursion_limit: OnceCell::new(),
|
||||||
|
move_size_limit: OnceCell::new(),
|
||||||
type_length_limit: OnceCell::new(),
|
type_length_limit: OnceCell::new(),
|
||||||
const_eval_limit: OnceCell::new(),
|
const_eval_limit: OnceCell::new(),
|
||||||
incr_comp_session: OneThread::new(RefCell::new(IncrCompSession::NotInitialized)),
|
incr_comp_session: OneThread::new(RefCell::new(IncrCompSession::NotInitialized)),
|
||||||
|
|
|
@ -669,6 +669,7 @@ symbols! {
|
||||||
label_break_value,
|
label_break_value,
|
||||||
lang,
|
lang,
|
||||||
lang_items,
|
lang_items,
|
||||||
|
large_assignments,
|
||||||
lateout,
|
lateout,
|
||||||
lazy_normalization_consts,
|
lazy_normalization_consts,
|
||||||
le,
|
le,
|
||||||
|
@ -749,6 +750,7 @@ symbols! {
|
||||||
more_struct_aliases,
|
more_struct_aliases,
|
||||||
movbe_target_feature,
|
movbe_target_feature,
|
||||||
move_ref_pattern,
|
move_ref_pattern,
|
||||||
|
move_size_limit,
|
||||||
mul,
|
mul,
|
||||||
mul_assign,
|
mul_assign,
|
||||||
mul_with_overflow,
|
mul_with_overflow,
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
#![deny(large_assignments)]
|
#![deny(large_assignments)]
|
||||||
|
#![feature(large_assignments)]
|
||||||
|
#![move_size_limit = "1000"]
|
||||||
// build-fail
|
// build-fail
|
||||||
|
|
||||||
// edition:2018
|
// edition:2018
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error: moving 10024 bytes
|
error: moving 10024 bytes
|
||||||
--> $DIR/large_moves.rs:7:13
|
--> $DIR/large_moves.rs:9:13
|
||||||
|
|
|
|
||||||
LL | let x = async {
|
LL | let x = async {
|
||||||
| _____________^
|
| _____________^
|
||||||
|
@ -17,19 +17,19 @@ LL | #![deny(large_assignments)]
|
||||||
| ^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: moving 10024 bytes
|
error: moving 10024 bytes
|
||||||
--> $DIR/large_moves.rs:13:14
|
--> $DIR/large_moves.rs:15:14
|
||||||
|
|
|
|
||||||
LL | let z = (x, 42);
|
LL | let z = (x, 42);
|
||||||
| ^ value moved from here
|
| ^ value moved from here
|
||||||
|
|
||||||
error: moving 10024 bytes
|
error: moving 10024 bytes
|
||||||
--> $DIR/large_moves.rs:13:13
|
--> $DIR/large_moves.rs:15:13
|
||||||
|
|
|
|
||||||
LL | let z = (x, 42);
|
LL | let z = (x, 42);
|
||||||
| ^^^^^^^ value moved from here
|
| ^^^^^^^ value moved from here
|
||||||
|
|
||||||
error: moving 10024 bytes
|
error: moving 10024 bytes
|
||||||
--> $DIR/large_moves.rs:15:13
|
--> $DIR/large_moves.rs:17:13
|
||||||
|
|
|
|
||||||
LL | let a = z.0;
|
LL | let a = z.0;
|
||||||
| ^^^ value moved from here
|
| ^^^ value moved from here
|
||||||
|
|
|
@ -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() {}
|
|
@ -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 <https://github.com/rust-lang/rust/issues/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`.
|
Loading…
Add table
Add a link
Reference in a new issue