Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-expand/src/db.rs')
| -rw-r--r-- | crates/hir-expand/src/db.rs | 108 |
1 files changed, 53 insertions, 55 deletions
diff --git a/crates/hir-expand/src/db.rs b/crates/hir-expand/src/db.rs index 965dfa824d..78b2db7306 100644 --- a/crates/hir-expand/src/db.rs +++ b/crates/hir-expand/src/db.rs @@ -14,9 +14,9 @@ use triomphe::Arc; use crate::{ ast_id_map::AstIdMap, builtin_attr_macro::pseudo_derive_attr_expansion, builtin_fn_macro::EagerExpander, fixup, hygiene::HygieneFrame, tt, BuiltinAttrExpander, - BuiltinDeriveExpander, BuiltinFnLikeExpander, ExpandError, ExpandResult, ExpandTo, HirFileId, - HirFileIdRepr, MacroCallId, MacroCallKind, MacroCallLoc, MacroDefId, MacroDefKind, MacroFile, - ProcMacroExpander, + BuiltinDeriveExpander, BuiltinFnLikeExpander, EagerCallInfo, ExpandError, ExpandResult, + ExpandTo, HirFileId, HirFileIdRepr, MacroCallId, MacroCallKind, MacroCallLoc, MacroDefId, + MacroDefKind, MacroFile, ProcMacroExpander, }; /// Total limit on the number of tokens produced by any macro invocation. @@ -53,9 +53,7 @@ impl TokenExpander { match self { TokenExpander::DeclarativeMacro { mac, .. } => mac.expand(tt).map_err(Into::into), TokenExpander::Builtin(it) => it.expand(db, id, tt).map_err(Into::into), - TokenExpander::BuiltinEager(it) => { - it.expand(db, id, tt).map_err(Into::into).map(|res| res.subtree) - } + TokenExpander::BuiltinEager(it) => it.expand(db, id, tt).map_err(Into::into), TokenExpander::BuiltinAttr(it) => it.expand(db, id, tt), TokenExpander::BuiltinDerive(it) => it.expand(db, id, tt), TokenExpander::ProcMacro(_) => { @@ -132,6 +130,14 @@ pub trait ExpandDatabase: SourceDatabase { /// Expand macro call to a token tree. // This query is LRU cached fn macro_expand(&self, macro_call: MacroCallId) -> ExpandResult<Arc<tt::Subtree>>; + #[salsa::invoke(crate::builtin_fn_macro::include_arg_to_tt)] + fn include_expand( + &self, + arg_id: MacroCallId, + ) -> Result< + (triomphe::Arc<(::tt::Subtree<::tt::TokenId>, mbe::TokenMap)>, base_db::FileId), + ExpandError, + >; /// Special case of the previous query for procedural macros. We can't LRU /// proc macros, since they are not deterministic in general, and /// non-determinism breaks salsa in a very, very, very bad way. @@ -281,31 +287,6 @@ fn parse_macro_expansion( let _p = profile::span("parse_macro_expansion"); let mbe::ValueResult { value: tt, err } = db.macro_expand(macro_file.macro_call_id); - if let Some(err) = &err { - if tracing::enabled!(tracing::Level::DEBUG) { - // Note: - // The final goal we would like to make all parse_macro success, - // such that the following log will not call anyway. - let loc = db.lookup_intern_macro_call(macro_file.macro_call_id); - let node = loc.to_node(db); - - // collect parent information for warning log - let parents = std::iter::successors(loc.kind.file_id().call_node(db), |it| { - it.file_id.call_node(db) - }) - .map(|n| format!("{:#}", n.value)) - .collect::<Vec<_>>() - .join("\n"); - - tracing::debug!( - "fail on macro_parse: (reason: {:?} macro_call: {:#}) parents: {}", - err, - node.value, - parents - ); - } - } - let expand_to = macro_expand_to(db, macro_file.macro_call_id); tracing::debug!("expanded = {}", tt.as_debug_string()); @@ -320,9 +301,14 @@ fn macro_arg( db: &dyn ExpandDatabase, id: MacroCallId, ) -> Option<Arc<(tt::Subtree, mbe::TokenMap, fixup::SyntaxFixupUndoInfo)>> { - let arg = db.macro_arg_text(id)?; let loc = db.lookup_intern_macro_call(id); + if let Some(EagerCallInfo { arg, arg_id: Some(_), error: _ }) = loc.eager.as_deref() { + return Some(Arc::new((arg.0.clone(), arg.1.clone(), Default::default()))); + } + + let arg = db.macro_arg_text(id)?; + let node = SyntaxNode::new_root(arg); let censor = censor_for_macro_input(&loc, &node); let mut fixups = fixup::fixup_syntax(&node); @@ -398,7 +384,17 @@ fn macro_arg_text(db: &dyn ExpandDatabase, id: MacroCallId) -> Option<GreenNode> return None; } } - Some(arg.green().into()) + if let Some(EagerCallInfo { arg, .. }) = loc.eager.as_deref() { + Some( + mbe::token_tree_to_syntax_node(&arg.0, mbe::TopEntryPoint::Expr) + .0 + .syntax_node() + .green() + .into(), + ) + } else { + Some(arg.green().into()) + } } fn macro_def( @@ -445,23 +441,21 @@ fn macro_def( fn macro_expand(db: &dyn ExpandDatabase, id: MacroCallId) -> ExpandResult<Arc<tt::Subtree>> { let _p = profile::span("macro_expand"); let loc = db.lookup_intern_macro_call(id); - if let Some(eager) = &loc.eager { - return ExpandResult { value: eager.arg_or_expansion.clone(), err: eager.error.clone() }; + if let Some(EagerCallInfo { arg, arg_id: None, error }) = loc.eager.as_deref() { + // This is an input expansion for an eager macro. These are already pre-expanded + return ExpandResult { value: Arc::new(arg.0.clone()), err: error.clone() }; } - let expander = match db.macro_def(loc.def) { Ok(it) => it, - // FIXME: This is weird -- we effectively report macro *definition* - // errors lazily, when we try to expand the macro. Instead, they should - // be reported at the definition site when we construct a def map. - // (Note we do report them also at the definition site in the late diagnostic pass) + // FIXME: We should make sure to enforce a variant that invalid macro + // definitions do not get expanders that could reach this call path! Err(err) => { return ExpandResult { value: Arc::new(tt::Subtree { delimiter: tt::Delimiter::UNSPECIFIED, token_trees: vec![], }), - err: Some(ExpandError::Other(format!("invalid macro definition: {err}").into())), + err: Some(ExpandError::other(format!("invalid macro definition: {err}"))), } } }; @@ -473,13 +467,21 @@ fn macro_expand(db: &dyn ExpandDatabase, id: MacroCallId) -> ExpandResult<Arc<tt token_trees: Vec::new(), }, ), - err: Some(ExpandError::Other( + // FIXME: We should make sure to enforce a variant that invalid macro + // calls do not reach this call path! + err: Some(ExpandError::other( "invalid token tree" - .into(), )), }; }; - let ExpandResult { value: mut tt, err } = expander.expand(db, id, ¯o_arg.0); + let (arg_tt, arg_tm, undo_info) = &*macro_arg; + let ExpandResult { value: mut tt, mut err } = expander.expand(db, id, arg_tt); + + if let Some(EagerCallInfo { error, .. }) = loc.eager.as_deref() { + // FIXME: We should report both errors! + err = error.clone().or(err); + } + // Set a hard limit for the expanded tt let count = tt.count(); if TOKEN_LIMIT.check(count).is_err() { @@ -488,18 +490,15 @@ fn macro_expand(db: &dyn ExpandDatabase, id: MacroCallId) -> ExpandResult<Arc<tt delimiter: tt::Delimiter::UNSPECIFIED, token_trees: vec![], }), - err: Some(ExpandError::Other( - format!( - "macro invocation exceeds token limit: produced {} tokens, limit is {}", - count, - TOKEN_LIMIT.inner(), - ) - .into(), - )), + err: Some(ExpandError::other(format!( + "macro invocation exceeds token limit: produced {} tokens, limit is {}", + count, + TOKEN_LIMIT.inner(), + ))), }; } - fixup::reverse_fixups(&mut tt, ¯o_arg.1, ¯o_arg.2); + fixup::reverse_fixups(&mut tt, arg_tm, undo_info); ExpandResult { value: Arc::new(tt), err } } @@ -520,9 +519,8 @@ fn expand_proc_macro(db: &dyn ExpandDatabase, id: MacroCallId) -> ExpandResult<t delimiter: tt::Delimiter::UNSPECIFIED, token_trees: Vec::new(), }, - err: Some(ExpandError::Other( + err: Some(ExpandError::other( "invalid token tree" - .into(), )), }; }; |