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