Skip to content

Commit d8e961e

Browse files
committed
Account for non-exhausitve match expression coming from macro expansion
``` error[E0004]: non-exhaustive patterns: `u8::MAX` not covered --> $DIR/exhaustiveness.rs:47:8 | LL | m!(0u8, 0..255); | ^^^ pattern `u8::MAX` not covered | = note: the matched value is of type `u8` note: within macro `m`, this `match` expression doesn't expand to cover all patterns --> $DIR/exhaustiveness.rs:7:9 | LL | / macro_rules! m { LL | | ($s:expr, $($t:tt)+) => { LL | | match $s { $($t)+ => {} } | | ^^^^^^^^^^^^^^^^^^^^^^^^^ LL | | } LL | | } | |_- = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern ```
1 parent abc0533 commit d8e961e

File tree

7 files changed

+1519
-537
lines changed

7 files changed

+1519
-537
lines changed

compiler/rustc_mir_build/src/thir/pattern/check_match.rs

+24-5
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ use rustc_session::lint::builtin::{
2424
};
2525
use rustc_span::edit_distance::find_best_match_for_name;
2626
use rustc_span::hygiene::DesugaringKind;
27-
use rustc_span::{Ident, Span};
27+
use rustc_span::{ExpnKind, Ident, Span};
2828
use rustc_trait_selection::infer::InferCtxtExt;
2929
use tracing::instrument;
3030

@@ -543,6 +543,7 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> {
543543
witnesses,
544544
arms,
545545
braces_span,
546+
expr_span,
546547
));
547548
}
548549
}
@@ -1210,6 +1211,7 @@ fn report_non_exhaustive_match<'p, 'tcx>(
12101211
witnesses: Vec<WitnessPat<'p, 'tcx>>,
12111212
arms: &[ArmId],
12121213
braces_span: Option<Span>,
1214+
expr_span: Span,
12131215
) -> ErrorGuaranteed {
12141216
let is_empty_match = arms.is_empty();
12151217
let non_empty_enum = match scrut_ty.kind() {
@@ -1350,11 +1352,10 @@ fn report_non_exhaustive_match<'p, 'tcx>(
13501352
format!(" {{{indentation}{more}{suggested_arm},{indentation}}}",),
13511353
));
13521354
}
1353-
[only] => {
1355+
[only] if let Some(braces_span) = braces_span => {
13541356
let only = &thir[*only];
13551357
let only_body = &thir[only.body];
13561358
let pre_indentation = if let Some(snippet) = sm.indentation_before(only.span)
1357-
&& let Some(braces_span) = braces_span
13581359
&& sm.is_multiline(braces_span)
13591360
{
13601361
format!("\n{snippet}")
@@ -1383,7 +1384,7 @@ fn report_non_exhaustive_match<'p, 'tcx>(
13831384
format!("{comma}{pre_indentation}{suggested_arm}"),
13841385
));
13851386
}
1386-
[.., prev, last] => {
1387+
[.., prev, last] if braces_span.is_some() => {
13871388
let prev = &thir[*prev];
13881389
let last = &thir[*last];
13891390
if prev.span.eq_ctxt(last.span) {
@@ -1418,7 +1419,25 @@ fn report_non_exhaustive_match<'p, 'tcx>(
14181419
}
14191420
}
14201421
}
1421-
_ => {}
1422+
_ => {
1423+
if let Some(data) = expr_span.macro_backtrace().next()
1424+
&& let ExpnKind::Macro(macro_kind, name) = data.kind
1425+
{
1426+
let macro_kind = macro_kind.descr();
1427+
// We don't want to point at the macro invocation place as that is already shown
1428+
// or talk about macro-backtrace and the macro's name, as we are already doing
1429+
// that as part of this note.
1430+
let mut span: MultiSpan = expr_span.with_ctxt(data.call_site.ctxt()).into();
1431+
span.push_span_label(data.def_site, "");
1432+
err.span_note(
1433+
span,
1434+
format!(
1435+
"within {macro_kind} `{name}`, this `match` expression doesn't expand to \
1436+
cover all patterns",
1437+
),
1438+
);
1439+
}
1440+
}
14221441
}
14231442

14241443
let msg = format!(

0 commit comments

Comments
 (0)