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

72 lines
2.7 KiB
Rust
Raw Normal View History

//! 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
//! this via an attribute on the crate like `#![recursion_limit="22"]`. This pass
//! just peeks and looks for that attribute.
2020-03-29 16:41:09 +02:00
use crate::bug;
use crate::ty;
use rustc_ast::Attribute;
use rustc_session::Limit;
use rustc_session::Session;
2020-01-01 19:30:57 +01:00
use rustc_span::symbol::{sym, Symbol};
use std::num::IntErrorKind;
pub fn provide(providers: &mut ty::query::Providers) {
providers.recursion_limit = |tcx, ()| get_recursion_limit(tcx.hir().krate_attrs(), tcx.sess);
providers.move_size_limit =
|tcx, ()| get_limit(tcx.hir().krate_attrs(), tcx.sess, sym::move_size_limit, 0).0;
providers.type_length_limit =
|tcx, ()| get_limit(tcx.hir().krate_attrs(), tcx.sess, sym::type_length_limit, 1048576);
providers.const_eval_limit =
|tcx, ()| get_limit(tcx.hir().krate_attrs(), tcx.sess, sym::const_eval_limit, 1_000_000);
}
pub fn get_recursion_limit(krate_attrs: &[Attribute], sess: &Session) -> Limit {
get_limit(krate_attrs, sess, sym::recursion_limit, 128)
}
fn get_limit(krate_attrs: &[Attribute], sess: &Session, name: Symbol, default: usize) -> Limit {
for attr in krate_attrs {
if !sess.check_name(attr, name) {
continue;
}
if let Some(s) = attr.value_str() {
2019-12-12 21:18:21 -07:00
match s.as_str().parse() {
Ok(n) => return Limit::new(n),
2019-12-12 21:18:21 -07:00
Err(e) => {
let mut err =
sess.struct_span_err(attr.span, "`limit` must be a non-negative integer");
2019-12-12 21:18:21 -07:00
let value_span = attr
.meta()
.and_then(|meta| meta.name_value_literal_span())
2019-12-12 21:18:21 -07:00
.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-26 18:14:12 +00:00
IntErrorKind::InvalidDigit => "not a valid integer",
IntErrorKind::NegOverflow => {
2020-10-26 18:16:25 +00:00
bug!("`limit` should never negatively overflow")
2020-10-26 18:14:12 +00:00
}
IntErrorKind::Zero => bug!("zero is a valid `limit`"),
2019-12-12 21:18:21 -07:00
kind => bug!("unimplemented IntErrorKind variant: {:?}", kind),
};
err.span_label(value_span, error_str);
err.emit();
}
}
}
}
return Limit::new(default);
}