Skip to content

Commit 372f3f3

Browse files
authored
Merge pull request rust-lang#19731 from Veykril/push-mmvowomkpwxy
refactor: Simplify macro call id construction
2 parents 3686ed9 + a8fb9d0 commit 372f3f3

File tree

8 files changed

+113
-175
lines changed

8 files changed

+113
-175
lines changed

src/tools/rust-analyzer/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@ process-wrap = { version = "8.2.0", features = ["std"] }
131131
pulldown-cmark-to-cmark = "10.0.4"
132132
pulldown-cmark = { version = "0.9.6", default-features = false }
133133
rayon = "1.10.0"
134+
rowan = "=0.15.15"
134135
salsa = { version = "0.21.1", default-features = false, features = ["rayon","salsa_unstable"] }
135136
salsa-macros = "0.21.1"
136137
semver = "1.0.26"

src/tools/rust-analyzer/crates/hir-def/src/expr_store/expander.rs

+28-3
Original file line numberDiff line numberDiff line change
@@ -5,20 +5,22 @@ use std::mem;
55
use base_db::Crate;
66
use cfg::CfgOptions;
77
use drop_bomb::DropBomb;
8+
use hir_expand::AstId;
89
use hir_expand::{
910
ExpandError, ExpandErrorKind, ExpandResult, HirFileId, InFile, Lookup, MacroCallId,
1011
eager::EagerCallBackFn, mod_path::ModPath, span_map::SpanMap,
1112
};
1213
use span::{AstIdMap, Edition, SyntaxContext};
1314
use syntax::ast::HasAttrs;
14-
use syntax::{Parse, ast};
15+
use syntax::{AstNode, Parse, ast};
1516
use triomphe::Arc;
1617
use tt::TextRange;
1718

1819
use crate::attr::Attrs;
1920
use crate::expr_store::HygieneId;
21+
use crate::macro_call_as_call_id;
2022
use crate::nameres::DefMap;
21-
use crate::{AsMacroCall, MacroId, UnresolvedMacro, db::DefDatabase};
23+
use crate::{MacroId, UnresolvedMacro, db::DefDatabase};
2224

2325
#[derive(Debug)]
2426
pub(super) struct Expander {
@@ -92,8 +94,31 @@ impl Expander {
9294

9395
let result = self.within_limit(db, |this| {
9496
let macro_call = this.in_file(&macro_call);
95-
match macro_call.as_call_id_with_errors(
97+
98+
let expands_to = hir_expand::ExpandTo::from_call_site(macro_call.value);
99+
let ast_id = AstId::new(macro_call.file_id, this.ast_id_map().ast_id(macro_call.value));
100+
let path = macro_call.value.path().and_then(|path| {
101+
let range = path.syntax().text_range();
102+
let mod_path = ModPath::from_src(db, path, &mut |range| {
103+
this.span_map.span_for_range(range).ctx
104+
})?;
105+
let call_site = this.span_map.span_for_range(range);
106+
Some((call_site, mod_path))
107+
});
108+
109+
let Some((call_site, path)) = path else {
110+
return ExpandResult::only_err(ExpandError::other(
111+
this.span_map.span_for_range(macro_call.value.syntax().text_range()),
112+
"malformed macro invocation",
113+
));
114+
};
115+
116+
match macro_call_as_call_id(
96117
db,
118+
ast_id,
119+
&path,
120+
call_site.ctx,
121+
expands_to,
97122
krate,
98123
|path| resolver(path).map(|it| db.macro_def(it)),
99124
eager_callback,

src/tools/rust-analyzer/crates/hir-def/src/lib.rs

+6-93
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,8 @@ use std::hash::{Hash, Hasher};
6464

6565
use base_db::{Crate, impl_intern_key};
6666
use hir_expand::{
67-
AstId, ExpandError, ExpandResult, ExpandTo, HirFileId, InFile, MacroCallId, MacroCallKind,
68-
MacroDefId, MacroDefKind,
67+
AstId, ExpandResult, ExpandTo, HirFileId, InFile, MacroCallId, MacroCallKind, MacroDefId,
68+
MacroDefKind,
6969
builtin::{BuiltinAttrExpander, BuiltinDeriveExpander, BuiltinFnLikeExpander, EagerExpander},
7070
db::ExpandDatabase,
7171
eager::expand_eager_macro_input,
@@ -79,7 +79,7 @@ use la_arena::Idx;
7979
use nameres::DefMap;
8080
use span::{AstIdNode, Edition, FileAstId, SyntaxContext};
8181
use stdx::impl_from;
82-
use syntax::{AstNode, ast};
82+
use syntax::ast;
8383

8484
pub use hir_expand::{Intern, Lookup, tt};
8585

@@ -1166,66 +1166,6 @@ impl ModuleDefId {
11661166
})
11671167
}
11681168
}
1169-
1170-
// FIXME: Replace this with a plain function, it only has one impl
1171-
/// A helper trait for converting to MacroCallId
1172-
trait AsMacroCall {
1173-
fn as_call_id_with_errors(
1174-
&self,
1175-
db: &dyn ExpandDatabase,
1176-
krate: Crate,
1177-
resolver: impl Fn(&ModPath) -> Option<MacroDefId> + Copy,
1178-
eager_callback: &mut dyn FnMut(
1179-
InFile<(syntax::AstPtr<ast::MacroCall>, span::FileAstId<ast::MacroCall>)>,
1180-
MacroCallId,
1181-
),
1182-
) -> Result<ExpandResult<Option<MacroCallId>>, UnresolvedMacro>;
1183-
}
1184-
1185-
impl AsMacroCall for InFile<&ast::MacroCall> {
1186-
fn as_call_id_with_errors(
1187-
&self,
1188-
db: &dyn ExpandDatabase,
1189-
krate: Crate,
1190-
resolver: impl Fn(&ModPath) -> Option<MacroDefId> + Copy,
1191-
eager_callback: &mut dyn FnMut(
1192-
InFile<(syntax::AstPtr<ast::MacroCall>, span::FileAstId<ast::MacroCall>)>,
1193-
MacroCallId,
1194-
),
1195-
) -> Result<ExpandResult<Option<MacroCallId>>, UnresolvedMacro> {
1196-
let expands_to = hir_expand::ExpandTo::from_call_site(self.value);
1197-
let ast_id = AstId::new(self.file_id, db.ast_id_map(self.file_id).ast_id(self.value));
1198-
let span_map = db.span_map(self.file_id);
1199-
let path = self.value.path().and_then(|path| {
1200-
let range = path.syntax().text_range();
1201-
let mod_path = ModPath::from_src(db, path, &mut |range| {
1202-
span_map.as_ref().span_for_range(range).ctx
1203-
})?;
1204-
let call_site = span_map.span_for_range(range);
1205-
Some((call_site, mod_path))
1206-
});
1207-
1208-
let Some((call_site, path)) = path else {
1209-
return Ok(ExpandResult::only_err(ExpandError::other(
1210-
span_map.span_for_range(self.value.syntax().text_range()),
1211-
"malformed macro invocation",
1212-
)));
1213-
};
1214-
1215-
macro_call_as_call_id_with_eager(
1216-
db,
1217-
ast_id,
1218-
&path,
1219-
call_site.ctx,
1220-
expands_to,
1221-
krate,
1222-
resolver,
1223-
resolver,
1224-
eager_callback,
1225-
)
1226-
}
1227-
}
1228-
12291169
/// Helper wrapper for `AstId` with `ModPath`
12301170
#[derive(Clone, Debug, Eq, PartialEq)]
12311171
struct AstIdWithPath<T: AstIdNode> {
@@ -1239,41 +1179,14 @@ impl<T: AstIdNode> AstIdWithPath<T> {
12391179
}
12401180
}
12411181

1242-
fn macro_call_as_call_id(
1243-
db: &dyn ExpandDatabase,
1244-
call: &AstIdWithPath<ast::MacroCall>,
1245-
call_site: SyntaxContext,
1246-
expand_to: ExpandTo,
1247-
krate: Crate,
1248-
resolver: impl Fn(&ModPath) -> Option<MacroDefId> + Copy,
1249-
eager_callback: &mut dyn FnMut(
1250-
InFile<(syntax::AstPtr<ast::MacroCall>, span::FileAstId<ast::MacroCall>)>,
1251-
MacroCallId,
1252-
),
1253-
) -> Result<Option<MacroCallId>, UnresolvedMacro> {
1254-
macro_call_as_call_id_with_eager(
1255-
db,
1256-
call.ast_id,
1257-
&call.path,
1258-
call_site,
1259-
expand_to,
1260-
krate,
1261-
resolver,
1262-
resolver,
1263-
eager_callback,
1264-
)
1265-
.map(|res| res.value)
1266-
}
1267-
1268-
fn macro_call_as_call_id_with_eager(
1182+
pub fn macro_call_as_call_id(
12691183
db: &dyn ExpandDatabase,
12701184
ast_id: AstId<ast::MacroCall>,
12711185
path: &ModPath,
12721186
call_site: SyntaxContext,
12731187
expand_to: ExpandTo,
12741188
krate: Crate,
1275-
resolver: impl FnOnce(&ModPath) -> Option<MacroDefId>,
1276-
eager_resolver: impl Fn(&ModPath) -> Option<MacroDefId>,
1189+
resolver: impl Fn(&ModPath) -> Option<MacroDefId> + Copy,
12771190
eager_callback: &mut dyn FnMut(
12781191
InFile<(syntax::AstPtr<ast::MacroCall>, span::FileAstId<ast::MacroCall>)>,
12791192
MacroCallId,
@@ -1289,7 +1202,7 @@ fn macro_call_as_call_id_with_eager(
12891202
ast_id,
12901203
def,
12911204
call_site,
1292-
&|path| eager_resolver(path).filter(MacroDefId::is_fn_like),
1205+
&|path| resolver(path).filter(MacroDefId::is_fn_like),
12931206
eager_callback,
12941207
),
12951208
_ if def.is_fn_like() => ExpandResult {

src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe.rs

+6-4
Original file line numberDiff line numberDiff line change
@@ -2001,8 +2001,9 @@ macro_rules! bug {
20012001
true
20022002
};
20032003
}
2004-
2005-
let _ = bug!(a;;;test);
2004+
fn f() {
2005+
let _ = bug!(a;;;test);
2006+
}
20062007
"#,
20072008
expect![[r#"
20082009
macro_rules! bug {
@@ -2022,8 +2023,9 @@ macro_rules! bug {
20222023
true
20232024
};
20242025
}
2025-
2026-
let _ = true;
2026+
fn f() {
2027+
let _ = true;
2028+
}
20272029
"#]],
20282030
);
20292031
}

src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mod.rs

+44-41
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ use std::{iter, ops::Range, sync};
1919
use base_db::RootQueryDb;
2020
use expect_test::Expect;
2121
use hir_expand::{
22-
InFile, MacroCallKind, MacroKind,
22+
AstId, InFile, MacroCallId, MacroCallKind, MacroKind,
2323
db::ExpandDatabase,
2424
proc_macro::{ProcMacro, ProcMacroExpander, ProcMacroExpansionError, ProcMacroKind},
2525
span_map::SpanMapRef,
@@ -29,18 +29,17 @@ use itertools::Itertools;
2929
use span::{Edition, Span};
3030
use stdx::{format_to, format_to_acc};
3131
use syntax::{
32-
AstNode,
32+
AstNode, AstPtr,
3333
SyntaxKind::{COMMENT, EOF, IDENT, LIFETIME_IDENT},
3434
SyntaxNode, T,
3535
ast::{self, edit::IndentLevel},
3636
};
3737
use test_fixture::WithFixture;
3838

3939
use crate::{
40-
AdtId, AsMacroCall, Lookup, ModuleDefId,
40+
AdtId, Lookup, ModuleDefId,
4141
db::DefDatabase,
42-
nameres::{DefMap, MacroSubNs, ModuleSource},
43-
resolver::HasResolver,
42+
nameres::{DefMap, ModuleSource},
4443
src::HasSource,
4544
test_db::TestDB,
4645
tt::TopSubtree,
@@ -78,7 +77,6 @@ fn check_errors(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect)
7877
expect.assert_eq(&errors);
7978
}
8079

81-
#[track_caller]
8280
fn check(#[rust_analyzer::rust_fixture] ra_fixture: &str, mut expect: Expect) {
8381
let extra_proc_macros = vec![(
8482
r#"
@@ -95,54 +93,59 @@ pub fn identity_when_valid(_attr: TokenStream, item: TokenStream) -> TokenStream
9593
disabled: false,
9694
},
9795
)];
96+
97+
fn resolve(
98+
db: &dyn DefDatabase,
99+
def_map: &DefMap,
100+
ast_id: AstId<ast::MacroCall>,
101+
ast_ptr: InFile<AstPtr<ast::MacroCall>>,
102+
) -> Option<MacroCallId> {
103+
def_map.modules().find_map(|module| {
104+
for decl in
105+
module.1.scope.declarations().chain(module.1.scope.unnamed_consts().map(Into::into))
106+
{
107+
let body = match decl {
108+
ModuleDefId::FunctionId(it) => it.into(),
109+
ModuleDefId::ConstId(it) => it.into(),
110+
ModuleDefId::StaticId(it) => it.into(),
111+
_ => continue,
112+
};
113+
114+
let (body, sm) = db.body_with_source_map(body);
115+
if let Some(it) =
116+
body.blocks(db).find_map(|block| resolve(db, &block.1, ast_id, ast_ptr))
117+
{
118+
return Some(it);
119+
}
120+
if let Some((_, res)) = sm.macro_calls().find(|it| it.0 == ast_ptr) {
121+
return Some(res);
122+
}
123+
}
124+
module.1.scope.macro_invoc(ast_id)
125+
})
126+
}
127+
98128
let db = TestDB::with_files_extra_proc_macros(ra_fixture, extra_proc_macros);
99129
let krate = db.fetch_test_crate();
100130
let def_map = db.crate_def_map(krate);
101131
let local_id = DefMap::ROOT;
102-
let module = def_map.module_id(local_id);
103-
let resolver = module.resolver(&db);
104132
let source = def_map[local_id].definition_source(&db);
105133
let source_file = match source.value {
106134
ModuleSource::SourceFile(it) => it,
107135
ModuleSource::Module(_) | ModuleSource::BlockExpr(_) => panic!(),
108136
};
109137

110-
// What we want to do is to replace all macros (fn-like, derive, attr) with
111-
// their expansions. Turns out, we don't actually store enough information
112-
// to do this precisely though! Specifically, if a macro expands to nothing,
113-
// it leaves zero traces in def-map, so we can't get its expansion after the
114-
// fact.
115-
//
116-
// This is the usual
117-
// <https://github.com/rust-lang/rust-analyzer/issues/3407>
118-
// resolve/record tension!
119-
//
120-
// So here we try to do a resolve, which is necessary a heuristic. For macro
121-
// calls, we use `as_call_id_with_errors`. For derives, we look at the impls
122-
// in the module and assume that, if impls's source is a different
123-
// `HirFileId`, than it came from macro expansion.
124-
125138
let mut text_edits = Vec::new();
126139
let mut expansions = Vec::new();
127140

128-
for macro_call in source_file.syntax().descendants().filter_map(ast::MacroCall::cast) {
129-
let macro_call = InFile::new(source.file_id, &macro_call);
130-
let res = macro_call
131-
.as_call_id_with_errors(
132-
&db,
133-
krate,
134-
|path| {
135-
resolver
136-
.resolve_path_as_macro(&db, path, Some(MacroSubNs::Bang))
137-
.map(|(it, _)| db.macro_def(it))
138-
},
139-
&mut |_, _| (),
140-
)
141-
.unwrap();
142-
let macro_call_id = res.value.unwrap();
143-
let mut expansion_result = db.parse_macro_expansion(macro_call_id);
144-
expansion_result.err = expansion_result.err.or(res.err);
145-
expansions.push((macro_call.value.clone(), expansion_result));
141+
for macro_call_node in source_file.syntax().descendants().filter_map(ast::MacroCall::cast) {
142+
let ast_id = db.ast_id_map(source.file_id).ast_id(&macro_call_node);
143+
let ast_id = InFile::new(source.file_id, ast_id);
144+
let ptr = InFile::new(source.file_id, AstPtr::new(&macro_call_node));
145+
let macro_call_id = resolve(&db, &def_map, ast_id, ptr)
146+
.unwrap_or_else(|| panic!("unable to find semantic macro call {macro_call_node}"));
147+
let expansion_result = db.parse_macro_expansion(macro_call_id);
148+
expansions.push((macro_call_node.clone(), expansion_result));
146149
}
147150

148151
for (call, exp) in expansions.into_iter().rev() {

src/tools/rust-analyzer/crates/hir-def/src/nameres/assoc.rs

+11-7
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,8 @@ impl<'a> AssocItemCollector<'a> {
259259
};
260260
match macro_call_as_call_id(
261261
self.db,
262-
&AstIdWithPath::new(tree_id.file_id(), ast_id, Clone::clone(path)),
262+
InFile::new(tree_id.file_id(), ast_id),
263+
path,
263264
ctxt,
264265
expand_to,
265266
self.module_id.krate(),
@@ -268,12 +269,15 @@ impl<'a> AssocItemCollector<'a> {
268269
self.macro_calls.push((ptr.map(|(_, it)| it.upcast()), call_id))
269270
},
270271
) {
271-
Ok(Some(call_id)) => {
272-
self.macro_calls
273-
.push((InFile::new(tree_id.file_id(), ast_id.upcast()), call_id));
274-
self.collect_macro_items(call_id);
275-
}
276-
Ok(None) => (),
272+
// FIXME: Expansion error?
273+
Ok(call_id) => match call_id.value {
274+
Some(call_id) => {
275+
self.macro_calls
276+
.push((InFile::new(tree_id.file_id(), ast_id.upcast()), call_id));
277+
self.collect_macro_items(call_id);
278+
}
279+
None => (),
280+
},
277281
Err(_) => {
278282
self.diagnostics.push(DefDiagnostic::unresolved_macro_call(
279283
self.module_id.local_id,

0 commit comments

Comments
 (0)