Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit 0f4ffaa

Browse files
committed
Fix duplicate eager expansion errors
1 parent d1632c2 commit 0f4ffaa

File tree

10 files changed

+70
-50
lines changed

10 files changed

+70
-50
lines changed

crates/hir-def/src/data.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -638,7 +638,6 @@ impl<'a> AssocItemCollector<'a> {
638638
self.items.push((item.name.clone(), def.into()));
639639
}
640640
AssocItem::MacroCall(call) => {
641-
// TODO: These are the wrong errors to report, report in collect_macro_items instead
642641
let file_id = self.expander.current_file_id();
643642
let root = self.db.parse_or_expand(file_id);
644643
if let Some(root) = root {

crates/hir-def/src/item_tree.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ pub struct ItemTree {
101101
top_level: SmallVec<[ModItem; 1]>,
102102
attrs: FxHashMap<AttrOwner, RawAttrs>,
103103

104+
// FIXME: Remove this indirection, an item tree is almost always non-empty?
104105
data: Option<Box<ItemTreeData>>,
105106
}
106107

crates/hir-def/src/lib.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -823,7 +823,7 @@ impl AsMacroCall for InFile<&ast::MacroCall> {
823823
return Ok(ExpandResult::only_err(ExpandError::Other("malformed macro invocation".into())));
824824
};
825825

826-
macro_call_as_call_id(
826+
macro_call_as_call_id_(
827827
db,
828828
&AstIdWithPath::new(ast_id.file_id, ast_id.value, path),
829829
expands_to,
@@ -852,6 +852,16 @@ fn macro_call_as_call_id(
852852
expand_to: ExpandTo,
853853
krate: CrateId,
854854
resolver: impl Fn(path::ModPath) -> Option<MacroDefId>,
855+
) -> Result<Option<MacroCallId>, UnresolvedMacro> {
856+
macro_call_as_call_id_(db, call, expand_to, krate, resolver).map(|res| res.value)
857+
}
858+
859+
fn macro_call_as_call_id_(
860+
db: &dyn db::DefDatabase,
861+
call: &AstIdWithPath<ast::MacroCall>,
862+
expand_to: ExpandTo,
863+
krate: CrateId,
864+
resolver: impl Fn(path::ModPath) -> Option<MacroDefId>,
855865
) -> Result<ExpandResult<Option<MacroCallId>>, UnresolvedMacro> {
856866
let def =
857867
resolver(call.path.clone()).ok_or_else(|| UnresolvedMacro { path: call.path.clone() })?;

crates/hir-def/src/nameres/collector.rs

Lines changed: 25 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1117,8 +1117,9 @@ impl DefCollector<'_> {
11171117
self.def_map.krate,
11181118
resolver_def_id,
11191119
);
1120-
if let Ok(ExpandResult { value: Some(call_id), .. }) = call_id {
1120+
if let Ok(Some(call_id)) = call_id {
11211121
push_resolved(directive, call_id);
1122+
11221123
res = ReachedFixedPoint::No;
11231124
return false;
11241125
}
@@ -1354,26 +1355,30 @@ impl DefCollector<'_> {
13541355
let file_id = macro_call_id.as_file();
13551356

13561357
// First, fetch the raw expansion result for purposes of error reporting. This goes through
1357-
// `macro_expand_error` to avoid depending on the full expansion result (to improve
1358+
// `parse_macro_expansion_error` to avoid depending on the full expansion result (to improve
13581359
// incrementality).
1359-
let loc: MacroCallLoc = self.db.lookup_intern_macro_call(macro_call_id);
1360-
let err = self.db.macro_expand_error(macro_call_id);
1360+
let ExpandResult { value, err } = self.db.parse_macro_expansion_error(macro_call_id);
13611361
if let Some(err) = err {
1362+
let loc: MacroCallLoc = self.db.lookup_intern_macro_call(macro_call_id);
13621363
let diag = match err {
1364+
// why is this reported here?
13631365
hir_expand::ExpandError::UnresolvedProcMacro(krate) => {
13641366
always!(krate == loc.def.krate);
1365-
// Missing proc macros are non-fatal, so they are handled specially.
13661367
DefDiagnostic::unresolved_proc_macro(module_id, loc.kind.clone(), loc.def.krate)
13671368
}
1368-
_ => DefDiagnostic::macro_error(module_id, loc.kind, err.to_string()),
1369+
_ => DefDiagnostic::macro_error(module_id, loc.kind.clone(), err.to_string()),
13691370
};
13701371

13711372
self.def_map.diagnostics.push(diag);
13721373
}
1374+
if let Some(errors) = value {
1375+
let loc: MacroCallLoc = self.db.lookup_intern_macro_call(macro_call_id);
1376+
let diag = DefDiagnostic::macro_expansion_parse_error(module_id, loc.kind, &errors);
1377+
self.def_map.diagnostics.push(diag);
1378+
}
13731379

13741380
// Then, fetch and process the item tree. This will reuse the expansion result from above.
13751381
let item_tree = self.db.file_item_tree(file_id);
1376-
// FIXME: report parse errors for the macro expansion here
13771382

13781383
let mod_dir = self.mod_dirs[&module_id].clone();
13791384
ModCollector {
@@ -1395,6 +1400,7 @@ impl DefCollector<'_> {
13951400
for directive in &self.unresolved_macros {
13961401
match &directive.kind {
13971402
MacroDirectiveKind::FnLike { ast_id, expand_to } => {
1403+
// FIXME: we shouldn't need to re-resolve the macro here just to get the unresolved error!
13981404
let macro_call_as_call_id = macro_call_as_call_id(
13991405
self.db,
14001406
ast_id,
@@ -2110,7 +2116,7 @@ impl ModCollector<'_, '_> {
21102116
let ast_id = AstIdWithPath::new(self.file_id(), mac.ast_id, ModPath::clone(&mac.path));
21112117

21122118
// Case 1: try to resolve in legacy scope and expand macro_rules
2113-
match macro_call_as_call_id(
2119+
if let Ok(res) = macro_call_as_call_id(
21142120
self.def_collector.db,
21152121
&ast_id,
21162122
mac.expand_to,
@@ -2131,29 +2137,18 @@ impl ModCollector<'_, '_> {
21312137
})
21322138
},
21332139
) {
2134-
Ok(res) => {
2135-
// Legacy macros need to be expanded immediately, so that any macros they produce
2136-
// are in scope.
2137-
if let Some(val) = res.value {
2138-
self.def_collector.collect_macro_expansion(
2139-
self.module_id,
2140-
val,
2141-
self.macro_depth + 1,
2142-
container,
2143-
);
2144-
}
2145-
2146-
if let Some(err) = res.err {
2147-
self.def_collector.def_map.diagnostics.push(DefDiagnostic::macro_error(
2148-
self.module_id,
2149-
MacroCallKind::FnLike { ast_id: ast_id.ast_id, expand_to: mac.expand_to },
2150-
err.to_string(),
2151-
));
2152-
}
2153-
2154-
return;
2140+
// Legacy macros need to be expanded immediately, so that any macros they produce
2141+
// are in scope.
2142+
if let Some(val) = res {
2143+
self.def_collector.collect_macro_expansion(
2144+
self.module_id,
2145+
val,
2146+
self.macro_depth + 1,
2147+
container,
2148+
);
21552149
}
2156-
Err(UnresolvedMacro { .. }) => (),
2150+
2151+
return;
21572152
}
21582153

21592154
// Case 2: resolve in module scope, expand during name resolution.

crates/hir-def/src/nameres/tests/incremental.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ m!(Z);
140140
let n_recalculated_item_trees = events.iter().filter(|it| it.contains("item_tree")).count();
141141
assert_eq!(n_recalculated_item_trees, 6);
142142
let n_reparsed_macros =
143-
events.iter().filter(|it| it.contains("parse_macro_expansion")).count();
143+
events.iter().filter(|it| it.contains("parse_macro_expansion(")).count();
144144
assert_eq!(n_reparsed_macros, 3);
145145
}
146146

crates/hir-expand/src/db.rs

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use mbe::syntax_node_to_token_tree;
99
use rustc_hash::FxHashSet;
1010
use syntax::{
1111
ast::{self, HasAttrs, HasDocComments},
12-
AstNode, GreenNode, Parse, SyntaxNode, SyntaxToken, T,
12+
AstNode, GreenNode, Parse, SyntaxError, SyntaxNode, SyntaxToken, T,
1313
};
1414

1515
use crate::{
@@ -132,15 +132,18 @@ pub trait ExpandDatabase: SourceDatabase {
132132
/// just fetches procedural ones.
133133
fn macro_def(&self, id: MacroDefId) -> Result<Arc<TokenExpander>, mbe::ParseError>;
134134

135-
/// Expand macro call to a token tree. This query is LRUed (we keep 128 or so results in memory)
135+
/// Expand macro call to a token tree.
136136
fn macro_expand(&self, macro_call: MacroCallId) -> ExpandResult<Option<Arc<tt::Subtree>>>;
137137
/// Special case of the previous query for procedural macros. We can't LRU
138138
/// proc macros, since they are not deterministic in general, and
139139
/// non-determinism breaks salsa in a very, very, very bad way. @edwin0cheng
140140
/// heroically debugged this once!
141141
fn expand_proc_macro(&self, call: MacroCallId) -> ExpandResult<tt::Subtree>;
142-
/// Firewall query that returns the error from the `macro_expand` query.
143-
fn macro_expand_error(&self, macro_call: MacroCallId) -> Option<ExpandError>;
142+
/// Firewall query that returns the errors from the `parse_macro_expansion` query.
143+
fn parse_macro_expansion_error(
144+
&self,
145+
macro_call: MacroCallId,
146+
) -> ExpandResult<Option<Box<[SyntaxError]>>>;
144147

145148
fn hygiene_frame(&self, file_id: HirFileId) -> Arc<HygieneFrame>;
146149
}
@@ -448,6 +451,7 @@ fn macro_def(
448451
fn macro_expand(
449452
db: &dyn ExpandDatabase,
450453
id: MacroCallId,
454+
// FIXME: Remove the OPtion if possible
451455
) -> ExpandResult<Option<Arc<tt::Subtree>>> {
452456
let _p = profile::span("macro_expand");
453457
let loc: MacroCallLoc = db.lookup_intern_macro_call(id);
@@ -498,8 +502,12 @@ fn macro_expand(
498502
ExpandResult { value: Some(Arc::new(tt)), err }
499503
}
500504

501-
fn macro_expand_error(db: &dyn ExpandDatabase, macro_call: MacroCallId) -> Option<ExpandError> {
502-
db.macro_expand(macro_call).err
505+
fn parse_macro_expansion_error(
506+
db: &dyn ExpandDatabase,
507+
macro_call_id: MacroCallId,
508+
) -> ExpandResult<Option<Box<[SyntaxError]>>> {
509+
db.parse_macro_expansion(MacroFile { macro_call_id })
510+
.map(|it| it.map(|(it, _)| it.errors().to_vec().into_boxed_slice()))
503511
}
504512

505513
fn expand_proc_macro(db: &dyn ExpandDatabase, id: MacroCallId) -> ExpandResult<tt::Subtree> {

crates/hir/src/db.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66
pub use hir_def::db::*;
77
pub use hir_expand::db::{
88
AstIdMapQuery, ExpandDatabase, ExpandDatabaseStorage, ExpandProcMacroQuery, HygieneFrameQuery,
9-
InternMacroCallQuery, MacroArgTextQuery, MacroDefQuery, MacroExpandErrorQuery,
10-
MacroExpandQuery, ParseMacroExpansionQuery,
9+
InternMacroCallQuery, MacroArgTextQuery, MacroDefQuery, MacroExpandQuery,
10+
ParseMacroExpansionQuery,
1111
};
1212
pub use hir_ty::db::*;
1313

crates/ide-db/src/apply_change.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,6 @@ impl RootDatabase {
8080
hir::db::MacroDefQuery
8181
hir::db::MacroExpandQuery
8282
hir::db::ExpandProcMacroQuery
83-
hir::db::MacroExpandErrorQuery
8483
hir::db::HygieneFrameQuery
8584

8685
// DefDatabase

crates/ide-db/src/lib.rs

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,6 @@ impl RootDatabase {
152152
let lru_capacity = lru_capacity.unwrap_or(base_db::DEFAULT_LRU_CAP);
153153
base_db::ParseQuery.in_db_mut(self).set_lru_capacity(lru_capacity);
154154
hir::db::ParseMacroExpansionQuery.in_db_mut(self).set_lru_capacity(lru_capacity);
155-
hir::db::MacroExpandQuery.in_db_mut(self).set_lru_capacity(lru_capacity);
156155
}
157156

158157
pub fn update_lru_capacities(&mut self, lru_capacities: &FxHashMap<Box<str>, usize>) {
@@ -167,12 +166,6 @@ impl RootDatabase {
167166
.copied()
168167
.unwrap_or(base_db::DEFAULT_LRU_CAP),
169168
);
170-
hir_db::MacroExpandQuery.in_db_mut(self).set_lru_capacity(
171-
lru_capacities
172-
.get(stringify!(MacroExpandQuery))
173-
.copied()
174-
.unwrap_or(base_db::DEFAULT_LRU_CAP),
175-
);
176169

177170
macro_rules! update_lru_capacity_per_query {
178171
($( $module:ident :: $query:ident )*) => {$(
@@ -201,7 +194,6 @@ impl RootDatabase {
201194
hir_db::MacroDefQuery
202195
// hir_db::MacroExpandQuery
203196
hir_db::ExpandProcMacroQuery
204-
hir_db::MacroExpandErrorQuery
205197
hir_db::HygieneFrameQuery
206198

207199
// DefDatabase

crates/ide-diagnostics/src/handlers/macro_error.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,22 @@ fn f() {
238238
//^^^ error: invalid macro definition: expected subtree
239239
240240
}
241+
"#,
242+
)
243+
}
244+
245+
#[test]
246+
fn expansion_syntax_diagnostic() {
247+
check_diagnostics(
248+
r#"
249+
macro_rules! foo {
250+
() => { struct; };
251+
}
252+
253+
fn f() {
254+
foo!();
255+
//^^^ error: Syntax Error in Expansion: expected a name
256+
}
241257
"#,
242258
)
243259
}

0 commit comments

Comments
 (0)