rust/compiler/rustc_middle/src/middle/limits.rs

67 lines
2.4 KiB
Rust
Raw Normal View History

//! Registering limits, recursion_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
//! this via an attribute on the crate like `#![recursion_limit="22"]`. This pass
//! just peeks and looks for that attribute.
2020-03-29 14:41:09 +00:00
use crate::bug;
2020-04-27 17:56:11 +00:00
use rustc_ast as ast;
2020-05-16 04:44:28 +00:00
use rustc_data_structures::sync::OnceCell;
use rustc_session::{Limit, Session};
2020-01-01 18:30:57 +00:00
use rustc_span::symbol::{sym, Symbol};
use std::num::IntErrorKind;
pub fn update_limits(sess: &Session, krate: &ast::Crate) {
2019-12-13 04:18:21 +00:00
update_limit(sess, krate, &sess.recursion_limit, sym::recursion_limit, 128);
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);
}
2019-12-13 04:18:21 +00:00
fn update_limit(
sess: &Session,
krate: &ast::Crate,
limit: &OnceCell<Limit>,
2019-12-13 04:18:21 +00:00
name: Symbol,
default: usize,
) {
2015-01-31 17:20:46 +00:00
for attr in &krate.attrs {
if !sess.check_name(attr, name) {
continue;
}
if let Some(s) = attr.value_str() {
2019-12-13 04:18:21 +00:00
match s.as_str().parse() {
Ok(n) => {
limit.set(Limit::new(n)).unwrap();
2019-12-13 04:18:21 +00:00
return;
}
Err(e) => {
let mut err =
sess.struct_span_err(attr.span, "`limit` must be a non-negative integer");
2019-12-13 04:18:21 +00:00
let value_span = attr
.meta()
.and_then(|meta| meta.name_value_literal().cloned())
.map(|lit| lit.span)
.unwrap_or(attr.span);
let error_str = match e.kind() {
IntErrorKind::PosOverflow => "`limit` is too large",
IntErrorKind::Empty => "`limit` must be a non-negative integer",
2020-10-06 18:05:25 +00:00
IntErrorKind::InvalidDigit(_) => "not a valid integer",
IntErrorKind::NegOverflow => bug!("`limit` should never underflow"),
IntErrorKind::Zero => bug!("zero is a valid `limit`"),
2019-12-13 04:18:21 +00:00
kind => bug!("unimplemented IntErrorKind variant: {:?}", kind),
};
err.span_label(value_span, error_str);
err.emit();
}
}
}
}
limit.set(Limit::new(default)).unwrap();
}