Skip to content

Commit d891ec6

Browse files
committed
Auto merge of #17221 - Veykril:lazier-validation, r=Veykril
internal: Lazier macro parse tree validation
2 parents 6e0c33d + f1aa040 commit d891ec6

File tree

14 files changed

+151
-140
lines changed

14 files changed

+151
-140
lines changed

src/tools/rust-analyzer/crates/base-db/src/lib.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ mod input;
88
use std::panic;
99

1010
use salsa::Durability;
11-
use syntax::{ast, Parse, SourceFile};
11+
use syntax::{ast, Parse, SourceFile, SyntaxError};
1212
use triomphe::Arc;
1313

1414
pub use crate::{
@@ -62,6 +62,9 @@ pub trait SourceDatabase: FileLoader + std::fmt::Debug {
6262
/// Parses the file into the syntax tree.
6363
fn parse(&self, file_id: FileId) -> Parse<ast::SourceFile>;
6464

65+
/// Returns the set of errors obtained from parsing the file including validation errors.
66+
fn parse_errors(&self, file_id: FileId) -> Option<Arc<[SyntaxError]>>;
67+
6568
/// The crate graph.
6669
#[salsa::input]
6770
fn crate_graph(&self) -> Arc<CrateGraph>;
@@ -88,6 +91,14 @@ fn parse(db: &dyn SourceDatabase, file_id: FileId) -> Parse<ast::SourceFile> {
8891
SourceFile::parse(&text, span::Edition::CURRENT)
8992
}
9093

94+
fn parse_errors(db: &dyn SourceDatabase, file_id: FileId) -> Option<Arc<[SyntaxError]>> {
95+
let errors = db.parse(file_id).errors();
96+
match &*errors {
97+
[] => None,
98+
[..] => Some(errors.into()),
99+
}
100+
}
101+
91102
/// We don't want to give HIR knowledge of source roots, hence we extract these
92103
/// methods into a separate DB.
93104
#[salsa::query_group(SourceDatabaseExtStorage)]

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

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,10 @@ use std::ops::Index;
1010

1111
use base_db::CrateId;
1212
use cfg::{CfgExpr, CfgOptions};
13-
use hir_expand::{name::Name, HirFileId, InFile};
13+
use hir_expand::{name::Name, InFile};
1414
use la_arena::{Arena, ArenaMap};
1515
use rustc_hash::FxHashMap;
16+
use span::MacroFileId;
1617
use syntax::{ast, AstPtr, SyntaxNodePtr};
1718
use triomphe::Arc;
1819

@@ -98,7 +99,7 @@ pub struct BodySourceMap {
9899

99100
format_args_template_map: FxHashMap<ExprId, Vec<(syntax::TextRange, Name)>>,
100101

101-
expansions: FxHashMap<InFile<AstPtr<ast::MacroCall>>, HirFileId>,
102+
expansions: FxHashMap<InFile<AstPtr<ast::MacroCall>>, MacroFileId>,
102103

103104
/// Diagnostics accumulated during body lowering. These contain `AstPtr`s and so are stored in
104105
/// the source map (since they're just as volatile).
@@ -349,11 +350,17 @@ impl BodySourceMap {
349350
self.expr_map.get(&src).cloned()
350351
}
351352

352-
pub fn node_macro_file(&self, node: InFile<&ast::MacroCall>) -> Option<HirFileId> {
353+
pub fn node_macro_file(&self, node: InFile<&ast::MacroCall>) -> Option<MacroFileId> {
353354
let src = node.map(AstPtr::new);
354355
self.expansions.get(&src).cloned()
355356
}
356357

358+
pub fn macro_calls(
359+
&self,
360+
) -> impl Iterator<Item = (InFile<AstPtr<ast::MacroCall>>, MacroFileId)> + '_ {
361+
self.expansions.iter().map(|(&a, &b)| (a, b))
362+
}
363+
357364
pub fn pat_syntax(&self, pat: PatId) -> Result<PatSource, SyntheticSyntax> {
358365
self.pat_map_back.get(pat).cloned().ok_or(SyntheticSyntax)
359366
}

src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1006,7 +1006,9 @@ impl ExprCollector<'_> {
10061006
Some((mark, expansion)) => {
10071007
// Keep collecting even with expansion errors so we can provide completions and
10081008
// other services in incomplete macro expressions.
1009-
self.source_map.expansions.insert(macro_call_ptr, self.expander.current_file_id());
1009+
self.source_map
1010+
.expansions
1011+
.insert(macro_call_ptr, self.expander.current_file_id().macro_file().unwrap());
10101012
let prev_ast_id_map = mem::replace(
10111013
&mut self.ast_id_map,
10121014
self.db.ast_id_map(self.expander.current_file_id()),

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

Lines changed: 18 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,7 @@ pub struct TraitData {
229229
/// method calls to this trait's methods when the receiver is an array and the crate edition is
230230
/// 2015 or 2018.
231231
// box it as the vec is usually empty anyways
232-
pub attribute_calls: Option<Box<Vec<(AstId<ast::Item>, MacroCallId)>>>,
232+
pub macro_calls: Option<Box<Vec<(AstId<ast::Item>, MacroCallId)>>>,
233233
}
234234

235235
impl TraitData {
@@ -258,12 +258,12 @@ impl TraitData {
258258
let mut collector =
259259
AssocItemCollector::new(db, module_id, tree_id.file_id(), ItemContainerId::TraitId(tr));
260260
collector.collect(&item_tree, tree_id.tree_id(), &tr_def.items);
261-
let (items, attribute_calls, diagnostics) = collector.finish();
261+
let (items, macro_calls, diagnostics) = collector.finish();
262262

263263
(
264264
Arc::new(TraitData {
265265
name,
266-
attribute_calls,
266+
macro_calls,
267267
items,
268268
is_auto,
269269
is_unsafe,
@@ -298,7 +298,7 @@ impl TraitData {
298298
}
299299

300300
pub fn attribute_calls(&self) -> impl Iterator<Item = (AstId<ast::Item>, MacroCallId)> + '_ {
301-
self.attribute_calls.iter().flat_map(|it| it.iter()).copied()
301+
self.macro_calls.iter().flat_map(|it| it.iter()).copied()
302302
}
303303
}
304304

@@ -319,15 +319,15 @@ impl TraitAliasData {
319319
}
320320
}
321321

322-
#[derive(Debug, Clone, PartialEq, Eq)]
322+
#[derive(Debug, PartialEq, Eq)]
323323
pub struct ImplData {
324324
pub target_trait: Option<Interned<TraitRef>>,
325325
pub self_ty: Interned<TypeRef>,
326326
pub items: Vec<AssocItemId>,
327327
pub is_negative: bool,
328328
pub is_unsafe: bool,
329329
// box it as the vec is usually empty anyways
330-
pub attribute_calls: Option<Box<Vec<(AstId<ast::Item>, MacroCallId)>>>,
330+
pub macro_calls: Option<Box<Vec<(AstId<ast::Item>, MacroCallId)>>>,
331331
}
332332

333333
impl ImplData {
@@ -354,7 +354,7 @@ impl ImplData {
354354
AssocItemCollector::new(db, module_id, tree_id.file_id(), ItemContainerId::ImplId(id));
355355
collector.collect(&item_tree, tree_id.tree_id(), &impl_def.items);
356356

357-
let (items, attribute_calls, diagnostics) = collector.finish();
357+
let (items, macro_calls, diagnostics) = collector.finish();
358358
let items = items.into_iter().map(|(_, item)| item).collect();
359359

360360
(
@@ -364,14 +364,14 @@ impl ImplData {
364364
items,
365365
is_negative,
366366
is_unsafe,
367-
attribute_calls,
367+
macro_calls,
368368
}),
369369
DefDiagnostics::new(diagnostics),
370370
)
371371
}
372372

373373
pub fn attribute_calls(&self) -> impl Iterator<Item = (AstId<ast::Item>, MacroCallId)> + '_ {
374-
self.attribute_calls.iter().flat_map(|it| it.iter()).copied()
374+
self.macro_calls.iter().flat_map(|it| it.iter()).copied()
375375
}
376376
}
377377

@@ -573,7 +573,7 @@ struct AssocItemCollector<'a> {
573573
expander: Expander,
574574

575575
items: Vec<(Name, AssocItemId)>,
576-
attr_calls: Vec<(AstId<ast::Item>, MacroCallId)>,
576+
macro_calls: Vec<(AstId<ast::Item>, MacroCallId)>,
577577
}
578578

579579
impl<'a> AssocItemCollector<'a> {
@@ -590,7 +590,7 @@ impl<'a> AssocItemCollector<'a> {
590590
container,
591591
expander: Expander::new(db, file_id, module_id),
592592
items: Vec::new(),
593-
attr_calls: Vec::new(),
593+
macro_calls: Vec::new(),
594594
diagnostics: Vec::new(),
595595
}
596596
}
@@ -604,7 +604,7 @@ impl<'a> AssocItemCollector<'a> {
604604
) {
605605
(
606606
self.items,
607-
if self.attr_calls.is_empty() { None } else { Some(Box::new(self.attr_calls)) },
607+
if self.macro_calls.is_empty() { None } else { Some(Box::new(self.macro_calls)) },
608608
self.diagnostics,
609609
)
610610
}
@@ -662,11 +662,11 @@ impl<'a> AssocItemCollector<'a> {
662662
}
663663
}
664664

665-
self.attr_calls.push((ast_id, call_id));
665+
self.macro_calls.push((ast_id, call_id));
666666

667667
let res =
668668
self.expander.enter_expand_id::<ast::MacroItems>(self.db, call_id);
669-
self.collect_macro_items(res, &|| loc.kind.clone());
669+
self.collect_macro_items(res);
670670
continue 'items;
671671
}
672672
Ok(_) => (),
@@ -743,11 +743,8 @@ impl<'a> AssocItemCollector<'a> {
743743
Ok(Some(call_id)) => {
744744
let res =
745745
self.expander.enter_expand_id::<ast::MacroItems>(self.db, call_id);
746-
self.collect_macro_items(res, &|| hir_expand::MacroCallKind::FnLike {
747-
ast_id: InFile::new(file_id, ast_id),
748-
expand_to: hir_expand::ExpandTo::Items,
749-
eager: None,
750-
});
746+
self.macro_calls.push((InFile::new(file_id, ast_id.upcast()), call_id));
747+
self.collect_macro_items(res);
751748
}
752749
Ok(None) => (),
753750
Err(_) => {
@@ -766,39 +763,8 @@ impl<'a> AssocItemCollector<'a> {
766763
}
767764
}
768765

769-
fn collect_macro_items(
770-
&mut self,
771-
ExpandResult { value, err }: ExpandResult<Option<(Mark, Parse<ast::MacroItems>)>>,
772-
error_call_kind: &dyn Fn() -> hir_expand::MacroCallKind,
773-
) {
774-
let Some((mark, parse)) = value else { return };
775-
776-
if let Some(err) = err {
777-
let diag = match err {
778-
// why is this reported here?
779-
hir_expand::ExpandError::UnresolvedProcMacro(krate) => {
780-
DefDiagnostic::unresolved_proc_macro(
781-
self.module_id.local_id,
782-
error_call_kind(),
783-
krate,
784-
)
785-
}
786-
_ => DefDiagnostic::macro_error(
787-
self.module_id.local_id,
788-
error_call_kind(),
789-
err.to_string(),
790-
),
791-
};
792-
self.diagnostics.push(diag);
793-
}
794-
let errors = parse.errors();
795-
if !errors.is_empty() {
796-
self.diagnostics.push(DefDiagnostic::macro_expansion_parse_error(
797-
self.module_id.local_id,
798-
error_call_kind(),
799-
errors.into_boxed_slice(),
800-
));
801-
}
766+
fn collect_macro_items(&mut self, res: ExpandResult<Option<(Mark, Parse<ast::MacroItems>)>>) {
767+
let Some((mark, _parse)) = res.value else { return };
802768

803769
let tree_id = item_tree::TreeId::new(self.expander.current_file_id(), None);
804770
let item_tree = tree_id.item_tree(self.db);

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,14 @@ impl ItemScope {
234234
self.impls.iter().copied()
235235
}
236236

237+
pub fn all_macro_calls(&self) -> impl Iterator<Item = MacroCallId> + '_ {
238+
self.macro_invocations.values().copied().chain(self.attr_macros.values().copied()).chain(
239+
self.derive_macros.values().flat_map(|it| {
240+
it.iter().flat_map(|it| it.derive_call_ids.iter().copied().flatten())
241+
}),
242+
)
243+
}
244+
237245
pub(crate) fn modules_in_scope(&self) -> impl Iterator<Item = (ModuleId, Visibility)> + '_ {
238246
self.types.values().copied().filter_map(|(def, vis, _)| match def {
239247
ModuleDefId::ModuleId(module) => Some((module, vis)),

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

Lines changed: 1 addition & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,13 @@ use hir_expand::{
1515
builtin_fn_macro::find_builtin_macro,
1616
name::{name, AsName, Name},
1717
proc_macro::CustomProcMacroExpander,
18-
ExpandResult, ExpandTo, HirFileId, InFile, MacroCallId, MacroCallKind, MacroCallLoc,
19-
MacroDefId, MacroDefKind,
18+
ExpandTo, HirFileId, InFile, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind,
2019
};
2120
use itertools::{izip, Itertools};
2221
use la_arena::Idx;
2322
use limit::Limit;
2423
use rustc_hash::{FxHashMap, FxHashSet};
2524
use span::{Edition, ErasedFileAstId, FileAstId, Span, SyntaxContextId};
26-
use stdx::always;
2725
use syntax::ast;
2826
use triomphe::Arc;
2927

@@ -1412,31 +1410,6 @@ impl DefCollector<'_> {
14121410
}
14131411
let file_id = macro_call_id.as_file();
14141412

1415-
// First, fetch the raw expansion result for purposes of error reporting. This goes through
1416-
// `parse_macro_expansion_error` to avoid depending on the full expansion result (to improve
1417-
// incrementality).
1418-
// FIXME: This kind of error fetching feels a bit odd?
1419-
let ExpandResult { value: errors, err } =
1420-
self.db.parse_macro_expansion_error(macro_call_id);
1421-
if let Some(err) = err {
1422-
let loc: MacroCallLoc = self.db.lookup_intern_macro_call(macro_call_id);
1423-
let diag = match err {
1424-
// why is this reported here?
1425-
hir_expand::ExpandError::UnresolvedProcMacro(krate) => {
1426-
always!(krate == loc.def.krate);
1427-
DefDiagnostic::unresolved_proc_macro(module_id, loc.kind.clone(), loc.def.krate)
1428-
}
1429-
_ => DefDiagnostic::macro_error(module_id, loc.kind, err.to_string()),
1430-
};
1431-
1432-
self.def_map.diagnostics.push(diag);
1433-
}
1434-
if !errors.is_empty() {
1435-
let loc: MacroCallLoc = self.db.lookup_intern_macro_call(macro_call_id);
1436-
let diag = DefDiagnostic::macro_expansion_parse_error(module_id, loc.kind, errors);
1437-
self.def_map.diagnostics.push(diag);
1438-
}
1439-
14401413
// Then, fetch and process the item tree. This will reuse the expansion result from above.
14411414
let item_tree = self.db.file_item_tree(file_id);
14421415

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

Lines changed: 2 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use base_db::CrateId;
66
use cfg::{CfgExpr, CfgOptions};
77
use hir_expand::{attrs::AttrId, ErasedAstId, MacroCallKind};
88
use la_arena::Idx;
9-
use syntax::{ast, SyntaxError};
9+
use syntax::ast;
1010

1111
use crate::{
1212
item_tree::{self, ItemTreeId},
@@ -23,8 +23,6 @@ pub enum DefDiagnosticKind {
2323
UnconfiguredCode { ast: ErasedAstId, cfg: CfgExpr, opts: CfgOptions },
2424
UnresolvedProcMacro { ast: MacroCallKind, krate: CrateId },
2525
UnresolvedMacroCall { ast: MacroCallKind, path: ModPath },
26-
MacroError { ast: MacroCallKind, message: String },
27-
MacroExpansionParseError { ast: MacroCallKind, errors: Box<[SyntaxError]> },
2826
UnimplementedBuiltinMacro { ast: AstId<ast::Macro> },
2927
InvalidDeriveTarget { ast: AstId<ast::Item>, id: usize },
3028
MalformedDerive { ast: AstId<ast::Adt>, id: usize },
@@ -98,33 +96,14 @@ impl DefDiagnostic {
9896
// FIXME: This is used for a lot of things, unresolved proc macros, disabled proc macros, etc
9997
// yet the diagnostic handler in ide-diagnostics has to figure out what happened because this
10098
// struct loses all that information!
101-
pub(crate) fn unresolved_proc_macro(
99+
pub fn unresolved_proc_macro(
102100
container: LocalModuleId,
103101
ast: MacroCallKind,
104102
krate: CrateId,
105103
) -> Self {
106104
Self { in_module: container, kind: DefDiagnosticKind::UnresolvedProcMacro { ast, krate } }
107105
}
108106

109-
pub(crate) fn macro_error(
110-
container: LocalModuleId,
111-
ast: MacroCallKind,
112-
message: String,
113-
) -> Self {
114-
Self { in_module: container, kind: DefDiagnosticKind::MacroError { ast, message } }
115-
}
116-
117-
pub(crate) fn macro_expansion_parse_error(
118-
container: LocalModuleId,
119-
ast: MacroCallKind,
120-
errors: Box<[SyntaxError]>,
121-
) -> Self {
122-
Self {
123-
in_module: container,
124-
kind: DefDiagnosticKind::MacroExpansionParseError { ast, errors },
125-
}
126-
}
127-
128107
// FIXME: Whats the difference between this and unresolved_proc_macro
129108
pub(crate) fn unresolved_macro_call(
130109
container: LocalModuleId,

0 commit comments

Comments
 (0)