let mut expander = Expander::new(db, impl_block.file_id, module_id);
let mut res = Vec::new();
+ // We set a limit to protect against infinite recursion
+ let limit = 100;
+
for m in impl_block.value.syntax().children().filter_map(ast::MacroCall::cast) {
- res.extend(collect_impl_items_in_macro(db, &mut expander, m, id))
+ res.extend(collect_impl_items_in_macro(db, &mut expander, m, id, limit))
}
res
expander: &mut Expander,
m: ast::MacroCall,
id: ImplId,
+ limit: usize,
) -> Vec<AssocItemId> {
+ if limit == 0 {
+ return Vec::new();
+ }
+
if let Some((mark, items)) = expander.enter_expand(db, m) {
let items: InFile<ast::MacroItems> = expander.to_source(items);
let mut res = collect_impl_items(
// Note that ast::ModuleItem do not include ast::MacroCall
// We cannot use ModuleItemOwner::items here
for it in items.value.syntax().children().filter_map(ast::MacroCall::cast) {
- res.extend(collect_impl_items_in_macro(db, expander, it, id))
+ res.extend(collect_impl_items_in_macro(db, expander, it, id, limit - 1))
}
expander.exit(db, mark);
res