This patch makes RA understand `#![recursion_limit = "N"]` annotations.
- `crate_limits` query is moved to `DefDatabase`
- `DefMap` now has `recursion_limit: Option<u32>` field
/// The crate graph.
#[salsa::input]
fn crate_graph(&self) -> Arc<CrateGraph>;
/// The crate graph.
#[salsa::input]
fn crate_graph(&self) -> Arc<CrateGraph>;
-
- #[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<ast::SourceFile> {
}
fn parse_query(db: &dyn SourceDatabase, file_id: FileId) -> Parse<ast::SourceFile> {
+#[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.
#[test]
fn macro_resolve() {
// Regression test for a path resolution bug introduced with inner item handling.
#[salsa::invoke(visibility::function_visibility_query)]
fn function_visibility(&self, def: FunctionId) -> Visibility;
#[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<DefMap> {
let _p = profile::span("crate_def_map:wait");
db.crate_def_map_query(krate)
}
}
fn crate_def_map_wait(db: &dyn DefDatabase, krate: CrateId) -> Arc<DefMap> {
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),
+ }
+}
registered_tools: Vec<SmolStr>,
edition: Edition,
registered_tools: Vec<SmolStr>,
edition: Edition,
+ recursion_limit: Option<u32>,
diagnostics: Vec<DefDiagnostic>,
}
diagnostics: Vec<DefDiagnostic>,
}
block: None,
krate,
edition,
block: None,
krate,
edition,
extern_prelude: FxHashMap::default(),
exported_proc_macros: FxHashMap::default(),
prelude: None,
extern_prelude: FxHashMap::default(),
exported_proc_macros: FxHashMap::default(),
prelude: None,
registered_tools,
block: _,
edition: _,
registered_tools,
block: _,
edition: _,
krate: _,
prelude: _,
root: _,
krate: _,
prelude: _,
root: _,
pub fn diagnostics(&self) -> &[DefDiagnostic] {
self.diagnostics.as_slice()
}
pub fn diagnostics(&self) -> &[DefDiagnostic] {
self.diagnostics.as_slice()
}
+
+ pub fn recursion_limit(&self) -> Option<u32> {
+ self.recursion_limit
+ }
+ 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 {
let attr_is_register_like = *attr_name == hir_expand::name![register_attr]
|| *attr_name == hir_expand::name![register_tool];
if !attr_is_register_like {
global_allocator,
test,
test_case,
global_allocator,
test,
test_case,
// Safe intrinsics
abort,
add_with_overflow,
// Safe intrinsics
abort,
add_with_overflow,