Skip to content

Commit 325ff4c

Browse files
committed
Factor out pointing at ADT definition
1 parent 820787e commit 325ff4c

File tree

1 file changed

+41
-44
lines changed

1 file changed

+41
-44
lines changed

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

Lines changed: 41 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,7 @@ use rustc_arena::TypedArena;
99
use rustc_ast::Mutability;
1010
use rustc_data_structures::fx::FxHashSet;
1111
use rustc_data_structures::stack::ensure_sufficient_stack;
12-
use rustc_errors::{
13-
struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, MultiSpan,
14-
};
12+
use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed, MultiSpan};
1513
use rustc_hir as hir;
1614
use rustc_hir::def::*;
1715
use rustc_hir::def_id::LocalDefId;
@@ -507,17 +505,7 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
507505
});
508506
};
509507

510-
let adt_defined_here = try {
511-
let ty = pattern_ty.peel_refs();
512-
let ty::Adt(def, _) = ty.kind() else { None? };
513-
let adt_def_span = cx.tcx.hir().get_if_local(def.did())?.ident()?.span;
514-
let mut variants = vec![];
515-
516-
for span in maybe_point_at_variant(&cx, *def, witnesses.iter().take(5)) {
517-
variants.push(Variant { span });
518-
}
519-
AdtDefinedHere { adt_def_span, ty, variants }
520-
};
508+
let adt_defined_here = report_adt_defined_here(self.tcx, pattern_ty, &witnesses, false);
521509

522510
// Emit an extra note if the first uncovered witness would be uninhabited
523511
// if we disregard visibility.
@@ -842,7 +830,22 @@ fn non_exhaustive_match<'p, 'tcx>(
842830
};
843831
};
844832

845-
adt_defined_here(cx, &mut err, scrut_ty, &witnesses);
833+
// Point at the definition of non-covered `enum` variants.
834+
if let Some(AdtDefinedHere { adt_def_span, ty, variants }) =
835+
report_adt_defined_here(cx.tcx, scrut_ty, &witnesses, true)
836+
{
837+
let mut multi_span = if variants.is_empty() {
838+
MultiSpan::from_span(adt_def_span)
839+
} else {
840+
MultiSpan::from_spans(variants.iter().map(|Variant { span }| *span).collect())
841+
};
842+
843+
multi_span.push_span_label(adt_def_span, "");
844+
for Variant { span } in variants {
845+
multi_span.push_span_label(span, "not covered");
846+
}
847+
err.span_note(multi_span, format!("`{ty}` defined here"));
848+
}
846849
err.note(format!("the matched value is of type `{}`", scrut_ty));
847850

848851
if !is_empty_match {
@@ -1024,39 +1027,33 @@ fn collect_non_exhaustive_tys<'tcx>(
10241027
.for_each(|field_pat| collect_non_exhaustive_tys(tcx, field_pat, non_exhaustive_tys))
10251028
}
10261029

1027-
/// Point at the definition of non-covered `enum` variants.
1028-
fn adt_defined_here<'p, 'tcx>(
1029-
cx: &MatchCheckCtxt<'p, 'tcx>,
1030-
err: &mut Diagnostic,
1030+
fn report_adt_defined_here<'tcx>(
1031+
tcx: TyCtxt<'tcx>,
10311032
ty: Ty<'tcx>,
10321033
witnesses: &[WitnessPat<'tcx>],
1033-
) {
1034+
point_at_non_local_ty: bool,
1035+
) -> Option<AdtDefinedHere<'tcx>> {
10341036
let ty = ty.peel_refs();
1035-
if let ty::Adt(def, _) = ty.kind() {
1036-
let mut spans = vec![];
1037-
for sp in maybe_point_at_variant(cx, *def, witnesses.iter().take(5)) {
1038-
spans.push(sp);
1039-
}
1040-
let def_span = cx
1041-
.tcx
1042-
.hir()
1043-
.get_if_local(def.did())
1044-
.and_then(|node| node.ident())
1045-
.map(|ident| ident.span)
1046-
.unwrap_or_else(|| cx.tcx.def_span(def.did()));
1047-
let mut span: MultiSpan =
1048-
if spans.is_empty() { def_span.into() } else { spans.clone().into() };
1049-
1050-
span.push_span_label(def_span, "");
1051-
for pat in spans {
1052-
span.push_span_label(pat, "not covered");
1053-
}
1054-
err.span_note(span, format!("`{ty}` defined here"));
1037+
let ty::Adt(def, _) = ty.kind() else {
1038+
return None;
1039+
};
1040+
let adt_def_span =
1041+
tcx.hir().get_if_local(def.did()).and_then(|node| node.ident()).map(|ident| ident.span);
1042+
let adt_def_span = if point_at_non_local_ty {
1043+
adt_def_span.unwrap_or_else(|| tcx.def_span(def.did()))
1044+
} else {
1045+
adt_def_span?
1046+
};
1047+
1048+
let mut variants = vec![];
1049+
for span in maybe_point_at_variant(tcx, *def, witnesses.iter().take(5)) {
1050+
variants.push(Variant { span });
10551051
}
1052+
Some(AdtDefinedHere { adt_def_span, ty, variants })
10561053
}
10571054

1058-
fn maybe_point_at_variant<'a, 'p: 'a, 'tcx: 'a>(
1059-
cx: &MatchCheckCtxt<'p, 'tcx>,
1055+
fn maybe_point_at_variant<'a, 'tcx: 'a>(
1056+
tcx: TyCtxt<'tcx>,
10601057
def: AdtDef<'tcx>,
10611058
patterns: impl Iterator<Item = &'a WitnessPat<'tcx>>,
10621059
) -> Vec<Span> {
@@ -1069,15 +1066,15 @@ fn maybe_point_at_variant<'a, 'p: 'a, 'tcx: 'a>(
10691066
{
10701067
continue;
10711068
}
1072-
let sp = def.variant(*variant_index).ident(cx.tcx).span;
1069+
let sp = def.variant(*variant_index).ident(tcx).span;
10731070
if covered.contains(&sp) {
10741071
// Don't point at variants that have already been covered due to other patterns to avoid
10751072
// visual clutter.
10761073
continue;
10771074
}
10781075
covered.push(sp);
10791076
}
1080-
covered.extend(maybe_point_at_variant(cx, def, pattern.iter_fields()));
1077+
covered.extend(maybe_point_at_variant(tcx, def, pattern.iter_fields()));
10811078
}
10821079
covered
10831080
}

0 commit comments

Comments
 (0)