diff options
Diffstat (limited to 'compiler/rustc_interface/src')
| -rw-r--r-- | compiler/rustc_interface/src/errors.rs | 10 | ||||
| -rw-r--r-- | compiler/rustc_interface/src/lib.rs | 1 | ||||
| -rw-r--r-- | compiler/rustc_interface/src/limits.rs | 85 | ||||
| -rw-r--r-- | compiler/rustc_interface/src/passes.rs | 5 | ||||
| -rw-r--r-- | compiler/rustc_interface/src/proc_macro_decls.rs | 2 |
5 files changed, 100 insertions, 3 deletions
diff --git a/compiler/rustc_interface/src/errors.rs b/compiler/rustc_interface/src/errors.rs index c3b858d4f2e..ca4e556dcdb 100644 --- a/compiler/rustc_interface/src/errors.rs +++ b/compiler/rustc_interface/src/errors.rs @@ -127,3 +127,13 @@ pub(crate) struct AbiRequiredTargetFeature<'a> { pub feature: &'a str, pub enabled: &'a str, } + +#[derive(Diagnostic)] +#[diag(interface_limit_invalid)] +pub(crate) struct LimitInvalid<'a> { + #[primary_span] + pub span: Span, + #[label] + pub value_span: Span, + pub error_str: &'a str, +} diff --git a/compiler/rustc_interface/src/lib.rs b/compiler/rustc_interface/src/lib.rs index a2a29612e48..54cd341698f 100644 --- a/compiler/rustc_interface/src/lib.rs +++ b/compiler/rustc_interface/src/lib.rs @@ -10,6 +10,7 @@ mod callbacks; pub mod errors; pub mod interface; +mod limits; pub mod passes; mod proc_macro_decls; mod queries; diff --git a/compiler/rustc_interface/src/limits.rs b/compiler/rustc_interface/src/limits.rs new file mode 100644 index 00000000000..3de513797e3 --- /dev/null +++ b/compiler/rustc_interface/src/limits.rs @@ -0,0 +1,85 @@ +//! Registering limits: +//! - recursion_limit: there are various parts of the compiler that must impose arbitrary limits +//! on how deeply they recurse to prevent stack overflow. +//! - move_size_limit +//! - type_length_limit +//! - pattern_complexity_limit +//! +//! Users can override these limits via an attribute on the crate like +//! `#![recursion_limit="22"]`. This pass just looks for those attributes. + +use std::num::IntErrorKind; + +use rustc_ast::attr::AttributeExt; +use rustc_middle::bug; +use rustc_middle::query::Providers; +use rustc_session::{Limit, Limits, Session}; +use rustc_span::{Symbol, sym}; + +use crate::errors::LimitInvalid; + +pub(crate) fn provide(providers: &mut Providers) { + providers.limits = |tcx, ()| Limits { + recursion_limit: get_recursion_limit(tcx.hir().krate_attrs(), tcx.sess), + move_size_limit: get_limit( + tcx.hir().krate_attrs(), + tcx.sess, + sym::move_size_limit, + Limit::new(tcx.sess.opts.unstable_opts.move_size_limit.unwrap_or(0)), + ), + type_length_limit: get_limit( + tcx.hir().krate_attrs(), + tcx.sess, + sym::type_length_limit, + Limit::new(2usize.pow(24)), + ), + pattern_complexity_limit: get_limit( + tcx.hir().krate_attrs(), + tcx.sess, + sym::pattern_complexity_limit, + Limit::unlimited(), + ), + } +} + +// This one is separate because it must be read prior to macro expansion. +pub(crate) fn get_recursion_limit(krate_attrs: &[impl AttributeExt], sess: &Session) -> Limit { + get_limit(krate_attrs, sess, sym::recursion_limit, Limit::new(128)) +} + +fn get_limit( + krate_attrs: &[impl AttributeExt], + sess: &Session, + name: Symbol, + default: Limit, +) -> Limit { + for attr in krate_attrs { + if !attr.has_name(name) { + continue; + } + + if let Some(sym) = attr.value_str() { + match sym.as_str().parse() { + Ok(n) => return Limit::new(n), + Err(e) => { + let error_str = match e.kind() { + IntErrorKind::PosOverflow => "`limit` is too large", + IntErrorKind::Empty => "`limit` must be a non-negative integer", + IntErrorKind::InvalidDigit => "not a valid integer", + IntErrorKind::NegOverflow => { + bug!("`limit` should never negatively overflow") + } + IntErrorKind::Zero => bug!("zero is a valid `limit`"), + kind => bug!("unimplemented IntErrorKind variant: {:?}", kind), + }; + sess.dcx().emit_err(LimitInvalid { + span: attr.span(), + value_span: attr.value_span().unwrap(), + error_str, + }); + } + } + } + } + default +} diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index fcebca3ecc9..d7d183e17ed 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -39,7 +39,7 @@ use rustc_trait_selection::traits; use tracing::{info, instrument}; use crate::interface::Compiler; -use crate::{errors, proc_macro_decls, util}; +use crate::{errors, limits, proc_macro_decls, util}; pub fn parse<'a>(sess: &'a Session) -> ast::Crate { let krate = sess @@ -687,6 +687,7 @@ pub static DEFAULT_QUERY_PROVIDERS: LazyLock<Providers> = LazyLock::new(|| { |tcx, _| tcx.arena.alloc_from_iter(tcx.resolutions(()).stripped_cfg_items.steal()); providers.resolutions = |tcx, ()| tcx.resolver_for_lowering_raw(()).1; providers.early_lint_checks = early_lint_checks; + limits::provide(providers); proc_macro_decls::provide(providers); rustc_const_eval::provide(providers); rustc_middle::hir::provide(providers); @@ -1134,7 +1135,7 @@ fn get_recursion_limit(krate_attrs: &[ast::Attribute], sess: &Session) -> Limit // because that would require expanding this while in the middle of expansion, which needs to // know the limit before expanding. let _ = validate_and_find_value_str_builtin_attr(sym::recursion_limit, sess, krate_attrs); - rustc_middle::middle::limits::get_recursion_limit(krate_attrs, sess) + crate::limits::get_recursion_limit(krate_attrs, sess) } /// Validate *all* occurrences of the given "[value-str]" built-in attribute and return the first find. diff --git a/compiler/rustc_interface/src/proc_macro_decls.rs b/compiler/rustc_interface/src/proc_macro_decls.rs index 82593dbc2b7..00600abb5f1 100644 --- a/compiler/rustc_interface/src/proc_macro_decls.rs +++ b/compiler/rustc_interface/src/proc_macro_decls.rs @@ -7,7 +7,7 @@ use rustc_span::sym; fn proc_macro_decls_static(tcx: TyCtxt<'_>, (): ()) -> Option<LocalDefId> { let mut decls = None; - for id in tcx.hir().items() { + for id in tcx.hir_free_items() { let attrs = tcx.hir().attrs(id.hir_id()); if attr::contains_name(attrs, sym::rustc_proc_macro_decls) { decls = Some(id.owner_id.def_id); |
