From: Maybe Waffle Date: Thu, 27 Jan 2022 22:23:09 +0000 (+0300) Subject: feat: Honor recursion limit configuration X-Git-Url: https://git.lizzy.rs/?a=commitdiff_plain;ds=sidebyside;h=6d18c5b69d9751bdee8feaa90b095247be350d61;p=rust.git feat: Honor recursion limit configuration This patch makes RA understand `#![recursion_limit = "N"]` annotations. - `crate_limits` query is moved to `DefDatabase` - `DefMap` now has `recursion_limit: Option` field --- diff --git a/crates/base_db/src/lib.rs b/crates/base_db/src/lib.rs index a4c590cf6d9..d80660f7c9a 100644 --- a/crates/base_db/src/lib.rs +++ b/crates/base_db/src/lib.rs @@ -69,21 +69,6 @@ pub trait SourceDatabase: FileLoader + std::fmt::Debug { /// The crate graph. #[salsa::input] fn crate_graph(&self) -> Arc; - - #[salsa::transparent] - fn crate_limits(&self, crate_id: CrateId) -> CrateLimits; -} - -pub struct CrateLimits { - /// The maximum depth for potentially infinitely-recursive compile-time operations like macro expansion or auto-dereference. - pub recursion_limit: u32, -} - -fn crate_limits(_db: &dyn SourceDatabase, _crate_id: CrateId) -> CrateLimits { - CrateLimits { - // 128 is the default in rustc. - recursion_limit: 128, - } } fn parse_query(db: &dyn SourceDatabase, file_id: FileId) -> Parse { diff --git a/crates/hir_def/src/body/tests.rs b/crates/hir_def/src/body/tests.rs index 673a7538616..1d84da48fb9 100644 --- a/crates/hir_def/src/body/tests.rs +++ b/crates/hir_def/src/body/tests.rs @@ -61,6 +61,24 @@ macro_rules! n_nuple { ); } +#[test] +fn recursion_limit() { + cov_mark::check!(your_stack_belongs_to_me); + + lower( + r#" +#![recursion_limit = "2"] +macro_rules! n_nuple { + ($e:tt) => (); + ($first:tt $($rest:tt)*) => {{ + n_nuple!($($rest)*) + }}; +} +fn main() { n_nuple!(1,2,3); } +"#, + ); +} + #[test] fn macro_resolve() { // Regression test for a path resolution bug introduced with inner item handling. diff --git a/crates/hir_def/src/db.rs b/crates/hir_def/src/db.rs index 7946558311a..f9dd935c4b0 100644 --- a/crates/hir_def/src/db.rs +++ b/crates/hir_def/src/db.rs @@ -157,9 +157,26 @@ fn fields_attrs_source_map( #[salsa::invoke(visibility::function_visibility_query)] fn function_visibility(&self, def: FunctionId) -> Visibility; + + #[salsa::transparent] + fn crate_limits(&self, crate_id: CrateId) -> CrateLimits; } fn crate_def_map_wait(db: &dyn DefDatabase, krate: CrateId) -> Arc { let _p = profile::span("crate_def_map:wait"); db.crate_def_map_query(krate) } + +pub struct CrateLimits { + /// The maximum depth for potentially infinitely-recursive compile-time operations like macro expansion or auto-dereference. + pub recursion_limit: u32, +} + +fn crate_limits(db: &dyn DefDatabase, crate_id: CrateId) -> CrateLimits { + let def_map = db.crate_def_map(crate_id); + + CrateLimits { + // 128 is the default in rustc. + recursion_limit: def_map.recursion_limit().unwrap_or(128), + } +} diff --git a/crates/hir_def/src/nameres.rs b/crates/hir_def/src/nameres.rs index 64929c02b40..ca4255c5819 100644 --- a/crates/hir_def/src/nameres.rs +++ b/crates/hir_def/src/nameres.rs @@ -114,6 +114,7 @@ pub struct DefMap { registered_tools: Vec, edition: Edition, + recursion_limit: Option, diagnostics: Vec, } @@ -272,6 +273,7 @@ fn empty(krate: CrateId, edition: Edition, root_module_origin: ModuleOrigin) -> block: None, krate, edition, + recursion_limit: None, extern_prelude: FxHashMap::default(), exported_proc_macros: FxHashMap::default(), prelude: None, @@ -461,6 +463,7 @@ fn shrink_to_fit(&mut self) { registered_tools, block: _, edition: _, + recursion_limit: _, krate: _, prelude: _, root: _, @@ -482,6 +485,10 @@ fn shrink_to_fit(&mut self) { pub fn diagnostics(&self) -> &[DefDiagnostic] { self.diagnostics.as_slice() } + + pub fn recursion_limit(&self) -> Option { + self.recursion_limit + } } impl ModuleData { diff --git a/crates/hir_def/src/nameres/collector.rs b/crates/hir_def/src/nameres/collector.rs index dc75dc4d91a..7f7213f4c3e 100644 --- a/crates/hir_def/src/nameres/collector.rs +++ b/crates/hir_def/src/nameres/collector.rs @@ -271,6 +271,17 @@ fn seed_with_top_level(&mut self) { None => continue, }; + if *attr_name == hir_expand::name![recursion_limit] { + if let Some(input) = &attr.input { + if let AttrInput::Literal(limit) = &**input { + if let Ok(limit) = limit.parse() { + self.def_map.recursion_limit = Some(limit); + } + } + } + continue; + } + let attr_is_register_like = *attr_name == hir_expand::name![register_attr] || *attr_name == hir_expand::name![register_tool]; if !attr_is_register_like { diff --git a/crates/hir_expand/src/name.rs b/crates/hir_expand/src/name.rs index 4dcda0fcdc8..c36bd09e2b3 100644 --- a/crates/hir_expand/src/name.rs +++ b/crates/hir_expand/src/name.rs @@ -270,6 +270,7 @@ macro_rules! known_names { global_allocator, test, test_case, + recursion_limit, // Safe intrinsics abort, add_with_overflow,