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

Commit f0a40c3

Browse files
committed
Auto merge of rust-lang#14583 - Veykril:macro-def-err, r=Veykril
internal: Report macro definition errors on the definition We still report them on the call site as well for the time being, and the diagnostic doesn't know where the error in the definition comes from, but that can be done later on
2 parents a3888fd + a5558cd commit f0a40c3

File tree

10 files changed

+115
-14
lines changed

10 files changed

+115
-14
lines changed

crates/hir-def/src/body.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -190,8 +190,9 @@ impl Expander {
190190

191191
let file_id = call_id.as_file();
192192

193-
let raw_node = match db.parse_or_expand(file_id) {
194-
Some(it) => it,
193+
let raw_node = match db.parse_or_expand_with_err(file_id) {
194+
// FIXME: report parse errors
195+
Some(it) => it.syntax_node(),
195196
None => {
196197
// Only `None` if the macro expansion produced no usable AST.
197198
if err.is_none() {

crates/hir-def/src/data.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -641,7 +641,12 @@ impl<'a> AssocItemCollector<'a> {
641641
self.items.push((item.name.clone(), def.into()));
642642
}
643643
AssocItem::MacroCall(call) => {
644-
if let Some(root) = self.db.parse_or_expand(self.expander.current_file_id()) {
644+
if let Some(root) =
645+
self.db.parse_or_expand_with_err(self.expander.current_file_id())
646+
{
647+
// FIXME: report parse errors
648+
let root = root.syntax_node();
649+
645650
let call = &item_tree[call];
646651

647652
let ast_id_map = self.db.ast_id_map(self.expander.current_file_id());

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1374,6 +1374,8 @@ impl DefCollector<'_> {
13741374

13751375
// Then, fetch and process the item tree. This will reuse the expansion result from above.
13761376
let item_tree = self.db.file_item_tree(file_id);
1377+
// FIXME: report parse errors for the macro expansion here
1378+
13771379
let mod_dir = self.mod_dirs[&module_id].clone();
13781380
ModCollector {
13791381
def_collector: &mut *self,

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ pub enum DefDiagnosticKind {
3434
InvalidDeriveTarget { ast: AstId<ast::Item>, id: usize },
3535

3636
MalformedDerive { ast: AstId<ast::Adt>, id: usize },
37+
38+
MacroDefError { ast: AstId<ast::Macro>, message: String },
3739
}
3840

3941
#[derive(Debug, PartialEq, Eq)]

crates/hir-expand/src/db.rs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,8 @@ pub trait ExpandDatabase: SourceDatabase {
9999
/// file or a macro expansion.
100100
#[salsa::transparent]
101101
fn parse_or_expand(&self, file_id: HirFileId) -> Option<SyntaxNode>;
102+
#[salsa::transparent]
103+
fn parse_or_expand_with_err(&self, file_id: HirFileId) -> Option<Parse<SyntaxNode>>;
102104
/// Implementation for the macro case.
103105
fn parse_macro_expansion(
104106
&self,
@@ -252,13 +254,23 @@ fn parse_or_expand(db: &dyn ExpandDatabase, file_id: HirFileId) -> Option<Syntax
252254
match file_id.repr() {
253255
HirFileIdRepr::FileId(file_id) => Some(db.parse(file_id).tree().syntax().clone()),
254256
HirFileIdRepr::MacroFile(macro_file) => {
255-
// FIXME: Note how we convert from `Parse` to `SyntaxNode` here,
256-
// forgetting about parse errors.
257257
db.parse_macro_expansion(macro_file).value.map(|(it, _)| it.syntax_node())
258258
}
259259
}
260260
}
261261

262+
fn parse_or_expand_with_err(
263+
db: &dyn ExpandDatabase,
264+
file_id: HirFileId,
265+
) -> Option<Parse<SyntaxNode>> {
266+
match file_id.repr() {
267+
HirFileIdRepr::FileId(file_id) => Some(db.parse(file_id).to_syntax()),
268+
HirFileIdRepr::MacroFile(macro_file) => {
269+
db.parse_macro_expansion(macro_file).value.map(|(parse, _)| parse)
270+
}
271+
}
272+
}
273+
262274
fn parse_macro_expansion(
263275
db: &dyn ExpandDatabase,
264276
macro_file: MacroFile,

crates/hir-expand/src/eager.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,10 @@ fn lazy_expand(
187187
);
188188

189189
let err = db.macro_expand_error(id);
190-
let value = db.parse_or_expand(id.as_file()).map(|node| InFile::new(id.as_file(), node));
190+
let value =
191+
db.parse_or_expand_with_err(id.as_file()).map(|node| InFile::new(id.as_file(), node));
192+
// FIXME: report parse errors
193+
let value = value.map(|it| it.map(|it| it.syntax_node()));
191194

192195
ExpandResult { value, err }
193196
}

crates/hir/src/diagnostics.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ diagnostics![
3939
InvalidDeriveTarget,
4040
IncoherentImpl,
4141
MacroError,
42+
MacroDefError,
4243
MalformedDerive,
4344
MismatchedArgCount,
4445
MissingFields,
@@ -131,6 +132,13 @@ pub struct MacroError {
131132
pub message: String,
132133
}
133134

135+
#[derive(Debug, Clone, Eq, PartialEq)]
136+
pub struct MacroDefError {
137+
pub node: InFile<AstPtr<ast::Macro>>,
138+
pub message: String,
139+
pub name: Option<TextRange>,
140+
}
141+
134142
#[derive(Debug)]
135143
pub struct UnimplementedBuiltinMacro {
136144
pub node: InFile<SyntaxNodePtr>,

crates/hir/src/lib.rs

Lines changed: 45 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ use hir_def::{
4646
item_tree::ItemTreeNode,
4747
lang_item::{LangItem, LangItemTarget},
4848
layout::ReprOptions,
49+
macro_id_to_def_id,
4950
nameres::{self, diagnostics::DefDiagnostic, ModuleOrigin},
5051
per_ns::PerNs,
5152
resolver::{HasResolver, Resolver},
@@ -86,12 +87,12 @@ pub use crate::{
8687
attrs::{HasAttrs, Namespace},
8788
diagnostics::{
8889
AnyDiagnostic, BreakOutsideOfLoop, ExpectedFunction, InactiveCode, IncoherentImpl,
89-
IncorrectCase, InvalidDeriveTarget, MacroError, MalformedDerive, MismatchedArgCount,
90-
MissingFields, MissingMatchArms, MissingUnsafe, NeedMut, NoSuchField, PrivateAssocItem,
91-
PrivateField, ReplaceFilterMapNextWithFindMap, TypeMismatch, UndeclaredLabel,
92-
UnimplementedBuiltinMacro, UnreachableLabel, UnresolvedExternCrate, UnresolvedField,
93-
UnresolvedImport, UnresolvedMacroCall, UnresolvedMethodCall, UnresolvedModule,
94-
UnresolvedProcMacro, UnusedMut,
90+
IncorrectCase, InvalidDeriveTarget, MacroDefError, MacroError, MalformedDerive,
91+
MismatchedArgCount, MissingFields, MissingMatchArms, MissingUnsafe, NeedMut, NoSuchField,
92+
PrivateAssocItem, PrivateField, ReplaceFilterMapNextWithFindMap, TypeMismatch,
93+
UndeclaredLabel, UnimplementedBuiltinMacro, UnreachableLabel, UnresolvedExternCrate,
94+
UnresolvedField, UnresolvedImport, UnresolvedMacroCall, UnresolvedMethodCall,
95+
UnresolvedModule, UnresolvedProcMacro, UnusedMut,
9596
},
9697
has_source::HasSource,
9798
semantics::{PathResolution, Semantics, SemanticsScope, TypeInfo, VisibleTraits},
@@ -563,6 +564,7 @@ impl Module {
563564
}
564565
emit_def_diagnostic(db, acc, diag);
565566
}
567+
566568
for decl in self.declarations(db) {
567569
match decl {
568570
ModuleDef::Module(m) => {
@@ -601,9 +603,11 @@ impl Module {
601603
}
602604
acc.extend(decl.diagnostics(db))
603605
}
606+
ModuleDef::Macro(m) => emit_macro_def_diagnostics(db, acc, m),
604607
_ => acc.extend(decl.diagnostics(db)),
605608
}
606609
}
610+
self.legacy_macros(db).into_iter().for_each(|m| emit_macro_def_diagnostics(db, acc, m));
607611

608612
let inherent_impls = db.inherent_impls_in_crate(self.id.krate());
609613

@@ -685,8 +689,31 @@ impl Module {
685689
}
686690
}
687691

692+
fn emit_macro_def_diagnostics(db: &dyn HirDatabase, acc: &mut Vec<AnyDiagnostic>, m: Macro) {
693+
let id = macro_id_to_def_id(db.upcast(), m.id);
694+
if let Err(e) = db.macro_def(id) {
695+
let Some(ast) = id.ast_id().left() else {
696+
never!("MacroDefError for proc-macro: {:?}", e);
697+
return;
698+
};
699+
emit_def_diagnostic_(
700+
db,
701+
acc,
702+
&DefDiagnosticKind::MacroDefError { ast, message: e.to_string() },
703+
);
704+
}
705+
}
706+
688707
fn emit_def_diagnostic(db: &dyn HirDatabase, acc: &mut Vec<AnyDiagnostic>, diag: &DefDiagnostic) {
689-
match &diag.kind {
708+
emit_def_diagnostic_(db, acc, &diag.kind)
709+
}
710+
711+
fn emit_def_diagnostic_(
712+
db: &dyn HirDatabase,
713+
acc: &mut Vec<AnyDiagnostic>,
714+
diag: &DefDiagnosticKind,
715+
) {
716+
match diag {
690717
DefDiagnosticKind::UnresolvedModule { ast: declaration, candidates } => {
691718
let decl = declaration.to_node(db.upcast());
692719
acc.push(
@@ -794,6 +821,17 @@ fn emit_def_diagnostic(db: &dyn HirDatabase, acc: &mut Vec<AnyDiagnostic>, diag:
794821
None => stdx::never!("derive diagnostic on item without derive attribute"),
795822
}
796823
}
824+
DefDiagnosticKind::MacroDefError { ast, message } => {
825+
let node = ast.to_node(db.upcast());
826+
acc.push(
827+
MacroDefError {
828+
node: InFile::new(ast.file_id, AstPtr::new(&node)),
829+
name: node.name().map(|it| it.syntax().text_range()),
830+
message: message.clone(),
831+
}
832+
.into(),
833+
);
834+
}
797835
}
798836
}
799837

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

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,16 @@ pub(crate) fn macro_error(ctx: &DiagnosticsContext<'_>, d: &hir::MacroError) ->
99
Diagnostic::new("macro-error", d.message.clone(), display_range).experimental()
1010
}
1111

12+
// Diagnostic: macro-error
13+
//
14+
// This diagnostic is shown for macro expansion errors.
15+
pub(crate) fn macro_def_error(ctx: &DiagnosticsContext<'_>, d: &hir::MacroDefError) -> Diagnostic {
16+
// Use more accurate position if available.
17+
let display_range =
18+
ctx.resolve_precise_location(&d.node.clone().map(|it| it.syntax_node_ptr()), d.name);
19+
Diagnostic::new("macro-def-error", d.message.clone(), display_range).experimental()
20+
}
21+
1222
#[cfg(test)]
1323
mod tests {
1424
use crate::{
@@ -188,6 +198,7 @@ fn f() {
188198
"#,
189199
);
190200
}
201+
191202
#[test]
192203
fn dollar_crate_in_builtin_macro() {
193204
check_diagnostics(
@@ -209,6 +220,24 @@ macro_rules! outer {
209220
fn f() {
210221
outer!();
211222
} //^^^^^^^^ error: leftover tokens
223+
"#,
224+
)
225+
}
226+
227+
#[test]
228+
fn def_diagnostic() {
229+
check_diagnostics(
230+
r#"
231+
macro_rules! foo {
232+
//^^^ error: expected subtree
233+
f => {};
234+
}
235+
236+
fn f() {
237+
foo!();
238+
//^^^ error: invalid macro definition: expected subtree
239+
240+
}
212241
"#,
213242
)
214243
}

crates/ide-diagnostics/src/lib.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,7 @@ pub fn diagnostics(
249249

250250
let mut diags = Vec::new();
251251
if let Some(m) = module {
252-
m.diagnostics(db, &mut diags)
252+
m.diagnostics(db, &mut diags);
253253
}
254254

255255
for diag in diags {
@@ -263,6 +263,7 @@ pub fn diagnostics(
263263
AnyDiagnostic::IncoherentImpl(d) => handlers::incoherent_impl::incoherent_impl(&ctx, &d),
264264
AnyDiagnostic::IncorrectCase(d) => handlers::incorrect_case::incorrect_case(&ctx, &d),
265265
AnyDiagnostic::InvalidDeriveTarget(d) => handlers::invalid_derive_target::invalid_derive_target(&ctx, &d),
266+
AnyDiagnostic::MacroDefError(d) => handlers::macro_error::macro_def_error(&ctx, &d),
266267
AnyDiagnostic::MacroError(d) => handlers::macro_error::macro_error(&ctx, &d),
267268
AnyDiagnostic::MalformedDerive(d) => handlers::malformed_derive::malformed_derive(&ctx, &d),
268269
AnyDiagnostic::MismatchedArgCount(d) => handlers::mismatched_arg_count::mismatched_arg_count(&ctx, &d),

0 commit comments

Comments
 (0)