Simplify eager macro representation

This commit is contained in:
Jonas Schievink 2021-05-19 20:19:08 +02:00
parent c7196620ab
commit ea8555b155
10 changed files with 166 additions and 278 deletions

View file

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

View file

@ -948,8 +948,7 @@ impl DefCollector<'_> {
// incrementality). // incrementality).
let err = self.db.macro_expand_error(macro_call_id); let err = self.db.macro_expand_error(macro_call_id);
if let Some(err) = err { if let Some(err) = err {
if let MacroCallId::LazyMacro(id) = macro_call_id { let loc: MacroCallLoc = self.db.lookup_intern_macro(macro_call_id);
let loc: MacroCallLoc = self.db.lookup_intern_macro(id);
let diag = match err { let diag = match err {
hir_expand::ExpandError::UnresolvedProcMacro => { hir_expand::ExpandError::UnresolvedProcMacro => {
@ -961,8 +960,6 @@ impl DefCollector<'_> {
self.def_map.diagnostics.push(diag); self.def_map.diagnostics.push(diag);
} }
// FIXME: Handle eager macros.
}
// Then, fetch and process the item tree. This will reuse the expansion result from above. // Then, fetch and process the item tree. This will reuse the expansion result from above.
let item_tree = self.db.file_item_tree(file_id); let item_tree = self.db.file_item_tree(file_id);

View file

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

View file

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

View file

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

View file

@ -22,7 +22,7 @@
use crate::{ use crate::{
ast::{self, AstNode}, ast::{self, AstNode},
db::AstDatabase, db::AstDatabase,
EagerCallLoc, EagerMacroId, InFile, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind, EagerCallInfo, InFile, MacroCallId, MacroCallKind, MacroCallLoc, MacroDefId, MacroDefKind,
}; };
use base_db::CrateId; use base_db::CrateId;
@ -105,7 +105,7 @@ pub fn expand_eager_macro(
def: MacroDefId, def: MacroDefId,
resolver: &dyn Fn(ast::Path) -> Option<MacroDefId>, resolver: &dyn Fn(ast::Path) -> Option<MacroDefId>,
mut diagnostic_sink: &mut dyn FnMut(mbe::ExpandError), mut diagnostic_sink: &mut dyn FnMut(mbe::ExpandError),
) -> Result<EagerMacroId, ErrorEmitted> { ) -> Result<MacroCallId, ErrorEmitted> {
let parsed_args = diagnostic_sink.option_with( let parsed_args = diagnostic_sink.option_with(
|| Some(mbe::ast_to_token_tree(&macro_call.value.token_tree()?).0), || Some(mbe::ast_to_token_tree(&macro_call.value.token_tree()?).0),
|| err("malformed macro invocation"), || 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. // 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 // Here we store an eager macro id for the argument expanded subtree here
// for that purpose. // for that purpose.
let arg_id = db.intern_eager_expansion({ let arg_id = db.intern_macro(MacroCallLoc {
EagerCallLoc {
def, def,
fragment: FragmentKind::Expr,
subtree: Arc::new(parsed_args.clone()),
krate, krate,
call: call_id, eager: Some(EagerCallInfo {
expansion: Arc::new(parsed_args.clone()),
included_file: None, included_file: None,
} }),
kind: MacroCallKind::FnLike { ast_id: call_id, fragment: FragmentKind::Expr },
}); });
let arg_file_id: MacroCallId = arg_id.into(); 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 res = eager.expand(db, arg_id, &subtree);
let expanded = diagnostic_sink.expand_result_option(res)?; let expanded = diagnostic_sink.expand_result_option(res)?;
let eager = EagerCallLoc { let loc = MacroCallLoc {
def, def,
fragment: expanded.fragment,
subtree: Arc::new(expanded.subtree),
krate, krate,
call: call_id, eager: Some(EagerCallInfo {
expansion: Arc::new(expanded.subtree),
included_file: expanded.included_file, 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 { } else {
panic!("called `expand_eager_macro` on non-eager macro def {:?}", def); 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::{ use crate::{
db::{self, AstDatabase}, db::{self, AstDatabase},
name::{AsName, Name}, name::{AsName, Name},
HirFileId, HirFileIdRepr, InFile, MacroCallId, MacroCallLoc, MacroDefKind, MacroFile, HirFileId, HirFileIdRepr, InFile, MacroCallLoc, MacroDefKind, MacroFile,
}; };
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
@ -140,10 +140,7 @@ impl HygieneInfo {
let (token_id, origin) = self.macro_def.map_id_up(token_id); let (token_id, origin) = self.macro_def.map_id_up(token_id);
let (token_map, tt) = match origin { let (token_map, tt) = match origin {
mbe::Origin::Call => { mbe::Origin::Call => {
let call_id = match self.file.macro_call_id { let call_id = self.file.macro_call_id;
MacroCallId::LazyMacro(lazy) => lazy,
MacroCallId::EagerMacro(_) => unreachable!(),
};
let loc: MacroCallLoc = db.lookup_intern_macro(call_id); let loc: MacroCallLoc = db.lookup_intern_macro(call_id);
let arg_start = loc.kind.arg(db)?.text_range().start(); let arg_start = loc.kind.arg(db)?.text_range().start();
(&self.macro_arg.1, InFile::new(loc.kind.file_id(), arg_start)) (&self.macro_arg.1, InFile::new(loc.kind.file_id(), arg_start))
@ -186,12 +183,10 @@ impl HygieneFrame {
pub(crate) fn new(db: &dyn AstDatabase, file_id: HirFileId) -> HygieneFrame { pub(crate) fn new(db: &dyn AstDatabase, file_id: HirFileId) -> HygieneFrame {
let (info, krate, local_inner) = match file_id.0 { let (info, krate, local_inner) = match file_id.0 {
HirFileIdRepr::FileId(_) => (None, None, false), HirFileIdRepr::FileId(_) => (None, None, false),
HirFileIdRepr::MacroFile(macro_file) => match macro_file.macro_call_id { HirFileIdRepr::MacroFile(macro_file) => {
MacroCallId::EagerMacro(_id) => (None, None, false), let loc = db.lookup_intern_macro(macro_file.macro_call_id);
MacroCallId::LazyMacro(id) => { let info =
let loc = db.lookup_intern_macro(id); make_hygiene_info(db, macro_file, &loc).map(|info| (loc.kind.file_id(), info));
let info = make_hygiene_info(db, macro_file, &loc)
.map(|info| (loc.kind.file_id(), info));
match loc.def.kind { match loc.def.kind {
MacroDefKind::Declarative(_) => { MacroDefKind::Declarative(_) => {
(info, Some(loc.def.krate), loc.def.local_inner) (info, Some(loc.def.krate), loc.def.local_inner)
@ -202,7 +197,6 @@ impl HygieneFrame {
MacroDefKind::ProcMacro(..) => (info, None, false), MacroDefKind::ProcMacro(..) => (info, None, false),
} }
} }
},
}; };
let (calling_file, info) = match info { let (calling_file, info) = match info {

View file

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

View file

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

View file

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