]> git.proxmox.com Git - rustc.git/blob - src/librustc_middle/middle/limits.rs
New upstream version 1.47.0+dfsg1
[rustc.git] / src / librustc_middle / middle / limits.rs
1 //! Registering limits, recursion_limit, type_length_limit and const_eval_limit
2 //!
3 //! There are various parts of the compiler that must impose arbitrary limits
4 //! on how deeply they recurse to prevent stack overflow. Users can override
5 //! this via an attribute on the crate like `#![recursion_limit="22"]`. This pass
6 //! just peeks and looks for that attribute.
7
8 use crate::bug;
9 use rustc_ast as ast;
10 use rustc_data_structures::sync::OnceCell;
11 use rustc_session::{Limit, Session};
12 use rustc_span::symbol::{sym, Symbol};
13
14 use std::num::IntErrorKind;
15
16 pub fn update_limits(sess: &Session, krate: &ast::Crate) {
17 update_limit(sess, krate, &sess.recursion_limit, sym::recursion_limit, 128);
18 update_limit(sess, krate, &sess.type_length_limit, sym::type_length_limit, 1048576);
19 update_limit(sess, krate, &sess.const_eval_limit, sym::const_eval_limit, 1_000_000);
20 }
21
22 fn update_limit(
23 sess: &Session,
24 krate: &ast::Crate,
25 limit: &OnceCell<Limit>,
26 name: Symbol,
27 default: usize,
28 ) {
29 for attr in &krate.attrs {
30 if !sess.check_name(attr, name) {
31 continue;
32 }
33
34 if let Some(s) = attr.value_str() {
35 match s.as_str().parse() {
36 Ok(n) => {
37 limit.set(Limit::new(n)).unwrap();
38 return;
39 }
40 Err(e) => {
41 let mut err =
42 sess.struct_span_err(attr.span, "`limit` must be a non-negative integer");
43
44 let value_span = attr
45 .meta()
46 .and_then(|meta| meta.name_value_literal().cloned())
47 .map(|lit| lit.span)
48 .unwrap_or(attr.span);
49
50 let error_str = match e.kind() {
51 IntErrorKind::Overflow => "`limit` is too large",
52 IntErrorKind::Empty => "`limit` must be a non-negative integer",
53 IntErrorKind::InvalidDigit => "not a valid integer",
54 IntErrorKind::Underflow => bug!("`limit` should never underflow"),
55 IntErrorKind::Zero => bug!("zero is a valid `limit`"),
56 kind => bug!("unimplemented IntErrorKind variant: {:?}", kind),
57 };
58
59 err.span_label(value_span, error_str);
60 err.emit();
61 }
62 }
63 }
64 }
65 limit.set(Limit::new(default)).unwrap();
66 }