aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_def
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2020-07-11 17:35:35 +0100
committerAleksey Kladov <[email protected]>2020-07-11 17:39:49 +0100
commita8891ae3ca1f23ef310a91b2e30bac7e08be4aa1 (patch)
tree8717f26bc20300c1eaf37baba97bb0f80dd69208 /crates/ra_hir_def
parentc884ceb31c2761a9eb7de8754c4be4cc47469dee (diff)
More tight recursion limit when expanding macros in function bodies
cc #4944 cc #5317 This doesn't fully close #4944 -- looks like we hit SO in syntax highlighting, when we use `Semantics::expand_macro`. Seems like we need to place expansion limit on the macro itself (store it as a part of MacroCallId?)!
Diffstat (limited to 'crates/ra_hir_def')
-rw-r--r--crates/ra_hir_def/src/body.rs54
1 files changed, 48 insertions, 6 deletions
diff --git a/crates/ra_hir_def/src/body.rs b/crates/ra_hir_def/src/body.rs
index 031ffe13f..8c233a717 100644
--- a/crates/ra_hir_def/src/body.rs
+++ b/crates/ra_hir_def/src/body.rs
@@ -14,6 +14,7 @@ use ra_db::CrateId;
14use ra_prof::profile; 14use ra_prof::profile;
15use ra_syntax::{ast, AstNode, AstPtr}; 15use ra_syntax::{ast, AstNode, AstPtr};
16use rustc_hash::FxHashMap; 16use rustc_hash::FxHashMap;
17use test_utils::mark;
17 18
18pub(crate) use lower::LowerCtx; 19pub(crate) use lower::LowerCtx;
19 20
@@ -42,7 +43,7 @@ pub(crate) struct Expander {
42 current_file_id: HirFileId, 43 current_file_id: HirFileId,
43 ast_id_map: Arc<AstIdMap>, 44 ast_id_map: Arc<AstIdMap>,
44 module: ModuleId, 45 module: ModuleId,
45 recursive_limit: usize, 46 recursion_limit: usize,
46} 47}
47 48
48impl CfgExpander { 49impl CfgExpander {
@@ -81,7 +82,7 @@ impl Expander {
81 current_file_id, 82 current_file_id,
82 ast_id_map, 83 ast_id_map,
83 module, 84 module,
84 recursive_limit: 0, 85 recursion_limit: 0,
85 } 86 }
86 } 87 }
87 88
@@ -91,7 +92,9 @@ impl Expander {
91 local_scope: Option<&ItemScope>, 92 local_scope: Option<&ItemScope>,
92 macro_call: ast::MacroCall, 93 macro_call: ast::MacroCall,
93 ) -> Option<(Mark, T)> { 94 ) -> Option<(Mark, T)> {
94 if self.recursive_limit > 1024 { 95 self.recursion_limit += 1;
96 if self.recursion_limit > 32 {
97 mark::hit!(your_stack_belongs_to_me);
95 return None; 98 return None;
96 } 99 }
97 100
@@ -118,8 +121,6 @@ impl Expander {
118 self.cfg_expander.hygiene = Hygiene::new(db.upcast(), file_id); 121 self.cfg_expander.hygiene = Hygiene::new(db.upcast(), file_id);
119 self.current_file_id = file_id; 122 self.current_file_id = file_id;
120 self.ast_id_map = db.ast_id_map(file_id); 123 self.ast_id_map = db.ast_id_map(file_id);
121 self.recursive_limit += 1;
122
123 return Some((mark, expr)); 124 return Some((mark, expr));
124 } 125 }
125 } 126 }
@@ -134,7 +135,7 @@ impl Expander {
134 self.cfg_expander.hygiene = Hygiene::new(db.upcast(), mark.file_id); 135 self.cfg_expander.hygiene = Hygiene::new(db.upcast(), mark.file_id);
135 self.current_file_id = mark.file_id; 136 self.current_file_id = mark.file_id;
136 self.ast_id_map = mem::take(&mut mark.ast_id_map); 137 self.ast_id_map = mem::take(&mut mark.ast_id_map);
137 self.recursive_limit -= 1; 138 self.recursion_limit -= 1;
138 mark.bomb.defuse(); 139 mark.bomb.defuse();
139 } 140 }
140 141
@@ -311,3 +312,44 @@ impl BodySourceMap {
311 self.field_map[&(expr, field)].clone() 312 self.field_map[&(expr, field)].clone()
312 } 313 }
313} 314}
315
316#[cfg(test)]
317mod tests {
318 use ra_db::{fixture::WithFixture, SourceDatabase};
319 use test_utils::mark;
320
321 use crate::ModuleDefId;
322
323 use super::*;
324
325 fn lower(ra_fixture: &str) -> Arc<Body> {
326 let (db, file_id) = crate::test_db::TestDB::with_single_file(ra_fixture);
327
328 let krate = db.crate_graph().iter().next().unwrap();
329 let def_map = db.crate_def_map(krate);
330 let module = def_map.modules_for_file(file_id).next().unwrap();
331 let module = &def_map[module];
332 let fn_def = match module.scope.declarations().next().unwrap() {
333 ModuleDefId::FunctionId(it) => it,
334 _ => panic!(),
335 };
336
337 db.body(fn_def.into())
338 }
339
340 #[test]
341 fn your_stack_belongs_to_me() {
342 mark::check!(your_stack_belongs_to_me);
343 lower(
344 r"
345macro_rules! n_nuple {
346 ($e:tt) => ();
347 ($($rest:tt)*) => {{
348 (n_nuple!($($rest)*)None,)
349 }};
350}
351fn main() { n_nuple!(1,2,3); }
352",
353 );
354 }
355}