Don't recommend if let if let else works

This commit is contained in:
mejrs 2022-12-23 22:23:37 +01:00 committed by David Tolnay
parent 31c20210b9
commit 8476c517c0
No known key found for this signature in database
GPG key ID: F9BA143B95FF6D82
11 changed files with 26 additions and 89 deletions

View file

@ -358,7 +358,7 @@ mir_build_suggest_if_let = you might want to use `if let` to ignore the {$count
*[other] variants that aren't
} matched
mir_build_suggest_let_else = alternatively, you might want to use `let else` to handle the {$count ->
mir_build_suggest_let_else = you might want to use `let else` to handle the {$count ->
[one] variant that isn't
*[other] variants that aren't
} matched

View file

@ -747,9 +747,7 @@ pub(crate) struct PatternNotCovered<'s, 'tcx> {
pub _p: (),
pub pattern_ty: Ty<'tcx>,
#[subdiagnostic]
pub if_let_suggestion: Option<SuggestIfLet>,
#[subdiagnostic]
pub let_else_suggestion: Option<SuggestLetElse>,
pub let_suggestion: Option<SuggestLet>,
#[subdiagnostic]
pub res_defined_here: Option<ResDefinedHere>,
}
@ -809,43 +807,23 @@ pub struct InterpretedAsConst {
}
#[derive(Subdiagnostic)]
pub enum SuggestIfLet {
pub enum SuggestLet {
#[multipart_suggestion(mir_build_suggest_if_let, applicability = "has-placeholders")]
None {
If {
#[suggestion_part(code = "if ")]
start_span: Span,
#[suggestion_part(code = " {{ todo!() }}")]
semi_span: Span,
count: usize,
},
#[multipart_suggestion(mir_build_suggest_if_let, applicability = "has-placeholders")]
One {
#[suggestion_part(code = "let {binding} = if ")]
start_span: Span,
#[suggestion_part(code = " {{ {binding} }} else {{ todo!() }}")]
#[suggestion(
mir_build_suggest_let_else,
code = " else {{ todo!() }}",
applicability = "has-placeholders"
)]
Else {
#[primary_span]
end_span: Span,
binding: Ident,
count: usize,
},
#[multipart_suggestion(mir_build_suggest_if_let, applicability = "has-placeholders")]
More {
#[suggestion_part(code = "let ({bindings}) = if ")]
start_span: Span,
#[suggestion_part(code = " {{ ({bindings}) }} else {{ todo!() }}")]
end_span: Span,
bindings: String,
count: usize,
},
}
#[derive(Subdiagnostic)]
#[suggestion(
mir_build_suggest_let_else,
code = " else {{ todo!() }}",
applicability = "has-placeholders"
)]
pub struct SuggestLetElse {
#[primary_span]
pub end_span: Span,
pub count: usize,
}

View file

@ -394,7 +394,7 @@ fn check_irrefutable(&self, pat: &'tcx Pat<'tcx>, origin: &str, sp: Option<Span>
return;
}
let (inform, interpreted_as_const, res_defined_here, if_let_suggestion, let_else_suggestion) =
let (inform, interpreted_as_const, res_defined_here,let_suggestion) =
if let hir::PatKind::Path(hir::QPath::Resolved(
None,
hir::Path {
@ -417,7 +417,7 @@ fn check_irrefutable(&self, pat: &'tcx Pat<'tcx>, origin: &str, sp: Option<Span>
res,
}
},
None, None,
None,
)
} else if let Some(span) = sp && self.tcx.sess.source_map().is_span_accessible(span) {
let mut bindings = vec![];
@ -430,19 +430,11 @@ fn check_irrefutable(&self, pat: &'tcx Pat<'tcx>, origin: &str, sp: Option<Span>
let start_span = span.shrink_to_lo();
let end_span = semi_span.shrink_to_lo();
let count = witnesses.len();
let if_let = match *bindings {
[] => SuggestIfLet::None{start_span, semi_span, count},
[binding] => SuggestIfLet::One{start_span, end_span, count, binding },
_ => SuggestIfLet::More{start_span, end_span, count, bindings: bindings
.iter()
.map(|ident| ident.to_string())
.collect::<Vec<_>>()
.join(", ")},
};
let let_else = if bindings.is_empty() {None} else{Some( SuggestLetElse{end_span, count })};
(sp.map(|_|Inform), None, None, Some(if_let), let_else)
let let_suggestion = if bindings.is_empty() {SuggestLet::If{start_span, semi_span, count}} else{ SuggestLet::Else{end_span, count }};
(sp.map(|_|Inform), None, None, Some(let_suggestion))
} else{
(sp.map(|_|Inform), None, None, None, None)
(sp.map(|_|Inform), None, None, None)
};
let adt_defined_here = try {
@ -465,8 +457,7 @@ fn check_irrefutable(&self, pat: &'tcx Pat<'tcx>, origin: &str, sp: Option<Span>
interpreted_as_const,
_p: (),
pattern_ty,
if_let_suggestion,
let_else_suggestion,
let_suggestion,
res_defined_here,
adt_defined_here,
});

View file

@ -14,11 +14,7 @@ LL | enum Helper<T, U> {
LL | T(T, [!; 0]),
| - not covered
= note: the matched value is of type `Helper<T, U>`
help: you might want to use `if let` to ignore the variant that isn't matched
|
LL | let u = if let Helper::U(u) = Helper::T(t, []) { u } else { todo!() };
| ++++++++++ ++++++++++++++++++++++
help: alternatively, you might want to use `let else` to handle the variant that isn't matched
help: you might want to use `let else` to handle the variant that isn't matched
|
LL | let Helper::U(u) = Helper::T(t, []) else { todo!() };
| ++++++++++++++++

View file

@ -7,11 +7,7 @@ LL | let Some(y) = x;
= note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
= note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
= note: the matched value is of type `Option<i32>`
help: you might want to use `if let` to ignore the variant that isn't matched
|
LL | let y = if let Some(y) = x { y } else { todo!() };
| ++++++++++ ++++++++++++++++++++++
help: alternatively, you might want to use `let else` to handle the variant that isn't matched
help: you might want to use `let else` to handle the variant that isn't matched
|
LL | let Some(y) = x else { todo!() };
| ++++++++++++++++

View file

@ -7,11 +7,7 @@ LL | let Ok(_x) = foo();
= note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
= note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
= note: the matched value is of type `Result<u32, !>`
help: you might want to use `if let` to ignore the variant that isn't matched
|
LL | let _x = if let Ok(_x) = foo() { _x } else { todo!() };
| +++++++++++ +++++++++++++++++++++++
help: alternatively, you might want to use `let else` to handle the variant that isn't matched
help: you might want to use `let else` to handle the variant that isn't matched
|
LL | let Ok(_x) = foo() else { todo!() };
| ++++++++++++++++

View file

@ -17,11 +17,7 @@ LL | Bar,
LL | Baz
| --- not covered
= note: the matched value is of type `Thing`
help: you might want to use `if let` to ignore the variants that aren't matched
|
LL | let y = if let Thing::Foo(y) = Thing::Foo(1) { y } else { todo!() };
| ++++++++++ ++++++++++++++++++++++
help: alternatively, you might want to use `let else` to handle the variants that aren't matched
help: you might want to use `let else` to handle the variants that aren't matched
|
LL | let Thing::Foo(y) = Thing::Foo(1) else { todo!() };
| ++++++++++++++++

View file

@ -183,11 +183,7 @@ LL | enum Opt {
LL | None,
| ---- not covered
= note: the matched value is of type `Opt`
help: you might want to use `if let` to ignore the variant that isn't matched
|
LL | let _x = if let Opt::Some(ref _x) = e { _x } else { todo!() };
| +++++++++++ +++++++++++++++++++++++
help: alternatively, you might want to use `let else` to handle the variant that isn't matched
help: you might want to use `let else` to handle the variant that isn't matched
|
LL | let Opt::Some(ref _x) = e else { todo!() };
| ++++++++++++++++

View file

@ -7,11 +7,7 @@ LL | let Ok(x) = res;
= note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
= note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
= note: the matched value is of type `Result<u32, &R<'_>>`
help: you might want to use `if let` to ignore the variant that isn't matched
|
LL | let x = if let Ok(x) = res { x } else { todo!() };
| ++++++++++ ++++++++++++++++++++++
help: alternatively, you might want to use `let else` to handle the variant that isn't matched
help: you might want to use `let else` to handle the variant that isn't matched
|
LL | let Ok(x) = res else { todo!() };
| ++++++++++++++++

View file

@ -14,11 +14,7 @@ LL | enum Foo {
LL | A(foo::SecretlyEmpty),
| - not covered
= note: the matched value is of type `Foo`
help: you might want to use `if let` to ignore the variant that isn't matched
|
LL | let (_y, _z) = if let Foo::D(_y, _z) = x { (_y, _z) } else { todo!() };
| +++++++++++++++++ +++++++++++++++++++++++++++++
help: alternatively, you might want to use `let else` to handle the variant that isn't matched
help: you might want to use `let else` to handle the variant that isn't matched
|
LL | let Foo::D(_y, _z) = x else { todo!() };
| ++++++++++++++++

View file

@ -104,11 +104,7 @@ LL | let Ok(x) = x;
= note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
= note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
= note: the matched value is of type `Result<u32, Void>`
help: you might want to use `if let` to ignore the variant that isn't matched
|
LL | let x = if let Ok(x) = x { x } else { todo!() };
| ++++++++++ ++++++++++++++++++++++
help: alternatively, you might want to use `let else` to handle the variant that isn't matched
help: you might want to use `let else` to handle the variant that isn't matched
|
LL | let Ok(x) = x else { todo!() };
| ++++++++++++++++