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.rs108
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, &macro_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, &macro_arg.1, &macro_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(),
)),
};
};