mirror of
https://github.com/rust-lang/rust.git
synced 2025-06-07 04:38:46 +00:00
Auto merge of #64271 - Centril:non-exhaustive-peel-refs, r=estebank
check_match: refactor + improve non-exhaustive diagnostics for default binding modes Refactor `check_match` a bit with more code-reuse and improve the diagnostics for a non-exhaustive pattern match by peeling off any references from the scrutinee type so that the "defined here" label is added in more cases. For example: ```rust error[E0004]: non-exhaustive patterns: `&mut &B` not covered --> foo.rs:4:11 | 1 | enum E { A, B } | --------------- | | | | | not covered | `E` defined here ... 4 | match x { | ^ pattern `&mut &B` not covered | = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms ``` Moreover, wrt. "defined here", we give irrefutable pattern matching (i.e. in `let`, `for`, and `fn` parameters) a more consistent treatment in line with `match`. r? @estebank
This commit is contained in:
commit
f0b58fcf03
@ -996,6 +996,24 @@ impl<'tcx> ty::TyS<'tcx> {
|
|||||||
debug!("is_type_representable: {:?} is {:?}", self, r);
|
debug!("is_type_representable: {:?} is {:?}", self, r);
|
||||||
r
|
r
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Peel off all reference types in this type until there are none left.
|
||||||
|
///
|
||||||
|
/// This method is idempotent, i.e. `ty.peel_refs().peel_refs() == ty.peel_refs()`.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// - `u8` -> `u8`
|
||||||
|
/// - `&'a mut u8` -> `u8`
|
||||||
|
/// - `&'a &'b u8` -> `u8`
|
||||||
|
/// - `&'a *const &'b u8 -> *const &'b u8`
|
||||||
|
pub fn peel_refs(&'tcx self) -> Ty<'tcx> {
|
||||||
|
let mut ty = self;
|
||||||
|
while let Ref(_, inner_ty, _) = ty.sty {
|
||||||
|
ty = inner_ty;
|
||||||
|
}
|
||||||
|
ty
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_copy_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
|
fn is_copy_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
|
||||||
|
@ -517,9 +517,9 @@ struct PatternContext<'tcx> {
|
|||||||
pub struct Witness<'tcx>(Vec<Pattern<'tcx>>);
|
pub struct Witness<'tcx>(Vec<Pattern<'tcx>>);
|
||||||
|
|
||||||
impl<'tcx> Witness<'tcx> {
|
impl<'tcx> Witness<'tcx> {
|
||||||
pub fn single_pattern(&self) -> &Pattern<'tcx> {
|
pub fn single_pattern(self) -> Pattern<'tcx> {
|
||||||
assert_eq!(self.0.len(), 1);
|
assert_eq!(self.0.len(), 1);
|
||||||
&self.0[0]
|
self.0.into_iter().next().unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn push_wild_constructor<'a>(
|
fn push_wild_constructor<'a>(
|
||||||
|
@ -52,7 +52,7 @@ struct MatchVisitor<'a, 'tcx> {
|
|||||||
signalled_error: SignalledError,
|
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> {
|
fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
|
||||||
NestedVisitorMap::None
|
NestedVisitorMap::None
|
||||||
}
|
}
|
||||||
@ -89,8 +89,7 @@ impl<'a, 'tcx> Visitor<'tcx> for MatchVisitor<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl PatternContext<'_, '_> {
|
||||||
impl<'a, 'tcx> PatternContext<'a, 'tcx> {
|
|
||||||
fn report_inlining_errors(&self, pat_span: Span) {
|
fn report_inlining_errors(&self, pat_span: Span) {
|
||||||
for error in &self.errors {
|
for error in &self.errors {
|
||||||
match *error {
|
match *error {
|
||||||
@ -122,7 +121,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx> MatchVisitor<'a, 'tcx> {
|
impl<'tcx> MatchVisitor<'_, 'tcx> {
|
||||||
fn check_patterns(&mut self, has_guard: bool, pats: &[P<Pat>]) {
|
fn check_patterns(&mut self, has_guard: bool, pats: &[P<Pat>]) {
|
||||||
check_legality_of_move_bindings(self, has_guard, pats);
|
check_legality_of_move_bindings(self, has_guard, pats);
|
||||||
for pat in pats {
|
for pat in pats {
|
||||||
@ -265,37 +264,26 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> {
|
|||||||
expand_pattern(cx, pattern)
|
expand_pattern(cx, pattern)
|
||||||
]].into_iter().collect();
|
]].into_iter().collect();
|
||||||
|
|
||||||
let wild_pattern = Pattern {
|
let witnesses = match check_not_useful(cx, pattern_ty, &pats) {
|
||||||
ty: pattern_ty,
|
Ok(_) => return,
|
||||||
span: DUMMY_SP,
|
Err(err) => err,
|
||||||
kind: box PatternKind::Wild,
|
|
||||||
};
|
|
||||||
let witness = match is_useful(cx, &pats, &[&wild_pattern], ConstructWitness) {
|
|
||||||
UsefulWithWitness(witness) => witness,
|
|
||||||
NotUseful => return,
|
|
||||||
Useful => bug!()
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let pattern_string = witness[0].single_pattern().to_string();
|
let joined_patterns = joined_uncovered_patterns(&witnesses);
|
||||||
let mut err = struct_span_err!(
|
let mut err = struct_span_err!(
|
||||||
self.tcx.sess, pat.span, E0005,
|
self.tcx.sess, pat.span, E0005,
|
||||||
"refutable pattern in {}: `{}` not covered",
|
"refutable pattern in {}: {} not covered",
|
||||||
origin, pattern_string
|
origin, joined_patterns
|
||||||
);
|
);
|
||||||
let label_msg = match pat.node {
|
err.span_label(pat.span, match &pat.node {
|
||||||
PatKind::Path(hir::QPath::Resolved(None, ref path))
|
PatKind::Path(hir::QPath::Resolved(None, path))
|
||||||
if path.segments.len() == 1 && path.segments[0].args.is_none() => {
|
if path.segments.len() == 1 && path.segments[0].args.is_none() => {
|
||||||
format!("interpreted as {} {} pattern, not new variable",
|
format!("interpreted as {} {} pattern, not new variable",
|
||||||
path.res.article(), path.res.descr())
|
path.res.article(), path.res.descr())
|
||||||
}
|
}
|
||||||
_ => format!("pattern `{}` not covered", pattern_string),
|
_ => pattern_not_convered_label(&witnesses, &joined_patterns),
|
||||||
};
|
});
|
||||||
err.span_label(pat.span, label_msg);
|
adt_defined_here(cx, &mut err, pattern_ty, &witnesses);
|
||||||
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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
err.emit();
|
err.emit();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -350,9 +338,9 @@ fn pat_is_catchall(pat: &Pat) -> bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check for unreachable patterns
|
// Check for unreachable patterns
|
||||||
fn check_arms<'a, 'tcx>(
|
fn check_arms<'tcx>(
|
||||||
cx: &mut MatchCheckCtxt<'a, 'tcx>,
|
cx: &mut MatchCheckCtxt<'_, 'tcx>,
|
||||||
arms: &[(Vec<(&'a Pattern<'tcx>, &hir::Pat)>, Option<&hir::Expr>)],
|
arms: &[(Vec<(&Pattern<'tcx>, &hir::Pat)>, Option<&hir::Expr>)],
|
||||||
source: hir::MatchSource,
|
source: hir::MatchSource,
|
||||||
) {
|
) {
|
||||||
let mut seen = Matrix::empty();
|
let mut seen = Matrix::empty();
|
||||||
@ -433,104 +421,124 @@ fn check_arms<'a, 'tcx>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_exhaustive<'p, 'a, 'tcx>(
|
fn check_not_useful(
|
||||||
cx: &mut MatchCheckCtxt<'a, 'tcx>,
|
cx: &mut MatchCheckCtxt<'_, 'tcx>,
|
||||||
scrut_ty: Ty<'tcx>,
|
ty: Ty<'tcx>,
|
||||||
sp: Span,
|
matrix: &Matrix<'_, 'tcx>,
|
||||||
matrix: &Matrix<'p, 'tcx>,
|
) -> Result<(), Vec<Pattern<'tcx>>> {
|
||||||
) {
|
let wild_pattern = Pattern { ty, span: DUMMY_SP, kind: box PatternKind::Wild };
|
||||||
let wild_pattern = Pattern {
|
|
||||||
ty: scrut_ty,
|
|
||||||
span: DUMMY_SP,
|
|
||||||
kind: box PatternKind::Wild,
|
|
||||||
};
|
|
||||||
match is_useful(cx, matrix, &[&wild_pattern], ConstructWitness) {
|
match is_useful(cx, matrix, &[&wild_pattern], ConstructWitness) {
|
||||||
UsefulWithWitness(pats) => {
|
NotUseful => Ok(()), // This is good, wildcard pattern isn't reachable.
|
||||||
let witnesses = if pats.is_empty() {
|
UsefulWithWitness(pats) => Err(if pats.is_empty() {
|
||||||
vec![&wild_pattern]
|
vec![wild_pattern]
|
||||||
} else {
|
} else {
|
||||||
pats.iter().map(|w| w.single_pattern()).collect()
|
pats.into_iter().map(|w| w.single_pattern()).collect()
|
||||||
};
|
}),
|
||||||
|
Useful => bug!(),
|
||||||
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 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();
|
|
||||||
}
|
|
||||||
NotUseful => {
|
|
||||||
// This is good, wildcard pattern isn't reachable
|
|
||||||
}
|
|
||||||
_ => bug!()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn maybe_point_at_variant(
|
fn check_exhaustive<'tcx>(
|
||||||
cx: &mut MatchCheckCtxt<'a, 'tcx>,
|
cx: &mut MatchCheckCtxt<'_, 'tcx>,
|
||||||
ty: Ty<'tcx>,
|
scrut_ty: Ty<'tcx>,
|
||||||
patterns: &[Pattern<'_>],
|
sp: Span,
|
||||||
) -> Vec<Span> {
|
matrix: &Matrix<'_, 'tcx>,
|
||||||
|
) {
|
||||||
|
let witnesses = match check_not_useful(cx, scrut_ty, matrix) {
|
||||||
|
Ok(_) => return,
|
||||||
|
Err(err) => err,
|
||||||
|
};
|
||||||
|
|
||||||
|
let joined_patterns = joined_uncovered_patterns(&witnesses);
|
||||||
|
let mut err = create_e0004(
|
||||||
|
cx.tcx.sess, sp,
|
||||||
|
format!("non-exhaustive patterns: {} not covered", joined_patterns),
|
||||||
|
);
|
||||||
|
err.span_label(sp, pattern_not_convered_label(&witnesses, &joined_patterns));
|
||||||
|
adt_defined_here(cx, &mut err, scrut_ty, &witnesses);
|
||||||
|
err.help(
|
||||||
|
"ensure that all possible cases are being handled, \
|
||||||
|
possibly by adding wildcards or more match arms"
|
||||||
|
)
|
||||||
|
.emit();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn joined_uncovered_patterns(witnesses: &[Pattern<'_>]) -> String {
|
||||||
|
const LIMIT: usize = 3;
|
||||||
|
match witnesses {
|
||||||
|
[] => bug!(),
|
||||||
|
[witness] => format!("`{}`", witness),
|
||||||
|
[head @ .., tail] if head.len() < LIMIT => {
|
||||||
|
let head: Vec<_> = head.iter().map(<_>::to_string).collect();
|
||||||
|
format!("`{}` and `{}`", head.join("`, `"), tail)
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
let (head, tail) = witnesses.split_at(LIMIT);
|
||||||
|
let head: Vec<_> = head.iter().map(<_>::to_string).collect();
|
||||||
|
format!("`{}` and {} more", head.join("`, `"), tail.len())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn pattern_not_convered_label(witnesses: &[Pattern<'_>], joined_patterns: &str) -> String {
|
||||||
|
format!("pattern{} {} not covered", rustc_errors::pluralise!(witnesses.len()), joined_patterns)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Point at the definition of non-covered `enum` variants.
|
||||||
|
fn adt_defined_here(
|
||||||
|
cx: &MatchCheckCtxt<'_, '_>,
|
||||||
|
err: &mut DiagnosticBuilder<'_>,
|
||||||
|
ty: Ty<'_>,
|
||||||
|
witnesses: &[Pattern<'_>],
|
||||||
|
) {
|
||||||
|
let ty = ty.peel_refs();
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
|
||||||
|
if witnesses.len() < 4 {
|
||||||
|
for sp in maybe_point_at_variant(ty, &witnesses) {
|
||||||
|
err.span_label(sp, "not covered");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn maybe_point_at_variant(ty: Ty<'_>, patterns: &[Pattern<'_>]) -> Vec<Span> {
|
||||||
let mut covered = vec![];
|
let mut covered = vec![];
|
||||||
if let ty::Adt(def, _) = ty.sty {
|
if let ty::Adt(def, _) = ty.sty {
|
||||||
// Don't point at variants that have already been covered due to other patterns to avoid
|
// Don't point at variants that have already been covered due to other patterns to avoid
|
||||||
// visual clutter
|
// visual clutter.
|
||||||
for pattern in patterns {
|
for pattern in patterns {
|
||||||
let pk: &PatternKind<'_> = &pattern.kind;
|
use PatternKind::{AscribeUserType, Deref, Variant, Or, Leaf};
|
||||||
if let PatternKind::Variant { adt_def, variant_index, subpatterns, .. } = pk {
|
match &*pattern.kind {
|
||||||
if adt_def.did == def.did {
|
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;
|
let sp = def.variants[*variant_index].ident.span;
|
||||||
if covered.contains(&sp) {
|
if covered.contains(&sp) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
covered.push(sp);
|
covered.push(sp);
|
||||||
let subpatterns = subpatterns.iter()
|
|
||||||
|
let pats = subpatterns.iter()
|
||||||
.map(|field_pattern| field_pattern.pattern.clone())
|
.map(|field_pattern| field_pattern.pattern.clone())
|
||||||
.collect::<Vec<_>>();
|
.collect::<Box<[_]>>();
|
||||||
covered.extend(
|
covered.extend(maybe_point_at_variant(ty, &pats));
|
||||||
maybe_point_at_variant(cx, ty, subpatterns.as_slice()),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
Leaf { subpatterns } => {
|
||||||
if let PatternKind::Leaf { subpatterns } = pk {
|
let pats = subpatterns.iter()
|
||||||
let subpatterns = subpatterns.iter()
|
.map(|field_pattern| field_pattern.pattern.clone())
|
||||||
.map(|field_pattern| field_pattern.pattern.clone())
|
.collect::<Box<[_]>>();
|
||||||
.collect::<Vec<_>>();
|
covered.extend(maybe_point_at_variant(ty, &pats));
|
||||||
covered.extend(maybe_point_at_variant(cx, ty, subpatterns.as_slice()));
|
}
|
||||||
|
Or { pats } => {
|
||||||
|
let pats = pats.iter().cloned().collect::<Box<[_]>>();
|
||||||
|
covered.extend(maybe_point_at_variant(ty, &pats));
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -627,7 +635,7 @@ struct AtBindingPatternVisitor<'a, 'b, 'tcx> {
|
|||||||
bindings_allowed: bool
|
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> {
|
fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'v> {
|
||||||
NestedVisitorMap::None
|
NestedVisitorMap::None
|
||||||
}
|
}
|
||||||
|
@ -268,7 +268,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
op.node.as_str(), lhs_ty),
|
op.node.as_str(), lhs_ty),
|
||||||
);
|
);
|
||||||
let mut suggested_deref = false;
|
let mut suggested_deref = false;
|
||||||
if let Ref(_, mut rty, _) = lhs_ty.sty {
|
if let Ref(_, rty, _) = lhs_ty.sty {
|
||||||
if {
|
if {
|
||||||
self.infcx.type_is_copy_modulo_regions(self.param_env,
|
self.infcx.type_is_copy_modulo_regions(self.param_env,
|
||||||
rty,
|
rty,
|
||||||
@ -279,13 +279,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
.is_ok()
|
.is_ok()
|
||||||
} {
|
} {
|
||||||
if let Ok(lstring) = source_map.span_to_snippet(lhs_expr.span) {
|
if let Ok(lstring) = source_map.span_to_snippet(lhs_expr.span) {
|
||||||
while let Ref(_, rty_inner, _) = rty.sty {
|
|
||||||
rty = rty_inner;
|
|
||||||
}
|
|
||||||
let msg = &format!(
|
let msg = &format!(
|
||||||
"`{}=` can be used on '{}', you can dereference `{}`",
|
"`{}=` can be used on '{}', you can dereference `{}`",
|
||||||
op.node.as_str(),
|
op.node.as_str(),
|
||||||
rty,
|
rty.peel_refs(),
|
||||||
lstring,
|
lstring,
|
||||||
);
|
);
|
||||||
err.span_suggestion(
|
err.span_suggestion(
|
||||||
@ -361,7 +358,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let mut suggested_deref = false;
|
let mut suggested_deref = false;
|
||||||
if let Ref(_, mut rty, _) = lhs_ty.sty {
|
if let Ref(_, rty, _) = lhs_ty.sty {
|
||||||
if {
|
if {
|
||||||
self.infcx.type_is_copy_modulo_regions(self.param_env,
|
self.infcx.type_is_copy_modulo_regions(self.param_env,
|
||||||
rty,
|
rty,
|
||||||
@ -372,17 +369,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
.is_ok()
|
.is_ok()
|
||||||
} {
|
} {
|
||||||
if let Ok(lstring) = source_map.span_to_snippet(lhs_expr.span) {
|
if let Ok(lstring) = source_map.span_to_snippet(lhs_expr.span) {
|
||||||
while let Ref(_, rty_inner, _) = rty.sty {
|
err.help(&format!(
|
||||||
rty = rty_inner;
|
"`{}` can be used on '{}', you can \
|
||||||
}
|
dereference `{2}`: `*{2}`",
|
||||||
let msg = &format!(
|
op.node.as_str(),
|
||||||
"`{}` can be used on '{}', you can \
|
rty.peel_refs(),
|
||||||
dereference `{2}`: `*{2}`",
|
lstring
|
||||||
op.node.as_str(),
|
));
|
||||||
rty,
|
|
||||||
lstring
|
|
||||||
);
|
|
||||||
err.help(msg);
|
|
||||||
suggested_deref = true;
|
suggested_deref = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
error[E0005]: refutable pattern in local binding: `std::i32::MIN..=-1i32` not covered
|
error[E0005]: refutable pattern in local binding: `std::i32::MIN..=-1i32` and `1i32..=std::i32::MAX` not covered
|
||||||
--> $DIR/const-match-check.rs:25:15
|
--> $DIR/const-match-check.rs:25:15
|
||||||
|
|
|
|
||||||
LL | A = { let 0 = 0; 0 },
|
LL | A = { let 0 = 0; 0 },
|
||||||
| ^ pattern `std::i32::MIN..=-1i32` not covered
|
| ^ patterns `std::i32::MIN..=-1i32` and `1i32..=std::i32::MAX` not covered
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
error[E0005]: refutable pattern in local binding: `std::i32::MIN..=-1i32` not covered
|
error[E0005]: refutable pattern in local binding: `std::i32::MIN..=-1i32` and `1i32..=std::i32::MAX` not covered
|
||||||
--> $DIR/const-match-check.rs:31:24
|
--> $DIR/const-match-check.rs:31:24
|
||||||
|
|
|
|
||||||
LL | let x: [i32; { let 0 = 0; 0 }] = [];
|
LL | let x: [i32; { let 0 = 0; 0 }] = [];
|
||||||
| ^ pattern `std::i32::MIN..=-1i32` not covered
|
| ^ patterns `std::i32::MIN..=-1i32` and `1i32..=std::i32::MAX` not covered
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
@ -1,26 +1,26 @@
|
|||||||
error[E0005]: refutable pattern in local binding: `std::i32::MIN..=-1i32` not covered
|
error[E0005]: refutable pattern in local binding: `std::i32::MIN..=-1i32` and `1i32..=std::i32::MAX` not covered
|
||||||
--> $DIR/const-match-check.rs:4:22
|
--> $DIR/const-match-check.rs:4:22
|
||||||
|
|
|
|
||||||
LL | const X: i32 = { let 0 = 0; 0 };
|
LL | const X: i32 = { let 0 = 0; 0 };
|
||||||
| ^ pattern `std::i32::MIN..=-1i32` not covered
|
| ^ patterns `std::i32::MIN..=-1i32` and `1i32..=std::i32::MAX` not covered
|
||||||
|
|
||||||
error[E0005]: refutable pattern in local binding: `std::i32::MIN..=-1i32` not covered
|
error[E0005]: refutable pattern in local binding: `std::i32::MIN..=-1i32` and `1i32..=std::i32::MAX` not covered
|
||||||
--> $DIR/const-match-check.rs:8:23
|
--> $DIR/const-match-check.rs:8:23
|
||||||
|
|
|
|
||||||
LL | static Y: i32 = { let 0 = 0; 0 };
|
LL | static Y: i32 = { let 0 = 0; 0 };
|
||||||
| ^ pattern `std::i32::MIN..=-1i32` not covered
|
| ^ patterns `std::i32::MIN..=-1i32` and `1i32..=std::i32::MAX` not covered
|
||||||
|
|
||||||
error[E0005]: refutable pattern in local binding: `std::i32::MIN..=-1i32` not covered
|
error[E0005]: refutable pattern in local binding: `std::i32::MIN..=-1i32` and `1i32..=std::i32::MAX` not covered
|
||||||
--> $DIR/const-match-check.rs:13:26
|
--> $DIR/const-match-check.rs:13:26
|
||||||
|
|
|
|
||||||
LL | const X: i32 = { let 0 = 0; 0 };
|
LL | const X: i32 = { let 0 = 0; 0 };
|
||||||
| ^ pattern `std::i32::MIN..=-1i32` not covered
|
| ^ patterns `std::i32::MIN..=-1i32` and `1i32..=std::i32::MAX` not covered
|
||||||
|
|
||||||
error[E0005]: refutable pattern in local binding: `std::i32::MIN..=-1i32` not covered
|
error[E0005]: refutable pattern in local binding: `std::i32::MIN..=-1i32` and `1i32..=std::i32::MAX` not covered
|
||||||
--> $DIR/const-match-check.rs:19:26
|
--> $DIR/const-match-check.rs:19:26
|
||||||
|
|
|
|
||||||
LL | const X: i32 = { let 0 = 0; 0 };
|
LL | const X: i32 = { let 0 = 0; 0 };
|
||||||
| ^ pattern `std::i32::MIN..=-1i32` not covered
|
| ^ patterns `std::i32::MIN..=-1i32` and `1i32..=std::i32::MAX` not covered
|
||||||
|
|
||||||
error: aborting due to 4 previous errors
|
error: aborting due to 4 previous errors
|
||||||
|
|
||||||
|
@ -9,8 +9,8 @@ use foo::d;
|
|||||||
const a: u8 = 2;
|
const a: u8 = 2;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let a = 4; //~ ERROR refutable pattern in local binding: `0u8..=1u8` not covered
|
let a = 4; //~ ERROR refutable pattern in local binding: `0u8..=1u8` and `3u8..=std::u8::MAX
|
||||||
let c = 4; //~ ERROR refutable pattern in local binding: `0u8..=1u8` not covered
|
let c = 4; //~ ERROR refutable pattern in local binding: `0u8..=1u8` and `3u8..=std::u8::MAX
|
||||||
let d = 4; //~ ERROR refutable pattern in local binding: `0u8..=1u8` not covered
|
let d = 4; //~ ERROR refutable pattern in local binding: `0u8..=1u8` and `3u8..=std::u8::MAX
|
||||||
fn f() {} // Check that the `NOTE`s still work with an item here (cf. issue #35115).
|
fn f() {} // Check that the `NOTE`s still work with an item here (cf. issue #35115).
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
error[E0005]: refutable pattern in local binding: `0u8..=1u8` not covered
|
error[E0005]: refutable pattern in local binding: `0u8..=1u8` and `3u8..=std::u8::MAX` not covered
|
||||||
--> $DIR/const-pattern-irrefutable.rs:12:9
|
--> $DIR/const-pattern-irrefutable.rs:12:9
|
||||||
|
|
|
|
||||||
LL | let a = 4;
|
LL | let a = 4;
|
||||||
| ^ interpreted as a constant pattern, not new variable
|
| ^ interpreted as a constant pattern, not new variable
|
||||||
|
|
||||||
error[E0005]: refutable pattern in local binding: `0u8..=1u8` not covered
|
error[E0005]: refutable pattern in local binding: `0u8..=1u8` and `3u8..=std::u8::MAX` not covered
|
||||||
--> $DIR/const-pattern-irrefutable.rs:13:9
|
--> $DIR/const-pattern-irrefutable.rs:13:9
|
||||||
|
|
|
|
||||||
LL | let c = 4;
|
LL | let c = 4;
|
||||||
| ^ interpreted as a constant pattern, not new variable
|
| ^ interpreted as a constant pattern, not new variable
|
||||||
|
|
||||||
error[E0005]: refutable pattern in local binding: `0u8..=1u8` not covered
|
error[E0005]: refutable pattern in local binding: `0u8..=1u8` and `3u8..=std::u8::MAX` not covered
|
||||||
--> $DIR/const-pattern-irrefutable.rs:14:9
|
--> $DIR/const-pattern-irrefutable.rs:14:9
|
||||||
|
|
|
|
||||||
LL | let d = 4;
|
LL | let d = 4;
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
error[E0005]: refutable pattern in function argument: `&[]` not covered
|
error[E0005]: refutable pattern in function argument: `&[]`, `&[_]` and `&[_, _, _]` not covered
|
||||||
--> $DIR/const_let_refutable.rs:3:16
|
--> $DIR/const_let_refutable.rs:3:16
|
||||||
|
|
|
|
||||||
LL | const fn slice([a, b]: &[i32]) -> i32 {
|
LL | const fn slice([a, b]: &[i32]) -> i32 {
|
||||||
| ^^^^^^ pattern `&[]` not covered
|
| ^^^^^^ patterns `&[]`, `&[_]` and `&[_, _, _]` not covered
|
||||||
|
|
||||||
error[E0723]: can only call other `const fn` within a `const fn`, but `const <&i32 as std::ops::Add>::add` is not stable as `const fn`
|
error[E0723]: can only call other `const fn` within a `const fn`, but `const <&i32 as std::ops::Add>::add` is not stable as `const fn`
|
||||||
--> $DIR/const_let_refutable.rs:4:5
|
--> $DIR/const_let_refutable.rs:4:5
|
||||||
|
@ -7,6 +7,9 @@ LL | C => {}
|
|||||||
error[E0004]: non-exhaustive patterns: `&T` not covered
|
error[E0004]: non-exhaustive patterns: `&T` not covered
|
||||||
--> $DIR/match_ice.rs:15:11
|
--> $DIR/match_ice.rs:15:11
|
||||||
|
|
|
|
||||||
|
LL | struct T;
|
||||||
|
| --------- `T` defined here
|
||||||
|
...
|
||||||
LL | match K {
|
LL | match K {
|
||||||
| ^ pattern `&T` not covered
|
| ^ pattern `&T` not covered
|
||||||
|
|
|
|
||||||
|
@ -3,6 +3,7 @@ error[E0005]: refutable pattern in local binding: `T(_, _)` not covered
|
|||||||
|
|
|
|
||||||
LL | / enum Helper<T, U> {
|
LL | / enum Helper<T, U> {
|
||||||
LL | | T(T, [!; 0]),
|
LL | | T(T, [!; 0]),
|
||||||
|
| | - not covered
|
||||||
LL | | #[allow(dead_code)]
|
LL | | #[allow(dead_code)]
|
||||||
LL | | U(U),
|
LL | | U(U),
|
||||||
LL | | }
|
LL | | }
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
error[E0005]: refutable pattern in `for` loop binding: `&std::i32::MIN..=0i32` not covered
|
error[E0005]: refutable pattern in `for` loop binding: `&std::i32::MIN..=0i32` and `&2i32..=std::i32::MAX` not covered
|
||||||
--> $DIR/for-loop-refutable-pattern-error-message.rs:2:9
|
--> $DIR/for-loop-refutable-pattern-error-message.rs:2:9
|
||||||
|
|
|
|
||||||
LL | for &1 in [1].iter() {}
|
LL | for &1 in [1].iter() {}
|
||||||
| ^^ pattern `&std::i32::MIN..=0i32` not covered
|
| ^^ patterns `&std::i32::MIN..=0i32` and `&2i32..=std::i32::MAX` not covered
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@ fn main() {
|
|||||||
let values: Vec<u8> = vec![1,2,3,4,5,6,7,8];
|
let values: Vec<u8> = vec![1,2,3,4,5,6,7,8];
|
||||||
|
|
||||||
for &[x,y,z] in values.chunks(3).filter(|&xs| xs.len() == 3) {
|
for &[x,y,z] in values.chunks(3).filter(|&xs| xs.len() == 3) {
|
||||||
//~^ ERROR refutable pattern in `for` loop binding: `&[]` not covered
|
//~^ ERROR refutable pattern in `for` loop binding: `&[]`, `&[_]`, `&[_, _]` and 1 more not
|
||||||
println!("y={}", y);
|
println!("y={}", y);
|
||||||
//~^ ERROR borrow of possibly-uninitialized variable: `y`
|
//~^ ERROR borrow of possibly-uninitialized variable: `y`
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
error[E0005]: refutable pattern in `for` loop binding: `&[]` not covered
|
error[E0005]: refutable pattern in `for` loop binding: `&[]`, `&[_]`, `&[_, _]` and 1 more not covered
|
||||||
--> $DIR/issue-15381.rs:4:9
|
--> $DIR/issue-15381.rs:4:9
|
||||||
|
|
|
|
||||||
LL | for &[x,y,z] in values.chunks(3).filter(|&xs| xs.len() == 3) {
|
LL | for &[x,y,z] in values.chunks(3).filter(|&xs| xs.len() == 3) {
|
||||||
| ^^^^^^^^ pattern `&[]` not covered
|
| ^^^^^^^^ patterns `&[]`, `&[_]`, `&[_, _]` and 1 more not covered
|
||||||
|
|
||||||
error[E0381]: borrow of possibly-uninitialized variable: `y`
|
error[E0381]: borrow of possibly-uninitialized variable: `y`
|
||||||
--> $DIR/issue-15381.rs:6:26
|
--> $DIR/issue-15381.rs:6:26
|
||||||
|
@ -6,5 +6,5 @@ enum Thing {
|
|||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let Thing::Foo(y) = Thing::Foo(1);
|
let Thing::Foo(y) = Thing::Foo(1);
|
||||||
//~^ ERROR refutable pattern in local binding: `Bar` not covered
|
//~^ ERROR refutable pattern in local binding: `Bar` and `Baz` not covered
|
||||||
}
|
}
|
||||||
|
@ -1,15 +1,17 @@
|
|||||||
error[E0005]: refutable pattern in local binding: `Bar` not covered
|
error[E0005]: refutable pattern in local binding: `Bar` and `Baz` not covered
|
||||||
--> $DIR/issue-31561.rs:8:9
|
--> $DIR/issue-31561.rs:8:9
|
||||||
|
|
|
|
||||||
LL | / enum Thing {
|
LL | / enum Thing {
|
||||||
LL | | Foo(u8),
|
LL | | Foo(u8),
|
||||||
LL | | Bar,
|
LL | | Bar,
|
||||||
|
| | --- not covered
|
||||||
LL | | Baz
|
LL | | Baz
|
||||||
|
| | --- not covered
|
||||||
LL | | }
|
LL | | }
|
||||||
| |_- `Thing` defined here
|
| |_- `Thing` defined here
|
||||||
...
|
...
|
||||||
LL | let Thing::Foo(y) = Thing::Foo(1);
|
LL | let Thing::Foo(y) = Thing::Foo(1);
|
||||||
| ^^^^^^^^^^^^^ pattern `Bar` not covered
|
| ^^^^^^^^^^^^^ patterns `Bar` and `Baz` not covered
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
72
src/test/ui/match/non-exhaustive-defined-here.rs
Normal file
72
src/test/ui/match/non-exhaustive-defined-here.rs
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
// Test the "defined here" and "not covered" diagnostic hints.
|
||||||
|
// We also make sure that references are peeled off from the scrutinee type
|
||||||
|
// so that the diagnostics work better with default binding modes.
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
enum E {
|
||||||
|
//~^ `E` defined here
|
||||||
|
//~| `E` defined here
|
||||||
|
//~| `E` defined here
|
||||||
|
//~| `E` defined here
|
||||||
|
//~| `E` defined here
|
||||||
|
//~| `E` defined here
|
||||||
|
A,
|
||||||
|
B,
|
||||||
|
//~^ not covered
|
||||||
|
//~| not covered
|
||||||
|
//~| not covered
|
||||||
|
//~| not covered
|
||||||
|
//~| not covered
|
||||||
|
//~| not covered
|
||||||
|
C
|
||||||
|
//~^ not covered
|
||||||
|
//~| not covered
|
||||||
|
//~| not covered
|
||||||
|
//~| not covered
|
||||||
|
//~| not covered
|
||||||
|
//~| not covered
|
||||||
|
}
|
||||||
|
|
||||||
|
fn by_val(e: E) {
|
||||||
|
let e1 = e.clone();
|
||||||
|
match e1 { //~ ERROR non-exhaustive patterns: `B` and `C` not covered
|
||||||
|
E::A => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
let E::A = e; //~ ERROR refutable pattern in local binding: `B` and `C` not covered
|
||||||
|
}
|
||||||
|
|
||||||
|
fn by_ref_once(e: &E) {
|
||||||
|
match e { //~ ERROR non-exhaustive patterns: `&B` and `&C` not covered
|
||||||
|
E::A => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
let E::A = e; //~ ERROR refutable pattern in local binding: `&B` and `&C` not covered
|
||||||
|
}
|
||||||
|
|
||||||
|
fn by_ref_thrice(e: & &mut &E) {
|
||||||
|
match e { //~ ERROR non-exhaustive patterns: `&&mut &B` and `&&mut &C` not covered
|
||||||
|
E::A => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
let E::A = e;
|
||||||
|
//~^ ERROR refutable pattern in local binding: `&&mut &B` and `&&mut &C` not covered
|
||||||
|
}
|
||||||
|
|
||||||
|
enum Opt {
|
||||||
|
//~^ `Opt` defined here
|
||||||
|
//~| `Opt` defined here
|
||||||
|
Some(u8),
|
||||||
|
None,
|
||||||
|
//~^ not covered
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ref_pat(e: Opt) {
|
||||||
|
match e {//~ ERROR non-exhaustive patterns: `None` not covered
|
||||||
|
Opt::Some(ref _x) => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
let Opt::Some(ref _x) = e; //~ ERROR refutable pattern in local binding: `None` not covered
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
170
src/test/ui/match/non-exhaustive-defined-here.stderr
Normal file
170
src/test/ui/match/non-exhaustive-defined-here.stderr
Normal file
@ -0,0 +1,170 @@
|
|||||||
|
error[E0004]: non-exhaustive patterns: `B` and `C` not covered
|
||||||
|
--> $DIR/non-exhaustive-defined-here.rs:32:11
|
||||||
|
|
|
||||||
|
LL | / enum E {
|
||||||
|
LL | |
|
||||||
|
LL | |
|
||||||
|
LL | |
|
||||||
|
... |
|
||||||
|
LL | | B,
|
||||||
|
| | - not covered
|
||||||
|
... |
|
||||||
|
LL | | C
|
||||||
|
| | - not covered
|
||||||
|
... |
|
||||||
|
LL | |
|
||||||
|
LL | | }
|
||||||
|
| |_- `E` defined here
|
||||||
|
...
|
||||||
|
LL | match e1 {
|
||||||
|
| ^^ patterns `B` and `C` not covered
|
||||||
|
|
|
||||||
|
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
|
||||||
|
|
||||||
|
error[E0005]: refutable pattern in local binding: `B` and `C` not covered
|
||||||
|
--> $DIR/non-exhaustive-defined-here.rs:36:9
|
||||||
|
|
|
||||||
|
LL | / enum E {
|
||||||
|
LL | |
|
||||||
|
LL | |
|
||||||
|
LL | |
|
||||||
|
... |
|
||||||
|
LL | | B,
|
||||||
|
| | - not covered
|
||||||
|
... |
|
||||||
|
LL | | C
|
||||||
|
| | - not covered
|
||||||
|
... |
|
||||||
|
LL | |
|
||||||
|
LL | | }
|
||||||
|
| |_- `E` defined here
|
||||||
|
...
|
||||||
|
LL | let E::A = e;
|
||||||
|
| ^^^^ patterns `B` and `C` not covered
|
||||||
|
|
||||||
|
error[E0004]: non-exhaustive patterns: `&B` and `&C` not covered
|
||||||
|
--> $DIR/non-exhaustive-defined-here.rs:40:11
|
||||||
|
|
|
||||||
|
LL | / enum E {
|
||||||
|
LL | |
|
||||||
|
LL | |
|
||||||
|
LL | |
|
||||||
|
... |
|
||||||
|
LL | | B,
|
||||||
|
| | - not covered
|
||||||
|
... |
|
||||||
|
LL | | C
|
||||||
|
| | - not covered
|
||||||
|
... |
|
||||||
|
LL | |
|
||||||
|
LL | | }
|
||||||
|
| |_- `E` defined here
|
||||||
|
...
|
||||||
|
LL | match e {
|
||||||
|
| ^ patterns `&B` and `&C` not covered
|
||||||
|
|
|
||||||
|
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
|
||||||
|
|
||||||
|
error[E0005]: refutable pattern in local binding: `&B` and `&C` not covered
|
||||||
|
--> $DIR/non-exhaustive-defined-here.rs:44:9
|
||||||
|
|
|
||||||
|
LL | / enum E {
|
||||||
|
LL | |
|
||||||
|
LL | |
|
||||||
|
LL | |
|
||||||
|
... |
|
||||||
|
LL | | B,
|
||||||
|
| | - not covered
|
||||||
|
... |
|
||||||
|
LL | | C
|
||||||
|
| | - not covered
|
||||||
|
... |
|
||||||
|
LL | |
|
||||||
|
LL | | }
|
||||||
|
| |_- `E` defined here
|
||||||
|
...
|
||||||
|
LL | let E::A = e;
|
||||||
|
| ^^^^ patterns `&B` and `&C` not covered
|
||||||
|
|
||||||
|
error[E0004]: non-exhaustive patterns: `&&mut &B` and `&&mut &C` not covered
|
||||||
|
--> $DIR/non-exhaustive-defined-here.rs:48:11
|
||||||
|
|
|
||||||
|
LL | / enum E {
|
||||||
|
LL | |
|
||||||
|
LL | |
|
||||||
|
LL | |
|
||||||
|
... |
|
||||||
|
LL | | B,
|
||||||
|
| | - not covered
|
||||||
|
... |
|
||||||
|
LL | | C
|
||||||
|
| | - not covered
|
||||||
|
... |
|
||||||
|
LL | |
|
||||||
|
LL | | }
|
||||||
|
| |_- `E` defined here
|
||||||
|
...
|
||||||
|
LL | match e {
|
||||||
|
| ^ patterns `&&mut &B` and `&&mut &C` not covered
|
||||||
|
|
|
||||||
|
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
|
||||||
|
|
||||||
|
error[E0005]: refutable pattern in local binding: `&&mut &B` and `&&mut &C` not covered
|
||||||
|
--> $DIR/non-exhaustive-defined-here.rs:52:9
|
||||||
|
|
|
||||||
|
LL | / enum E {
|
||||||
|
LL | |
|
||||||
|
LL | |
|
||||||
|
LL | |
|
||||||
|
... |
|
||||||
|
LL | | B,
|
||||||
|
| | - not covered
|
||||||
|
... |
|
||||||
|
LL | | C
|
||||||
|
| | - not covered
|
||||||
|
... |
|
||||||
|
LL | |
|
||||||
|
LL | | }
|
||||||
|
| |_- `E` defined here
|
||||||
|
...
|
||||||
|
LL | let E::A = e;
|
||||||
|
| ^^^^ patterns `&&mut &B` and `&&mut &C` not covered
|
||||||
|
|
||||||
|
error[E0004]: non-exhaustive patterns: `None` not covered
|
||||||
|
--> $DIR/non-exhaustive-defined-here.rs:65:11
|
||||||
|
|
|
||||||
|
LL | / enum Opt {
|
||||||
|
LL | |
|
||||||
|
LL | |
|
||||||
|
LL | | Some(u8),
|
||||||
|
LL | | None,
|
||||||
|
| | ---- not covered
|
||||||
|
LL | |
|
||||||
|
LL | | }
|
||||||
|
| |_- `Opt` defined here
|
||||||
|
...
|
||||||
|
LL | match e {
|
||||||
|
| ^ pattern `None` not covered
|
||||||
|
|
|
||||||
|
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
|
||||||
|
|
||||||
|
error[E0005]: refutable pattern in local binding: `None` not covered
|
||||||
|
--> $DIR/non-exhaustive-defined-here.rs:69:9
|
||||||
|
|
|
||||||
|
LL | / enum Opt {
|
||||||
|
LL | |
|
||||||
|
LL | |
|
||||||
|
LL | | Some(u8),
|
||||||
|
LL | | None,
|
||||||
|
| | ---- not covered
|
||||||
|
LL | |
|
||||||
|
LL | | }
|
||||||
|
| |_- `Opt` defined here
|
||||||
|
...
|
||||||
|
LL | let Opt::Some(ref _x) = e;
|
||||||
|
| ^^^^^^^^^^^^^^^^^ pattern `None` not covered
|
||||||
|
|
||||||
|
error: aborting due to 8 previous errors
|
||||||
|
|
||||||
|
Some errors have detailed explanations: E0004, E0005.
|
||||||
|
For more information about an error, try `rustc --explain E0004`.
|
@ -1,7 +1,9 @@
|
|||||||
|
// ignore-tidy-linelength
|
||||||
|
|
||||||
fn func((1, (Some(1), 2..=3)): (isize, (Option<isize>, isize))) { }
|
fn func((1, (Some(1), 2..=3)): (isize, (Option<isize>, isize))) { }
|
||||||
//~^ ERROR refutable pattern in function argument: `(_, _)` not covered
|
//~^ ERROR refutable pattern in function argument: `(_, _)` not covered
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let (1, (Some(1), 2..=3)) = (1, (None, 2));
|
let (1, (Some(1), 2..=3)) = (1, (None, 2));
|
||||||
//~^ ERROR refutable pattern in local binding: `(std::i32::MIN..=0i32, _)` not covered
|
//~^ ERROR refutable pattern in local binding: `(std::i32::MIN..=0i32, _)` and `(2i32..=std::i32::MAX, _)` not covered
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
error[E0005]: refutable pattern in function argument: `(_, _)` not covered
|
error[E0005]: refutable pattern in function argument: `(_, _)` not covered
|
||||||
--> $DIR/refutable-pattern-errors.rs:1:9
|
--> $DIR/refutable-pattern-errors.rs:3:9
|
||||||
|
|
|
|
||||||
LL | fn func((1, (Some(1), 2..=3)): (isize, (Option<isize>, isize))) { }
|
LL | fn func((1, (Some(1), 2..=3)): (isize, (Option<isize>, isize))) { }
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^ pattern `(_, _)` not covered
|
| ^^^^^^^^^^^^^^^^^^^^^ pattern `(_, _)` not covered
|
||||||
|
|
||||||
error[E0005]: refutable pattern in local binding: `(std::i32::MIN..=0i32, _)` not covered
|
error[E0005]: refutable pattern in local binding: `(std::i32::MIN..=0i32, _)` and `(2i32..=std::i32::MAX, _)` not covered
|
||||||
--> $DIR/refutable-pattern-errors.rs:5:9
|
--> $DIR/refutable-pattern-errors.rs:7:9
|
||||||
|
|
|
|
||||||
LL | let (1, (Some(1), 2..=3)) = (1, (None, 2));
|
LL | let (1, (Some(1), 2..=3)) = (1, (None, 2));
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^ pattern `(std::i32::MIN..=0i32, _)` not covered
|
| ^^^^^^^^^^^^^^^^^^^^^ patterns `(std::i32::MIN..=0i32, _)` and `(2i32..=std::i32::MAX, _)` not covered
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@ error[E0005]: refutable pattern in local binding: `A(_)` not covered
|
|||||||
|
|
|
|
||||||
LL | / enum Foo {
|
LL | / enum Foo {
|
||||||
LL | | A(foo::SecretlyEmpty),
|
LL | | A(foo::SecretlyEmpty),
|
||||||
|
| | - not covered
|
||||||
LL | | B(foo::NotSoSecretlyEmpty),
|
LL | | B(foo::NotSoSecretlyEmpty),
|
||||||
LL | | C(NotSoSecretlyEmpty),
|
LL | | C(NotSoSecretlyEmpty),
|
||||||
LL | | D(u32),
|
LL | | D(u32),
|
||||||
|
Loading…
Reference in New Issue
Block a user