Skip to content

Commit 013e257

Browse files
committed
Factor out pointing at ADT definition
1 parent e3fd670 commit 013e257

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 && witnesses.len() == 1 {
@@ -1008,39 +1011,33 @@ fn collect_non_exhaustive_tys<'tcx>(
10081011
.for_each(|field_pat| collect_non_exhaustive_tys(field_pat, non_exhaustive_tys))
10091012
}
10101013

1011-
/// Point at the definition of non-covered `enum` variants.
1012-
fn adt_defined_here<'p, 'tcx>(
1013-
cx: &MatchCheckCtxt<'p, 'tcx>,
1014-
err: &mut Diagnostic,
1014+
fn report_adt_defined_here<'tcx>(
1015+
tcx: TyCtxt<'tcx>,
10151016
ty: Ty<'tcx>,
10161017
witnesses: &[WitnessPat<'tcx>],
1017-
) {
1018+
point_at_non_local_ty: bool,
1019+
) -> Option<AdtDefinedHere<'tcx>> {
10181020
let ty = ty.peel_refs();
1019-
if let ty::Adt(def, _) = ty.kind() {
1020-
let mut spans = vec![];
1021-
for sp in maybe_point_at_variant(cx, *def, witnesses.iter().take(5)) {
1022-
spans.push(sp);
1023-
}
1024-
let def_span = cx
1025-
.tcx
1026-
.hir()
1027-
.get_if_local(def.did())
1028-
.and_then(|node| node.ident())
1029-
.map(|ident| ident.span)
1030-
.unwrap_or_else(|| cx.tcx.def_span(def.did()));
1031-
let mut span: MultiSpan =
1032-
if spans.is_empty() { def_span.into() } else { spans.clone().into() };
1033-
1034-
span.push_span_label(def_span, "");
1035-
for pat in spans {
1036-
span.push_span_label(pat, "not covered");
1037-
}
1038-
err.span_note(span, format!("`{ty}` defined here"));
1021+
let ty::Adt(def, _) = ty.kind() else {
1022+
return None;
1023+
};
1024+
let adt_def_span =
1025+
tcx.hir().get_if_local(def.did()).and_then(|node| node.ident()).map(|ident| ident.span);
1026+
let adt_def_span = if point_at_non_local_ty {
1027+
adt_def_span.unwrap_or_else(|| tcx.def_span(def.did()))
1028+
} else {
1029+
adt_def_span?
1030+
};
1031+
1032+
let mut variants = vec![];
1033+
for span in maybe_point_at_variant(tcx, *def, witnesses.iter().take(5)) {
1034+
variants.push(Variant { span });
10391035
}
1036+
Some(AdtDefinedHere { adt_def_span, ty, variants })
10401037
}
10411038

1042-
fn maybe_point_at_variant<'a, 'p: 'a, 'tcx: 'a>(
1043-
cx: &MatchCheckCtxt<'p, 'tcx>,
1039+
fn maybe_point_at_variant<'a, 'tcx: 'a>(
1040+
tcx: TyCtxt<'tcx>,
10441041
def: AdtDef<'tcx>,
10451042
patterns: impl Iterator<Item = &'a WitnessPat<'tcx>>,
10461043
) -> Vec<Span> {
@@ -1053,15 +1050,15 @@ fn maybe_point_at_variant<'a, 'p: 'a, 'tcx: 'a>(
10531050
{
10541051
continue;
10551052
}
1056-
let sp = def.variant(*variant_index).ident(cx.tcx).span;
1053+
let sp = def.variant(*variant_index).ident(tcx).span;
10571054
if covered.contains(&sp) {
10581055
// Don't point at variants that have already been covered due to other patterns to avoid
10591056
// visual clutter.
10601057
continue;
10611058
}
10621059
covered.push(sp);
10631060
}
1064-
covered.extend(maybe_point_at_variant(cx, def, pattern.iter_fields()));
1061+
covered.extend(maybe_point_at_variant(tcx, def, pattern.iter_fields()));
10651062
}
10661063
covered
10671064
}

0 commit comments

Comments
 (0)