Support struct patterns
This commit is contained in:
parent
86d57b7bd4
commit
f538402701
|
@ -147,8 +147,8 @@ fn emit_manual_let_else(
|
|||
"this could be rewritten as `let...else`",
|
||||
|diag| {
|
||||
// This is far from perfect, for example there needs to be:
|
||||
// * tracking for multi-binding cases: let (foo, bar) = if let (Some(foo), Ok(bar)) = ...
|
||||
// * renamings of the bindings for many `PatKind`s like structs, slices, etc.
|
||||
// * renamings of the bindings for many `PatKind`s like slices, etc.
|
||||
// * limitations in the existing replacement algorithms
|
||||
// * unused binding collision detection with existing ones
|
||||
// for this to be machine applicable.
|
||||
let mut app = Applicability::HasPlaceholders;
|
||||
|
@ -227,6 +227,33 @@ fn replace_in_pattern(
|
|||
}
|
||||
return or_pat;
|
||||
},
|
||||
PatKind::Struct(path, fields, has_dot_dot) => {
|
||||
let fields = fields
|
||||
.iter()
|
||||
.map(|fld| {
|
||||
if let PatKind::Binding(_, _, name, None) = fld.pat.kind &&
|
||||
let Some(pat_to_put) = ident_map.get(&name.name)
|
||||
{
|
||||
let (sn_fld_name, _) = snippet_with_context(cx, fld.ident.span, span.ctxt(), "", app);
|
||||
let (sn_ptp, _) = snippet_with_context(cx, pat_to_put.span, span.ctxt(), "", app);
|
||||
// TODO: this is a bit of a hack, but it does its job. Ideally, we'd check if pat_to_put is
|
||||
// a PatKind::Binding but that is also hard to get right.
|
||||
if sn_fld_name == sn_ptp {
|
||||
// Field init shorthand
|
||||
return format!("{sn_fld_name}");
|
||||
}
|
||||
return format!("{sn_fld_name}: {sn_ptp}");
|
||||
}
|
||||
let (sn_fld, _) = snippet_with_context(cx, fld.span, span.ctxt(), "", app);
|
||||
sn_fld.into_owned()
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
let fields_string = fields.join(", ");
|
||||
|
||||
let dot_dot_str = if has_dot_dot { " .." } else { "" };
|
||||
let (sn_pth, _) = snippet_with_context(cx, path.span(), span.ctxt(), "", app);
|
||||
return format!("{sn_pth} {{ {fields_string}{dot_dot_str} }}");
|
||||
},
|
||||
// Replace the variable name iff `TupleStruct` has one argument like `Variant(v)`.
|
||||
PatKind::TupleStruct(ref w, args, dot_dot_pos) => {
|
||||
let mut args = args
|
||||
|
|
|
@ -163,6 +163,27 @@ fn fire() {
|
|||
|
||||
// () is preserved: a bit of an edge case but make sure it stays around
|
||||
let w = if let (Some(v), ()) = (g(), ()) { v } else { return };
|
||||
|
||||
// Tuple structs work
|
||||
let w = if let Some(S { v: x }) = Some(S { v: 0 }) {
|
||||
x
|
||||
} else {
|
||||
return;
|
||||
};
|
||||
|
||||
// Field init shorthand is suggested
|
||||
let v = if let Some(S { v: x }) = Some(S { v: 0 }) {
|
||||
x
|
||||
} else {
|
||||
return;
|
||||
};
|
||||
|
||||
// Multi-field structs also work
|
||||
let (x, S { v }, w) = if let Some(U { v, w, x }) = None::<U<S<()>>> {
|
||||
(x, v, w)
|
||||
} else {
|
||||
return;
|
||||
};
|
||||
}
|
||||
|
||||
fn not_fire() {
|
||||
|
@ -298,6 +319,12 @@ fn not_fire() {
|
|||
};
|
||||
}
|
||||
|
||||
struct S {
|
||||
v: u32,
|
||||
struct S<T> {
|
||||
v: T,
|
||||
}
|
||||
|
||||
struct U<T> {
|
||||
v: T,
|
||||
w: T,
|
||||
x: T,
|
||||
}
|
||||
|
|
|
@ -301,7 +301,58 @@ LL | let w = if let (Some(v), ()) = (g(), ()) { v } else { return };
|
|||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let (Some(w), ()) = (g(), ()) else { return };`
|
||||
|
||||
error: this could be rewritten as `let...else`
|
||||
--> $DIR/manual_let_else.rs:275:5
|
||||
--> $DIR/manual_let_else.rs:168:5
|
||||
|
|
||||
LL | / let w = if let Some(S { v: x }) = Some(S { v: 0 }) {
|
||||
LL | | x
|
||||
LL | | } else {
|
||||
LL | | return;
|
||||
LL | | };
|
||||
| |______^
|
||||
|
|
||||
help: consider writing
|
||||
|
|
||||
LL ~ let Some(S { v: w }) = Some(S { v: 0 }) else {
|
||||
LL + return;
|
||||
LL + };
|
||||
|
|
||||
|
||||
error: this could be rewritten as `let...else`
|
||||
--> $DIR/manual_let_else.rs:175:5
|
||||
|
|
||||
LL | / let v = if let Some(S { v: x }) = Some(S { v: 0 }) {
|
||||
LL | | x
|
||||
LL | | } else {
|
||||
LL | | return;
|
||||
LL | | };
|
||||
| |______^
|
||||
|
|
||||
help: consider writing
|
||||
|
|
||||
LL ~ let Some(S { v }) = Some(S { v: 0 }) else {
|
||||
LL + return;
|
||||
LL + };
|
||||
|
|
||||
|
||||
error: this could be rewritten as `let...else`
|
||||
--> $DIR/manual_let_else.rs:182:5
|
||||
|
|
||||
LL | / let (x, S { v }, w) = if let Some(U { v, w, x }) = None::<U<S<()>>> {
|
||||
LL | | (x, v, w)
|
||||
LL | | } else {
|
||||
LL | | return;
|
||||
LL | | };
|
||||
| |______^
|
||||
|
|
||||
help: consider writing
|
||||
|
|
||||
LL ~ let Some(U { v: S { v }, w, x }) = None::<U<S<()>>> else {
|
||||
LL + return;
|
||||
LL + };
|
||||
|
|
||||
|
||||
error: this could be rewritten as `let...else`
|
||||
--> $DIR/manual_let_else.rs:296:5
|
||||
|
|
||||
LL | / let _ = match ff {
|
||||
LL | | Some(value) => value,
|
||||
|
@ -309,5 +360,5 @@ LL | | _ => macro_call!(),
|
|||
LL | | };
|
||||
| |______^ help: consider writing: `let Some(_) = ff else { macro_call!() };`
|
||||
|
||||
error: aborting due to 23 previous errors
|
||||
error: aborting due to 26 previous errors
|
||||
|
||||
|
|
Loading…
Reference in New Issue