Generate let binding variable name for some cases
Given a map call like `x.field.map ...` the suggestion will contain: `if let Some(x_field) ...` Given a map call like `x.map ...` the suggestion will contain: `if let Some(_x) ...` Otherwise it will suggest: `if let Some(_) ...`
This commit is contained in:
parent
d87385b406
commit
d54f70f1f6
@ -133,6 +133,20 @@ fn unit_closure<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'a hir::Expr) -> Op
|
||||
None
|
||||
}
|
||||
|
||||
/// Builds a name for the let binding variable (var_arg)
|
||||
///
|
||||
/// `x.field` => `x_field`
|
||||
/// `y` => `_y`
|
||||
///
|
||||
/// Anything else will return `_`.
|
||||
fn let_binding_name(cx: &LateContext, var_arg: &hir::Expr) -> String {
|
||||
match &var_arg.node {
|
||||
hir::ExprField(_, _) => snippet(cx, var_arg.span, "_").replace(".", "_"),
|
||||
hir::ExprPath(_) => format!("_{}", snippet(cx, var_arg.span, "")),
|
||||
_ => "_".to_string()
|
||||
}
|
||||
}
|
||||
|
||||
fn lint_map_unit_fn(cx: &LateContext, stmt: &hir::Stmt, expr: &hir::Expr, map_args: &[hir::Expr]) {
|
||||
let var_arg = &map_args[0];
|
||||
let fn_arg = &map_args[1];
|
||||
@ -143,7 +157,8 @@ fn lint_map_unit_fn(cx: &LateContext, stmt: &hir::Stmt, expr: &hir::Expr, map_ar
|
||||
|
||||
if is_unit_function(cx, fn_arg) {
|
||||
let msg = "called `map(f)` on an Option value where `f` is a unit function";
|
||||
let suggestion = format!("if let Some(...) = {0} {{ {1}(...) }}",
|
||||
let suggestion = format!("if let Some({0}) = {1} {{ {2}(...) }}",
|
||||
let_binding_name(cx, var_arg),
|
||||
snippet(cx, var_arg.span, "_"),
|
||||
snippet(cx, fn_arg.span, "_"));
|
||||
|
||||
|
@ -86,4 +86,13 @@ fn main() {
|
||||
do_nothing(value)
|
||||
});
|
||||
x.field.map(|value| { do_nothing(value); do_nothing(value); });
|
||||
|
||||
// The following should suggest `if let Some(_X) ...` as it's difficult to generate a proper let variable name for them
|
||||
Some(42).map(diverge);
|
||||
"12".parse::<i32>().ok().map(diverge);
|
||||
Some(plus_one(1)).map(do_nothing);
|
||||
|
||||
// Should suggest `if let Some(_y) ...` to not override the existing foo variable
|
||||
let y = Some(42);
|
||||
y.map(do_nothing);
|
||||
}
|
||||
|
@ -4,7 +4,7 @@ error: called `map(f)` on an Option value where `f` is a unit function
|
||||
33 | x.field.map(do_nothing);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^-
|
||||
| |
|
||||
| help: try this: `if let Some(...) = x.field { do_nothing(...) }`
|
||||
| help: try this: `if let Some(x_field) = x.field { do_nothing(...) }`
|
||||
|
|
||||
= note: `-D option-map-unit-fn` implied by `-D warnings`
|
||||
|
||||
@ -14,7 +14,7 @@ error: called `map(f)` on an Option value where `f` is a unit function
|
||||
35 | x.field.map(do_nothing);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^-
|
||||
| |
|
||||
| help: try this: `if let Some(...) = x.field { do_nothing(...) }`
|
||||
| help: try this: `if let Some(x_field) = x.field { do_nothing(...) }`
|
||||
|
||||
error: called `map(f)` on an Option value where `f` is a unit function
|
||||
--> $DIR/option_map_unit_fn.rs:37:5
|
||||
@ -22,7 +22,7 @@ error: called `map(f)` on an Option value where `f` is a unit function
|
||||
37 | x.field.map(diverge);
|
||||
| ^^^^^^^^^^^^^^^^^^^^-
|
||||
| |
|
||||
| help: try this: `if let Some(...) = x.field { diverge(...) }`
|
||||
| help: try this: `if let Some(x_field) = x.field { diverge(...) }`
|
||||
|
||||
error: called `map(f)` on an Option value where `f` is a unit closure
|
||||
--> $DIR/option_map_unit_fn.rs:43:5
|
||||
@ -164,7 +164,7 @@ error: called `map(f)` on an Option value where `f` is a unit closure
|
||||
87 | || });
|
||||
| ||______^- help: try this: `if let Some(value) = x.field { ... }`
|
||||
| |_______|
|
||||
|
|
||||
|
|
||||
|
||||
error: called `map(f)` on an Option value where `f` is a unit closure
|
||||
--> $DIR/option_map_unit_fn.rs:88:5
|
||||
@ -174,5 +174,37 @@ error: called `map(f)` on an Option value where `f` is a unit closure
|
||||
| |
|
||||
| help: try this: `if let Some(value) = x.field { ... }`
|
||||
|
||||
error: aborting due to 21 previous errors
|
||||
error: called `map(f)` on an Option value where `f` is a unit function
|
||||
--> $DIR/option_map_unit_fn.rs:91:5
|
||||
|
|
||||
91 | Some(42).map(diverge);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^-
|
||||
| |
|
||||
| help: try this: `if let Some(_) = Some(42) { diverge(...) }`
|
||||
|
||||
error: called `map(f)` on an Option value where `f` is a unit function
|
||||
--> $DIR/option_map_unit_fn.rs:92:5
|
||||
|
|
||||
92 | "12".parse::<i32>().ok().map(diverge);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-
|
||||
| |
|
||||
| help: try this: `if let Some(_) = "12".parse::<i32>().ok() { diverge(...) }`
|
||||
|
||||
error: called `map(f)` on an Option value where `f` is a unit function
|
||||
--> $DIR/option_map_unit_fn.rs:93:5
|
||||
|
|
||||
93 | Some(plus_one(1)).map(do_nothing);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-
|
||||
| |
|
||||
| help: try this: `if let Some(_) = Some(plus_one(1)) { do_nothing(...) }`
|
||||
|
||||
error: called `map(f)` on an Option value where `f` is a unit function
|
||||
--> $DIR/option_map_unit_fn.rs:97:5
|
||||
|
|
||||
97 | y.map(do_nothing);
|
||||
| ^^^^^^^^^^^^^^^^^-
|
||||
| |
|
||||
| help: try this: `if let Some(_y) = y { do_nothing(...) }`
|
||||
|
||||
error: aborting due to 25 previous errors
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user