Skip to content

Commit af9fe58

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 e4efdce commit af9fe58

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
}
@@ -1214,6 +1215,7 @@ fn report_non_exhaustive_match<'p, 'tcx>(
12141215
witnesses: Vec<WitnessPat<'p, 'tcx>>,
12151216
arms: &[ArmId],
12161217
braces_span: Option<Span>,
1218+
expr_span: Span,
12171219
) -> ErrorGuaranteed {
12181220
let is_empty_match = arms.is_empty();
12191221
let non_empty_enum = match scrut_ty.kind() {
@@ -1354,11 +1356,10 @@ fn report_non_exhaustive_match<'p, 'tcx>(
13541356
format!(" {{{indentation}{more}{suggested_arm},{indentation}}}",),
13551357
));
13561358
}
1357-
[only] => {
1359+
[only] if let Some(braces_span) = braces_span => {
13581360
let only = &thir[*only];
13591361
let only_body = &thir[only.body];
13601362
let pre_indentation = if let Some(snippet) = sm.indentation_before(only.span)
1361-
&& let Some(braces_span) = braces_span
13621363
&& sm.is_multiline(braces_span)
13631364
{
13641365
format!("\n{snippet}")
@@ -1387,7 +1388,7 @@ fn report_non_exhaustive_match<'p, 'tcx>(
13871388
format!("{comma}{pre_indentation}{suggested_arm}"),
13881389
));
13891390
}
1390-
[.., prev, last] => {
1391+
[.., prev, last] if braces_span.is_some() => {
13911392
let prev = &thir[*prev];
13921393
let last = &thir[*last];
13931394
if prev.span.eq_ctxt(last.span) {
@@ -1422,7 +1423,25 @@ fn report_non_exhaustive_match<'p, 'tcx>(
14221423
}
14231424
}
14241425
}
1425-
_ => {}
1426+
_ => {
1427+
if let Some(data) = expr_span.macro_backtrace().next()
1428+
&& let ExpnKind::Macro(macro_kind, name) = data.kind
1429+
{
1430+
let macro_kind = macro_kind.descr();
1431+
// We don't want to point at the macro invocation place as that is already shown
1432+
// or talk about macro-backtrace and the macro's name, as we are already doing
1433+
// that as part of this note.
1434+
let mut span: MultiSpan = expr_span.with_ctxt(data.call_site.ctxt()).into();
1435+
span.push_span_label(data.def_site, "");
1436+
err.span_note(
1437+
span,
1438+
format!(
1439+
"within {macro_kind} `{name}`, this `match` expression doesn't expand to \
1440+
cover all patterns",
1441+
),
1442+
);
1443+
}
1444+
}
14261445
}
14271446

14281447
let msg = format!(

0 commit comments

Comments
 (0)