Unnamed repository; edit this file 'description' to name the repository.
Merge pull request #22719 from ada4a/unquerygroup-macro_call_id-and-hir_file_id-methods
internal: remove some more `ExpandDatabase` queries
Lukas Wirth 5 days ago
parent 28242b9 · parent 307571a · commit 3f80777
-rw-r--r--crates/hir-def/src/attrs/docs.rs6
-rw-r--r--crates/hir-def/src/expr_store/expander.rs8
-rw-r--r--crates/hir-def/src/item_tree.rs2
-rw-r--r--crates/hir-def/src/item_tree/lower.rs2
-rw-r--r--crates/hir-def/src/macro_expansion_tests/mod.rs10
-rw-r--r--crates/hir-def/src/nameres/assoc.rs8
-rw-r--r--crates/hir-def/src/nameres/tests/incremental.rs126
-rw-r--r--crates/hir-def/src/signatures.rs2
-rw-r--r--crates/hir-def/src/src.rs4
-rw-r--r--crates/hir-expand/src/builtin/derive_macro.rs2
-rw-r--r--crates/hir-expand/src/db.rs443
-rw-r--r--crates/hir-expand/src/declarative.rs3
-rw-r--r--crates/hir-expand/src/eager.rs10
-rw-r--r--crates/hir-expand/src/files.rs12
-rw-r--r--crates/hir-expand/src/lib.rs571
-rw-r--r--crates/hir-expand/src/mod_path.rs2
-rw-r--r--crates/hir-expand/src/span_map.rs6
-rw-r--r--crates/hir-ty/src/tests.rs14
-rw-r--r--crates/hir-ty/src/tests/incremental.rs28
-rw-r--r--crates/hir/src/diagnostics.rs4
-rw-r--r--crates/hir/src/has_source.rs2
-rw-r--r--crates/hir/src/lib.rs10
-rw-r--r--crates/hir/src/semantics.rs15
-rw-r--r--crates/hir/src/semantics/child_by_source.rs2
-rw-r--r--crates/hir/src/source_analyzer.rs2
-rw-r--r--crates/ide-diagnostics/src/handlers/incorrect_case.rs4
-rw-r--r--crates/ide-diagnostics/src/handlers/missing_fields.rs6
-rw-r--r--crates/ide-diagnostics/src/handlers/missing_unsafe.rs3
-rw-r--r--crates/ide-diagnostics/src/handlers/mutability_errors.rs3
-rw-r--r--crates/ide-diagnostics/src/handlers/no_such_field.rs4
-rw-r--r--crates/ide-diagnostics/src/handlers/remove_trailing_return.rs4
-rw-r--r--crates/ide-diagnostics/src/handlers/remove_unnecessary_else.rs4
-rw-r--r--crates/ide-diagnostics/src/handlers/replace_filter_map_next_with_find_map.rs4
-rw-r--r--crates/ide-diagnostics/src/handlers/trait_impl_redundant_assoc_item.rs4
-rw-r--r--crates/ide-diagnostics/src/handlers/type_mismatch.rs12
-rw-r--r--crates/ide-diagnostics/src/handlers/typed_hole.rs3
-rw-r--r--crates/ide-diagnostics/src/handlers/unresolved_field.rs6
-rw-r--r--crates/ide-diagnostics/src/handlers/unresolved_method.rs6
-rw-r--r--crates/ide-diagnostics/src/handlers/unresolved_module.rs3
-rw-r--r--crates/load-cargo/src/lib.rs4
-rw-r--r--crates/rust-analyzer/src/cli/analysis_stats.rs10
41 files changed, 674 insertions, 700 deletions
diff --git a/crates/hir-def/src/attrs/docs.rs b/crates/hir-def/src/attrs/docs.rs
index 0d01d54786..69eac7b3c9 100644
--- a/crates/hir-def/src/attrs/docs.rs
+++ b/crates/hir-def/src/attrs/docs.rs
@@ -390,7 +390,7 @@ fn expand_doc_macro_call<'db>(
.value?;
expander.recursion_depth += 1;
- let parse = expander.db.parse_macro_expansion(call_id).value.0.clone();
+ let parse = call_id.parse_macro_expansion(expander.db).value.0.clone();
let expr = parse.cast::<ast::Expr>().map(|parse| parse.tree())?;
expander.recursion_depth -= 1;
@@ -401,7 +401,7 @@ fn expand_doc_macro_call<'db>(
let new_source_ctx = DocExprSourceCtx {
resolver: source_ctx.resolver.clone(),
file_id: expansion_file_id,
- ast_id_map: expander.db.ast_id_map(expansion_file_id),
+ ast_id_map: expansion_file_id.ast_id_map(expander.db),
span_map: expander.db.span_map(expansion_file_id),
};
Some((expr, new_source_ctx))
@@ -456,7 +456,7 @@ fn extend_with_attrs<'a, 'db>(
DocExprSourceCtx {
resolver,
file_id,
- ast_id_map: db.ast_id_map(file_id),
+ ast_id_map: file_id.ast_id_map(db),
span_map: db.span_map(file_id),
},
)
diff --git a/crates/hir-def/src/expr_store/expander.rs b/crates/hir-def/src/expr_store/expander.rs
index c79a1db847..fbe7bab457 100644
--- a/crates/hir-def/src/expr_store/expander.rs
+++ b/crates/hir-def/src/expr_store/expander.rs
@@ -47,7 +47,7 @@ impl<'db> Expander<'db> {
recursion_depth: 0,
recursion_limit,
span_map: db.span_map(current_file_id),
- ast_id_map: db.ast_id_map(current_file_id),
+ ast_id_map: current_file_id.ast_id_map(db),
}
}
@@ -184,12 +184,12 @@ impl<'db> Expander<'db> {
self.recursion_depth = u32::MAX;
cov_mark::hit!(your_stack_belongs_to_me);
return ExpandResult::only_err(ExpandError::new(
- db.macro_arg_considering_derives(call_id, &call_id.lookup(db).kind).2,
+ call_id.macro_arg_considering_derives(db, &call_id.lookup(db).kind).2,
ExpandErrorKind::RecursionOverflow,
));
}
- let res = db.parse_macro_expansion(call_id);
+ let res = call_id.parse_macro_expansion(db);
let err = err.or_else(|| res.err.clone());
ExpandResult {
@@ -201,7 +201,7 @@ impl<'db> Expander<'db> {
let old_span_map =
std::mem::replace(&mut self.span_map, SpanMap::ExpansionSpanMap(&res.value.1));
let prev_ast_id_map =
- mem::replace(&mut self.ast_id_map, db.ast_id_map(self.current_file_id));
+ mem::replace(&mut self.ast_id_map, self.current_file_id.ast_id_map(db));
let mark = Mark {
file_id: old_file_id,
span_map: old_span_map,
diff --git a/crates/hir-def/src/item_tree.rs b/crates/hir-def/src/item_tree.rs
index 4b50161c04..ffd89e41ff 100644
--- a/crates/hir-def/src/item_tree.rs
+++ b/crates/hir-def/src/item_tree.rs
@@ -146,7 +146,7 @@ fn file_item_tree_query(
let _p = tracing::info_span!("file_item_tree_query", ?file_id).entered();
let ctx = lower::Ctx::new(db, file_id, krate);
- let syntax = db.parse_or_expand(file_id);
+ let syntax = file_id.parse_or_expand(db);
let mut item_tree = match_ast! {
match syntax {
ast::SourceFile(file) => {
diff --git a/crates/hir-def/src/item_tree/lower.rs b/crates/hir-def/src/item_tree/lower.rs
index 91c2e60fd7..b0d9d960d8 100644
--- a/crates/hir-def/src/item_tree/lower.rs
+++ b/crates/hir-def/src/item_tree/lower.rs
@@ -40,7 +40,7 @@ impl<'db> Ctx<'db> {
Self {
db,
tree: ItemTree::default(),
- source_ast_id_map: db.ast_id_map(file),
+ source_ast_id_map: file.ast_id_map(db),
file,
cfg_options: OnceCell::new(),
span_map: OnceCell::new(),
diff --git a/crates/hir-def/src/macro_expansion_tests/mod.rs b/crates/hir-def/src/macro_expansion_tests/mod.rs
index 1d6812ad56..c53a7321e8 100644
--- a/crates/hir-def/src/macro_expansion_tests/mod.rs
+++ b/crates/hir-def/src/macro_expansion_tests/mod.rs
@@ -62,7 +62,7 @@ fn check_errors(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect)
.modules()
.flat_map(|module| module.1.scope.all_macro_calls())
.filter_map(|macro_call| {
- let errors = db.parse_macro_expansion_error(macro_call)?;
+ let errors = macro_call.parse_macro_expansion_error(&db)?;
let errors = errors.err.as_ref()?.render_to_string(&db);
let macro_loc = macro_call.loc(&db);
let ast_id = match macro_loc.kind {
@@ -75,7 +75,7 @@ fn check_errors(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect)
ast_id.file_id.file_id().expect("macros inside macros are not supported");
let ast = editioned_file_id.parse(&db).syntax_node();
- let ast_id_map = db.ast_id_map(ast_id.file_id);
+ let ast_id_map = ast_id.file_id.ast_id_map(&db);
let node = ast_id_map.get_erased(ast_id.value).to_node(&ast);
Some((node.text_range(), errors))
})
@@ -120,12 +120,12 @@ pub fn identity_when_valid(_attr: TokenStream, item: TokenStream) -> TokenStream
let mut expansions = Vec::new();
for macro_call_node in source_file.syntax().descendants().filter_map(ast::MacroCall::cast) {
- let ast_id = db.ast_id_map(source.file_id).ast_id(&macro_call_node);
+ let ast_id = source.file_id.ast_id_map(&db).ast_id(&macro_call_node);
let ast_id = InFile::new(source.file_id, ast_id);
let ptr = InFile::new(source.file_id, AstPtr::new(&macro_call_node));
let macro_call_id = resolve_macro_call_id(&db, def_map, ast_id, ptr)
.unwrap_or_else(|| panic!("unable to find semantic macro call {macro_call_node}"));
- let expansion_result = db.parse_macro_expansion(macro_call_id);
+ let expansion_result = macro_call_id.parse_macro_expansion(&db);
expansions.push((macro_call_node.clone(), expansion_result));
}
@@ -476,7 +476,7 @@ m!(g);
.collect();
for macro_call_node in source_file.syntax().descendants().filter_map(ast::MacroCall::cast) {
- let ast_id = db.ast_id_map(source.file_id).ast_id(&macro_call_node);
+ let ast_id = source.file_id.ast_id_map(&db).ast_id(&macro_call_node);
let ast_id = InFile::new(source.file_id, ast_id);
let ptr = InFile::new(source.file_id, AstPtr::new(&macro_call_node));
let macro_call_id = resolve_macro_call_id(&db, def_map, ast_id, ptr)
diff --git a/crates/hir-def/src/nameres/assoc.rs b/crates/hir-def/src/nameres/assoc.rs
index 7b5b39cb08..8bac83c369 100644
--- a/crates/hir-def/src/nameres/assoc.rs
+++ b/crates/hir-def/src/nameres/assoc.rs
@@ -51,7 +51,7 @@ impl TraitItems {
tr: TraitId,
) -> (TraitItems, DefDiagnostics) {
let ItemLoc { container: module_id, id: ast_id } = *tr.lookup(db);
- let ast_id_map = db.ast_id_map(ast_id.file_id);
+ let ast_id_map = ast_id.file_id.ast_id_map(db);
let source = ast_id.with_value(ast_id_map.get(ast_id.value)).to_node(db);
if source.eq_token().is_some() {
// FIXME(trait-alias) probably needs special handling here
@@ -162,7 +162,7 @@ impl<'db> AssocItemCollector<'db> {
module_id,
def_map,
local_def_map,
- ast_id_map: db.ast_id_map(file_id),
+ ast_id_map: file_id.ast_id_map(db),
span_map: db.span_map(file_id),
cfg_options: module_id.krate(db).cfg_options(db),
file_id,
@@ -356,9 +356,9 @@ impl<'db> AssocItemCollector<'db> {
return;
}
- let (syntax, span_map) = &self.db.parse_macro_expansion(macro_call_id).value;
+ let (syntax, span_map) = &macro_call_id.parse_macro_expansion(self.db).value;
let old_file_id = mem::replace(&mut self.file_id, macro_call_id.into());
- let old_ast_id_map = mem::replace(&mut self.ast_id_map, self.db.ast_id_map(self.file_id));
+ let old_ast_id_map = mem::replace(&mut self.ast_id_map, self.file_id.ast_id_map(self.db));
let old_span_map = mem::replace(&mut self.span_map, SpanMap::ExpansionSpanMap(span_map));
self.depth += 1;
diff --git a/crates/hir-def/src/nameres/tests/incremental.rs b/crates/hir-def/src/nameres/tests/incremental.rs
index bb19456f46..8e339fa973 100644
--- a/crates/hir-def/src/nameres/tests/incremental.rs
+++ b/crates/hir-def/src/nameres/tests/incremental.rs
@@ -166,15 +166,15 @@ fn no() {}
[
"crate_local_def_map",
"file_item_tree_query",
- "ast_id_map",
+ "HirFileId::ast_id_map_",
"parse",
"real_span_map",
"file_item_tree_query",
- "ast_id_map",
+ "HirFileId::ast_id_map_",
"parse",
"real_span_map",
"file_item_tree_query",
- "ast_id_map",
+ "HirFileId::ast_id_map_",
"parse",
"real_span_map",
"EnumVariants::of_",
@@ -183,7 +183,7 @@ fn no() {}
expect![[r#"
[
"parse",
- "ast_id_map",
+ "HirFileId::ast_id_map_",
"file_item_tree_query",
"real_span_map",
"EnumVariants::of_",
@@ -224,34 +224,34 @@ pub struct S {}
[
"crate_local_def_map",
"file_item_tree_query",
- "ast_id_map",
+ "HirFileId::ast_id_map_",
"parse",
"real_span_map",
"DeclarativeMacroExpander::expander_",
"file_item_tree_query",
- "ast_id_map",
+ "HirFileId::ast_id_map_",
"parse",
"real_span_map",
"file_item_tree_query",
- "ast_id_map",
+ "HirFileId::ast_id_map_",
"parse",
"real_span_map",
"macro_def_shim",
"file_item_tree_query",
- "ast_id_map",
- "parse_macro_expansion",
- "macro_arg",
+ "HirFileId::ast_id_map_",
+ "MacroCallId::parse_macro_expansion_",
+ "MacroCallId::macro_arg_",
]
"#]],
expect![[r#"
[
"parse",
- "ast_id_map",
+ "HirFileId::ast_id_map_",
"file_item_tree_query",
"real_span_map",
- "macro_arg",
- "parse_macro_expansion",
- "ast_id_map",
+ "MacroCallId::macro_arg_",
+ "MacroCallId::parse_macro_expansion_",
+ "HirFileId::ast_id_map_",
"file_item_tree_query",
]
"#]],
@@ -282,42 +282,42 @@ fn f() { foo }
[
"crate_local_def_map",
"file_item_tree_query",
- "ast_id_map",
+ "HirFileId::ast_id_map_",
"parse",
"real_span_map",
"crate_local_def_map",
"ProcMacros::get_for_crate_",
"file_item_tree_query",
- "ast_id_map",
+ "HirFileId::ast_id_map_",
"parse",
"real_span_map",
"file_item_tree_query",
- "ast_id_map",
+ "HirFileId::ast_id_map_",
"parse",
"real_span_map",
"file_item_tree_query",
- "ast_id_map",
+ "HirFileId::ast_id_map_",
"parse",
"real_span_map",
"macro_def_shim",
"file_item_tree_query",
- "ast_id_map",
- "parse_macro_expansion",
- "expand_proc_macro",
- "macro_arg",
+ "HirFileId::ast_id_map_",
+ "MacroCallId::parse_macro_expansion_",
+ "MacroCallId::expand_proc_macro_",
+ "MacroCallId::macro_arg_",
"proc_macro_span",
]
"#]],
expect![[r#"
[
"parse",
- "ast_id_map",
+ "HirFileId::ast_id_map_",
"file_item_tree_query",
"real_span_map",
- "macro_arg",
- "expand_proc_macro",
- "parse_macro_expansion",
- "ast_id_map",
+ "MacroCallId::macro_arg_",
+ "MacroCallId::expand_proc_macro_",
+ "MacroCallId::parse_macro_expansion_",
+ "HirFileId::ast_id_map_",
"file_item_tree_query",
]
"#]],
@@ -406,54 +406,54 @@ pub struct S {}
[
"crate_local_def_map",
"file_item_tree_query",
- "ast_id_map",
+ "HirFileId::ast_id_map_",
"parse",
"real_span_map",
"crate_local_def_map",
"ProcMacros::get_for_crate_",
"file_item_tree_query",
- "ast_id_map",
+ "HirFileId::ast_id_map_",
"parse",
"real_span_map",
"DeclarativeMacroExpander::expander_",
"file_item_tree_query",
- "ast_id_map",
+ "HirFileId::ast_id_map_",
"parse",
"real_span_map",
"file_item_tree_query",
- "ast_id_map",
+ "HirFileId::ast_id_map_",
"parse",
"real_span_map",
"macro_def_shim",
"file_item_tree_query",
- "ast_id_map",
- "parse_macro_expansion",
- "macro_arg",
+ "HirFileId::ast_id_map_",
+ "MacroCallId::parse_macro_expansion_",
+ "MacroCallId::macro_arg_",
"DeclarativeMacroExpander::expander_",
"macro_def_shim",
"file_item_tree_query",
- "ast_id_map",
- "parse_macro_expansion",
- "macro_arg",
+ "HirFileId::ast_id_map_",
+ "MacroCallId::parse_macro_expansion_",
+ "MacroCallId::macro_arg_",
"macro_def_shim",
"file_item_tree_query",
- "ast_id_map",
- "parse_macro_expansion",
- "expand_proc_macro",
- "macro_arg",
+ "HirFileId::ast_id_map_",
+ "MacroCallId::parse_macro_expansion_",
+ "MacroCallId::expand_proc_macro_",
+ "MacroCallId::macro_arg_",
"proc_macro_span",
]
"#]],
expect![[r#"
[
"parse",
- "ast_id_map",
+ "HirFileId::ast_id_map_",
"file_item_tree_query",
"real_span_map",
- "macro_arg",
+ "MacroCallId::macro_arg_",
"DeclarativeMacroExpander::expander_",
- "macro_arg",
- "macro_arg",
+ "MacroCallId::macro_arg_",
+ "MacroCallId::macro_arg_",
]
"#]],
);
@@ -523,31 +523,31 @@ m!(Z);
[
"crate_local_def_map",
"file_item_tree_query",
- "ast_id_map",
+ "HirFileId::ast_id_map_",
"parse",
"real_span_map",
"DeclarativeMacroExpander::expander_",
"file_item_tree_query",
- "ast_id_map",
+ "HirFileId::ast_id_map_",
"parse",
"real_span_map",
"file_item_tree_query",
- "ast_id_map",
+ "HirFileId::ast_id_map_",
"parse",
"real_span_map",
"macro_def_shim",
"file_item_tree_query",
- "ast_id_map",
- "parse_macro_expansion",
- "macro_arg",
+ "HirFileId::ast_id_map_",
+ "MacroCallId::parse_macro_expansion_",
+ "MacroCallId::macro_arg_",
"file_item_tree_query",
- "ast_id_map",
- "parse_macro_expansion",
- "macro_arg",
+ "HirFileId::ast_id_map_",
+ "MacroCallId::parse_macro_expansion_",
+ "MacroCallId::macro_arg_",
"file_item_tree_query",
- "ast_id_map",
- "parse_macro_expansion",
- "macro_arg",
+ "HirFileId::ast_id_map_",
+ "MacroCallId::parse_macro_expansion_",
+ "MacroCallId::macro_arg_",
]
"#]],
);
@@ -572,12 +572,12 @@ m!(Z);
expect![[r#"
[
"parse",
- "ast_id_map",
+ "HirFileId::ast_id_map_",
"file_item_tree_query",
"real_span_map",
- "macro_arg",
- "macro_arg",
- "macro_arg",
+ "MacroCallId::macro_arg_",
+ "MacroCallId::macro_arg_",
+ "MacroCallId::macro_arg_",
]
"#]],
);
@@ -610,7 +610,7 @@ pub type Ty = ();
expect![[r#"
[
"file_item_tree_query",
- "ast_id_map",
+ "HirFileId::ast_id_map_",
"parse",
"real_span_map",
]
@@ -630,7 +630,7 @@ pub type Ty = ();
expect![[r#"
[
"parse",
- "ast_id_map",
+ "HirFileId::ast_id_map_",
"file_item_tree_query",
"real_span_map",
]
diff --git a/crates/hir-def/src/signatures.rs b/crates/hir-def/src/signatures.rs
index e9307a1255..5a4f78cfbc 100644
--- a/crates/hir-def/src/signatures.rs
+++ b/crates/hir-def/src/signatures.rs
@@ -1068,7 +1068,7 @@ impl EnumVariants {
) -> (EnumVariants, ThinVec<InactiveEnumVariantCode>) {
let loc = e.lookup(db);
let source = loc.source(db);
- let ast_id_map = db.ast_id_map(source.file_id);
+ let ast_id_map = source.file_id.ast_id_map(db);
let mut diagnostics = ThinVec::new();
let cfg_options = loc.container.krate(db).cfg_options(db);
diff --git a/crates/hir-def/src/src.rs b/crates/hir-def/src/src.rs
index e33fd95908..6d60030798 100644
--- a/crates/hir-def/src/src.rs
+++ b/crates/hir-def/src/src.rs
@@ -14,7 +14,7 @@ pub trait HasSource {
type Value: AstNode;
fn source(&self, db: &dyn DefDatabase) -> InFile<Self::Value> {
let InFile { file_id, value } = self.ast_ptr(db);
- InFile::new(file_id, value.to_node(&db.parse_or_expand(file_id)))
+ InFile::new(file_id, value.to_node(&file_id.parse_or_expand(db)))
}
fn ast_ptr(&self, db: &dyn DefDatabase) -> InFile<AstPtr<Self::Value>>;
}
@@ -26,7 +26,7 @@ where
type Value = T::Ast;
fn ast_ptr(&self, db: &dyn DefDatabase) -> InFile<AstPtr<Self::Value>> {
let id = self.ast_id();
- let ast_id_map = db.ast_id_map(id.file_id);
+ let ast_id_map = id.file_id.ast_id_map(db);
InFile::new(id.file_id, ast_id_map.get(id.value))
}
}
diff --git a/crates/hir-expand/src/builtin/derive_macro.rs b/crates/hir-expand/src/builtin/derive_macro.rs
index c4da558fda..86ee3f153b 100644
--- a/crates/hir-expand/src/builtin/derive_macro.rs
+++ b/crates/hir-expand/src/builtin/derive_macro.rs
@@ -391,7 +391,7 @@ fn to_adt_syntax(
tt: &tt::TopSubtree,
call_site: Span,
) -> Result<(ast::Adt, span::SpanMap), ExpandError> {
- let (parsed, tm) = crate::db::token_tree_to_syntax_node(db, tt, crate::ExpandTo::Items);
+ let (parsed, tm) = crate::token_tree_to_syntax_node(db, tt, crate::ExpandTo::Items);
let macro_items = ast::MacroItems::cast(parsed.syntax_node())
.ok_or_else(|| ExpandError::other(call_site, "invalid item definition"))?;
let item =
diff --git a/crates/hir-expand/src/db.rs b/crates/hir-expand/src/db.rs
index 90e4e0086e..69c8ffe609 100644
--- a/crates/hir-expand/src/db.rs
+++ b/crates/hir-expand/src/db.rs
@@ -1,17 +1,13 @@
//! Defines database & queries for macro expansion.
use base_db::{Crate, SourceDatabase};
-use mbe::MatchedArmIndex;
-use span::{AstIdMap, Span};
-use std::borrow::Cow;
-use syntax::{AstNode, Parse, SyntaxError, SyntaxNode, SyntaxToken, T, ast};
+use span::Span;
+use syntax::{AstNode, SyntaxNode, SyntaxToken, ast};
use syntax_bridge::{DocCommentDesugarMode, syntax_node_to_token_tree};
-use triomphe::Arc;
use crate::{
- AstId, BuiltinAttrExpander, BuiltinDeriveExpander, BuiltinFnLikeExpander, EagerCallInfo,
- EagerExpander, EditionedFileId, ExpandError, ExpandResult, ExpandTo, FileRange, HirFileId,
- MacroCallId, MacroCallKind, MacroCallLoc, MacroDefId, MacroDefKind,
+ AstId, BuiltinAttrExpander, BuiltinDeriveExpander, BuiltinFnLikeExpander, EagerExpander,
+ EditionedFileId, FileRange, HirFileId, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind,
builtin::pseudo_derive_attr_expansion,
cfg_process::attr_macro_input_to_token_tree,
declarative::DeclarativeMacroExpander,
@@ -21,15 +17,6 @@ use crate::{
span_map::{ExpansionSpanMap, RealSpanMap, SpanMap},
tt,
};
-/// This is just to ensure the types of smart_macro_arg and macro_arg are the same
-type MacroArgResult = (tt::TopSubtree, SyntaxFixupUndoInfo, Span);
-/// Total limit on the number of tokens produced by any macro invocation.
-///
-/// If an invocation produces more tokens than this limit, it will not be stored in the database and
-/// an error will be emitted.
-///
-/// Actual max for `analysis-stats .` at some point: 30672.
-const TOKEN_LIMIT: usize = 2_097_152;
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub enum TokenExpander<'db> {
@@ -50,49 +37,21 @@ pub enum TokenExpander<'db> {
#[query_group::query_group]
pub trait ExpandDatabase: SourceDatabase {
- #[salsa::invoke(ast_id_map)]
- #[salsa::transparent]
- fn ast_id_map(&self, file_id: HirFileId) -> &AstIdMap;
-
#[salsa::transparent]
fn resolve_span(&self, span: Span) -> FileRange;
#[salsa::transparent]
- fn parse_or_expand(&self, file_id: HirFileId) -> SyntaxNode;
-
- /// Implementation for the macro case.
- #[salsa::transparent]
- fn parse_macro_expansion(
- &self,
- macro_file: MacroCallId,
- ) -> &ExpandResult<(Parse<SyntaxNode>, ExpansionSpanMap)>;
-
- #[salsa::transparent]
#[salsa::invoke(SpanMap::new)]
fn span_map(&self, file_id: HirFileId) -> SpanMap<'_>;
#[salsa::transparent]
#[salsa::invoke(crate::span_map::expansion_span_map)]
fn expansion_span_map(&self, file_id: MacroCallId) -> &ExpansionSpanMap;
+
#[salsa::invoke(crate::span_map::real_span_map)]
#[salsa::transparent]
fn real_span_map(&self, file_id: EditionedFileId) -> &RealSpanMap;
- /// Lowers syntactic macro call to a token tree representation. That's a firewall
- /// query, only typing in the macro call itself changes the returned
- /// subtree.
- #[deprecated = "calling this is incorrect, call `macro_arg_considering_derives` instead"]
- #[salsa::invoke(macro_arg)]
- #[salsa::transparent]
- fn macro_arg(&self, id: MacroCallId) -> &MacroArgResult;
-
- #[salsa::transparent]
- fn macro_arg_considering_derives<'db>(
- &'db self,
- id: MacroCallId,
- kind: &MacroCallKind,
- ) -> &'db MacroArgResult;
-
/// Fetches the expander for this macro.
#[salsa::transparent]
#[salsa::invoke(TokenExpander::macro_expander)]
@@ -106,19 +65,12 @@ pub trait ExpandDatabase: SourceDatabase {
def_crate: Crate,
id: AstId<ast::Macro>,
) -> &DeclarativeMacroExpander;
-
- #[salsa::invoke(parse_macro_expansion_error)]
- #[salsa::transparent]
- fn parse_macro_expansion_error(
- &self,
- macro_call: MacroCallId,
- ) -> Option<ExpandResult<Arc<[SyntaxError]>>>;
}
fn resolve_span(db: &dyn ExpandDatabase, Span { range, anchor, ctx: _ }: Span) -> FileRange {
let file_id = EditionedFileId::from_span_file_id(db, anchor.file_id);
let anchor_offset =
- db.ast_id_map(file_id.into()).get_erased(anchor.ast_id).text_range().start();
+ HirFileId::from(file_id).ast_id_map(db).get_erased(anchor.ast_id).text_range().start();
FileRange { file_id, range: range + anchor_offset }
}
@@ -133,7 +85,7 @@ pub fn expand_speculative(
token_to_map: SyntaxToken,
) -> Option<(SyntaxNode, Vec<(SyntaxToken, u8)>)> {
let loc = actual_macro_call.loc(db);
- let (_, _, span) = *db.macro_arg_considering_derives(actual_macro_call, &loc.kind);
+ let (_, _, span) = *actual_macro_call.macro_arg_considering_derives(db, &loc.kind);
let span_map = RealSpanMap::absolute(span.anchor.file_id);
let span_map = SpanMap::RealSpanMap(&span_map);
@@ -241,7 +193,7 @@ pub fn expand_speculative(
// Otherwise the expand query will fetch the non speculative attribute args and pass those instead.
let mut speculative_expansion = match loc.def.kind {
MacroDefKind::ProcMacro(ast, expander, _) => {
- let span = proc_macro_span(db, ast);
+ let span = crate::proc_macro_span(db, ast);
tt.set_top_subtree_delimiter_kind(tt::DelimiterKind::Invisible);
tt.set_top_subtree_delimiter_span(tt::DelimSpan::from_single(span));
expander.expand(
@@ -271,13 +223,14 @@ pub fn expand_speculative(
it.expand(db, actual_macro_call, &tt, span).map_err(Into::into)
}
MacroDefKind::BuiltInAttr(_, it) => it.expand(db, actual_macro_call, &tt, span),
- MacroDefKind::UnimplementedBuiltIn(_) => expand_unimplemented_builtin_macro(span),
+ MacroDefKind::UnimplementedBuiltIn(_) => crate::expand_unimplemented_builtin_macro(span),
};
let expand_to = loc.expand_to();
fixup::reverse_fixups(&mut speculative_expansion.value, &undo_info);
- let (node, rev_tmap) = token_tree_to_syntax_node(db, &speculative_expansion.value, expand_to);
+ let (node, rev_tmap) =
+ crate::token_tree_to_syntax_node(db, &speculative_expansion.value, expand_to);
let syntax_node = node.syntax_node();
let token = rev_tmap
@@ -296,205 +249,6 @@ pub fn expand_speculative(
Some((node.syntax_node(), token))
}
-fn expand_unimplemented_builtin_macro(span: Span) -> ExpandResult<tt::TopSubtree> {
- ExpandResult::new(
- tt::TopSubtree::empty(tt::DelimSpan::from_single(span)),
- ExpandError::other(span, "this built-in macro is not implemented"),
- )
-}
-
-#[salsa::tracked(lru = 1024, returns(ref))]
-fn ast_id_map(db: &dyn ExpandDatabase, file_id: HirFileId) -> AstIdMap {
- AstIdMap::from_source(&db.parse_or_expand(file_id))
-}
-
-/// Main public API -- parses a hir file, not caring whether it's a real
-/// file or a macro expansion.
-fn parse_or_expand(db: &dyn ExpandDatabase, file_id: HirFileId) -> SyntaxNode {
- match file_id {
- HirFileId::FileId(file_id) => file_id.parse(db).syntax_node(),
- HirFileId::MacroFile(macro_file) => {
- db.parse_macro_expansion(macro_file).value.0.syntax_node()
- }
- }
-}
-
-// FIXME: We should verify that the parsed node is one of the many macro node variants we expect
-// instead of having it be untyped
-#[salsa_macros::tracked(returns(ref), lru = 512)]
-fn parse_macro_expansion(
- db: &dyn ExpandDatabase,
- macro_file: MacroCallId,
-) -> ExpandResult<(Parse<SyntaxNode>, ExpansionSpanMap)> {
- let _p = tracing::info_span!("parse_macro_expansion").entered();
- let loc = macro_file.loc(db);
- let expand_to = loc.expand_to();
- let mbe::ValueResult { value: (tt, matched_arm), err } = macro_expand(db, macro_file, loc);
-
- let (parse, mut rev_token_map) = token_tree_to_syntax_node(db, &tt, expand_to);
- rev_token_map.matched_arm = matched_arm;
-
- ExpandResult { value: (parse, rev_token_map), err }
-}
-
-fn parse_macro_expansion_error(
- db: &dyn ExpandDatabase,
- macro_call_id: MacroCallId,
-) -> Option<ExpandResult<Arc<[SyntaxError]>>> {
- let e: ExpandResult<Arc<[SyntaxError]>> =
- db.parse_macro_expansion(macro_call_id).as_ref().map(|it| Arc::from(it.0.errors()));
- if e.value.is_empty() && e.err.is_none() { None } else { Some(e) }
-}
-
-pub(crate) fn parse_with_map(
- db: &dyn ExpandDatabase,
- file_id: HirFileId,
-) -> (Parse<SyntaxNode>, SpanMap<'_>) {
- match file_id {
- HirFileId::FileId(file_id) => {
- (file_id.parse(db).to_syntax(), SpanMap::RealSpanMap(db.real_span_map(file_id)))
- }
- HirFileId::MacroFile(macro_file) => {
- let (parse, map) = &db.parse_macro_expansion(macro_file).value;
- (parse.clone(), SpanMap::ExpansionSpanMap(map))
- }
- }
-}
-
-/// This resolves the [MacroCallId] to check if it is a derive macro if so get the [macro_arg] for the derive.
-/// Other wise return the [macro_arg] for the macro_call_id.
-///
-/// This is not connected to the database so it does not cache the result. However, the inner [macro_arg] query is
-#[allow(deprecated)] // we are macro_arg_considering_derives
-fn macro_arg_considering_derives<'db>(
- db: &'db dyn ExpandDatabase,
- id: MacroCallId,
- kind: &MacroCallKind,
-) -> &'db MacroArgResult {
- match kind {
- // Get the macro arg for the derive macro
- MacroCallKind::Derive { derive_macro_id, .. } => db.macro_arg(*derive_macro_id),
- // Normal macro arg
- _ => db.macro_arg(id),
- }
-}
-
-#[salsa_macros::tracked(returns(ref))]
-fn macro_arg(db: &dyn ExpandDatabase, id: MacroCallId) -> MacroArgResult {
- let loc = id.loc(db);
-
- if let MacroCallLoc {
- def: MacroDefId { kind: MacroDefKind::BuiltInEager(..), .. },
- kind: MacroCallKind::FnLike { eager: Some(eager), .. },
- ..
- } = &loc
- {
- return (eager.arg.clone(), SyntaxFixupUndoInfo::NONE, eager.span);
- }
-
- let (parse, map) = parse_with_map(db, loc.kind.file_id());
- let root = parse.syntax_node();
-
- let (is_derive, censor_item_tree_attr_ids, item_node, span) = match &loc.kind {
- MacroCallKind::FnLike { ast_id, .. } => {
- let node = &ast_id.to_ptr(db).to_node(&root);
- let path_range = node
- .path()
- .map_or_else(|| node.syntax().text_range(), |path| path.syntax().text_range());
- let span = map.span_for_range(path_range);
-
- let dummy_tt = |kind| {
- (
- tt::TopSubtree::from_token_trees(
- tt::Delimiter { open: span, close: span, kind },
- tt::TokenTreesView::empty(),
- ),
- SyntaxFixupUndoInfo::default(),
- span,
- )
- };
-
- let Some(tt) = node.token_tree() else {
- return dummy_tt(tt::DelimiterKind::Invisible);
- };
- let first = tt.left_delimiter_token().map(|it| it.kind()).unwrap_or(T!['(']);
- let last = tt.right_delimiter_token().map(|it| it.kind()).unwrap_or(T![.]);
-
- let mismatched_delimiters = !matches!(
- (first, last),
- (T!['('], T![')']) | (T!['['], T![']']) | (T!['{'], T!['}'])
- );
- if mismatched_delimiters {
- // Don't expand malformed (unbalanced) macro invocations. This is
- // less than ideal, but trying to expand unbalanced macro calls
- // sometimes produces pathological, deeply nested code which breaks
- // all kinds of things.
- //
- // So instead, we'll return an empty subtree here
- cov_mark::hit!(issue9358_bad_macro_stack_overflow);
-
- let kind = match first {
- _ if loc.def.is_proc_macro() => tt::DelimiterKind::Invisible,
- T!['('] => tt::DelimiterKind::Parenthesis,
- T!['['] => tt::DelimiterKind::Bracket,
- T!['{'] => tt::DelimiterKind::Brace,
- _ => tt::DelimiterKind::Invisible,
- };
- return dummy_tt(kind);
- }
-
- let mut tt = syntax_bridge::syntax_node_to_token_tree(
- tt.syntax(),
- map,
- span,
- if loc.def.is_proc_macro() {
- DocCommentDesugarMode::ProcMacro
- } else {
- DocCommentDesugarMode::Mbe
- },
- );
- if loc.def.is_proc_macro() {
- // proc macros expect their inputs without parentheses, MBEs expect it with them included
- tt.set_top_subtree_delimiter_kind(tt::DelimiterKind::Invisible);
- }
- return (tt, SyntaxFixupUndoInfo::NONE, span);
- }
- // MacroCallKind::Derive should not be here. As we are getting the argument for the derive macro
- MacroCallKind::Derive { .. } => {
- unreachable!("`ExpandDatabase::macro_arg` called with `MacroCallKind::Derive`")
- }
- MacroCallKind::Attr { ast_id, censored_attr_ids: attr_ids, .. } => {
- let node = ast_id.to_ptr(db).to_node(&root);
- let (_, attr) = attr_ids.invoc_attr().find_attr_range_with_source(db, loc.krate, &node);
- let range = attr
- .path()
- .map(|path| path.syntax().text_range())
- .unwrap_or_else(|| attr.syntax().text_range());
- let span = map.span_for_range(range);
-
- let is_derive = matches!(loc.def.kind, MacroDefKind::BuiltInAttr(_, expander) if expander.is_derive());
- (is_derive, &**attr_ids, node, span)
- }
- };
-
- let (mut tt, undo_info) = attr_macro_input_to_token_tree(
- db,
- item_node.syntax(),
- map,
- span,
- is_derive,
- censor_item_tree_attr_ids,
- loc.krate,
- );
-
- if loc.def.is_proc_macro() {
- // proc macros expect their inputs without parentheses, MBEs expect it with them included
- tt.set_top_subtree_delimiter_kind(tt::DelimiterKind::Invisible);
- }
-
- (tt, undo_info, span)
-}
-
impl<'db> TokenExpander<'db> {
fn macro_expander(db: &'db dyn ExpandDatabase, id: MacroDefId) -> TokenExpander<'db> {
match id.kind {
@@ -510,178 +264,3 @@ impl<'db> TokenExpander<'db> {
}
}
}
-
-fn macro_expand<'db>(
- db: &'db dyn ExpandDatabase,
- macro_call_id: MacroCallId,
- loc: &MacroCallLoc,
-) -> ExpandResult<(Cow<'db, tt::TopSubtree>, MatchedArmIndex)> {
- let _p = tracing::info_span!("macro_expand").entered();
-
- let (ExpandResult { value: (tt, matched_arm), err }, span) = match loc.def.kind {
- MacroDefKind::ProcMacro(..) => {
- return expand_proc_macro(db, macro_call_id)
- .as_ref()
- .map(|it| (Cow::Borrowed(it), None));
- }
- _ => {
- let (macro_arg, undo_info, span) =
- db.macro_arg_considering_derives(macro_call_id, &loc.kind);
- let span = *span;
-
- let arg = macro_arg;
- let res = match loc.def.kind {
- MacroDefKind::Declarative(id, _) => {
- db.decl_macro_expander(loc.def.krate, id).expand(db, arg, macro_call_id, span)
- }
- MacroDefKind::BuiltIn(_, it) => {
- it.expand(db, macro_call_id, arg, span).map_err(Into::into).zip_val(None)
- }
- MacroDefKind::BuiltInDerive(_, it) => {
- it.expand(db, macro_call_id, arg, span).map_err(Into::into).zip_val(None)
- }
- MacroDefKind::UnimplementedBuiltIn(_) => {
- expand_unimplemented_builtin_macro(span).zip_val(None)
- }
- MacroDefKind::BuiltInEager(_, it) => {
- // This might look a bit odd, but we do not expand the inputs to eager macros here.
- // Eager macros inputs are expanded, well, eagerly when we collect the macro calls.
- // That kind of expansion uses the ast id map of an eager macros input though which goes through
- // the HirFileId machinery. As eager macro inputs are assigned a macro file id that query
- // will end up going through here again, whereas we want to just want to inspect the raw input.
- // As such we just return the input subtree here.
- let eager = match &loc.kind {
- MacroCallKind::FnLike { eager: None, .. } => {
- return ExpandResult::ok(Cow::Borrowed(macro_arg)).zip_val(None);
- }
- MacroCallKind::FnLike { eager: Some(eager), .. } => Some(&**eager),
- _ => None,
- };
-
- let mut res = it.expand(db, macro_call_id, arg, span).map_err(Into::into);
-
- if let Some(EagerCallInfo { error, .. }) = eager {
- // FIXME: We should report both errors!
- res.err = error.clone().or(res.err);
- }
- res.zip_val(None)
- }
- MacroDefKind::BuiltInAttr(_, it) => {
- let mut res = it.expand(db, macro_call_id, arg, span);
- fixup::reverse_fixups(&mut res.value, undo_info);
- res.zip_val(None)
- }
- MacroDefKind::ProcMacro(_, _, _) => unreachable!(),
- };
- (res, span)
- }
- };
-
- // Skip checking token tree limit for include! macro call
- if !loc.def.is_include() {
- // Set a hard limit for the expanded tt
- if let Err(value) = check_tt_count(&tt) {
- return value
- .map(|()| Cow::Owned(tt::TopSubtree::empty(tt::DelimSpan::from_single(span))))
- .zip_val(matched_arm);
- }
- }
-
- ExpandResult { value: (Cow::Owned(tt), matched_arm), err }
-}
-
-/// Retrieves the span to be used for a proc-macro expansions spans.
-/// This is a firewall query as it requires parsing the file, which we don't want proc-macros to
-/// directly depend on as that would cause to frequent invalidations, mainly because of the
-/// parse queries being LRU cached. If they weren't the invalidations would only happen if the
-/// user wrote in the file that defines the proc-macro.
-fn proc_macro_span(db: &dyn ExpandDatabase, ast: AstId<ast::Fn>) -> Span {
- #[salsa::tracked]
- fn proc_macro_span(db: &dyn ExpandDatabase, ast: AstId<ast::Fn>, _: ()) -> Span {
- let root = db.parse_or_expand(ast.file_id);
- let ast_id_map = db.ast_id_map(ast.file_id);
- let span_map = db.span_map(ast.file_id);
-
- let node = ast_id_map.get(ast.value).to_node(&root);
- let range = ast::HasName::name(&node)
- .map_or_else(|| node.syntax().text_range(), |name| name.syntax().text_range());
- span_map.span_for_range(range)
- }
- proc_macro_span(db, ast, ())
-}
-
-/// Special case of [`macro_expand`] 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.
-/// @edwin0cheng heroically debugged this once! See #4315 for details
-#[salsa_macros::tracked(returns(ref))]
-fn expand_proc_macro(db: &dyn ExpandDatabase, id: MacroCallId) -> ExpandResult<tt::TopSubtree> {
- let loc = id.loc(db);
- let (macro_arg, undo_info, span) = db.macro_arg_considering_derives(id, &loc.kind);
-
- let (ast, expander) = match loc.def.kind {
- MacroDefKind::ProcMacro(ast, expander, _) => (ast, expander),
- _ => unreachable!(),
- };
-
- let attr_arg = match &loc.kind {
- MacroCallKind::Attr { attr_args: Some(attr_args), .. } => Some(&**attr_args),
- _ => None,
- };
-
- let ExpandResult { value: mut tt, err } = {
- let span = proc_macro_span(db, ast);
- expander.expand(
- db,
- loc.def.krate,
- loc.krate,
- macro_arg,
- attr_arg,
- span_with_def_site_ctxt(db, span, id.into(), loc.def.edition),
- span_with_call_site_ctxt(db, span, id.into(), loc.def.edition),
- span_with_mixed_site_ctxt(db, span, id.into(), loc.def.edition),
- )
- };
-
- // Set a hard limit for the expanded tt
- if let Err(value) = check_tt_count(&tt) {
- return value.map(|()| tt::TopSubtree::empty(tt::DelimSpan::from_single(*span)));
- }
-
- fixup::reverse_fixups(&mut tt, undo_info);
-
- ExpandResult { value: tt, err }
-}
-
-pub(crate) fn token_tree_to_syntax_node(
- db: &dyn ExpandDatabase,
- tt: &tt::TopSubtree,
- expand_to: ExpandTo,
-) -> (Parse<SyntaxNode>, ExpansionSpanMap) {
- let entry_point = match expand_to {
- ExpandTo::Statements => syntax_bridge::TopEntryPoint::MacroStmts,
- ExpandTo::Items => syntax_bridge::TopEntryPoint::MacroItems,
- ExpandTo::Pattern => syntax_bridge::TopEntryPoint::Pattern,
- ExpandTo::Type => syntax_bridge::TopEntryPoint::Type,
- ExpandTo::Expr => syntax_bridge::TopEntryPoint::Expr,
- };
- syntax_bridge::token_tree_to_syntax_node(tt, entry_point, &mut |ctx| ctx.edition(db))
-}
-
-fn check_tt_count(tt: &tt::TopSubtree) -> Result<(), ExpandResult<()>> {
- let tt = tt.top_subtree();
- let count = tt.count();
- if count <= TOKEN_LIMIT {
- Ok(())
- } else {
- Err(ExpandResult {
- value: (),
- err: Some(ExpandError::other(
- tt.delimiter.open,
- format!(
- "macro invocation exceeds token limit: produced {count} tokens, limit is {TOKEN_LIMIT}",
- ),
- )),
- })
- }
-}
diff --git a/crates/hir-expand/src/declarative.rs b/crates/hir-expand/src/declarative.rs
index 107014164e..5ba30f1256 100644
--- a/crates/hir-expand/src/declarative.rs
+++ b/crates/hir-expand/src/declarative.rs
@@ -87,7 +87,8 @@ impl DeclarativeMacroExpander {
def_crate: Crate,
id: AstId<ast::Macro>,
) -> DeclarativeMacroExpander {
- let (root, map) = crate::db::parse_with_map(db, id.file_id);
+ let (root, map) = id.file_id.parse_with_map(db);
+
let root = root.syntax_node();
let transparency = |node: ast::AnyHasAttrs| {
diff --git a/crates/hir-expand/src/eager.rs b/crates/hir-expand/src/eager.rs
index f8a560834a..16053840b7 100644
--- a/crates/hir-expand/src/eager.rs
+++ b/crates/hir-expand/src/eager.rs
@@ -62,9 +62,9 @@ pub fn expand_eager_macro_input(
};
let arg_id = MacroCallId::new(db, loc);
#[allow(deprecated)] // builtin eager macros are never derives
- let (_, _, span) = db.macro_arg(arg_id);
+ let (_, _, span) = arg_id.macro_arg(db);
let ExpandResult { value: (arg_exp, arg_exp_map), err: parse_err } =
- db.parse_macro_expansion(arg_id);
+ arg_id.parse_macro_expansion(db);
let mut arg_map = ExpansionSpanMap::empty();
@@ -136,7 +136,7 @@ fn lazy_expand<'db>(
);
eager_callback(ast_id.map(|ast_id| (AstPtr::new(macro_call), ast_id)), id);
- db.parse_macro_expansion(id)
+ id.parse_macro_expansion(db)
.as_ref()
.map(|parse| (InFile::new(id.into(), parse.0.clone()), &parse.1))
}
@@ -206,7 +206,7 @@ fn eager_macro_recur(
continue;
}
};
- let ast_id = db.ast_id_map(curr.file_id).ast_id(&call);
+ let ast_id = curr.file_id.ast_id_map(db).ast_id(&call);
let ExpandResult { value, err } = match def.kind {
MacroDefKind::BuiltInEager(..) => {
let ExpandResult { value, err } = expand_eager_macro_input(
@@ -226,7 +226,7 @@ fn eager_macro_recur(
call_id,
);
let ExpandResult { value: (parse, map), err: err2 } =
- db.parse_macro_expansion(call_id);
+ call_id.parse_macro_expansion(db);
map.iter().for_each(|(o, span)| expanded_map.push(o + offset, span));
diff --git a/crates/hir-expand/src/files.rs b/crates/hir-expand/src/files.rs
index a4c206156d..a5e2433880 100644
--- a/crates/hir-expand/src/files.rs
+++ b/crates/hir-expand/src/files.rs
@@ -94,16 +94,16 @@ pub type AstId<N> = crate::InFile<FileAstId<N>>;
impl<N: AstNode> AstId<N> {
pub fn to_node(&self, db: &dyn ExpandDatabase) -> N {
- self.to_ptr(db).to_node(&db.parse_or_expand(self.file_id))
+ self.to_ptr(db).to_node(&self.file_id.parse_or_expand(db))
}
pub fn to_range(&self, db: &dyn ExpandDatabase) -> TextRange {
self.to_ptr(db).text_range()
}
pub fn to_in_file_node(&self, db: &dyn ExpandDatabase) -> crate::InFile<N> {
- crate::InFile::new(self.file_id, self.to_ptr(db).to_node(&db.parse_or_expand(self.file_id)))
+ crate::InFile::new(self.file_id, self.to_ptr(db).to_node(&self.file_id.parse_or_expand(db)))
}
pub fn to_ptr(&self, db: &dyn ExpandDatabase) -> AstPtr<N> {
- db.ast_id_map(self.file_id).get(self.value)
+ self.file_id.ast_id_map(db).get(self.value)
}
pub fn erase(&self) -> ErasedAstId {
crate::InFile::new(self.file_id, self.value.erase())
@@ -124,7 +124,7 @@ impl ErasedAstId {
self.to_ptr(db).text_range()
}
pub fn to_ptr(&self, db: &dyn ExpandDatabase) -> SyntaxNodePtr {
- db.ast_id_map(self.file_id).get_erased(self.value)
+ self.file_id.ast_id_map(db).get_erased(self.value)
}
}
@@ -213,12 +213,12 @@ impl FileIdToSyntax for EditionedFileId {
}
impl FileIdToSyntax for MacroCallId {
fn file_syntax(self, db: &dyn db::ExpandDatabase) -> SyntaxNode {
- db.parse_macro_expansion(self).value.0.syntax_node()
+ self.parse_macro_expansion(db).value.0.syntax_node()
}
}
impl FileIdToSyntax for HirFileId {
fn file_syntax(self, db: &dyn db::ExpandDatabase) -> SyntaxNode {
- db.parse_or_expand(self)
+ self.parse_or_expand(db)
}
}
diff --git a/crates/hir-expand/src/lib.rs b/crates/hir-expand/src/lib.rs
index 0ba04bc395..719a38edf4 100644
--- a/crates/hir-expand/src/lib.rs
+++ b/crates/hir-expand/src/lib.rs
@@ -33,17 +33,20 @@ use thin_vec::ThinVec;
use triomphe::Arc;
use core::fmt;
-use std::{hash::Hash, ops};
+use std::{borrow::Cow, ops};
use base_db::Crate;
use either::Either;
+use mbe::MatchedArmIndex;
use span::{
- Edition, ErasedFileAstId, FileAstId, NO_DOWNMAP_ERASED_FILE_AST_ID_MARKER, Span, SyntaxContext,
+ AstIdMap, Edition, ErasedFileAstId, FileAstId, NO_DOWNMAP_ERASED_FILE_AST_ID_MARKER, Span,
+ SyntaxContext,
};
use syntax::{
- SyntaxNode, SyntaxToken, TextRange, TextSize,
+ Parse, SyntaxError, SyntaxNode, SyntaxToken, T, TextRange, TextSize,
ast::{self, AstNode},
};
+use syntax_bridge::DocCommentDesugarMode;
use crate::{
attrs::AttrId,
@@ -51,8 +54,10 @@ use crate::{
BuiltinAttrExpander, BuiltinDeriveExpander, BuiltinFnLikeExpander, EagerExpander,
include_input_to_file_id,
},
+ cfg_process::attr_macro_input_to_token_tree,
db::ExpandDatabase,
- mod_path::ModPath,
+ fixup::SyntaxFixupUndoInfo,
+ hygiene::{span_with_call_site_ctxt, span_with_def_site_ctxt, span_with_mixed_site_ctxt},
proc_macro::{CustomProcMacroExpander, ProcMacroKind, ProcMacros},
span_map::{ExpansionSpanMap, SpanMap},
};
@@ -67,6 +72,18 @@ pub use mbe::{DeclarativeMacro, MacroCallStyle, MacroCallStyles, ValueResult};
pub use tt;
+/// This is just to ensure the types of [`MacroCallId::macro_arg_considering_derives`]
+/// and [`MacroCallId::macro_arg`] are the same.
+type MacroArgResult = (tt::TopSubtree, SyntaxFixupUndoInfo, Span);
+
+/// Total limit on the number of tokens produced by any macro invocation.
+///
+/// If an invocation produces more tokens than this limit, it will not be stored in the database and
+/// an error will be emitted.
+///
+/// Actual max for `analysis-stats .` at some point: 30672.
+const TOKEN_LIMIT: usize = 2_097_152;
+
#[macro_export]
macro_rules! impl_intern_lookup {
($db:ident, $id:ident, $loc:ident) => {
@@ -378,75 +395,6 @@ impl MacroCallKind {
}
}
-impl HirFileId {
- pub fn edition(self, db: &dyn ExpandDatabase) -> Edition {
- match self {
- HirFileId::FileId(file_id) => file_id.edition(db),
- HirFileId::MacroFile(m) => m.loc(db).def.edition,
- }
- }
- pub fn original_file(self, db: &dyn ExpandDatabase) -> EditionedFileId {
- let mut file_id = self;
- loop {
- match file_id {
- HirFileId::FileId(id) => break id,
- HirFileId::MacroFile(macro_call_id) => {
- file_id = macro_call_id.loc(db).kind.file_id()
- }
- }
- }
- }
-
- pub fn original_file_respecting_includes(mut self, db: &dyn ExpandDatabase) -> EditionedFileId {
- loop {
- match self {
- HirFileId::FileId(id) => break id,
- HirFileId::MacroFile(file) => {
- let loc = file.loc(db);
- if loc.def.is_include()
- && let MacroCallKind::FnLike { eager: Some(eager), .. } = &loc.kind
- && let Ok(it) = include_input_to_file_id(db, file, &eager.arg)
- {
- break it;
- }
- self = loc.kind.file_id();
- }
- }
- }
- }
-
- pub fn original_call_node(self, db: &dyn ExpandDatabase) -> Option<InRealFile<SyntaxNode>> {
- let mut call = self.macro_file()?.loc(db).to_node(db);
- loop {
- match call.file_id {
- HirFileId::FileId(file_id) => {
- break Some(InRealFile { file_id, value: call.value });
- }
- HirFileId::MacroFile(macro_call_id) => {
- call = macro_call_id.loc(db).to_node(db);
- }
- }
- }
- }
-
- pub fn call_node(self, db: &dyn ExpandDatabase) -> Option<InFile<SyntaxNode>> {
- Some(self.macro_file()?.loc(db).to_node(db))
- }
-
- pub fn as_builtin_derive_attr_node(
- &self,
- db: &dyn ExpandDatabase,
- ) -> Option<InFile<ast::Attr>> {
- let macro_file = self.macro_file()?;
- let loc = macro_file.loc(db);
- let attr = match loc.def.kind {
- MacroDefKind::BuiltInDerive(..) => loc.to_node(db),
- _ => return None,
- };
- Some(attr.with_value(ast::Attr::cast(attr.value.clone())?))
- }
-}
-
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum MacroKind {
/// `macro_rules!` or Macros 2.0 macro.
@@ -537,6 +485,357 @@ impl MacroCallId {
}
}
+#[salsa::tracked]
+impl MacroCallId {
+ /// Implementation of [`HirFileId::parse_or_expand`] for the macro case.
+ // FIXME: We should verify that the parsed node is one of the many macro node variants we expect
+ // instead of having it be untyped
+ #[salsa::tracked(returns(ref), lru = 512)]
+ pub fn parse_macro_expansion(
+ self,
+ db: &dyn ExpandDatabase,
+ ) -> ExpandResult<(Parse<SyntaxNode>, ExpansionSpanMap)> {
+ let _p = tracing::info_span!("parse_macro_expansion").entered();
+ let loc = self.loc(db);
+ let expand_to = loc.expand_to();
+ let mbe::ValueResult { value: (tt, matched_arm), err } = self.macro_expand(db, loc);
+
+ let (parse, mut rev_token_map) = token_tree_to_syntax_node(db, &tt, expand_to);
+ rev_token_map.matched_arm = matched_arm;
+
+ ExpandResult { value: (parse, rev_token_map), err }
+ }
+
+ pub fn parse_macro_expansion_error(
+ self,
+ db: &dyn ExpandDatabase,
+ ) -> Option<ExpandResult<Arc<[SyntaxError]>>> {
+ let e: ExpandResult<Arc<[SyntaxError]>> =
+ self.parse_macro_expansion(db).as_ref().map(|it| Arc::from(it.0.errors()));
+ if e.value.is_empty() && e.err.is_none() { None } else { Some(e) }
+ }
+
+ /// This resolves the [MacroCallId] to check if it is a derive macro if so get the [macro_arg] for the derive.
+ /// Other wise return the [macro_arg] for the macro_call_id.
+ ///
+ /// This is not connected to the database so it does not cache the result. However, the inner [macro_arg] query is
+ ///
+ /// [macro_arg]: Self::macro_arg
+ #[allow(deprecated)] // we are macro_arg_considering_derives
+ pub fn macro_arg_considering_derives<'db>(
+ self,
+ db: &'db dyn ExpandDatabase,
+ kind: &MacroCallKind,
+ ) -> &'db MacroArgResult {
+ match kind {
+ // Get the macro arg for the derive macro
+ MacroCallKind::Derive { derive_macro_id, .. } => derive_macro_id.macro_arg(db),
+ // Normal macro arg
+ _ => self.macro_arg(db),
+ }
+ }
+
+ /// Lowers syntactic macro call to a token tree representation. That's a firewall
+ /// query, only typing in the macro call itself changes the returned
+ /// subtree.
+ #[salsa::tracked(returns(ref))]
+ fn macro_arg(self, db: &dyn ExpandDatabase) -> MacroArgResult {
+ let loc = self.loc(db);
+
+ if let MacroCallLoc {
+ def: MacroDefId { kind: MacroDefKind::BuiltInEager(..), .. },
+ kind: MacroCallKind::FnLike { eager: Some(eager), .. },
+ ..
+ } = &loc
+ {
+ return (eager.arg.clone(), SyntaxFixupUndoInfo::NONE, eager.span);
+ }
+
+ let (parse, map) = loc.kind.file_id().parse_with_map(db);
+ let root = parse.syntax_node();
+
+ let (is_derive, censor_item_tree_attr_ids, item_node, span) = match &loc.kind {
+ MacroCallKind::FnLike { ast_id, .. } => {
+ let node = &ast_id.to_ptr(db).to_node(&root);
+ let path_range = node
+ .path()
+ .map_or_else(|| node.syntax().text_range(), |path| path.syntax().text_range());
+ let span = map.span_for_range(path_range);
+
+ let dummy_tt = |kind| {
+ (
+ tt::TopSubtree::from_token_trees(
+ tt::Delimiter { open: span, close: span, kind },
+ tt::TokenTreesView::empty(),
+ ),
+ SyntaxFixupUndoInfo::default(),
+ span,
+ )
+ };
+
+ let Some(tt) = node.token_tree() else {
+ return dummy_tt(tt::DelimiterKind::Invisible);
+ };
+ let first = tt.left_delimiter_token().map(|it| it.kind()).unwrap_or(T!['(']);
+ let last = tt.right_delimiter_token().map(|it| it.kind()).unwrap_or(T![.]);
+
+ let mismatched_delimiters = !matches!(
+ (first, last),
+ (T!['('], T![')']) | (T!['['], T![']']) | (T!['{'], T!['}'])
+ );
+ if mismatched_delimiters {
+ // Don't expand malformed (unbalanced) macro invocations. This is
+ // less than ideal, but trying to expand unbalanced macro calls
+ // sometimes produces pathological, deeply nested code which breaks
+ // all kinds of things.
+ //
+ // So instead, we'll return an empty subtree here
+ cov_mark::hit!(issue9358_bad_macro_stack_overflow);
+
+ let kind = match first {
+ _ if loc.def.is_proc_macro() => tt::DelimiterKind::Invisible,
+ T!['('] => tt::DelimiterKind::Parenthesis,
+ T!['['] => tt::DelimiterKind::Bracket,
+ T!['{'] => tt::DelimiterKind::Brace,
+ _ => tt::DelimiterKind::Invisible,
+ };
+ return dummy_tt(kind);
+ }
+
+ let mut tt = syntax_bridge::syntax_node_to_token_tree(
+ tt.syntax(),
+ map,
+ span,
+ if loc.def.is_proc_macro() {
+ DocCommentDesugarMode::ProcMacro
+ } else {
+ DocCommentDesugarMode::Mbe
+ },
+ );
+ if loc.def.is_proc_macro() {
+ // proc macros expect their inputs without parentheses, MBEs expect it with them included
+ tt.set_top_subtree_delimiter_kind(tt::DelimiterKind::Invisible);
+ }
+ return (tt, SyntaxFixupUndoInfo::NONE, span);
+ }
+ // MacroCallKind::Derive should not be here. As we are getting the argument for the derive macro
+ MacroCallKind::Derive { .. } => {
+ unreachable!("`ExpandDatabase::macro_arg` called with `MacroCallKind::Derive`")
+ }
+ MacroCallKind::Attr { ast_id, censored_attr_ids: attr_ids, .. } => {
+ let node = ast_id.to_ptr(db).to_node(&root);
+ let (_, attr) =
+ attr_ids.invoc_attr().find_attr_range_with_source(db, loc.krate, &node);
+ let range = attr
+ .path()
+ .map(|path| path.syntax().text_range())
+ .unwrap_or_else(|| attr.syntax().text_range());
+ let span = map.span_for_range(range);
+
+ let is_derive = matches!(loc.def.kind, MacroDefKind::BuiltInAttr(_, expander) if expander.is_derive());
+ (is_derive, &**attr_ids, node, span)
+ }
+ };
+
+ let (mut tt, undo_info) = attr_macro_input_to_token_tree(
+ db,
+ item_node.syntax(),
+ map,
+ span,
+ is_derive,
+ censor_item_tree_attr_ids,
+ loc.krate,
+ );
+
+ if loc.def.is_proc_macro() {
+ // proc macros expect their inputs without parentheses, MBEs expect it with them included
+ tt.set_top_subtree_delimiter_kind(tt::DelimiterKind::Invisible);
+ }
+
+ (tt, undo_info, span)
+ }
+
+ fn macro_expand<'db>(
+ self,
+ db: &'db dyn ExpandDatabase,
+ loc: &MacroCallLoc,
+ ) -> ExpandResult<(Cow<'db, tt::TopSubtree>, MatchedArmIndex)> {
+ let _p = tracing::info_span!("macro_expand").entered();
+
+ let (ExpandResult { value: (tt, matched_arm), err }, span) = match loc.def.kind {
+ MacroDefKind::ProcMacro(..) => {
+ return self.expand_proc_macro(db).as_ref().map(|it| (Cow::Borrowed(it), None));
+ }
+ _ => {
+ let (macro_arg, undo_info, span) =
+ self.macro_arg_considering_derives(db, &loc.kind);
+ let span = *span;
+
+ let arg = macro_arg;
+ let res = match loc.def.kind {
+ MacroDefKind::Declarative(id, _) => {
+ db.decl_macro_expander(loc.def.krate, id).expand(db, arg, self, span)
+ }
+ MacroDefKind::BuiltIn(_, it) => {
+ it.expand(db, self, arg, span).map_err(Into::into).zip_val(None)
+ }
+ MacroDefKind::BuiltInDerive(_, it) => {
+ it.expand(db, self, arg, span).map_err(Into::into).zip_val(None)
+ }
+ MacroDefKind::UnimplementedBuiltIn(_) => {
+ expand_unimplemented_builtin_macro(span).zip_val(None)
+ }
+ MacroDefKind::BuiltInEager(_, it) => {
+ // This might look a bit odd, but we do not expand the inputs to eager macros here.
+ // Eager macros inputs are expanded, well, eagerly when we collect the macro calls.
+ // That kind of expansion uses the ast id map of an eager macros input though which goes through
+ // the HirFileId machinery. As eager macro inputs are assigned a macro file id that query
+ // will end up going through here again, whereas we want to just want to inspect the raw input.
+ // As such we just return the input subtree here.
+ let eager = match &loc.kind {
+ MacroCallKind::FnLike { eager: None, .. } => {
+ return ExpandResult::ok(Cow::Borrowed(macro_arg)).zip_val(None);
+ }
+ MacroCallKind::FnLike { eager: Some(eager), .. } => Some(&**eager),
+ _ => None,
+ };
+
+ let mut res = it.expand(db, self, arg, span).map_err(Into::into);
+
+ if let Some(EagerCallInfo { error, .. }) = eager {
+ // FIXME: We should report both errors!
+ res.err = error.clone().or(res.err);
+ }
+ res.zip_val(None)
+ }
+ MacroDefKind::BuiltInAttr(_, it) => {
+ let mut res = it.expand(db, self, arg, span);
+ fixup::reverse_fixups(&mut res.value, undo_info);
+ res.zip_val(None)
+ }
+ MacroDefKind::ProcMacro(_, _, _) => unreachable!(),
+ };
+ (res, span)
+ }
+ };
+
+ // Skip checking token tree limit for include! macro call
+ if !loc.def.is_include() {
+ // Set a hard limit for the expanded tt
+ if let Err(value) = check_tt_count(&tt) {
+ return value
+ .map(|()| Cow::Owned(tt::TopSubtree::empty(tt::DelimSpan::from_single(span))))
+ .zip_val(matched_arm);
+ }
+ }
+
+ ExpandResult { value: (Cow::Owned(tt), matched_arm), err }
+ }
+
+ /// Special case of [`Self::macro_expand`] 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.
+ /// @edwin0cheng heroically debugged this once! See #4315 for details
+ #[salsa::tracked(returns(ref))]
+ fn expand_proc_macro(self, db: &dyn ExpandDatabase) -> ExpandResult<tt::TopSubtree> {
+ let loc = self.loc(db);
+ let (macro_arg, undo_info, span) = self.macro_arg_considering_derives(db, &loc.kind);
+
+ let (ast, expander) = match loc.def.kind {
+ MacroDefKind::ProcMacro(ast, expander, _) => (ast, expander),
+ _ => unreachable!(),
+ };
+
+ let attr_arg = match &loc.kind {
+ MacroCallKind::Attr { attr_args: Some(attr_args), .. } => Some(&**attr_args),
+ _ => None,
+ };
+
+ let ExpandResult { value: mut tt, err } = {
+ let span = proc_macro_span(db, ast);
+ expander.expand(
+ db,
+ loc.def.krate,
+ loc.krate,
+ macro_arg,
+ attr_arg,
+ span_with_def_site_ctxt(db, span, self.into(), loc.def.edition),
+ span_with_call_site_ctxt(db, span, self.into(), loc.def.edition),
+ span_with_mixed_site_ctxt(db, span, self.into(), loc.def.edition),
+ )
+ };
+
+ // Set a hard limit for the expanded tt
+ if let Err(value) = check_tt_count(&tt) {
+ return value.map(|()| tt::TopSubtree::empty(tt::DelimSpan::from_single(*span)));
+ }
+
+ fixup::reverse_fixups(&mut tt, undo_info);
+
+ ExpandResult { value: tt, err }
+ }
+}
+
+fn expand_unimplemented_builtin_macro(span: Span) -> ExpandResult<tt::TopSubtree> {
+ ExpandResult::new(
+ tt::TopSubtree::empty(tt::DelimSpan::from_single(span)),
+ ExpandError::other(span, "this built-in macro is not implemented"),
+ )
+}
+
+/// Retrieves the span to be used for a proc-macro expansions spans.
+/// This is a firewall query as it requires parsing the file, which we don't want proc-macros to
+/// directly depend on as that would cause to frequent invalidations, mainly because of the
+/// parse queries being LRU cached. If they weren't the invalidations would only happen if the
+/// user wrote in the file that defines the proc-macro.
+fn proc_macro_span(db: &dyn ExpandDatabase, ast: AstId<ast::Fn>) -> Span {
+ #[salsa::tracked]
+ fn proc_macro_span(db: &dyn ExpandDatabase, ast: AstId<ast::Fn>, _: ()) -> Span {
+ let root = ast.file_id.parse_or_expand(db);
+ let ast_id_map = ast.file_id.ast_id_map(db);
+ let span_map = db.span_map(ast.file_id);
+
+ let node = ast_id_map.get(ast.value).to_node(&root);
+ let range = ast::HasName::name(&node)
+ .map_or_else(|| node.syntax().text_range(), |name| name.syntax().text_range());
+ span_map.span_for_range(range)
+ }
+ proc_macro_span(db, ast, ())
+}
+
+pub(crate) fn token_tree_to_syntax_node(
+ db: &dyn ExpandDatabase,
+ tt: &tt::TopSubtree,
+ expand_to: ExpandTo,
+) -> (Parse<SyntaxNode>, ExpansionSpanMap) {
+ let entry_point = match expand_to {
+ ExpandTo::Statements => syntax_bridge::TopEntryPoint::MacroStmts,
+ ExpandTo::Items => syntax_bridge::TopEntryPoint::MacroItems,
+ ExpandTo::Pattern => syntax_bridge::TopEntryPoint::Pattern,
+ ExpandTo::Type => syntax_bridge::TopEntryPoint::Type,
+ ExpandTo::Expr => syntax_bridge::TopEntryPoint::Expr,
+ };
+ syntax_bridge::token_tree_to_syntax_node(tt, entry_point, &mut |ctx| ctx.edition(db))
+}
+
+fn check_tt_count(tt: &tt::TopSubtree) -> Result<(), ExpandResult<()>> {
+ let tt = tt.top_subtree();
+ let count = tt.count();
+ if count <= TOKEN_LIMIT {
+ Ok(())
+ } else {
+ Err(ExpandResult {
+ value: (),
+ err: Some(ExpandError::other(
+ tt.delimiter.open,
+ format!(
+ "macro invocation exceeds token limit: produced {count} tokens, limit is {TOKEN_LIMIT}",
+ ),
+ )),
+ })
+ }
+}
+
impl MacroDefId {
pub fn make_call(
self,
@@ -556,10 +855,10 @@ impl MacroDefId {
| MacroDefKind::BuiltInDerive(id, _)
| MacroDefKind::BuiltInEager(id, _)
| MacroDefKind::UnimplementedBuiltIn(id) => {
- id.with_value(db.ast_id_map(id.file_id).get(id.value).text_range())
+ id.with_value(id.file_id.ast_id_map(db).get(id.value).text_range())
}
MacroDefKind::ProcMacro(id, _, _) => {
- id.with_value(db.ast_id_map(id.file_id).get(id.value).text_range())
+ id.with_value(id.file_id.ast_id_map(db).get(id.value).text_range())
}
}
}
@@ -932,7 +1231,7 @@ impl<'db> ExpansionInfo<'db> {
let arg_tt = loc.kind.arg(db);
let arg_map = db.span_map(arg_tt.file_id);
- let (parse, exp_map) = &db.parse_macro_expansion(macro_file).value;
+ let (parse, exp_map) = &macro_file.parse_macro_expansion(db).value;
let expanded = InMacroFile { file_id: macro_file, value: parse.syntax_node() };
ExpansionInfo { expanded, loc, arg: arg_tt, exp_map, arg_map }
@@ -1059,8 +1358,6 @@ impl ExpandTo {
}
}
-intern::impl_internable!(ModPath);
-
/// Macro ids. That's probably the tricksiest bit in rust-analyzer, and the
/// reason why we use salsa at all.
///
@@ -1107,6 +1404,17 @@ impl From<MacroCallId> for HirFileId {
}
}
+impl PartialEq<EditionedFileId> for HirFileId {
+ fn eq(&self, &other: &EditionedFileId) -> bool {
+ *self == HirFileId::from(other)
+ }
+}
+impl PartialEq<HirFileId> for EditionedFileId {
+ fn eq(&self, &other: &HirFileId) -> bool {
+ other == HirFileId::from(*self)
+ }
+}
+
impl HirFileId {
#[inline]
pub fn macro_file(self) -> Option<MacroCallId> {
@@ -1134,19 +1442,110 @@ impl HirFileId {
HirFileId::FileId(_) => SyntaxContext::root(edition),
HirFileId::MacroFile(m) => {
let kind = &m.loc(db).kind;
- db.macro_arg_considering_derives(m, kind).2.ctx
+ m.macro_arg_considering_derives(db, kind).2.ctx
}
}
}
-}
-impl PartialEq<EditionedFileId> for HirFileId {
- fn eq(&self, &other: &EditionedFileId) -> bool {
- *self == HirFileId::from(other)
+ pub fn edition(self, db: &dyn ExpandDatabase) -> Edition {
+ match self {
+ HirFileId::FileId(file_id) => file_id.edition(db),
+ HirFileId::MacroFile(m) => m.loc(db).def.edition,
+ }
+ }
+
+ pub fn original_file(self, db: &dyn ExpandDatabase) -> EditionedFileId {
+ let mut file_id = self;
+ loop {
+ match file_id {
+ HirFileId::FileId(id) => break id,
+ HirFileId::MacroFile(macro_call_id) => {
+ file_id = macro_call_id.loc(db).kind.file_id()
+ }
+ }
+ }
+ }
+
+ pub fn original_file_respecting_includes(mut self, db: &dyn ExpandDatabase) -> EditionedFileId {
+ loop {
+ match self {
+ HirFileId::FileId(id) => break id,
+ HirFileId::MacroFile(file) => {
+ let loc = file.loc(db);
+ if loc.def.is_include()
+ && let MacroCallKind::FnLike { eager: Some(eager), .. } = &loc.kind
+ && let Ok(it) = include_input_to_file_id(db, file, &eager.arg)
+ {
+ break it;
+ }
+ self = loc.kind.file_id();
+ }
+ }
+ }
+ }
+
+ pub fn original_call_node(self, db: &dyn ExpandDatabase) -> Option<InRealFile<SyntaxNode>> {
+ let mut call = self.macro_file()?.loc(db).to_node(db);
+ loop {
+ match call.file_id {
+ HirFileId::FileId(file_id) => {
+ break Some(InRealFile { file_id, value: call.value });
+ }
+ HirFileId::MacroFile(macro_call_id) => {
+ call = macro_call_id.loc(db).to_node(db);
+ }
+ }
+ }
+ }
+
+ pub fn call_node(self, db: &dyn ExpandDatabase) -> Option<InFile<SyntaxNode>> {
+ Some(self.macro_file()?.loc(db).to_node(db))
+ }
+
+ pub fn as_builtin_derive_attr_node(
+ &self,
+ db: &dyn ExpandDatabase,
+ ) -> Option<InFile<ast::Attr>> {
+ let macro_file = self.macro_file()?;
+ let loc = macro_file.loc(db);
+ let attr = match loc.def.kind {
+ MacroDefKind::BuiltInDerive(..) => loc.to_node(db),
+ _ => return None,
+ };
+ Some(attr.with_value(ast::Attr::cast(attr.value.clone())?))
+ }
+
+ /// Main public API -- parses a hir file, not caring whether it's a real
+ /// file or a macro expansion.
+ pub fn parse_or_expand(self, db: &dyn ExpandDatabase) -> SyntaxNode {
+ match self {
+ HirFileId::FileId(file_id) => file_id.parse(db).syntax_node(),
+ HirFileId::MacroFile(macro_file) => {
+ macro_file.parse_macro_expansion(db).value.0.syntax_node()
+ }
+ }
+ }
+
+ pub(crate) fn parse_with_map(
+ self,
+ db: &dyn ExpandDatabase,
+ ) -> (Parse<SyntaxNode>, SpanMap<'_>) {
+ match self {
+ HirFileId::FileId(file_id) => {
+ (file_id.parse(db).to_syntax(), SpanMap::RealSpanMap(db.real_span_map(file_id)))
+ }
+ HirFileId::MacroFile(macro_file) => {
+ let (parse, map) = &macro_file.parse_macro_expansion(db).value;
+ (parse.clone(), SpanMap::ExpansionSpanMap(map))
+ }
+ }
}
}
-impl PartialEq<HirFileId> for EditionedFileId {
- fn eq(&self, &other: &HirFileId) -> bool {
- other == HirFileId::from(*self)
+
+#[salsa::tracked]
+impl HirFileId {
+ #[salsa::tracked(lru = 1024, returns(ref))]
+ pub fn ast_id_map(self, db: &dyn ExpandDatabase) -> AstIdMap {
+ AstIdMap::from_source(&self.parse_or_expand(db))
}
}
diff --git a/crates/hir-expand/src/mod_path.rs b/crates/hir-expand/src/mod_path.rs
index 9142ad8b92..b90bfac483 100644
--- a/crates/hir-expand/src/mod_path.rs
+++ b/crates/hir-expand/src/mod_path.rs
@@ -24,6 +24,8 @@ pub struct ModPath {
segments: SmallVec<[Name; 1]>,
}
+intern::impl_internable!(ModPath);
+
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum PathKind {
Plain,
diff --git a/crates/hir-expand/src/span_map.rs b/crates/hir-expand/src/span_map.rs
index 6a94df8b5a..1b588a8425 100644
--- a/crates/hir-expand/src/span_map.rs
+++ b/crates/hir-expand/src/span_map.rs
@@ -41,7 +41,7 @@ impl<'db> SpanMap<'db> {
match file_id {
HirFileId::FileId(file_id) => SpanMap::RealSpanMap(db.real_span_map(file_id)),
HirFileId::MacroFile(m) => {
- SpanMap::ExpansionSpanMap(&db.parse_macro_expansion(m).value.1)
+ SpanMap::ExpansionSpanMap(&m.parse_macro_expansion(db).value.1)
}
}
}
@@ -54,7 +54,7 @@ pub(crate) fn real_span_map(
) -> RealSpanMap {
use syntax::ast::HasModuleItem;
let mut pairs = vec![(syntax::TextSize::new(0), span::ROOT_ERASED_FILE_AST_ID)];
- let ast_id_map = db.ast_id_map(editioned_file_id.into());
+ let ast_id_map = HirFileId::from(editioned_file_id).ast_id_map(db);
let tree = editioned_file_id.parse(db).tree();
// This is an incrementality layer. Basically we can't use absolute ranges for our spans as that
@@ -115,5 +115,5 @@ pub(crate) fn expansion_span_map(
db: &dyn ExpandDatabase,
file_id: MacroCallId,
) -> &ExpansionSpanMap {
- &db.parse_macro_expansion(file_id).value.1
+ &file_id.parse_macro_expansion(db).value.1
}
diff --git a/crates/hir-ty/src/tests.rs b/crates/hir-ty/src/tests.rs
index 9ffe38e749..febd2a833a 100644
--- a/crates/hir-ty/src/tests.rs
+++ b/crates/hir-ty/src/tests.rs
@@ -25,7 +25,7 @@ use hir_def::{
src::HasSource,
type_ref::TypeRefId,
};
-use hir_expand::{FileRange, InFile, db::ExpandDatabase};
+use hir_expand::{FileRange, InFile};
use itertools::Itertools;
use rustc_hash::FxHashMap;
use stdx::format_to;
@@ -278,7 +278,7 @@ fn expr_node(
) -> Option<InFile<SyntaxNode>> {
Some(match body_source_map.expr_syntax(expr) {
Ok(sp) => {
- let root = db.parse_or_expand(sp.file_id);
+ let root = sp.file_id.parse_or_expand(db);
sp.map(|ptr| ptr.to_node(&root).syntax().clone())
}
Err(SyntheticSyntax) => return None,
@@ -292,7 +292,7 @@ fn pat_node(
) -> Option<InFile<SyntaxNode>> {
Some(match body_source_map.pat_syntax(pat) {
Ok(sp) => {
- let root = db.parse_or_expand(sp.file_id);
+ let root = sp.file_id.parse_or_expand(db);
sp.map(|ptr| ptr.to_node(&root).syntax().clone())
}
Err(SyntheticSyntax) => return None,
@@ -306,7 +306,7 @@ fn type_node(
) -> Option<InFile<SyntaxNode>> {
Some(match body_source_map.type_syntax(type_ref) {
Ok(sp) => {
- let root = db.parse_or_expand(sp.file_id);
+ let root = sp.file_id.parse_or_expand(db);
sp.map(|ptr| ptr.to_node(&root).syntax().clone())
}
Err(SyntheticSyntax) => return None,
@@ -349,7 +349,7 @@ fn infer_with_mismatches(content: &str, include_mismatches: bool) -> String {
if let Some((binding_id, syntax_ptr)) = self_param {
let ty = &inference_result.type_of_binding[binding_id];
if let Some(syntax_ptr) = syntax_ptr {
- let root = db.parse_or_expand(syntax_ptr.file_id);
+ let root = syntax_ptr.file_id.parse_or_expand(&db);
let node = syntax_ptr.map(|ptr| ptr.to_node(&root).syntax().clone());
types.push((node, ty.as_ref()));
}
@@ -361,7 +361,7 @@ fn infer_with_mismatches(content: &str, include_mismatches: bool) -> String {
}
let node = match source_map.pat_syntax(pat) {
Ok(sp) => {
- let root = db.parse_or_expand(sp.file_id);
+ let root = sp.file_id.parse_or_expand(&db);
sp.map(|ptr| ptr.to_node(&root).syntax().clone())
}
Err(SyntheticSyntax) => continue,
@@ -375,7 +375,7 @@ fn infer_with_mismatches(content: &str, include_mismatches: bool) -> String {
for (expr, ty) in inference_result.type_of_expr.iter() {
let node = match source_map.expr_syntax(expr) {
Ok(sp) => {
- let root = db.parse_or_expand(sp.file_id);
+ let root = sp.file_id.parse_or_expand(&db);
sp.map(|ptr| ptr.to_node(&root).syntax().clone())
}
Err(SyntheticSyntax) => continue,
diff --git a/crates/hir-ty/src/tests/incremental.rs b/crates/hir-ty/src/tests/incremental.rs
index 4c26b19120..3432d47b2f 100644
--- a/crates/hir-ty/src/tests/incremental.rs
+++ b/crates/hir-ty/src/tests/incremental.rs
@@ -34,7 +34,7 @@ fn foo() -> i32 {
"source_root_crates",
"crate_local_def_map",
"file_item_tree_query",
- "ast_id_map",
+ "HirFileId::ast_id_map_",
"parse",
"real_span_map",
"InferenceResult::for_body_",
@@ -78,7 +78,7 @@ fn foo() -> i32 {
expect_test::expect![[r#"
[
"parse",
- "ast_id_map",
+ "HirFileId::ast_id_map_",
"file_item_tree_query",
"real_span_map",
"AttrFlags::query_",
@@ -123,7 +123,7 @@ fn baz() -> i32 {
"source_root_crates",
"crate_local_def_map",
"file_item_tree_query",
- "ast_id_map",
+ "HirFileId::ast_id_map_",
"parse",
"real_span_map",
"InferenceResult::for_body_",
@@ -194,7 +194,7 @@ fn baz() -> i32 {
expect_test::expect![[r#"
[
"parse",
- "ast_id_map",
+ "HirFileId::ast_id_map_",
"file_item_tree_query",
"real_span_map",
"AttrFlags::query_",
@@ -247,7 +247,7 @@ $0",
"source_root_crates",
"crate_local_def_map",
"file_item_tree_query",
- "ast_id_map",
+ "HirFileId::ast_id_map_",
"parse",
"real_span_map",
"TraitImpls::for_crate_",
@@ -284,7 +284,7 @@ pub struct NewStruct {
expect_test::expect![[r#"
[
"parse",
- "ast_id_map",
+ "HirFileId::ast_id_map_",
"file_item_tree_query",
"real_span_map",
"crate_local_def_map",
@@ -322,7 +322,7 @@ $0",
"source_root_crates",
"crate_local_def_map",
"file_item_tree_query",
- "ast_id_map",
+ "HirFileId::ast_id_map_",
"parse",
"real_span_map",
"TraitImpls::for_crate_",
@@ -360,7 +360,7 @@ pub enum SomeEnum {
expect_test::expect![[r#"
[
"parse",
- "ast_id_map",
+ "HirFileId::ast_id_map_",
"file_item_tree_query",
"real_span_map",
"crate_local_def_map",
@@ -398,7 +398,7 @@ $0",
"source_root_crates",
"crate_local_def_map",
"file_item_tree_query",
- "ast_id_map",
+ "HirFileId::ast_id_map_",
"parse",
"real_span_map",
"TraitImpls::for_crate_",
@@ -433,7 +433,7 @@ fn bar() -> f32 {
expect_test::expect![[r#"
[
"parse",
- "ast_id_map",
+ "HirFileId::ast_id_map_",
"file_item_tree_query",
"real_span_map",
"crate_local_def_map",
@@ -475,7 +475,7 @@ $0",
"source_root_crates",
"crate_local_def_map",
"file_item_tree_query",
- "ast_id_map",
+ "HirFileId::ast_id_map_",
"parse",
"real_span_map",
"TraitImpls::for_crate_",
@@ -518,7 +518,7 @@ impl SomeStruct {
expect_test::expect![[r#"
[
"parse",
- "ast_id_map",
+ "HirFileId::ast_id_map_",
"file_item_tree_query",
"real_span_map",
"crate_local_def_map",
@@ -576,7 +576,7 @@ fn main() {
"source_root_crates",
"crate_local_def_map",
"file_item_tree_query",
- "ast_id_map",
+ "HirFileId::ast_id_map_",
"parse",
"real_span_map",
"TraitItems::query_with_diagnostics_",
@@ -671,7 +671,7 @@ fn main() {
expect_test::expect![[r#"
[
"parse",
- "ast_id_map",
+ "HirFileId::ast_id_map_",
"file_item_tree_query",
"real_span_map",
"crate_local_def_map",
diff --git a/crates/hir/src/diagnostics.rs b/crates/hir/src/diagnostics.rs
index c551cfac79..cfb967f486 100644
--- a/crates/hir/src/diagnostics.rs
+++ b/crates/hir/src/diagnostics.rs
@@ -1013,7 +1013,7 @@ impl<'db> AnyDiagnostic<'db> {
}
InferenceDiagnostic::PathDiagnostic { node, diag } => {
let source = expr_or_pat_syntax(*node)?;
- let syntax = source.value.to_node(&db.parse_or_expand(source.file_id));
+ let syntax = source.value.to_node(&source.file_id.parse_or_expand(db));
let path = match_ast! {
match (syntax.syntax()) {
ast::RecordExpr(it) => it.path()?,
@@ -1316,7 +1316,7 @@ impl<'db> AnyDiagnostic<'db> {
Some(match diag {
TyLoweringDiagnostic::PathDiagnostic { source, diag } => {
let source = Self::type_syntax(*source, source_map)?;
- let syntax = source.value.to_node(&db.parse_or_expand(source.file_id));
+ let syntax = source.value.to_node(&source.file_id.parse_or_expand(db));
let ast::Type::PathType(syntax) = syntax else { return None };
Self::path_diagnostic(diag, source.with_value(syntax.path()?))?
}
diff --git a/crates/hir/src/has_source.rs b/crates/hir/src/has_source.rs
index 9bff8bda3a..9248aaec02 100644
--- a/crates/hir/src/has_source.rs
+++ b/crates/hir/src/has_source.rs
@@ -297,7 +297,7 @@ impl HasSource for Param<'_> {
let (_, source_map) =
ExpressionStore::with_source_map(db, owner.expression_store_owner(db));
let ast @ InFile { file_id, value } = source_map.expr_syntax(expr_id).ok()?;
- let root = db.parse_or_expand(file_id);
+ let root = file_id.parse_or_expand(db);
match value.to_node(&root) {
Either::Left(ast::Expr::ClosureExpr(it)) => it
.param_list()?
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index 8d21b351e4..a78ce2a2ab 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -813,7 +813,7 @@ impl Module {
expr_store_diagnostics(db, acc, source_map);
let (variants, diagnostics) = e.id.enum_variants_with_diagnostics(db);
let file = e.id.lookup(db).id.file_id;
- let ast_id_map = db.ast_id_map(file);
+ let ast_id_map = file.ast_id_map(db);
for diag in diagnostics {
acc.push(
InactiveCode {
@@ -883,7 +883,7 @@ impl Module {
.iter()
.for_each(|&(_ast, call_id)| macro_call_diagnostics(db, call_id, acc));
- let ast_id_map = db.ast_id_map(file_id);
+ let ast_id_map = file_id.ast_id_map(db);
for diag in impl_id.impl_items_with_diagnostics(db).1.iter() {
emit_def_diagnostic(db, acc, diag, edition, loc.container.krate(db));
@@ -1159,7 +1159,7 @@ fn macro_call_diagnostics<'db>(
macro_call_id: MacroCallId,
acc: &mut Vec<AnyDiagnostic<'db>>,
) {
- let Some(e) = db.parse_macro_expansion_error(macro_call_id) else {
+ let Some(e) = macro_call_id.parse_macro_expansion_error(db) else {
return;
};
let ValueResult { value: parse_errors, err } = e;
@@ -1170,7 +1170,7 @@ fn macro_call_diagnostics<'db>(
let RenderedExpandError { message, error, kind } = err.render_to_string(db);
if Some(err.span().anchor.file_id) == file_id.file_id().map(|it| it.span_file_id(db)) {
range.value = err.span().range
- + db.ast_id_map(file_id).get_erased(err.span().anchor.ast_id).text_range().start();
+ + file_id.ast_id_map(db).get_erased(err.span().anchor.ast_id).text_range().start();
}
acc.push(MacroError { range, message, error, kind }.into());
}
@@ -1260,7 +1260,7 @@ fn emit_def_diagnostic_<'db>(
}
DefDiagnosticKind::UnconfiguredCode { ast_id, cfg, opts } => {
- let ast_id_map = db.ast_id_map(ast_id.file_id);
+ let ast_id_map = ast_id.file_id.ast_id_map(db);
let ptr = ast_id_map.get_erased(ast_id.value);
acc.push(
InactiveCode {
diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs
index dcbd6c37af..c696ebcf18 100644
--- a/crates/hir/src/semantics.rs
+++ b/crates/hir/src/semantics.rs
@@ -550,7 +550,7 @@ impl<'db> SemanticsImpl<'db> {
}
pub fn parse_or_expand(&self, file_id: HirFileId) -> SyntaxNode {
- let node = self.db.parse_or_expand(file_id);
+ let node = file_id.parse_or_expand(self.db);
self.cache(node.clone(), file_id);
node
}
@@ -564,7 +564,7 @@ impl<'db> SemanticsImpl<'db> {
}
pub fn expand(&self, file_id: MacroCallId) -> ExpandResult<SyntaxNode> {
- let res = self.db.parse_macro_expansion(file_id).as_ref().map(|it| it.0.syntax_node());
+ let res = file_id.parse_macro_expansion(self.db).as_ref().map(|it| it.0.syntax_node());
self.cache(res.value.clone(), file_id.into());
res
}
@@ -661,7 +661,7 @@ impl<'db> SemanticsImpl<'db> {
.into_iter()
.map(|call| {
let file_id = call?.left()?;
- let ExpandResult { value, err } = self.db.parse_macro_expansion(file_id);
+ let ExpandResult { value, err } = file_id.parse_macro_expansion(self.db);
let root_node = value.0.syntax_node();
self.cache(root_node.clone(), file_id.into());
Some(ExpandResult { value: root_node, err: err.clone() })
@@ -690,7 +690,7 @@ impl<'db> SemanticsImpl<'db> {
pub fn derive_helpers_in_scope(&self, adt: &ast::Adt) -> Option<Vec<(Symbol, Symbol)>> {
let sa = self.analyze_no_infer(adt.syntax())?;
- let id = self.db.ast_id_map(sa.file_id).ast_id(adt);
+ let id = sa.file_id.ast_id_map(self.db).ast_id(adt);
let result = sa
.resolver
.def_map()
@@ -713,7 +713,7 @@ impl<'db> SemanticsImpl<'db> {
})?;
let attr_name = attr.path().and_then(|it| it.as_single_name_ref())?.as_name();
let sa = self.analyze_no_infer(adt.syntax())?;
- let id = self.db.ast_id_map(sa.file_id).ast_id(&adt);
+ let id = sa.file_id.ast_id_map(self.db).ast_id(&adt);
let res: Vec<_> = sa
.resolver
.def_map()
@@ -1498,7 +1498,7 @@ impl<'db> SemanticsImpl<'db> {
self.analyze_impl(InFile::new(expansion, &parent), None, false)
})?
.resolver;
- let id = db.ast_id_map(expansion).ast_id(&adt);
+ let id = expansion.ast_id_map(db).ast_id(&adt);
let helpers = resolver
.def_map()
.derive_helpers_in_scope(InFile::new(expansion, id))?;
@@ -1979,8 +1979,7 @@ impl<'db> SemanticsImpl<'db> {
}
pub fn resolve_macro_call_arm(&self, macro_call: &ast::MacroCall) -> Option<u32> {
- let file_id = self.to_def(macro_call)?;
- self.db.parse_macro_expansion(file_id).value.1.matched_arm
+ self.to_def(macro_call)?.parse_macro_expansion(self.db).value.1.matched_arm
}
pub fn get_unsafe_ops(&self, def: ExpressionStoreOwner) -> FxHashSet<ExprOrPatSource> {
diff --git a/crates/hir/src/semantics/child_by_source.rs b/crates/hir/src/semantics/child_by_source.rs
index 97c5a451ab..d9c98c920e 100644
--- a/crates/hir/src/semantics/child_by_source.rs
+++ b/crates/hir/src/semantics/child_by_source.rs
@@ -200,7 +200,7 @@ impl ChildBySource for EnumId {
return;
}
- let ast_id_map = db.ast_id_map(loc.id.file_id);
+ let ast_id_map = loc.id.file_id.ast_id_map(db);
self.enum_variants(db).variants.values().for_each(|&(variant, _)| {
res[keys::ENUM_VARIANT].insert(ast_id_map.get(variant.lookup(db).id.value), variant);
diff --git a/crates/hir/src/source_analyzer.rs b/crates/hir/src/source_analyzer.rs
index fc03f82135..59d029b1e2 100644
--- a/crates/hir/src/source_analyzer.rs
+++ b/crates/hir/src/source_analyzer.rs
@@ -1366,7 +1366,7 @@ impl<'db> SourceAnalyzer<'db> {
},
);
if let Some(adt) = adt {
- let ast_id = db.ast_id_map(self.file_id).ast_id(&adt);
+ let ast_id = self.file_id.ast_id_map(db).ast_id(&adt);
if let Some(helpers) = self
.resolver
.def_map()
diff --git a/crates/ide-diagnostics/src/handlers/incorrect_case.rs b/crates/ide-diagnostics/src/handlers/incorrect_case.rs
index bda3f9bf0a..888f55cea7 100644
--- a/crates/ide-diagnostics/src/handlers/incorrect_case.rs
+++ b/crates/ide-diagnostics/src/handlers/incorrect_case.rs
@@ -1,4 +1,4 @@
-use hir::{CaseType, InFile, db::ExpandDatabase};
+use hir::{CaseType, InFile};
use ide_db::{assists::Assist, defs::NameClass, rename::RenameDefinition};
use syntax::AstNode;
@@ -37,7 +37,7 @@ pub(crate) fn incorrect_case(
}
fn fixes(ctx: &DiagnosticsContext<'_, '_>, d: &hir::IncorrectCase) -> Option<Vec<Assist>> {
- let root = ctx.sema.db.parse_or_expand(d.file);
+ let root = d.file.parse_or_expand(ctx.sema.db);
let name_node = d.ident.to_node(&root);
let def = NameClass::classify(&ctx.sema, &name_node)?.defined()?;
diff --git a/crates/ide-diagnostics/src/handlers/missing_fields.rs b/crates/ide-diagnostics/src/handlers/missing_fields.rs
index fe71707f07..2030be4368 100644
--- a/crates/ide-diagnostics/src/handlers/missing_fields.rs
+++ b/crates/ide-diagnostics/src/handlers/missing_fields.rs
@@ -1,8 +1,6 @@
use either::Either;
use hir::{
- AssocItem, FindPathConfig, HasVisibility, HirDisplay, InFile, Type,
- db::{ExpandDatabase, HirDatabase},
- sym,
+ AssocItem, FindPathConfig, HasVisibility, HirDisplay, InFile, Type, db::HirDatabase, sym,
};
use ide_db::{
FxHashMap,
@@ -65,7 +63,7 @@ fn fixes(ctx: &DiagnosticsContext<'_, '_>, d: &hir::MissingFields) -> Option<Vec
return None;
}
- let root = ctx.sema.db.parse_or_expand(d.file);
+ let root = d.file.parse_or_expand(ctx.sema.db);
let current_module =
ctx.sema.scope(d.field_list_parent.to_node(&root).syntax()).map(|it| it.module());
diff --git a/crates/ide-diagnostics/src/handlers/missing_unsafe.rs b/crates/ide-diagnostics/src/handlers/missing_unsafe.rs
index d279e9b4e8..808b76e082 100644
--- a/crates/ide-diagnostics/src/handlers/missing_unsafe.rs
+++ b/crates/ide-diagnostics/src/handlers/missing_unsafe.rs
@@ -1,4 +1,3 @@
-use hir::db::ExpandDatabase;
use hir::{UnsafeLint, UnsafetyReason};
use ide_db::text_edit::TextEdit;
use ide_db::{assists::Assist, source_change::SourceChange};
@@ -47,7 +46,7 @@ fn fixes(ctx: &DiagnosticsContext<'_, '_>, d: &hir::MissingUnsafe) -> Option<Vec
return None;
}
- let root = ctx.sema.db.parse_or_expand(d.node.file_id);
+ let root = d.node.file_id.parse_or_expand(ctx.sema.db);
let node = d.node.value.to_node(&root);
let expr = node.syntax().ancestors().find_map(ast::Expr::cast)?;
diff --git a/crates/ide-diagnostics/src/handlers/mutability_errors.rs b/crates/ide-diagnostics/src/handlers/mutability_errors.rs
index 49aa6d7bd9..e4ee066653 100644
--- a/crates/ide-diagnostics/src/handlers/mutability_errors.rs
+++ b/crates/ide-diagnostics/src/handlers/mutability_errors.rs
@@ -1,4 +1,3 @@
-use hir::db::ExpandDatabase;
use ide_db::source_change::SourceChange;
use ide_db::text_edit::TextEdit;
use syntax::{AstNode, SyntaxKind, SyntaxNode, SyntaxNodePtr, SyntaxToken, T, ast};
@@ -9,7 +8,7 @@ use crate::{Diagnostic, DiagnosticCode, DiagnosticsContext, fix};
//
// This diagnostic is triggered on mutating an immutable variable.
pub(crate) fn need_mut(ctx: &DiagnosticsContext<'_, '_>, d: &hir::NeedMut) -> Option<Diagnostic> {
- let root = ctx.sema.db.parse_or_expand(d.span.file_id);
+ let root = d.span.file_id.parse_or_expand(ctx.sema.db);
let node = d.span.value.to_node(&root);
let mut span = d.span;
if let Some(parent) = node.parent()
diff --git a/crates/ide-diagnostics/src/handlers/no_such_field.rs b/crates/ide-diagnostics/src/handlers/no_such_field.rs
index 3dd6744b05..f6fe83177f 100644
--- a/crates/ide-diagnostics/src/handlers/no_such_field.rs
+++ b/crates/ide-diagnostics/src/handlers/no_such_field.rs
@@ -1,5 +1,5 @@
use either::Either;
-use hir::{HasSource, HirDisplay, Semantics, VariantId, db::ExpandDatabase};
+use hir::{HasSource, HirDisplay, Semantics, VariantId};
use ide_db::text_edit::TextEdit;
use ide_db::{EditionedFileId, RootDatabase, source_change::SourceChange};
use syntax::{
@@ -32,7 +32,7 @@ pub(crate) fn no_such_field(ctx: &DiagnosticsContext<'_, '_>, d: &hir::NoSuchFie
fn fixes(ctx: &DiagnosticsContext<'_, '_>, d: &hir::NoSuchField) -> Option<Vec<Assist>> {
// FIXME: quickfix for pattern
- let root = ctx.sema.db.parse_or_expand(d.field.file_id);
+ let root = d.field.file_id.parse_or_expand(ctx.sema.db);
match &d.field.value.to_node(&root) {
Either::Left(node) => {
if let Some(private_field) = d.private {
diff --git a/crates/ide-diagnostics/src/handlers/remove_trailing_return.rs b/crates/ide-diagnostics/src/handlers/remove_trailing_return.rs
index b5a47e508e..7e431f3ff4 100644
--- a/crates/ide-diagnostics/src/handlers/remove_trailing_return.rs
+++ b/crates/ide-diagnostics/src/handlers/remove_trailing_return.rs
@@ -1,4 +1,4 @@
-use hir::{FileRange, db::ExpandDatabase, diagnostics::RemoveTrailingReturn};
+use hir::{FileRange, diagnostics::RemoveTrailingReturn};
use ide_db::text_edit::TextEdit;
use ide_db::{assists::Assist, source_change::SourceChange};
use syntax::{AstNode, ast};
@@ -37,7 +37,7 @@ pub(crate) fn remove_trailing_return(
}
fn fixes(ctx: &DiagnosticsContext<'_, '_>, d: &RemoveTrailingReturn) -> Option<Vec<Assist>> {
- let root = ctx.sema.db.parse_or_expand(d.return_expr.file_id);
+ let root = d.return_expr.file_id.parse_or_expand(ctx.sema.db);
let return_expr = d.return_expr.value.to_node(&root);
let stmt = return_expr.syntax().parent().and_then(ast::ExprStmt::cast);
diff --git a/crates/ide-diagnostics/src/handlers/remove_unnecessary_else.rs b/crates/ide-diagnostics/src/handlers/remove_unnecessary_else.rs
index aa7b57e292..337b05e21f 100644
--- a/crates/ide-diagnostics/src/handlers/remove_unnecessary_else.rs
+++ b/crates/ide-diagnostics/src/handlers/remove_unnecessary_else.rs
@@ -1,4 +1,4 @@
-use hir::{db::ExpandDatabase, diagnostics::RemoveUnnecessaryElse};
+use hir::diagnostics::RemoveUnnecessaryElse;
use ide_db::text_edit::TextEdit;
use ide_db::{assists::Assist, source_change::SourceChange};
use itertools::Itertools;
@@ -41,7 +41,7 @@ pub(crate) fn remove_unnecessary_else(
}
fn fixes(ctx: &DiagnosticsContext<'_, '_>, d: &RemoveUnnecessaryElse) -> Option<Vec<Assist>> {
- let root = ctx.sema.db.parse_or_expand(d.if_expr.file_id);
+ let root = d.if_expr.file_id.parse_or_expand(ctx.sema.db);
let if_expr = d.if_expr.value.to_node(&root);
let if_expr = ctx.sema.original_ast_node(if_expr)?;
diff --git a/crates/ide-diagnostics/src/handlers/replace_filter_map_next_with_find_map.rs b/crates/ide-diagnostics/src/handlers/replace_filter_map_next_with_find_map.rs
index f974c55023..e67d86b8a2 100644
--- a/crates/ide-diagnostics/src/handlers/replace_filter_map_next_with_find_map.rs
+++ b/crates/ide-diagnostics/src/handlers/replace_filter_map_next_with_find_map.rs
@@ -1,4 +1,4 @@
-use hir::{InFile, db::ExpandDatabase};
+use hir::InFile;
use ide_db::source_change::SourceChange;
use ide_db::text_edit::TextEdit;
use syntax::{
@@ -29,7 +29,7 @@ fn fixes(
ctx: &DiagnosticsContext<'_, '_>,
d: &hir::ReplaceFilterMapNextWithFindMap,
) -> Option<Vec<Assist>> {
- let root = ctx.sema.db.parse_or_expand(d.file);
+ let root = d.file.parse_or_expand(ctx.sema.db);
let next_expr = d.next_expr.to_node(&root);
let next_call = ast::MethodCallExpr::cast(next_expr.syntax().clone())?;
diff --git a/crates/ide-diagnostics/src/handlers/trait_impl_redundant_assoc_item.rs b/crates/ide-diagnostics/src/handlers/trait_impl_redundant_assoc_item.rs
index ee972f2d1d..9374688d0e 100644
--- a/crates/ide-diagnostics/src/handlers/trait_impl_redundant_assoc_item.rs
+++ b/crates/ide-diagnostics/src/handlers/trait_impl_redundant_assoc_item.rs
@@ -1,4 +1,4 @@
-use hir::{HasSource, HirDisplay, db::ExpandDatabase};
+use hir::{HasSource, HirDisplay};
use ide_db::text_edit::TextRange;
use ide_db::{
assists::{Assist, AssistId},
@@ -82,7 +82,7 @@ fn quickfix_for_redundant_assoc_item(
let file_id = d.file_id.file_id()?;
let add_assoc_item_def = |builder: &mut SourceChangeBuilder| -> Option<()> {
let db = ctx.sema.db;
- let root = db.parse_or_expand(d.file_id);
+ let root = d.file_id.parse_or_expand(db);
// don't modify trait def in outer crate
let impl_def = d.impl_.to_node(&root);
let current_crate = ctx.sema.scope(impl_def.syntax())?.krate();
diff --git a/crates/ide-diagnostics/src/handlers/type_mismatch.rs b/crates/ide-diagnostics/src/handlers/type_mismatch.rs
index da6fc20c3e..8950850d4a 100644
--- a/crates/ide-diagnostics/src/handlers/type_mismatch.rs
+++ b/crates/ide-diagnostics/src/handlers/type_mismatch.rs
@@ -1,5 +1,5 @@
use either::Either;
-use hir::{CallableKind, ClosureStyle, HirDisplay, InFile, db::ExpandDatabase};
+use hir::{CallableKind, ClosureStyle, HirDisplay, InFile};
use ide_db::{
famous_defs::FamousDefs,
source_change::{SourceChange, SourceChangeBuilder},
@@ -151,7 +151,7 @@ fn add_missing_ok_or_some(
expr_ptr: &InFile<AstPtr<ast::Expr>>,
acc: &mut Vec<Assist>,
) -> Option<()> {
- let root = ctx.db().parse_or_expand(expr_ptr.file_id);
+ let root = expr_ptr.file_id.parse_or_expand(ctx.db());
let expr = expr_ptr.value.to_node(&root);
let hir::FileRange { file_id, range: expr_range } =
ctx.sema.original_range_opt(expr.syntax())?;
@@ -246,7 +246,7 @@ fn remove_unnecessary_wrapper(
acc: &mut Vec<Assist>,
) -> Option<()> {
let db = ctx.db();
- let root = db.parse_or_expand(expr_ptr.file_id);
+ let root = expr_ptr.file_id.parse_or_expand(db);
let expr = expr_ptr.value.to_node(&root);
// FIXME: support inside MacroCall?
let expr = ctx.sema.original_ast_node(expr)?;
@@ -327,7 +327,7 @@ fn remove_semicolon(
expr_ptr: &InFile<AstPtr<ast::Expr>>,
acc: &mut Vec<Assist>,
) -> Option<()> {
- let root = ctx.db().parse_or_expand(expr_ptr.file_id);
+ let root = expr_ptr.file_id.parse_or_expand(ctx.db());
let expr = expr_ptr.value.to_node(&root);
if !d.actual.is_unit() {
return None;
@@ -365,7 +365,7 @@ fn str_ref_to_owned(
return None;
}
- let root = ctx.db().parse_or_expand(expr_ptr.file_id);
+ let root = expr_ptr.file_id.parse_or_expand(ctx.db());
let expr = expr_ptr.value.to_node(&root);
let hir::FileRange { file_id, range } = ctx.sema.original_range_opt(expr.syntax())?;
@@ -391,7 +391,7 @@ fn add_await(
return None;
}
- let root = ctx.db().parse_or_expand(expr_ptr.file_id);
+ let root = expr_ptr.file_id.parse_or_expand(ctx.db());
let expr = expr_ptr.value.to_node(&root);
let hir::FileRange { file_id, range } = ctx.sema.original_range_opt(expr.syntax())?;
diff --git a/crates/ide-diagnostics/src/handlers/typed_hole.rs b/crates/ide-diagnostics/src/handlers/typed_hole.rs
index e000d6388a..4c59482961 100644
--- a/crates/ide-diagnostics/src/handlers/typed_hole.rs
+++ b/crates/ide-diagnostics/src/handlers/typed_hole.rs
@@ -2,7 +2,6 @@ use std::ops::Not;
use hir::{
ClosureStyle, FindPathConfig, HirDisplay,
- db::ExpandDatabase,
term_search::{TermSearchConfig, TermSearchCtx, term_search},
};
use ide_db::text_edit::TextEdit;
@@ -46,7 +45,7 @@ pub(crate) fn typed_hole<'db>(
fn fixes<'db>(ctx: &DiagnosticsContext<'_, 'db>, d: &hir::TypedHole<'db>) -> Option<Vec<Assist>> {
let db = ctx.sema.db;
- let root = db.parse_or_expand(d.expr.file_id);
+ let root = d.expr.file_id.parse_or_expand(db);
let (original_range, _) =
d.expr.as_ref().map(|it| it.to_node(&root)).syntax().original_file_range_opt(db)?;
let scope = ctx.sema.scope(d.expr.value.to_node(&root).syntax())?;
diff --git a/crates/ide-diagnostics/src/handlers/unresolved_field.rs b/crates/ide-diagnostics/src/handlers/unresolved_field.rs
index 78e13677cf..682a8130a8 100644
--- a/crates/ide-diagnostics/src/handlers/unresolved_field.rs
+++ b/crates/ide-diagnostics/src/handlers/unresolved_field.rs
@@ -1,5 +1,5 @@
use either::Either;
-use hir::{Adt, FileRange, HasSource, HirDisplay, InFile, Struct, Union, db::ExpandDatabase};
+use hir::{Adt, FileRange, HasSource, HirDisplay, InFile, Struct, Union};
use ide_db::text_edit::TextEdit;
use ide_db::{
assists::{Assist, AssistId},
@@ -64,7 +64,7 @@ fn fixes(ctx: &DiagnosticsContext<'_, '_>, d: &hir::UnresolvedField<'_>) -> Opti
// FIXME: Add Snippet Support
fn field_fix(ctx: &DiagnosticsContext<'_, '_>, d: &hir::UnresolvedField<'_>) -> Option<Assist> {
// Get the FileRange of the invalid field access
- let root = ctx.sema.db.parse_or_expand(d.expr.file_id);
+ let root = d.expr.file_id.parse_or_expand(ctx.sema.db);
let expr = d.expr.value.to_node(&root).left()?;
let error_range = ctx.sema.original_range_opt(expr.syntax())?;
@@ -266,7 +266,7 @@ fn method_fix(
ctx: &DiagnosticsContext<'_, '_>,
expr_ptr: &InFile<AstPtr<Either<ast::Expr, ast::Pat>>>,
) -> Option<Assist> {
- let root = ctx.sema.db.parse_or_expand(expr_ptr.file_id);
+ let root = expr_ptr.file_id.parse_or_expand(ctx.sema.db);
let expr = expr_ptr.value.to_node(&root);
let FileRange { range, file_id } = ctx.sema.original_range_opt(expr.syntax())?;
Some(Assist {
diff --git a/crates/ide-diagnostics/src/handlers/unresolved_method.rs b/crates/ide-diagnostics/src/handlers/unresolved_method.rs
index 01929a5144..853e9d9f56 100644
--- a/crates/ide-diagnostics/src/handlers/unresolved_method.rs
+++ b/crates/ide-diagnostics/src/handlers/unresolved_method.rs
@@ -1,4 +1,4 @@
-use hir::{FileRange, HirDisplay, InFile, db::ExpandDatabase};
+use hir::{FileRange, HirDisplay, InFile};
use ide_db::text_edit::TextEdit;
use ide_db::{
assists::{Assist, AssistId},
@@ -82,7 +82,7 @@ fn field_fix(
return None;
}
let expr_ptr = &d.expr;
- let root = ctx.sema.db.parse_or_expand(expr_ptr.file_id);
+ let root = expr_ptr.file_id.parse_or_expand(ctx.sema.db);
let expr = expr_ptr.value.to_node(&root);
let (file_id, range) = match expr.left()? {
ast::Expr::MethodCallExpr(mcall) => {
@@ -118,7 +118,7 @@ fn assoc_func_fix(
let db = ctx.sema.db;
let expr_ptr = &d.expr;
- let root = db.parse_or_expand(expr_ptr.file_id);
+ let root = expr_ptr.file_id.parse_or_expand(db);
let expr: ast::Expr = expr_ptr.value.to_node(&root).left()?;
let call = ast::MethodCallExpr::cast(expr.syntax().clone())?;
diff --git a/crates/ide-diagnostics/src/handlers/unresolved_module.rs b/crates/ide-diagnostics/src/handlers/unresolved_module.rs
index 1e0e9105d8..d5f2697bd2 100644
--- a/crates/ide-diagnostics/src/handlers/unresolved_module.rs
+++ b/crates/ide-diagnostics/src/handlers/unresolved_module.rs
@@ -1,4 +1,3 @@
-use hir::db::ExpandDatabase;
use ide_db::{assists::Assist, base_db::AnchoredPathBuf, source_change::FileSystemEdit};
use itertools::Itertools;
use syntax::AstNode;
@@ -33,7 +32,7 @@ pub(crate) fn unresolved_module(
}
fn fixes(ctx: &DiagnosticsContext<'_, '_>, d: &hir::UnresolvedModule) -> Option<Vec<Assist>> {
- let root = ctx.sema.db.parse_or_expand(d.decl.file_id);
+ let root = d.decl.file_id.parse_or_expand(ctx.sema.db);
let unresolved_module = d.decl.value.to_node(&root);
Some(
d.candidates
diff --git a/crates/load-cargo/src/lib.rs b/crates/load-cargo/src/lib.rs
index 96c95ec277..4a97a5f05e 100644
--- a/crates/load-cargo/src/lib.rs
+++ b/crates/load-cargo/src/lib.rs
@@ -705,8 +705,8 @@ impl ProcMacroExpander for Expander {
let call_site_ast_id = macro_call_loc.kind.erased_ast_id();
if let Some(editioned_file_id) = call_site_file.file_id() {
- let range = db
- .ast_id_map(editioned_file_id.into())
+ let range = hir_expand::HirFileId::from(editioned_file_id)
+ .ast_id_map(db)
.get_erased(call_site_ast_id)
.text_range();
diff --git a/crates/rust-analyzer/src/cli/analysis_stats.rs b/crates/rust-analyzer/src/cli/analysis_stats.rs
index 1a036c3b99..f53512e5ec 100644
--- a/crates/rust-analyzer/src/cli/analysis_stats.rs
+++ b/crates/rust-analyzer/src/cli/analysis_stats.rs
@@ -13,7 +13,7 @@ use cfg::{CfgAtom, CfgDiff};
use hir::{
Adt, AssocItem, Crate, DefWithBody, FindPathConfig, GenericDef, HasCrate, HasSource,
HirDisplay, ModuleDef, Name, Variant, crate_lang_items,
- db::{DefDatabase, ExpandDatabase, HirDatabase},
+ db::{DefDatabase, HirDatabase},
};
use hir_def::{
DefWithBodyId, ExpressionStoreOwnerId, GenericDefId, SyntheticSyntax,
@@ -1503,7 +1503,7 @@ fn location_csv_expr(db: &RootDatabase, vfs: &Vfs, sm: &BodySourceMap, expr_id:
Ok(s) => s,
Err(SyntheticSyntax) => return "synthetic,,".to_owned(),
};
- let root = db.parse_or_expand(src.file_id);
+ let root = src.file_id.parse_or_expand(db);
let node = src.map(|e| e.to_node(&root).syntax().clone());
let original_range = node.as_ref().original_file_range_rooted(db);
let path = vfs.file_path(original_range.file_id.file_id(db));
@@ -1519,7 +1519,7 @@ fn location_csv_pat(db: &RootDatabase, vfs: &Vfs, sm: &BodySourceMap, pat_id: Pa
Ok(s) => s,
Err(SyntheticSyntax) => return "synthetic,,".to_owned(),
};
- let root = db.parse_or_expand(src.file_id);
+ let root = src.file_id.parse_or_expand(db);
let node = src.map(|e| e.to_node(&root).syntax().clone());
let original_range = node.as_ref().original_file_range_rooted(db);
let path = vfs.file_path(original_range.file_id.file_id(db));
@@ -1538,7 +1538,7 @@ fn expr_syntax_range<'a>(
) -> Option<(&'a VfsPath, LineCol, LineCol)> {
let src = sm.expr_syntax(expr_id);
if let Ok(src) = src {
- let root = db.parse_or_expand(src.file_id);
+ let root = src.file_id.parse_or_expand(db);
let node = src.map(|e| e.to_node(&root).syntax().clone());
let original_range = node.as_ref().original_file_range_rooted(db);
let path = vfs.file_path(original_range.file_id.file_id(db));
@@ -1559,7 +1559,7 @@ fn pat_syntax_range<'a>(
) -> Option<(&'a VfsPath, LineCol, LineCol)> {
let src = sm.pat_syntax(pat_id);
if let Ok(src) = src {
- let root = db.parse_or_expand(src.file_id);
+ let root = src.file_id.parse_or_expand(db);
let node = src.map(|e| e.to_node(&root).syntax().clone());
let original_range = node.as_ref().original_file_range_rooted(db);
let path = vfs.file_path(original_range.file_id.file_id(db));