rustc_middle/middle/
limits.rs
1use std::num::IntErrorKind;
12
13use rustc_ast::attr::AttributeExt;
14use rustc_session::{Limit, Limits, Session};
15use rustc_span::{Symbol, sym};
16
17use crate::error::LimitInvalid;
18use crate::query::Providers;
19
20pub fn provide(providers: &mut Providers) {
21 providers.limits = |tcx, ()| Limits {
22 recursion_limit: get_recursion_limit(tcx.hir().krate_attrs(), tcx.sess),
23 move_size_limit: get_limit(
24 tcx.hir().krate_attrs(),
25 tcx.sess,
26 sym::move_size_limit,
27 tcx.sess.opts.unstable_opts.move_size_limit.unwrap_or(0),
28 ),
29 type_length_limit: get_limit(
30 tcx.hir().krate_attrs(),
31 tcx.sess,
32 sym::type_length_limit,
33 2usize.pow(24),
34 ),
35 }
36}
37
38pub fn get_recursion_limit(krate_attrs: &[impl AttributeExt], sess: &Session) -> Limit {
39 get_limit(krate_attrs, sess, sym::recursion_limit, 128)
40}
41
42fn get_limit(
43 krate_attrs: &[impl AttributeExt],
44 sess: &Session,
45 name: Symbol,
46 default: usize,
47) -> Limit {
48 match get_limit_size(krate_attrs, sess, name) {
49 Some(size) => Limit::new(size),
50 None => Limit::new(default),
51 }
52}
53
54pub fn get_limit_size(
55 krate_attrs: &[impl AttributeExt],
56 sess: &Session,
57 name: Symbol,
58) -> Option<usize> {
59 for attr in krate_attrs {
60 if !attr.has_name(name) {
61 continue;
62 }
63
64 if let Some(sym) = attr.value_str() {
65 match sym.as_str().parse() {
66 Ok(n) => return Some(n),
67 Err(e) => {
68 let error_str = match e.kind() {
69 IntErrorKind::PosOverflow => "`limit` is too large",
70 IntErrorKind::Empty => "`limit` must be a non-negative integer",
71 IntErrorKind::InvalidDigit => "not a valid integer",
72 IntErrorKind::NegOverflow => {
73 bug!("`limit` should never negatively overflow")
74 }
75 IntErrorKind::Zero => bug!("zero is a valid `limit`"),
76 kind => bug!("unimplemented IntErrorKind variant: {:?}", kind),
77 };
78 sess.dcx().emit_err(LimitInvalid {
79 span: attr.span(),
80 value_span: attr.value_span().unwrap(),
81 error_str,
82 });
83 }
84 }
85 }
86 }
87 None
88}