From bbbcfaab8be7cc5fdcbf8e208eafa1de5446b094 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Wed, 28 May 2025 06:56:48 +0200 Subject: [PATCH 1/3] fix: Fix IDE layer not resolving some macro calls --- crates/hir-def/src/nameres/assoc.rs | 4 +- crates/hir/src/semantics.rs | 32 +++------------ crates/hir/src/semantics/child_by_source.rs | 19 ++++++--- crates/ide/src/expand_macro.rs | 40 +++++++++++++++++++ .../rust-analyzer/src/cli/analysis_stats.rs | 2 +- 5 files changed, 62 insertions(+), 35 deletions(-) diff --git a/crates/hir-def/src/nameres/assoc.rs b/crates/hir-def/src/nameres/assoc.rs index d45709b8b9..86225d33b4 100644 --- a/crates/hir-def/src/nameres/assoc.rs +++ b/crates/hir-def/src/nameres/assoc.rs @@ -75,7 +75,7 @@ impl TraitItems { }) } - pub fn attribute_calls(&self) -> impl Iterator, MacroCallId)> + '_ { + pub fn macro_calls(&self) -> impl Iterator, MacroCallId)> + '_ { self.macro_calls.iter().flat_map(|it| it.iter()).copied() } } @@ -109,7 +109,7 @@ impl ImplItems { (Arc::new(ImplItems { items, macro_calls }), DefDiagnostics::new(diagnostics)) } - pub fn attribute_calls(&self) -> impl Iterator, MacroCallId)> + '_ { + pub fn macro_calls(&self) -> impl Iterator, MacroCallId)> + '_ { self.macro_calls.iter().flat_map(|it| it.iter()).copied() } } diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs index 117d9c4920..5823f6260b 100644 --- a/crates/hir/src/semantics.rs +++ b/crates/hir/src/semantics.rs @@ -408,11 +408,7 @@ impl<'db> SemanticsImpl<'db> { } pub fn expand_macro_call(&self, macro_call: &ast::MacroCall) -> Option> { - let sa = self.analyze_no_infer(macro_call.syntax())?; - - let macro_call = InFile::new(sa.file_id, macro_call); - let file_id = sa.expansion(self.db, macro_call)?; - + let file_id = self.to_def(macro_call)?; let node = self.parse_or_expand(file_id.into()); Some(InFile::new(file_id.into(), node)) } @@ -434,10 +430,7 @@ impl<'db> SemanticsImpl<'db> { &self, macro_call: &ast::MacroCall, ) -> Option> { - let sa = self.analyze_no_infer(macro_call.syntax())?; - - let macro_call = InFile::new(sa.file_id, macro_call); - let file_id = sa.expansion(self.db, macro_call)?; + let file_id = self.to_def(macro_call)?; let macro_call = self.db.lookup_intern_macro_call(file_id); let skip = matches!( @@ -1097,16 +1090,7 @@ impl<'db> SemanticsImpl<'db> { let file_id = match m_cache.get(&mcall) { Some(&it) => it, None => { - let it = token - .parent() - .and_then(|parent| { - self.analyze_impl( - InFile::new(expansion, &parent), - None, - false, - ) - })? - .expansion(self.db, mcall.as_ref())?; + let it = ast::MacroCall::to_def(self, mcall.as_ref())?; m_cache.insert(mcall, it); it } @@ -1562,14 +1546,8 @@ impl<'db> SemanticsImpl<'db> { } pub fn resolve_macro_call_arm(&self, macro_call: &ast::MacroCall) -> Option { - let sa = self.analyze(macro_call.syntax())?; - self.db - .parse_macro_expansion( - sa.expansion(self.db, self.wrap_node_infile(macro_call.clone()).as_ref())?, - ) - .value - .1 - .matched_arm + let file_id = self.to_def(macro_call)?; + self.db.parse_macro_expansion(file_id).value.1.matched_arm } pub fn get_unsafe_ops(&self, def: DefWithBody) -> FxHashSet { diff --git a/crates/hir/src/semantics/child_by_source.rs b/crates/hir/src/semantics/child_by_source.rs index 9393d08ad3..6accf9b2e9 100644 --- a/crates/hir/src/semantics/child_by_source.rs +++ b/crates/hir/src/semantics/child_by_source.rs @@ -36,9 +36,14 @@ impl ChildBySource for TraitId { fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap, file_id: HirFileId) { let data = db.trait_items(*self); - data.attribute_calls().filter(|(ast_id, _)| ast_id.file_id == file_id).for_each( + data.macro_calls().filter(|(ast_id, _)| ast_id.file_id == file_id).for_each( |(ast_id, call_id)| { - res[keys::ATTR_MACRO_CALL].insert(ast_id.to_ptr(db), call_id); + let ptr = ast_id.to_ptr(db); + if let Some(ptr) = ptr.cast::() { + res[keys::MACRO_CALL].insert(ptr, call_id); + } else { + res[keys::ATTR_MACRO_CALL].insert(ptr, call_id); + } }, ); data.items.iter().for_each(|&(_, item)| { @@ -50,10 +55,14 @@ impl ChildBySource for TraitId { impl ChildBySource for ImplId { fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap, file_id: HirFileId) { let data = db.impl_items(*self); - // FIXME: Macro calls - data.attribute_calls().filter(|(ast_id, _)| ast_id.file_id == file_id).for_each( + data.macro_calls().filter(|(ast_id, _)| ast_id.file_id == file_id).for_each( |(ast_id, call_id)| { - res[keys::ATTR_MACRO_CALL].insert(ast_id.to_ptr(db), call_id); + let ptr = ast_id.to_ptr(db); + if let Some(ptr) = ptr.cast::() { + res[keys::MACRO_CALL].insert(ptr, call_id); + } else { + res[keys::ATTR_MACRO_CALL].insert(ptr, call_id); + } }, ); data.items.iter().for_each(|&(_, item)| { diff --git a/crates/ide/src/expand_macro.rs b/crates/ide/src/expand_macro.rs index 9beed2cac1..f8f9378b9e 100644 --- a/crates/ide/src/expand_macro.rs +++ b/crates/ide/src/expand_macro.rs @@ -719,4 +719,44 @@ __log!(written:%; "Test"$0); "#]], ); } + + #[test] + fn assoc_call() { + check( + r#" +macro_rules! mac { + () => { fn assoc() {} } +} +impl () { + mac$0!(); +} + "#, + expect![[r#" + mac! + fn assoc(){}"#]], + ); + } + + #[test] + fn eager() { + check( + r#" +//- minicore: concat +macro_rules! my_concat { + ($head:expr, $($tail:tt)*) => { concat!($head, $($tail)*) }; +} + + +fn test() { + _ = my_concat!( + conc$0at!("<", ">"), + "hi", + ); +} + "#, + expect![[r#" + my_concat! + "<>hi""#]], + ); + } } diff --git a/crates/rust-analyzer/src/cli/analysis_stats.rs b/crates/rust-analyzer/src/cli/analysis_stats.rs index 671e838421..12b393b80c 100644 --- a/crates/rust-analyzer/src/cli/analysis_stats.rs +++ b/crates/rust-analyzer/src/cli/analysis_stats.rs @@ -1023,7 +1023,7 @@ impl flags::AnalysisStats { percentage(num_pats_partially_unknown, num_pats), num_pat_type_mismatches ); - eprintln!(" panics: {}", panics); + eprintln!(" panics: {panics}"); eprintln!("{:<20} {}", "Inference:", inference_time); report_metric("unknown type", num_exprs_unknown, "#"); report_metric("type mismatches", num_expr_type_mismatches, "#"); From 5b28e9022e6f3f89a2ae44d0f8f1c9ee08438f5a Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Wed, 28 May 2025 07:05:48 +0200 Subject: [PATCH 2/3] Drop unnecessay code --- crates/hir/src/semantics.rs | 7 +------ crates/hir/src/source_analyzer.rs | 31 ++----------------------------- 2 files changed, 3 insertions(+), 35 deletions(-) diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs index 5823f6260b..0dac64d6f2 100644 --- a/crates/hir/src/semantics.rs +++ b/crates/hir/src/semantics.rs @@ -567,9 +567,7 @@ impl<'db> SemanticsImpl<'db> { speculative_args: &ast::TokenTree, token_to_map: SyntaxToken, ) -> Option<(SyntaxNode, Vec<(SyntaxToken, u8)>)> { - let analyzer = self.analyze_no_infer(actual_macro_call.syntax())?; - let macro_call = InFile::new(analyzer.file_id, actual_macro_call); - let macro_file = analyzer.expansion(self.db, macro_call)?; + let macro_file = self.to_def(actual_macro_call)?; hir_expand::db::expand_speculative( self.db, macro_file, @@ -1535,9 +1533,6 @@ impl<'db> SemanticsImpl<'db> { .and_then(|call| macro_call_to_macro_id(ctx, call)) .map(Into::into) }) - .or_else(|| { - self.analyze(macro_call.value.syntax())?.resolve_macro_call(self.db, macro_call) - }) } pub fn is_proc_macro_call(&self, macro_call: InFile<&ast::MacroCall>) -> bool { diff --git a/crates/hir/src/source_analyzer.rs b/crates/hir/src/source_analyzer.rs index be58129215..d22812d3c6 100644 --- a/crates/hir/src/source_analyzer.rs +++ b/crates/hir/src/source_analyzer.rs @@ -26,12 +26,12 @@ use hir_def::{ }, hir::{BindingId, Expr, ExprId, ExprOrPatId, Pat}, lang_item::LangItem, - nameres::{MacroSubNs, block_def_map, crate_def_map}, + nameres::MacroSubNs, resolver::{HasResolver, Resolver, TypeNs, ValueNs, resolver_for_scope}, type_ref::{Mutability, TypeRefId}, }; use hir_expand::{ - HirFileId, InFile, MacroCallId, + HirFileId, InFile, mod_path::{ModPath, PathKind, path}, name::{AsName, Name}, }; @@ -218,18 +218,6 @@ impl<'db> SourceAnalyzer<'db> { }) } - pub(crate) fn expansion( - &self, - db: &dyn HirDatabase, - macro_call: InFile<&ast::MacroCall>, - ) -> Option { - self.store_sm().and_then(|sm| sm.expansion(macro_call)).or_else(|| { - let ast_id_map = db.ast_id_map(macro_call.file_id); - let call_ast_id = macro_call.with_value(ast_id_map.ast_id(macro_call.value)); - self.resolver.item_scopes().find_map(|scope| scope.macro_invoc(call_ast_id)) - }) - } - fn trait_environment(&self, db: &'db dyn HirDatabase) -> Arc { self.body_().map(|(def, ..)| def).map_or_else( || TraitEnvironment::empty(self.resolver.krate()), @@ -753,21 +741,6 @@ impl<'db> SourceAnalyzer<'db> { )) } - pub(crate) fn resolve_macro_call( - &self, - db: &dyn HirDatabase, - macro_call: InFile<&ast::MacroCall>, - ) -> Option { - self.expansion(db, macro_call).and_then(|it| { - let def = it.lookup(db).def; - let def_map = match def.block { - Some(block) => block_def_map(db, base_db::salsa::plumbing::FromId::from_id(block)), - None => crate_def_map(db, def.krate), - }; - def_map.macro_def_to_macro_id.get(&def.kind.erased_ast_id()).map(|it| (*it).into()) - }) - } - pub(crate) fn resolve_bind_pat_to_const( &self, db: &'db dyn HirDatabase, From 6440fe2a01b4e8db9c06332b8fc3ee5d406037ac Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Wed, 28 May 2025 07:06:03 +0200 Subject: [PATCH 3/3] Back out "Fix IDE resolution of item macros" This backs out commit 3e0ab7219a5464999652beca22698cd46e1e48e8. --- crates/hir-def/src/db.rs | 3 --- crates/hir-def/src/resolver.rs | 9 --------- crates/hir-expand/src/lib.rs | 2 -- 3 files changed, 14 deletions(-) diff --git a/crates/hir-def/src/db.rs b/crates/hir-def/src/db.rs index 6f9340a0e4..4a9a3b12cf 100644 --- a/crates/hir-def/src/db.rs +++ b/crates/hir-def/src/db.rs @@ -422,7 +422,6 @@ fn macro_def(db: &dyn DefDatabase, id: MacroId) -> MacroDefId { let makro = &item_tree[loc.id.value]; MacroDefId { krate: loc.container.krate, - block: loc.container.block.map(|block| salsa::plumbing::AsId::as_id(&block)), kind: kind(loc.expander, loc.id.file_id(), makro.ast_id.upcast()), local_inner: false, allow_internal_unsafe: loc.allow_internal_unsafe, @@ -436,7 +435,6 @@ fn macro_def(db: &dyn DefDatabase, id: MacroId) -> MacroDefId { let makro = &item_tree[loc.id.value]; MacroDefId { krate: loc.container.krate, - block: loc.container.block.map(|block| salsa::plumbing::AsId::as_id(&block)), kind: kind(loc.expander, loc.id.file_id(), makro.ast_id.upcast()), local_inner: loc.flags.contains(MacroRulesLocFlags::LOCAL_INNER), allow_internal_unsafe: loc @@ -452,7 +450,6 @@ fn macro_def(db: &dyn DefDatabase, id: MacroId) -> MacroDefId { let makro = &item_tree[loc.id.value]; MacroDefId { krate: loc.container.krate, - block: None, kind: MacroDefKind::ProcMacro( InFile::new(loc.id.file_id(), makro.ast_id), loc.expander, diff --git a/crates/hir-def/src/resolver.rs b/crates/hir-def/src/resolver.rs index 416bcbb096..16988ddf04 100644 --- a/crates/hir-def/src/resolver.rs +++ b/crates/hir-def/src/resolver.rs @@ -696,15 +696,6 @@ impl<'db> Resolver<'db> { &def_map[local_id].scope } - pub fn item_scopes(&self) -> impl Iterator { - self.scopes() - .filter_map(move |scope| match scope { - Scope::BlockScope(m) => Some(&m.def_map[m.module_id].scope), - _ => None, - }) - .chain(std::iter::once(&self.module_scope.def_map[self.module_scope.module_id].scope)) - } - pub fn krate(&self) -> Crate { self.module_scope.def_map.krate() } diff --git a/crates/hir-expand/src/lib.rs b/crates/hir-expand/src/lib.rs index 19cd0298e9..d844d8f41e 100644 --- a/crates/hir-expand/src/lib.rs +++ b/crates/hir-expand/src/lib.rs @@ -258,8 +258,6 @@ pub struct MacroCallLoc { #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct MacroDefId { pub krate: Crate, - // FIXME: In `hir-expand` we can't refer to `BlockId`. - pub block: Option, pub edition: Edition, pub kind: MacroDefKind, pub local_inner: bool,