Skip to content

Commit 6d18c5b

Browse files
committed
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<u32>` field
1 parent 81211f5 commit 6d18c5b

File tree

6 files changed

+54
-15
lines changed

6 files changed

+54
-15
lines changed

crates/base_db/src/lib.rs

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -69,21 +69,6 @@ pub trait SourceDatabase: FileLoader + std::fmt::Debug {
6969
/// The crate graph.
7070
#[salsa::input]
7171
fn crate_graph(&self) -> Arc<CrateGraph>;
72-
73-
#[salsa::transparent]
74-
fn crate_limits(&self, crate_id: CrateId) -> CrateLimits;
75-
}
76-
77-
pub struct CrateLimits {
78-
/// The maximum depth for potentially infinitely-recursive compile-time operations like macro expansion or auto-dereference.
79-
pub recursion_limit: u32,
80-
}
81-
82-
fn crate_limits(_db: &dyn SourceDatabase, _crate_id: CrateId) -> CrateLimits {
83-
CrateLimits {
84-
// 128 is the default in rustc.
85-
recursion_limit: 128,
86-
}
8772
}
8873

8974
fn parse_query(db: &dyn SourceDatabase, file_id: FileId) -> Parse<ast::SourceFile> {

crates/hir_def/src/body/tests.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,24 @@ fn main() { n_nuple!(1,2,3); }
6161
);
6262
}
6363

64+
#[test]
65+
fn recursion_limit() {
66+
cov_mark::check!(your_stack_belongs_to_me);
67+
68+
lower(
69+
r#"
70+
#![recursion_limit = "2"]
71+
macro_rules! n_nuple {
72+
($e:tt) => ();
73+
($first:tt $($rest:tt)*) => {{
74+
n_nuple!($($rest)*)
75+
}};
76+
}
77+
fn main() { n_nuple!(1,2,3); }
78+
"#,
79+
);
80+
}
81+
6482
#[test]
6583
fn macro_resolve() {
6684
// Regression test for a path resolution bug introduced with inner item handling.

crates/hir_def/src/db.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,9 +157,26 @@ pub trait DefDatabase: InternDatabase + AstDatabase + Upcast<dyn AstDatabase> {
157157

158158
#[salsa::invoke(visibility::function_visibility_query)]
159159
fn function_visibility(&self, def: FunctionId) -> Visibility;
160+
161+
#[salsa::transparent]
162+
fn crate_limits(&self, crate_id: CrateId) -> CrateLimits;
160163
}
161164

162165
fn crate_def_map_wait(db: &dyn DefDatabase, krate: CrateId) -> Arc<DefMap> {
163166
let _p = profile::span("crate_def_map:wait");
164167
db.crate_def_map_query(krate)
165168
}
169+
170+
pub struct CrateLimits {
171+
/// The maximum depth for potentially infinitely-recursive compile-time operations like macro expansion or auto-dereference.
172+
pub recursion_limit: u32,
173+
}
174+
175+
fn crate_limits(db: &dyn DefDatabase, crate_id: CrateId) -> CrateLimits {
176+
let def_map = db.crate_def_map(crate_id);
177+
178+
CrateLimits {
179+
// 128 is the default in rustc.
180+
recursion_limit: def_map.recursion_limit().unwrap_or(128),
181+
}
182+
}

crates/hir_def/src/nameres.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ pub struct DefMap {
114114
registered_tools: Vec<SmolStr>,
115115

116116
edition: Edition,
117+
recursion_limit: Option<u32>,
117118
diagnostics: Vec<DefDiagnostic>,
118119
}
119120

@@ -272,6 +273,7 @@ impl DefMap {
272273
block: None,
273274
krate,
274275
edition,
276+
recursion_limit: None,
275277
extern_prelude: FxHashMap::default(),
276278
exported_proc_macros: FxHashMap::default(),
277279
prelude: None,
@@ -461,6 +463,7 @@ impl DefMap {
461463
registered_tools,
462464
block: _,
463465
edition: _,
466+
recursion_limit: _,
464467
krate: _,
465468
prelude: _,
466469
root: _,
@@ -482,6 +485,10 @@ impl DefMap {
482485
pub fn diagnostics(&self) -> &[DefDiagnostic] {
483486
self.diagnostics.as_slice()
484487
}
488+
489+
pub fn recursion_limit(&self) -> Option<u32> {
490+
self.recursion_limit
491+
}
485492
}
486493

487494
impl ModuleData {

crates/hir_def/src/nameres/collector.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,17 @@ impl DefCollector<'_> {
271271
None => continue,
272272
};
273273

274+
if *attr_name == hir_expand::name![recursion_limit] {
275+
if let Some(input) = &attr.input {
276+
if let AttrInput::Literal(limit) = &**input {
277+
if let Ok(limit) = limit.parse() {
278+
self.def_map.recursion_limit = Some(limit);
279+
}
280+
}
281+
}
282+
continue;
283+
}
284+
274285
let attr_is_register_like = *attr_name == hir_expand::name![register_attr]
275286
|| *attr_name == hir_expand::name![register_tool];
276287
if !attr_is_register_like {

crates/hir_expand/src/name.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,7 @@ pub mod known {
270270
global_allocator,
271271
test,
272272
test_case,
273+
recursion_limit,
273274
// Safe intrinsics
274275
abort,
275276
add_with_overflow,

0 commit comments

Comments
 (0)