Skip to content

Commit 0cc0b11

Browse files
committed
mbe: Emit an error if a macro call has no function-like rules
Add a FIXME for moving this error earlier.
1 parent f0a5e70 commit 0cc0b11

File tree

1 file changed

+21
-3
lines changed

1 file changed

+21
-3
lines changed

compiler/rustc_expand/src/mbe/diagnostics.rs

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use rustc_macros::Subdiagnostic;
77
use rustc_parse::parser::{Parser, Recovery, token_descr};
88
use rustc_session::parse::ParseSess;
99
use rustc_span::source_map::SourceMap;
10-
use rustc_span::{ErrorGuaranteed, Ident, Span};
10+
use rustc_span::{DUMMY_SP, ErrorGuaranteed, Ident, Span};
1111
use tracing::debug;
1212

1313
use super::macro_rules::{MacroRule, NoopTracker, parser_from_cx};
@@ -25,6 +25,12 @@ pub(super) fn failed_to_match_macro(
2525
rules: &[MacroRule],
2626
) -> (Span, ErrorGuaranteed) {
2727
debug!("failed to match macro");
28+
let def_head_span = if !def_span.is_dummy() && !psess.source_map().is_imported(def_span) {
29+
psess.source_map().guess_head_span(def_span)
30+
} else {
31+
DUMMY_SP
32+
};
33+
2834
// An error occurred, try the expansion again, tracking the expansion closely for better
2935
// diagnostics.
3036
let mut tracker = CollectTrackerAndEmitter::new(psess.dcx(), sp);
@@ -47,15 +53,27 @@ pub(super) fn failed_to_match_macro(
4753

4854
let Some(BestFailure { token, msg: label, remaining_matcher, .. }) = tracker.best_failure
4955
else {
56+
// FIXME: we should report this at macro resolution time, as we do for
57+
// `resolve_macro_cannot_use_as_attr`. We can do that once we track multiple macro kinds for a
58+
// Def.
59+
if !rules.iter().any(|rule| matches!(rule, MacroRule::Func { .. })) {
60+
let msg = format!("macro has no rules for function-like invocation `{name}!`");
61+
let mut err = psess.dcx().struct_span_err(sp, msg);
62+
if !def_head_span.is_dummy() {
63+
let msg = "this macro has no rules for function-like invocation";
64+
err.span_label(def_head_span, msg);
65+
}
66+
return (sp, err.emit());
67+
}
5068
return (sp, psess.dcx().span_delayed_bug(sp, "failed to match a macro"));
5169
};
5270

5371
let span = token.span.substitute_dummy(sp);
5472

5573
let mut err = psess.dcx().struct_span_err(span, parse_failure_msg(&token, None));
5674
err.span_label(span, label);
57-
if !def_span.is_dummy() && !psess.source_map().is_imported(def_span) {
58-
err.span_label(psess.source_map().guess_head_span(def_span), "when calling this macro");
75+
if !def_head_span.is_dummy() {
76+
err.span_label(def_head_span, "when calling this macro");
5977
}
6078

6179
annotate_doc_comment(&mut err, psess.source_map(), span);

0 commit comments

Comments
 (0)