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
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(¯o_call_node); + let ast_id = source.file_id.ast_id_map(&db).ast_id(¯o_call_node); let ast_id = InFile::new(source.file_id, ast_id); let ptr = InFile::new(source.file_id, AstPtr::new(¯o_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(¯o_call_node); + let ast_id = source.file_id.ast_id_map(&db).ast_id(¯o_call_node); let ast_id = InFile::new(source.file_id, ast_id); let ptr = InFile::new(source.file_id, AstPtr::new(¯o_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) = ¯o_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) = ¯o_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) = ¯o_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)); |