8885: internal: greatly simplify eager macro representation r=jonas-schievink a=jonas-schievink

- Share structures with lazy macros, make both use `MacroCallLoc`.
- Remove `intern_eager_expansion`, `EagerCallLoc`, `EagerMacroId`, and *many* matches on `MacroCallId`.
- Make a lot of FIXMEs obsolete since the code no longer distinguishes between eager and lazy macros.
- Add `EagerCallInfo`, which is `Some` for calls to eager macros and holds the argument or expansion result and the included file.

8887: fix: fix derive collection after unresolved attribute fallback r=jonas-schievink a=jonas-schievink

Fixes https://github.com/rust-analyzer/rust-analyzer/pull/8882#issuecomment-844379170

bors r+

Co-authored-by: Jonas Schievink <jonasschievink@gmail.com>
This commit is contained in:
bors[bot] 2021-05-19 19:07:05 +00:00 committed by GitHub
commit 49922cb2c3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 192 additions and 280 deletions

View file

@ -2,8 +2,8 @@
pub use hir_def::db::*;
pub use hir_expand::db::{
AstDatabase, AstDatabaseStorage, AstIdMapQuery, HygieneFrameQuery, InternEagerExpansionQuery,
InternMacroQuery, MacroArgTextQuery, MacroDefQuery, MacroExpandQuery, ParseMacroExpansionQuery,
AstDatabase, AstDatabaseStorage, AstIdMapQuery, HygieneFrameQuery, InternMacroQuery,
MacroArgTextQuery, MacroDefQuery, MacroExpandQuery, ParseMacroExpansionQuery,
};
pub use hir_ty::db::*;

View file

@ -367,6 +367,8 @@ impl DefCollector<'_> {
/// This improves UX when proc macros are turned off or don't work, and replicates the behavior
/// before we supported proc. attribute macros.
fn reseed_with_unresolved_attributes(&mut self) -> ReachedFixedPoint {
cov_mark::hit!(unresolved_attribute_fallback);
let mut added_items = false;
let unexpanded_macros = std::mem::replace(&mut self.unexpanded_macros, Vec::new());
for directive in &unexpanded_macros {
@ -391,7 +393,9 @@ impl DefCollector<'_> {
added_items = true;
}
}
self.unexpanded_macros = unexpanded_macros;
// The collection above might add new unresolved macros (eg. derives), so merge the lists.
self.unexpanded_macros.extend(unexpanded_macros);
if added_items {
// Continue name resolution with the new data.
@ -948,20 +952,17 @@ impl DefCollector<'_> {
// incrementality).
let err = self.db.macro_expand_error(macro_call_id);
if let Some(err) = err {
if let MacroCallId::LazyMacro(id) = macro_call_id {
let loc: MacroCallLoc = self.db.lookup_intern_macro(id);
let loc: MacroCallLoc = self.db.lookup_intern_macro(macro_call_id);
let diag = match err {
hir_expand::ExpandError::UnresolvedProcMacro => {
// Missing proc macros are non-fatal, so they are handled specially.
DefDiagnostic::unresolved_proc_macro(module_id, loc.kind)
}
_ => DefDiagnostic::macro_error(module_id, loc.kind, err.to_string()),
};
let diag = match err {
hir_expand::ExpandError::UnresolvedProcMacro => {
// Missing proc macros are non-fatal, so they are handled specially.
DefDiagnostic::unresolved_proc_macro(module_id, loc.kind)
}
_ => DefDiagnostic::macro_error(module_id, loc.kind, err.to_string()),
};
self.def_map.diagnostics.push(diag);
}
// FIXME: Handle eager macros.
self.def_map.diagnostics.push(diag);
}
// Then, fetch and process the item tree. This will reuse the expansion result from above.

View file

@ -685,6 +685,27 @@ pub trait Clone {}
);
}
#[test]
fn builtin_derive_with_unresolved_attributes_fall_back() {
// Tests that we still resolve derives after ignoring an unresolved attribute.
cov_mark::check!(unresolved_attribute_fallback);
let map = compute_crate_def_map(
r#"
//- /main.rs crate:main deps:core
use core::Clone;
#[derive(Clone)]
#[unresolved]
struct Foo;
//- /core.rs crate:core
#[rustc_builtin_macro]
pub macro Clone {}
"#,
);
assert_eq!(map.modules[map.root].scope.impls().len(), 1);
}
#[test]
fn macro_expansion_overflow() {
cov_mark::check!(macro_expansion_overflow);
@ -842,7 +863,6 @@ fn collects_derive_helpers() {
fn resolve_macro_def() {
check(
r#"
//- /lib.rs
pub macro structs($($i:ident),*) {
$(struct $i { field: u32 } )*
}

View file

@ -8,7 +8,7 @@ use syntax::{
match_ast,
};
use crate::{db::AstDatabase, name, quote, AstId, CrateId, LazyMacroId, MacroDefId, MacroDefKind};
use crate::{db::AstDatabase, name, quote, AstId, CrateId, MacroCallId, MacroDefId, MacroDefKind};
macro_rules! register_builtin {
( $($trait:ident => $expand:ident),* ) => {
@ -21,7 +21,7 @@ macro_rules! register_builtin {
pub fn expand(
&self,
db: &dyn AstDatabase,
id: LazyMacroId,
id: MacroCallId,
tt: &tt::Subtree,
) -> Result<tt::Subtree, mbe::ExpandError> {
let expander = match *self {
@ -164,7 +164,7 @@ fn expand_simple_derive(
Ok(expanded)
}
fn find_builtin_crate(db: &dyn AstDatabase, id: LazyMacroId) -> tt::TokenTree {
fn find_builtin_crate(db: &dyn AstDatabase, id: MacroCallId) -> tt::TokenTree {
// FIXME: make hygiene works for builtin derive macro
// such that $crate can be used here.
let cg = db.crate_graph();
@ -184,7 +184,7 @@ fn find_builtin_crate(db: &dyn AstDatabase, id: LazyMacroId) -> tt::TokenTree {
fn copy_expand(
db: &dyn AstDatabase,
id: LazyMacroId,
id: MacroCallId,
tt: &tt::Subtree,
) -> Result<tt::Subtree, mbe::ExpandError> {
let krate = find_builtin_crate(db, id);
@ -193,7 +193,7 @@ fn copy_expand(
fn clone_expand(
db: &dyn AstDatabase,
id: LazyMacroId,
id: MacroCallId,
tt: &tt::Subtree,
) -> Result<tt::Subtree, mbe::ExpandError> {
let krate = find_builtin_crate(db, id);
@ -202,7 +202,7 @@ fn clone_expand(
fn default_expand(
db: &dyn AstDatabase,
id: LazyMacroId,
id: MacroCallId,
tt: &tt::Subtree,
) -> Result<tt::Subtree, mbe::ExpandError> {
let krate = find_builtin_crate(db, id);
@ -211,7 +211,7 @@ fn default_expand(
fn debug_expand(
db: &dyn AstDatabase,
id: LazyMacroId,
id: MacroCallId,
tt: &tt::Subtree,
) -> Result<tt::Subtree, mbe::ExpandError> {
let krate = find_builtin_crate(db, id);
@ -220,7 +220,7 @@ fn debug_expand(
fn hash_expand(
db: &dyn AstDatabase,
id: LazyMacroId,
id: MacroCallId,
tt: &tt::Subtree,
) -> Result<tt::Subtree, mbe::ExpandError> {
let krate = find_builtin_crate(db, id);
@ -229,7 +229,7 @@ fn hash_expand(
fn eq_expand(
db: &dyn AstDatabase,
id: LazyMacroId,
id: MacroCallId,
tt: &tt::Subtree,
) -> Result<tt::Subtree, mbe::ExpandError> {
let krate = find_builtin_crate(db, id);
@ -238,7 +238,7 @@ fn eq_expand(
fn partial_eq_expand(
db: &dyn AstDatabase,
id: LazyMacroId,
id: MacroCallId,
tt: &tt::Subtree,
) -> Result<tt::Subtree, mbe::ExpandError> {
let krate = find_builtin_crate(db, id);
@ -247,7 +247,7 @@ fn partial_eq_expand(
fn ord_expand(
db: &dyn AstDatabase,
id: LazyMacroId,
id: MacroCallId,
tt: &tt::Subtree,
) -> Result<tt::Subtree, mbe::ExpandError> {
let krate = find_builtin_crate(db, id);
@ -256,7 +256,7 @@ fn ord_expand(
fn partial_ord_expand(
db: &dyn AstDatabase,
id: LazyMacroId,
id: MacroCallId,
tt: &tt::Subtree,
) -> Result<tt::Subtree, mbe::ExpandError> {
let krate = find_builtin_crate(db, id);
@ -317,6 +317,7 @@ $0
local_inner: false,
},
krate: CrateId(0),
eager: None,
kind: MacroCallKind::Derive {
ast_id,
derive_name: name.to_string(),

View file

@ -1,7 +1,7 @@
//! Builtin macro
use crate::{
db::AstDatabase, name, quote, AstId, CrateId, EagerMacroId, LazyMacroId, MacroCallId,
MacroCallLoc, MacroDefId, MacroDefKind, TextSize,
db::AstDatabase, name, quote, AstId, CrateId, MacroCallId, MacroCallLoc, MacroDefId,
MacroDefKind, TextSize,
};
use base_db::{AnchoredPath, Edition, FileId};
@ -27,7 +27,7 @@ macro_rules! register_builtin {
pub fn expand(
&self,
db: &dyn AstDatabase,
id: LazyMacroId,
id: MacroCallId,
tt: &tt::Subtree,
) -> ExpandResult<tt::Subtree> {
let expander = match *self {
@ -41,7 +41,7 @@ macro_rules! register_builtin {
pub fn expand(
&self,
db: &dyn AstDatabase,
arg_id: EagerMacroId,
arg_id: MacroCallId,
tt: &tt::Subtree,
) -> ExpandResult<Option<ExpandedEager>> {
let expander = match *self {
@ -128,7 +128,7 @@ register_builtin! {
fn module_path_expand(
_db: &dyn AstDatabase,
_id: LazyMacroId,
_id: MacroCallId,
_tt: &tt::Subtree,
) -> ExpandResult<tt::Subtree> {
// Just return a dummy result.
@ -137,7 +137,7 @@ fn module_path_expand(
fn line_expand(
_db: &dyn AstDatabase,
_id: LazyMacroId,
_id: MacroCallId,
_tt: &tt::Subtree,
) -> ExpandResult<tt::Subtree> {
// dummy implementation for type-checking purposes
@ -151,7 +151,7 @@ fn line_expand(
fn stringify_expand(
db: &dyn AstDatabase,
id: LazyMacroId,
id: MacroCallId,
_tt: &tt::Subtree,
) -> ExpandResult<tt::Subtree> {
let loc = db.lookup_intern_macro(id);
@ -176,7 +176,7 @@ fn stringify_expand(
fn column_expand(
_db: &dyn AstDatabase,
_id: LazyMacroId,
_id: MacroCallId,
_tt: &tt::Subtree,
) -> ExpandResult<tt::Subtree> {
// dummy implementation for type-checking purposes
@ -190,7 +190,7 @@ fn column_expand(
fn assert_expand(
_db: &dyn AstDatabase,
_id: LazyMacroId,
_id: MacroCallId,
tt: &tt::Subtree,
) -> ExpandResult<tt::Subtree> {
// A hacky implementation for goto def and hover
@ -214,7 +214,7 @@ fn assert_expand(
fn file_expand(
_db: &dyn AstDatabase,
_id: LazyMacroId,
_id: MacroCallId,
_tt: &tt::Subtree,
) -> ExpandResult<tt::Subtree> {
// FIXME: RA purposefully lacks knowledge of absolute file names
@ -230,7 +230,7 @@ fn file_expand(
fn format_args_expand(
_db: &dyn AstDatabase,
_id: LazyMacroId,
_id: MacroCallId,
tt: &tt::Subtree,
) -> ExpandResult<tt::Subtree> {
// We expand `format_args!("", a1, a2)` to
@ -265,7 +265,7 @@ fn format_args_expand(
fn asm_expand(
_db: &dyn AstDatabase,
_id: LazyMacroId,
_id: MacroCallId,
_tt: &tt::Subtree,
) -> ExpandResult<tt::Subtree> {
// both asm and llvm_asm don't return anything, so we can expand them to nothing,
@ -278,7 +278,7 @@ fn asm_expand(
fn global_asm_expand(
_db: &dyn AstDatabase,
_id: LazyMacroId,
_id: MacroCallId,
_tt: &tt::Subtree,
) -> ExpandResult<tt::Subtree> {
// Expand to nothing (at item-level)
@ -287,7 +287,7 @@ fn global_asm_expand(
fn cfg_expand(
db: &dyn AstDatabase,
id: LazyMacroId,
id: MacroCallId,
tt: &tt::Subtree,
) -> ExpandResult<tt::Subtree> {
let loc = db.lookup_intern_macro(id);
@ -299,7 +299,7 @@ fn cfg_expand(
fn panic_expand(
db: &dyn AstDatabase,
id: LazyMacroId,
id: MacroCallId,
tt: &tt::Subtree,
) -> ExpandResult<tt::Subtree> {
let loc: MacroCallLoc = db.lookup_intern_macro(id);
@ -324,7 +324,7 @@ fn unquote_str(lit: &tt::Literal) -> Option<String> {
fn compile_error_expand(
_db: &dyn AstDatabase,
_id: EagerMacroId,
_id: MacroCallId,
tt: &tt::Subtree,
) -> ExpandResult<Option<ExpandedEager>> {
let err = match &*tt.token_trees {
@ -345,7 +345,7 @@ fn compile_error_expand(
fn concat_expand(
_db: &dyn AstDatabase,
_arg_id: EagerMacroId,
_arg_id: MacroCallId,
tt: &tt::Subtree,
) -> ExpandResult<Option<ExpandedEager>> {
let mut err = None;
@ -376,7 +376,7 @@ fn concat_expand(
fn concat_idents_expand(
_db: &dyn AstDatabase,
_arg_id: EagerMacroId,
_arg_id: MacroCallId,
tt: &tt::Subtree,
) -> ExpandResult<Option<ExpandedEager>> {
let mut err = None;
@ -427,7 +427,7 @@ fn parse_string(tt: &tt::Subtree) -> Result<String, mbe::ExpandError> {
fn include_expand(
db: &dyn AstDatabase,
arg_id: EagerMacroId,
arg_id: MacroCallId,
tt: &tt::Subtree,
) -> ExpandResult<Option<ExpandedEager>> {
let res = (|| {
@ -457,7 +457,7 @@ fn include_expand(
fn include_bytes_expand(
_db: &dyn AstDatabase,
_arg_id: EagerMacroId,
_arg_id: MacroCallId,
tt: &tt::Subtree,
) -> ExpandResult<Option<ExpandedEager>> {
if let Err(e) = parse_string(tt) {
@ -477,7 +477,7 @@ fn include_bytes_expand(
fn include_str_expand(
db: &dyn AstDatabase,
arg_id: EagerMacroId,
arg_id: MacroCallId,
tt: &tt::Subtree,
) -> ExpandResult<Option<ExpandedEager>> {
let path = match parse_string(tt) {
@ -502,14 +502,14 @@ fn include_str_expand(
ExpandResult::ok(Some(ExpandedEager::new(quote!(#text), FragmentKind::Expr)))
}
fn get_env_inner(db: &dyn AstDatabase, arg_id: EagerMacroId, key: &str) -> Option<String> {
let krate = db.lookup_intern_eager_expansion(arg_id).krate;
fn get_env_inner(db: &dyn AstDatabase, arg_id: MacroCallId, key: &str) -> Option<String> {
let krate = db.lookup_intern_macro(arg_id).krate;
db.crate_graph()[krate].env.get(key)
}
fn env_expand(
db: &dyn AstDatabase,
arg_id: EagerMacroId,
arg_id: MacroCallId,
tt: &tt::Subtree,
) -> ExpandResult<Option<ExpandedEager>> {
let key = match parse_string(tt) {
@ -540,7 +540,7 @@ fn env_expand(
fn option_env_expand(
db: &dyn AstDatabase,
arg_id: EagerMacroId,
arg_id: MacroCallId,
tt: &tt::Subtree,
) -> ExpandResult<Option<ExpandedEager>> {
let key = match parse_string(tt) {
@ -560,7 +560,7 @@ fn option_env_expand(
mod tests {
use super::*;
use crate::{
name::AsName, test_db::TestDB, AstNode, EagerCallLoc, MacroCallId, MacroCallKind,
name::AsName, test_db::TestDB, AstNode, EagerCallInfo, MacroCallId, MacroCallKind,
MacroCallLoc,
};
use base_db::{fixture::WithFixture, SourceDatabase};
@ -599,6 +599,7 @@ mod tests {
let loc = MacroCallLoc {
def,
krate,
eager: None,
kind: MacroCallKind::FnLike {
ast_id: AstId::new(file_id.into(), ast_id_map.ast_id(&macro_call)),
fragment: FragmentKind::Expr,
@ -620,28 +621,28 @@ mod tests {
let parsed_args = mbe::ast_to_token_tree(&args).0;
let call_id = AstId::new(file_id.into(), ast_id_map.ast_id(&macro_call));
let arg_id = db.intern_eager_expansion({
EagerCallLoc {
def,
fragment: FragmentKind::Expr,
subtree: Arc::new(parsed_args.clone()),
krate,
call: call_id,
let arg_id = db.intern_macro(MacroCallLoc {
def,
krate,
eager: Some(EagerCallInfo {
arg_or_expansion: Arc::new(parsed_args.clone()),
included_file: None,
}
}),
kind: MacroCallKind::FnLike { ast_id: call_id, fragment: FragmentKind::Expr },
});
let expanded = expander.expand(&db, arg_id, &parsed_args).value.unwrap();
let eager = EagerCallLoc {
let loc = MacroCallLoc {
def,
fragment: expanded.fragment,
subtree: Arc::new(expanded.subtree),
krate,
call: call_id,
included_file: expanded.included_file,
eager: Some(EagerCallInfo {
arg_or_expansion: Arc::new(expanded.subtree),
included_file: expanded.included_file,
}),
kind: MacroCallKind::FnLike { ast_id: call_id, fragment: expanded.fragment },
};
let id: MacroCallId = db.intern_eager_expansion(eager).into();
let id: MacroCallId = db.intern_macro(loc).into();
id.as_file()
}
};

View file

@ -13,8 +13,8 @@ use syntax::{
use crate::{
ast_id_map::AstIdMap, hygiene::HygieneFrame, input::process_macro_input, BuiltinDeriveExpander,
BuiltinFnLikeExpander, EagerCallLoc, EagerMacroId, HirFileId, HirFileIdRepr, LazyMacroId,
MacroCallId, MacroCallLoc, MacroDefId, MacroDefKind, MacroFile, ProcMacroExpander,
BuiltinFnLikeExpander, HirFileId, HirFileIdRepr, MacroCallId, MacroCallLoc, MacroDefId,
MacroDefKind, MacroFile, ProcMacroExpander,
};
/// Total limit on the number of tokens produced by any macro invocation.
@ -41,7 +41,7 @@ impl TokenExpander {
fn expand(
&self,
db: &dyn AstDatabase,
id: LazyMacroId,
id: MacroCallId,
tt: &tt::Subtree,
) -> mbe::ExpandResult<tt::Subtree> {
match self {
@ -101,11 +101,7 @@ pub trait AstDatabase: SourceDatabase {
/// We encode macro definitions into ids of macro calls, this what allows us
/// to be incremental.
#[salsa::interned]
fn intern_macro(&self, macro_call: MacroCallLoc) -> LazyMacroId;
/// Certain built-in macros are eager (`format!(concat!("file: ", file!(), "{}"")), 92`).
/// For them, we actually want to encode the whole token tree as an argument.
#[salsa::interned]
fn intern_eager_expansion(&self, eager: EagerCallLoc) -> EagerMacroId;
fn intern_macro(&self, macro_call: MacroCallLoc) -> MacroCallId;
/// Lowers syntactic macro call to a token tree representation.
#[salsa::transparent]
@ -146,17 +142,12 @@ pub fn expand_hypothetical(
token_to_map.text_range().checked_sub(hypothetical_args.syntax().text_range().start())?;
let token_id = tmap_1.token_by_range(range)?;
let lazy_id = match actual_macro_call {
MacroCallId::LazyMacro(id) => id,
MacroCallId::EagerMacro(_) => return None,
};
let macro_def = {
let loc = db.lookup_intern_macro(lazy_id);
let loc: MacroCallLoc = db.lookup_intern_macro(actual_macro_call);
db.macro_def(loc.def)?
};
let hypothetical_expansion = macro_def.expand(db, lazy_id, &tt);
let hypothetical_expansion = macro_def.expand(db, actual_macro_call, &tt);
let fragment_kind = macro_fragment_kind(db, actual_macro_call);
@ -194,30 +185,22 @@ fn parse_macro_expansion(
// Note:
// The final goal we would like to make all parse_macro success,
// such that the following log will not call anyway.
match macro_file.macro_call_id {
MacroCallId::LazyMacro(id) => {
let loc: MacroCallLoc = db.lookup_intern_macro(id);
let node = loc.kind.node(db);
let loc: MacroCallLoc = db.lookup_intern_macro(macro_file.macro_call_id);
let node = loc.kind.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)
})
// 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");
log::warn!(
"fail on macro_parse: (reason: {:?} macro_call: {:#}) parents: {}",
err,
node.value,
parents
);
}
_ => {
log::warn!("fail on macro_parse: (reason: {:?})", err);
}
}
log::warn!(
"fail on macro_parse: (reason: {:?} macro_call: {:#}) parents: {}",
err,
node.value,
parents
);
}
let tt = match result.value {
Some(tt) => tt,
@ -269,25 +252,16 @@ fn macro_arg(db: &dyn AstDatabase, id: MacroCallId) -> Option<Arc<(tt::Subtree,
let arg = db.macro_arg_text(id)?;
let (mut tt, tmap) = mbe::syntax_node_to_token_tree(&SyntaxNode::new_root(arg));
if let MacroCallId::LazyMacro(id) = id {
let loc: MacroCallLoc = db.lookup_intern_macro(id);
if loc.def.is_proc_macro() {
// proc macros expect their inputs without parentheses, MBEs expect it with them included
tt.delimiter = None;
}
let loc: MacroCallLoc = db.lookup_intern_macro(id);
if loc.def.is_proc_macro() {
// proc macros expect their inputs without parentheses, MBEs expect it with them included
tt.delimiter = None;
}
Some(Arc::new((tt, tmap)))
}
fn macro_arg_text(db: &dyn AstDatabase, id: MacroCallId) -> Option<GreenNode> {
let id = match id {
MacroCallId::LazyMacro(id) => id,
MacroCallId::EagerMacro(_id) => {
// FIXME: support macro_arg for eager macro
return None;
}
};
let loc = db.lookup_intern_macro(id);
let arg = loc.kind.arg(db)?;
let arg = process_macro_input(db, arg, id);
@ -347,24 +321,21 @@ fn macro_expand_with_arg(
arg: Option<Arc<(tt::Subtree, mbe::TokenMap)>>,
) -> ExpandResult<Option<Arc<tt::Subtree>>> {
let _p = profile::span("macro_expand");
let lazy_id = match id {
MacroCallId::LazyMacro(id) => id,
MacroCallId::EagerMacro(id) => {
if arg.is_some() {
return ExpandResult::str_err(
"hypothetical macro expansion not implemented for eager macro".to_owned(),
);
} else {
return ExpandResult {
value: Some(db.lookup_intern_eager_expansion(id).subtree),
// FIXME: There could be errors here!
err: None,
};
}
let loc: MacroCallLoc = db.lookup_intern_macro(id);
if let Some(eager) = &loc.eager {
if arg.is_some() {
return ExpandResult::str_err(
"hypothetical macro expansion not implemented for eager macro".to_owned(),
);
} else {
return ExpandResult {
value: Some(eager.arg_or_expansion.clone()),
// FIXME: There could be errors here!
err: None,
};
}
};
}
let loc = db.lookup_intern_macro(lazy_id);
let macro_arg = match arg.or_else(|| db.macro_arg(id)) {
Some(it) => it,
None => return ExpandResult::str_err("Fail to args in to tt::TokenTree".into()),
@ -374,7 +345,7 @@ fn macro_expand_with_arg(
Some(it) => it,
None => return ExpandResult::str_err("Fail to find macro definition".into()),
};
let ExpandResult { value: tt, err } = macro_rules.expand(db, lazy_id, &macro_arg.0);
let ExpandResult { value: tt, err } = macro_rules.expand(db, id, &macro_arg.0);
// Set a hard limit for the expanded tt
let count = tt.count();
if count > TOKEN_LIMIT {
@ -391,12 +362,7 @@ fn expand_proc_macro(
db: &dyn AstDatabase,
id: MacroCallId,
) -> Result<tt::Subtree, mbe::ExpandError> {
let lazy_id = match id {
MacroCallId::LazyMacro(id) => id,
MacroCallId::EagerMacro(_) => unreachable!(),
};
let loc = db.lookup_intern_macro(lazy_id);
let loc: MacroCallLoc = db.lookup_intern_macro(id);
let macro_arg = match db.macro_arg(id) {
Some(it) => it,
None => {
@ -436,14 +402,6 @@ fn hygiene_frame(db: &dyn AstDatabase, file_id: HirFileId) -> Arc<HygieneFrame>
}
fn macro_fragment_kind(db: &dyn AstDatabase, id: MacroCallId) -> FragmentKind {
match id {
MacroCallId::LazyMacro(id) => {
let loc: MacroCallLoc = db.lookup_intern_macro(id);
loc.kind.fragment_kind()
}
MacroCallId::EagerMacro(id) => {
let loc: EagerCallLoc = db.lookup_intern_eager_expansion(id);
loc.fragment
}
}
let loc: MacroCallLoc = db.lookup_intern_macro(id);
loc.kind.fragment_kind()
}

View file

@ -22,7 +22,7 @@
use crate::{
ast::{self, AstNode},
db::AstDatabase,
EagerCallLoc, EagerMacroId, InFile, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind,
EagerCallInfo, InFile, MacroCallId, MacroCallKind, MacroCallLoc, MacroDefId, MacroDefKind,
};
use base_db::CrateId;
@ -105,7 +105,7 @@ pub fn expand_eager_macro(
def: MacroDefId,
resolver: &dyn Fn(ast::Path) -> Option<MacroDefId>,
mut diagnostic_sink: &mut dyn FnMut(mbe::ExpandError),
) -> Result<EagerMacroId, ErrorEmitted> {
) -> Result<MacroCallId, ErrorEmitted> {
let parsed_args = diagnostic_sink.option_with(
|| Some(mbe::ast_to_token_tree(&macro_call.value.token_tree()?).0),
|| err("malformed macro invocation"),
@ -118,15 +118,14 @@ pub fn expand_eager_macro(
// When `lazy_expand` is called, its *parent* file must be already exists.
// Here we store an eager macro id for the argument expanded subtree here
// for that purpose.
let arg_id = db.intern_eager_expansion({
EagerCallLoc {
def,
fragment: FragmentKind::Expr,
subtree: Arc::new(parsed_args.clone()),
krate,
call: call_id,
let arg_id = db.intern_macro(MacroCallLoc {
def,
krate,
eager: Some(EagerCallInfo {
arg_or_expansion: Arc::new(parsed_args.clone()),
included_file: None,
}
}),
kind: MacroCallKind::FnLike { ast_id: call_id, fragment: FragmentKind::Expr },
});
let arg_file_id: MacroCallId = arg_id.into();
@ -146,16 +145,17 @@ pub fn expand_eager_macro(
let res = eager.expand(db, arg_id, &subtree);
let expanded = diagnostic_sink.expand_result_option(res)?;
let eager = EagerCallLoc {
let loc = MacroCallLoc {
def,
fragment: expanded.fragment,
subtree: Arc::new(expanded.subtree),
krate,
call: call_id,
included_file: expanded.included_file,
eager: Some(EagerCallInfo {
arg_or_expansion: Arc::new(expanded.subtree),
included_file: expanded.included_file,
}),
kind: MacroCallKind::FnLike { ast_id: call_id, fragment: expanded.fragment },
};
Ok(db.intern_eager_expansion(eager))
Ok(db.intern_macro(loc))
} else {
panic!("called `expand_eager_macro` on non-eager macro def {:?}", def);
}

View file

@ -14,7 +14,7 @@ use syntax::{ast, AstNode, SyntaxNode, TextRange, TextSize};
use crate::{
db::{self, AstDatabase},
name::{AsName, Name},
HirFileId, HirFileIdRepr, InFile, MacroCallId, MacroCallLoc, MacroDefKind, MacroFile,
HirFileId, HirFileIdRepr, InFile, MacroCallLoc, MacroDefKind, MacroFile,
};
#[derive(Clone, Debug)]
@ -140,10 +140,7 @@ impl HygieneInfo {
let (token_id, origin) = self.macro_def.map_id_up(token_id);
let (token_map, tt) = match origin {
mbe::Origin::Call => {
let call_id = match self.file.macro_call_id {
MacroCallId::LazyMacro(lazy) => lazy,
MacroCallId::EagerMacro(_) => unreachable!(),
};
let call_id = self.file.macro_call_id;
let loc: MacroCallLoc = db.lookup_intern_macro(call_id);
let arg_start = loc.kind.arg(db)?.text_range().start();
(&self.macro_arg.1, InFile::new(loc.kind.file_id(), arg_start))
@ -186,23 +183,20 @@ impl HygieneFrame {
pub(crate) fn new(db: &dyn AstDatabase, file_id: HirFileId) -> HygieneFrame {
let (info, krate, local_inner) = match file_id.0 {
HirFileIdRepr::FileId(_) => (None, None, false),
HirFileIdRepr::MacroFile(macro_file) => match macro_file.macro_call_id {
MacroCallId::EagerMacro(_id) => (None, None, false),
MacroCallId::LazyMacro(id) => {
let loc = db.lookup_intern_macro(id);
let info = make_hygiene_info(db, macro_file, &loc)
.map(|info| (loc.kind.file_id(), info));
match loc.def.kind {
MacroDefKind::Declarative(_) => {
(info, Some(loc.def.krate), loc.def.local_inner)
}
MacroDefKind::BuiltIn(..) => (info, Some(loc.def.krate), false),
MacroDefKind::BuiltInDerive(..) => (info, None, false),
MacroDefKind::BuiltInEager(..) => (info, None, false),
MacroDefKind::ProcMacro(..) => (info, None, false),
HirFileIdRepr::MacroFile(macro_file) => {
let loc = db.lookup_intern_macro(macro_file.macro_call_id);
let info =
make_hygiene_info(db, macro_file, &loc).map(|info| (loc.kind.file_id(), info));
match loc.def.kind {
MacroDefKind::Declarative(_) => {
(info, Some(loc.def.krate), loc.def.local_inner)
}
MacroDefKind::BuiltIn(..) => (info, Some(loc.def.krate), false),
MacroDefKind::BuiltInDerive(..) => (info, None, false),
MacroDefKind::BuiltInEager(..) => (info, None, false),
MacroDefKind::ProcMacro(..) => (info, None, false),
}
},
}
};
let (calling_file, info) = match info {

View file

@ -8,13 +8,13 @@ use syntax::{
use crate::{
db::AstDatabase,
name::{name, AsName},
LazyMacroId, MacroCallKind, MacroCallLoc,
MacroCallId, MacroCallKind, MacroCallLoc,
};
pub(crate) fn process_macro_input(
db: &dyn AstDatabase,
node: SyntaxNode,
id: LazyMacroId,
id: MacroCallId,
) -> SyntaxNode {
let loc: MacroCallLoc = db.lookup_intern_macro(id);

View file

@ -80,19 +80,10 @@ impl HirFileId {
match self.0 {
HirFileIdRepr::FileId(file_id) => file_id,
HirFileIdRepr::MacroFile(macro_file) => {
let file_id = match macro_file.macro_call_id {
MacroCallId::LazyMacro(id) => {
let loc = db.lookup_intern_macro(id);
loc.kind.file_id()
}
MacroCallId::EagerMacro(id) => {
let loc = db.lookup_intern_eager_expansion(id);
if let Some(included_file) = loc.included_file {
return included_file;
} else {
loc.call.file_id
}
}
let loc: MacroCallLoc = db.lookup_intern_macro(macro_file.macro_call_id);
let file_id = match &loc.eager {
Some(EagerCallInfo { included_file: Some(file), .. }) => (*file).into(),
_ => loc.kind.file_id(),
};
file_id.original_file(db)
}
@ -103,17 +94,10 @@ impl HirFileId {
let mut level = 0;
let mut curr = self;
while let HirFileIdRepr::MacroFile(macro_file) = curr.0 {
let loc: MacroCallLoc = db.lookup_intern_macro(macro_file.macro_call_id);
level += 1;
curr = match macro_file.macro_call_id {
MacroCallId::LazyMacro(id) => {
let loc = db.lookup_intern_macro(id);
loc.kind.file_id()
}
MacroCallId::EagerMacro(id) => {
let loc = db.lookup_intern_eager_expansion(id);
loc.call.file_id
}
};
curr = loc.kind.file_id();
}
level
}
@ -122,16 +106,10 @@ impl HirFileId {
pub fn call_node(self, db: &dyn db::AstDatabase) -> Option<InFile<SyntaxNode>> {
match self.0 {
HirFileIdRepr::FileId(_) => None,
HirFileIdRepr::MacroFile(macro_file) => match macro_file.macro_call_id {
MacroCallId::LazyMacro(lazy_id) => {
let loc: MacroCallLoc = db.lookup_intern_macro(lazy_id);
Some(loc.kind.node(db))
}
MacroCallId::EagerMacro(id) => {
let loc: EagerCallLoc = db.lookup_intern_eager_expansion(id);
Some(loc.call.with_value(loc.call.to_node(db).syntax().clone()))
}
},
HirFileIdRepr::MacroFile(macro_file) => {
let loc: MacroCallLoc = db.lookup_intern_macro(macro_file.macro_call_id);
Some(loc.kind.node(db))
}
}
}
@ -140,14 +118,7 @@ impl HirFileId {
match self.0 {
HirFileIdRepr::FileId(_) => None,
HirFileIdRepr::MacroFile(macro_file) => {
let lazy_id = match macro_file.macro_call_id {
MacroCallId::LazyMacro(id) => id,
MacroCallId::EagerMacro(_id) => {
// FIXME: handle expansion_info for eager macro
return None;
}
};
let loc: MacroCallLoc = db.lookup_intern_macro(lazy_id);
let loc: MacroCallLoc = db.lookup_intern_macro(macro_file.macro_call_id);
let arg_tt = loc.kind.arg(db)?;
@ -180,13 +151,7 @@ impl HirFileId {
match self.0 {
HirFileIdRepr::FileId(_) => None,
HirFileIdRepr::MacroFile(macro_file) => {
let lazy_id = match macro_file.macro_call_id {
MacroCallId::LazyMacro(id) => id,
MacroCallId::EagerMacro(_id) => {
return None;
}
};
let loc: MacroCallLoc = db.lookup_intern_macro(lazy_id);
let loc: MacroCallLoc = db.lookup_intern_macro(macro_file.macro_call_id);
let item = match loc.def.kind {
MacroDefKind::BuiltInDerive(..) => loc.kind.node(db),
_ => return None,
@ -199,16 +164,12 @@ impl HirFileId {
/// Return whether this file is an include macro
pub fn is_include_macro(&self, db: &dyn db::AstDatabase) -> bool {
match self.0 {
HirFileIdRepr::MacroFile(macro_file) => match macro_file.macro_call_id {
MacroCallId::EagerMacro(id) => {
let loc = db.lookup_intern_eager_expansion(id);
return loc.included_file.is_some();
}
_ => {}
},
_ => {}
HirFileIdRepr::MacroFile(macro_file) => {
let loc: MacroCallLoc = db.lookup_intern_macro(macro_file.macro_call_id);
matches!(loc.eager, Some(EagerCallInfo { included_file: Some(_), .. }))
}
_ => false,
}
false
}
}
@ -220,29 +181,8 @@ pub struct MacroFile {
/// `MacroCallId` identifies a particular macro invocation, like
/// `println!("Hello, {}", world)`.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum MacroCallId {
LazyMacro(LazyMacroId),
EagerMacro(EagerMacroId),
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct LazyMacroId(salsa::InternId);
impl_intern_key!(LazyMacroId);
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct EagerMacroId(salsa::InternId);
impl_intern_key!(EagerMacroId);
impl From<LazyMacroId> for MacroCallId {
fn from(it: LazyMacroId) -> Self {
MacroCallId::LazyMacro(it)
}
}
impl From<EagerMacroId> for MacroCallId {
fn from(it: EagerMacroId) -> Self {
MacroCallId::EagerMacro(it)
}
}
pub struct MacroCallId(salsa::InternId);
impl_intern_key!(MacroCallId);
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct MacroDefId {
@ -258,8 +198,8 @@ impl MacroDefId {
db: &dyn db::AstDatabase,
krate: CrateId,
kind: MacroCallKind,
) -> LazyMacroId {
db.intern_macro(MacroCallLoc { def: self, krate, kind })
) -> MacroCallId {
db.intern_macro(MacroCallLoc { def: self, krate, eager: None, kind })
}
pub fn ast_id(&self) -> Either<AstId<ast::Macro>, AstId<ast::Fn>> {
@ -288,10 +228,18 @@ pub enum MacroDefKind {
ProcMacro(ProcMacroExpander, AstId<ast::Fn>),
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
struct EagerCallInfo {
/// NOTE: This can be *either* the expansion result, *or* the argument to the eager macro!
arg_or_expansion: Arc<tt::Subtree>,
included_file: Option<FileId>,
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct MacroCallLoc {
pub(crate) def: MacroDefId,
pub(crate) krate: CrateId,
eager: Option<EagerCallInfo>,
pub kind: MacroCallKind,
}
@ -313,6 +261,7 @@ pub enum MacroCallKind {
}
impl MacroCallKind {
/// Returns the file containing the macro invocation.
fn file_id(&self) -> HirFileId {
match self {
MacroCallKind::FnLike { ast_id, .. } => ast_id.file_id,
@ -354,17 +303,6 @@ impl MacroCallId {
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct EagerCallLoc {
pub(crate) def: MacroDefId,
pub(crate) fragment: FragmentKind,
pub(crate) subtree: Arc<tt::Subtree>,
pub(crate) krate: CrateId,
pub(crate) call: AstId<ast::MacroCall>,
// The included file ID of the include macro.
pub(crate) included_file: Option<FileId>,
}
/// ExpansionInfo mainly describes how to map text range between src and expanded macro
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ExpansionInfo {

View file

@ -222,7 +222,6 @@ impl RootDatabase {
sweep_each_query![
// AstDatabase
hir::db::InternMacroQuery
hir::db::InternEagerExpansionQuery
// InternDatabase
hir::db::InternFunctionQuery