Unnamed repository; edit this file 'description' to name the repository.
| -rw-r--r-- | crates/hir-def/src/attrs/docs.rs | 2 | ||||
| -rw-r--r-- | crates/hir-def/src/expr_store/expander.rs | 4 | ||||
| -rw-r--r-- | crates/hir-def/src/macro_expansion_tests/mod.rs | 4 | ||||
| -rw-r--r-- | crates/hir-def/src/nameres/assoc.rs | 2 | ||||
| -rw-r--r-- | crates/hir-def/src/nameres/tests/incremental.rs | 58 | ||||
| -rw-r--r-- | crates/hir-expand/src/builtin/derive_macro.rs | 2 | ||||
| -rw-r--r-- | crates/hir-expand/src/db.rs | 406 | ||||
| -rw-r--r-- | crates/hir-expand/src/eager.rs | 8 | ||||
| -rw-r--r-- | crates/hir-expand/src/files.rs | 2 | ||||
| -rw-r--r-- | crates/hir-expand/src/lib.rs | 376 | ||||
| -rw-r--r-- | crates/hir-expand/src/span_map.rs | 4 | ||||
| -rw-r--r-- | crates/hir/src/lib.rs | 2 | ||||
| -rw-r--r-- | crates/hir/src/semantics.rs | 7 |
13 files changed, 429 insertions, 448 deletions
diff --git a/crates/hir-def/src/attrs/docs.rs b/crates/hir-def/src/attrs/docs.rs index 0d01d54786..cb91f08af3 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; diff --git a/crates/hir-def/src/expr_store/expander.rs b/crates/hir-def/src/expr_store/expander.rs index c79a1db847..35cf1c9681 100644 --- a/crates/hir-def/src/expr_store/expander.rs +++ b/crates/hir-def/src/expr_store/expander.rs @@ -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 { diff --git a/crates/hir-def/src/macro_expansion_tests/mod.rs b/crates/hir-def/src/macro_expansion_tests/mod.rs index 1d6812ad56..88f41274e4 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 { @@ -125,7 +125,7 @@ pub fn identity_when_valid(_attr: TokenStream, item: TokenStream) -> TokenStream 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)); } diff --git a/crates/hir-def/src/nameres/assoc.rs b/crates/hir-def/src/nameres/assoc.rs index 7b5b39cb08..cc88d21fbf 100644 --- a/crates/hir-def/src/nameres/assoc.rs +++ b/crates/hir-def/src/nameres/assoc.rs @@ -356,7 +356,7 @@ 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_span_map = mem::replace(&mut self.span_map, SpanMap::ExpansionSpanMap(span_map)); diff --git a/crates/hir-def/src/nameres/tests/incremental.rs b/crates/hir-def/src/nameres/tests/incremental.rs index bb19456f46..e7aa994c07 100644 --- a/crates/hir-def/src/nameres/tests/incremental.rs +++ b/crates/hir-def/src/nameres/tests/incremental.rs @@ -239,8 +239,8 @@ pub struct S {} "macro_def_shim", "file_item_tree_query", "ast_id_map", - "parse_macro_expansion", - "macro_arg", + "MacroCallId::parse_macro_expansion_", + "MacroCallId::macro_arg_", ] "#]], expect![[r#" @@ -249,8 +249,8 @@ pub struct S {} "ast_id_map", "file_item_tree_query", "real_span_map", - "macro_arg", - "parse_macro_expansion", + "MacroCallId::macro_arg_", + "MacroCallId::parse_macro_expansion_", "ast_id_map", "file_item_tree_query", ] @@ -302,9 +302,9 @@ fn f() { foo } "macro_def_shim", "file_item_tree_query", "ast_id_map", - "parse_macro_expansion", - "expand_proc_macro", - "macro_arg", + "MacroCallId::parse_macro_expansion_", + "MacroCallId::expand_proc_macro_", + "MacroCallId::macro_arg_", "proc_macro_span", ] "#]], @@ -314,9 +314,9 @@ fn f() { foo } "ast_id_map", "file_item_tree_query", "real_span_map", - "macro_arg", - "expand_proc_macro", - "parse_macro_expansion", + "MacroCallId::macro_arg_", + "MacroCallId::expand_proc_macro_", + "MacroCallId::parse_macro_expansion_", "ast_id_map", "file_item_tree_query", ] @@ -427,20 +427,20 @@ pub struct S {} "macro_def_shim", "file_item_tree_query", "ast_id_map", - "parse_macro_expansion", - "macro_arg", + "MacroCallId::parse_macro_expansion_", + "MacroCallId::macro_arg_", "DeclarativeMacroExpander::expander_", "macro_def_shim", "file_item_tree_query", "ast_id_map", - "parse_macro_expansion", - "macro_arg", + "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", + "MacroCallId::parse_macro_expansion_", + "MacroCallId::expand_proc_macro_", + "MacroCallId::macro_arg_", "proc_macro_span", ] "#]], @@ -450,10 +450,10 @@ pub struct S {} "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_", ] "#]], ); @@ -538,16 +538,16 @@ m!(Z); "macro_def_shim", "file_item_tree_query", "ast_id_map", - "parse_macro_expansion", - "macro_arg", + "MacroCallId::parse_macro_expansion_", + "MacroCallId::macro_arg_", "file_item_tree_query", "ast_id_map", - "parse_macro_expansion", - "macro_arg", + "MacroCallId::parse_macro_expansion_", + "MacroCallId::macro_arg_", "file_item_tree_query", "ast_id_map", - "parse_macro_expansion", - "macro_arg", + "MacroCallId::parse_macro_expansion_", + "MacroCallId::macro_arg_", ] "#]], ); @@ -575,9 +575,9 @@ m!(Z); "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_", ] "#]], ); 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 ffa64fe01b..c8a8be4311 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 syntax::{AstNode, Parse, 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, @@ -22,17 +18,6 @@ use crate::{ tt, }; -/// This is just to ensure the types of [`macro_arg_considering_derives`] 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> { /// Old-style `macro_rules` or the new macros 2.0 @@ -62,13 +47,6 @@ pub trait ExpandDatabase: SourceDatabase { #[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<'_>; @@ -80,21 +58,6 @@ pub trait ExpandDatabase: SourceDatabase { #[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)] @@ -108,13 +71,6 @@ 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 { @@ -135,7 +91,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); @@ -243,7 +199,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( @@ -273,13 +229,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 @@ -298,13 +255,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)) @@ -316,38 +266,11 @@ 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() + macro_file.parse_macro_expansion(db).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, @@ -357,146 +280,12 @@ pub(crate) fn parse_with_map( (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; + let (parse, map) = ¯o_file.parse_macro_expansion(db).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 { @@ -512,178 +301,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/eager.rs b/crates/hir-expand/src/eager.rs index f8a560834a..30e9624b2b 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)) } @@ -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..5f03e1b6b3 100644 --- a/crates/hir-expand/src/files.rs +++ b/crates/hir-expand/src/files.rs @@ -213,7 +213,7 @@ 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 { diff --git a/crates/hir-expand/src/lib.rs b/crates/hir-expand/src/lib.rs index a8933a424e..73647d0ece 100644 --- a/crates/hir-expand/src/lib.rs +++ b/crates/hir-expand/src/lib.rs @@ -33,17 +33,19 @@ use thin_vec::ThinVec; use triomphe::Arc; use core::fmt; -use std::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, }; 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,7 +53,10 @@ use crate::{ BuiltinAttrExpander, BuiltinDeriveExpander, BuiltinFnLikeExpander, EagerExpander, include_input_to_file_id, }, + cfg_process::attr_macro_input_to_token_tree, db::ExpandDatabase, + 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}, }; @@ -66,6 +71,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) => { @@ -467,6 +484,357 @@ impl MacroCallId { } } +#[salsa::tracked] +impl MacroCallId { + /// Implementation of [`crate::db::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) = crate::db::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) + } + + 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 = 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, ()) +} + +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, @@ -862,7 +1230,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 } @@ -1073,7 +1441,7 @@ 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 } } } diff --git a/crates/hir-expand/src/span_map.rs b/crates/hir-expand/src/span_map.rs index 6a94df8b5a..d19eead4a8 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) } } } @@ -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/src/lib.rs b/crates/hir/src/lib.rs index 8d21b351e4..ceac3f0876 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -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; diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs index dcbd6c37af..8fc08abef1 100644 --- a/crates/hir/src/semantics.rs +++ b/crates/hir/src/semantics.rs @@ -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() }) @@ -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> { |