use drop_bomb::DropBomb;
use either::Either;
use hir_expand::{
- ast_id_map::AstIdMap, hygiene::Hygiene, AstId, ExpandResult, HirFileId, InFile, MacroDefId,
+ ast_id_map::AstIdMap, hygiene::Hygiene, AstId, ExpandError, ExpandResult, HirFileId, InFile,
+ MacroCallId, MacroDefId,
};
use la_arena::{Arena, ArenaMap};
use limit::Limit;
recursion_limit: usize,
}
-#[cfg(test)]
-const EXPANSION_RECURSION_LIMIT: Limit = Limit::new(32);
-
-#[cfg(not(test))]
-const EXPANSION_RECURSION_LIMIT: Limit = Limit::new(128);
-
impl CfgExpander {
pub(crate) fn new(
db: &dyn DefDatabase,
db: &dyn DefDatabase,
macro_call: ast::MacroCall,
) -> Result<ExpandResult<Option<(Mark, T)>>, UnresolvedMacro> {
- if EXPANSION_RECURSION_LIMIT.check(self.recursion_limit + 1).is_err() {
+ if self.recursion_limit(db).check(self.recursion_limit + 1).is_err() {
cov_mark::hit!(your_stack_belongs_to_me);
return Ok(ExpandResult::str_err(
"reached recursion limit during macro expansion".into(),
}
};
+ Ok(self.enter_expand_inner(db, call_id, err))
+ }
+
+ pub fn enter_expand_id<T: ast::AstNode>(
+ &mut self,
+ db: &dyn DefDatabase,
+ call_id: MacroCallId,
+ ) -> ExpandResult<Option<(Mark, T)>> {
+ self.enter_expand_inner(db, call_id, None)
+ }
+
+ fn enter_expand_inner<T: ast::AstNode>(
+ &mut self,
+ db: &dyn DefDatabase,
+ call_id: MacroCallId,
+ mut err: Option<ExpandError>,
+ ) -> ExpandResult<Option<(Mark, T)>> {
if err.is_none() {
err = db.macro_expand_error(call_id);
}
tracing::warn!("no error despite `parse_or_expand` failing");
}
- return Ok(ExpandResult::only_err(err.unwrap_or_else(|| {
+ return ExpandResult::only_err(err.unwrap_or_else(|| {
mbe::ExpandError::Other("failed to parse macro invocation".into())
- })));
+ }));
}
};
Some(it) => it,
None => {
// This can happen without being an error, so only forward previous errors.
- return Ok(ExpandResult { value: None, err });
+ return ExpandResult { value: None, err };
}
};
self.current_file_id = file_id;
self.ast_id_map = db.ast_id_map(file_id);
- Ok(ExpandResult { value: Some((mark, node)), err })
+ ExpandResult { value: Some((mark, node)), err }
}
pub fn exit(&mut self, db: &dyn DefDatabase, mut mark: Mark) {
let file_local_id = self.ast_id_map.ast_id(item);
AstId::new(self.current_file_id, file_local_id)
}
+
+ fn recursion_limit(&self, db: &dyn DefDatabase) -> Limit {
+ let limit = db.crate_limits(self.cfg_expander.krate).recursion_limit as _;
+
+ #[cfg(not(test))]
+ return Limit::new(limit);
+
+ // Without this, `body::tests::your_stack_belongs_to_me` stack-overflows in debug
+ #[cfg(test)]
+ return Limit::new(std::cmp::min(32, limit));
+ }
}
#[derive(Debug)]