-use super::_match::{MatchCheckCtxt, Matrix, expand_pattern, is_useful};
+use super::_match::{MatchCheckCtxt, Matrix, Witness, expand_pattern, is_useful};
use super::_match::Usefulness::*;
use super::_match::WitnessPreference::*;
signalled_error: SignalledError,
}
-impl<'a, 'tcx> Visitor<'tcx> for MatchVisitor<'a, 'tcx> {
+impl<'tcx> Visitor<'tcx> for MatchVisitor<'_, 'tcx> {
fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
NestedVisitorMap::None
}
}
}
-
-impl<'a, 'tcx> PatternContext<'a, 'tcx> {
+impl PatternContext<'_, '_> {
fn report_inlining_errors(&self, pat_span: Span) {
for error in &self.errors {
match *error {
}
}
-impl<'a, 'tcx> MatchVisitor<'a, 'tcx> {
+impl<'tcx> MatchVisitor<'_, 'tcx> {
fn check_patterns(&mut self, has_guard: bool, pats: &[P<Pat>]) {
check_legality_of_move_bindings(self, has_guard, pats);
for pat in pats {
expand_pattern(cx, pattern)
]].into_iter().collect();
- let wild_pattern = Pattern {
- ty: pattern_ty,
- span: DUMMY_SP,
- kind: box PatternKind::Wild,
- };
- let witness = match is_useful(cx, &pats, &[&wild_pattern], ConstructWitness) {
- UsefulWithWitness(witness) => witness,
- NotUseful => return,
- Useful => bug!()
+ let witness = match check_not_useful(cx, pattern_ty, &pats) {
+ Ok(_) => return,
+ Err((witness, _)) => witness,
};
let pattern_string = witness[0].single_pattern().to_string();
"refutable pattern in {}: `{}` not covered",
origin, pattern_string
);
- let label_msg = match pat.node {
+ err.span_label(pat.span, match pat.node {
PatKind::Path(hir::QPath::Resolved(None, ref path))
if path.segments.len() == 1 && path.segments[0].args.is_none() => {
format!("interpreted as {} {} pattern, not new variable",
path.res.article(), path.res.descr())
}
_ => format!("pattern `{}` not covered", pattern_string),
- };
- err.span_label(pat.span, label_msg);
- if let ty::Adt(def, _) = pattern_ty.sty {
- if let Some(sp) = self.tcx.hir().span_if_local(def.did){
- err.span_label(sp, format!("`{}` defined here", pattern_ty));
- }
- }
+ });
+ adt_defined_here(cx, pattern_ty.peel_refs(), &mut err);
err.emit();
});
}
}
// Check for unreachable patterns
-fn check_arms<'a, 'tcx>(
- cx: &mut MatchCheckCtxt<'a, 'tcx>,
- arms: &[(Vec<(&'a Pattern<'tcx>, &hir::Pat)>, Option<&hir::Expr>)],
+fn check_arms<'tcx>(
+ cx: &mut MatchCheckCtxt<'_, 'tcx>,
+ arms: &[(Vec<(&Pattern<'tcx>, &hir::Pat)>, Option<&hir::Expr>)],
source: hir::MatchSource,
) {
let mut seen = Matrix::empty();
}
}
-fn check_exhaustive<'p, 'a, 'tcx>(
- cx: &mut MatchCheckCtxt<'a, 'tcx>,
+fn check_not_useful(
+ cx: &mut MatchCheckCtxt<'_, 'tcx>,
+ ty: Ty<'tcx>,
+ matrix: &Matrix<'_, 'tcx>,
+) -> Result<(), (Vec<Witness<'tcx>>, Pattern<'tcx>)> {
+ let wild_pattern = Pattern { ty, span: DUMMY_SP, kind: box PatternKind::Wild };
+ match is_useful(cx, matrix, &[&wild_pattern], ConstructWitness) {
+ NotUseful => Ok(()), // This is good, wildcard pattern isn't reachable.
+ UsefulWithWitness(pats) => Err((pats, wild_pattern)),
+ Useful => bug!(),
+ }
+}
+
+fn check_exhaustive<'tcx>(
+ cx: &mut MatchCheckCtxt<'_, 'tcx>,
scrut_ty: Ty<'tcx>,
sp: Span,
- matrix: &Matrix<'p, 'tcx>,
+ matrix: &Matrix<'_, 'tcx>,
) {
- let wild_pattern = Pattern {
- ty: scrut_ty,
- span: DUMMY_SP,
- kind: box PatternKind::Wild,
+ let (pats, wild_pattern) = match check_not_useful(cx, scrut_ty, matrix) {
+ Ok(_) => return,
+ Err(err) => err,
};
- match is_useful(cx, matrix, &[&wild_pattern], ConstructWitness) {
- UsefulWithWitness(pats) => {
- let witnesses = if pats.is_empty() {
- vec![&wild_pattern]
- } else {
- pats.iter().map(|w| w.single_pattern()).collect()
- };
- const LIMIT: usize = 3;
- let joined_patterns = match witnesses.len() {
- 0 => bug!(),
- 1 => format!("`{}`", witnesses[0]),
- 2..=LIMIT => {
- let (tail, head) = witnesses.split_last().unwrap();
- let head: Vec<_> = head.iter().map(|w| w.to_string()).collect();
- format!("`{}` and `{}`", head.join("`, `"), tail)
- }
- _ => {
- let (head, tail) = witnesses.split_at(LIMIT);
- let head: Vec<_> = head.iter().map(|w| w.to_string()).collect();
- format!("`{}` and {} more", head.join("`, `"), tail.len())
- }
- };
+ let witnesses = if pats.is_empty() {
+ vec![&wild_pattern]
+ } else {
+ pats.iter().map(|w| w.single_pattern()).collect()
+ };
- let label_text = match witnesses.len() {
- 1 => format!("pattern {} not covered", joined_patterns),
- _ => format!("patterns {} not covered", joined_patterns),
- };
- let mut err = create_e0004(cx.tcx.sess, sp, format!(
- "non-exhaustive patterns: {} not covered",
- joined_patterns,
- ));
- err.span_label(sp, label_text);
- // point at the definition of non-covered enum variants
- if let ty::Adt(def, _) = scrut_ty.sty {
- if let Some(sp) = cx.tcx.hir().span_if_local(def.did){
- err.span_label(sp, format!("`{}` defined here", scrut_ty));
- }
- }
- let patterns = witnesses.iter().map(|p| (**p).clone()).collect::<Vec<Pattern<'_>>>();
- if patterns.len() < 4 {
- for sp in maybe_point_at_variant(cx, scrut_ty, patterns.as_slice()) {
- err.span_label(sp, "not covered");
- }
- }
- err.help("ensure that all possible cases are being handled, \
- possibly by adding wildcards or more match arms");
- err.emit();
+ const LIMIT: usize = 3;
+ let joined_patterns = match witnesses.len() {
+ 0 => bug!(),
+ 1 => format!("`{}`", witnesses[0]),
+ 2..=LIMIT => {
+ let (tail, head) = witnesses.split_last().unwrap();
+ let head: Vec<_> = head.iter().map(|w| w.to_string()).collect();
+ format!("`{}` and `{}`", head.join("`, `"), tail)
}
- NotUseful => {
- // This is good, wildcard pattern isn't reachable
+ _ => {
+ let (head, tail) = witnesses.split_at(LIMIT);
+ let head: Vec<_> = head.iter().map(|w| w.to_string()).collect();
+ format!("`{}` and {} more", head.join("`, `"), tail.len())
+ }
+ };
+
+ let mut err = create_e0004(cx.tcx.sess, sp, format!(
+ "non-exhaustive patterns: {} not covered",
+ joined_patterns,
+ ));
+ err.span_label(sp, match witnesses.len() {
+ 1 => format!("pattern {} not covered", joined_patterns),
+ _ => format!("patterns {} not covered", joined_patterns),
+ });
+ // point at the definition of non-covered enum variants
+ let scrut_ty = scrut_ty.peel_refs();
+ adt_defined_here(cx, scrut_ty, &mut err);
+ let patterns = witnesses.iter().map(|p| (**p).clone()).collect::<Vec<Pattern<'_>>>();
+ if patterns.len() < 4 {
+ for sp in maybe_point_at_variant(scrut_ty, &patterns) {
+ err.span_label(sp, "not covered");
}
- _ => bug!()
}
+ err.help("ensure that all possible cases are being handled, \
+ possibly by adding wildcards or more match arms");
+ err.emit();
}
-fn maybe_point_at_variant(
- cx: &mut MatchCheckCtxt<'a, 'tcx>,
- ty: Ty<'tcx>,
- patterns: &[Pattern<'_>],
-) -> Vec<Span> {
+fn adt_defined_here(cx: &mut MatchCheckCtxt<'_, '_>, ty: Ty<'_>, err: &mut DiagnosticBuilder<'_>) {
+ if let ty::Adt(def, _) = ty.sty {
+ if let Some(sp) = cx.tcx.hir().span_if_local(def.did) {
+ err.span_label(sp, format!("`{}` defined here", ty));
+ }
+ }
+}
+
+fn maybe_point_at_variant(ty: Ty<'_>, patterns: &[Pattern<'_>]) -> Vec<Span> {
let mut covered = vec![];
if let ty::Adt(def, _) = ty.sty {
// Don't point at variants that have already been covered due to other patterns to avoid
- // visual clutter
+ // visual clutter.
for pattern in patterns {
- let pk: &PatternKind<'_> = &pattern.kind;
- if let PatternKind::Variant { adt_def, variant_index, subpatterns, .. } = pk {
- if adt_def.did == def.did {
+ use PatternKind::{AscribeUserType, Deref, Variant, Or, Leaf};
+ match &*pattern.kind {
+ AscribeUserType { subpattern, .. } | Deref { subpattern } => {
+ covered.extend(maybe_point_at_variant(ty, slice::from_ref(&subpattern)));
+ }
+ Variant { adt_def, variant_index, subpatterns, .. } if adt_def.did == def.did => {
let sp = def.variants[*variant_index].ident.span;
if covered.contains(&sp) {
continue;
}
covered.push(sp);
- let subpatterns = subpatterns.iter()
+
+ let pats = subpatterns.iter()
.map(|field_pattern| field_pattern.pattern.clone())
- .collect::<Vec<_>>();
- covered.extend(
- maybe_point_at_variant(cx, ty, subpatterns.as_slice()),
- );
+ .collect::<Box<[_]>>();
+ covered.extend(maybe_point_at_variant(ty, &pats));
}
- }
- if let PatternKind::Leaf { subpatterns } = pk {
- let subpatterns = subpatterns.iter()
- .map(|field_pattern| field_pattern.pattern.clone())
- .collect::<Vec<_>>();
- covered.extend(maybe_point_at_variant(cx, ty, subpatterns.as_slice()));
+ Leaf { subpatterns } => {
+ let pats = subpatterns.iter()
+ .map(|field_pattern| field_pattern.pattern.clone())
+ .collect::<Box<[_]>>();
+ covered.extend(maybe_point_at_variant(ty, &pats));
+ }
+ Or { pats } => {
+ let pats = pats.iter().cloned().collect::<Box<[_]>>();
+ covered.extend(maybe_point_at_variant(ty, &pats));
+ }
+ _ => {}
}
}
}
bindings_allowed: bool
}
-impl<'a, 'b, 'tcx, 'v> Visitor<'v> for AtBindingPatternVisitor<'a, 'b, 'tcx> {
+impl<'v> Visitor<'v> for AtBindingPatternVisitor<'_, '_, '_> {
fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'v> {
NestedVisitorMap::None
}