/// ```
pub MANUAL_UNWRAP_OR,
complexity,
- "finds patterns that can be encoded more concisely with `Option::unwrap_or(_else)`"
+ "finds patterns that can be encoded more concisely with `Option::unwrap_or`"
}
declare_lint_pass!(ManualUnwrapOr => [MANUAL_UNWRAP_OR]);
if let Some(scrutinee_snippet) = utils::snippet_opt(cx, scrutinee.span);
if let Some(none_body_snippet) = utils::snippet_opt(cx, none_arm.body.span);
if let Some(indent) = utils::indent_of(cx, expr.span);
+ if constant_simple(cx, cx.typeck_results(), none_arm.body).is_some();
then {
let reindented_none_body =
utils::reindent_multiline(none_body_snippet.into(), true, Some(indent));
- let eager_eval = constant_simple(cx, cx.typeck_results(), none_arm.body).is_some();
- let method = if eager_eval {
- "unwrap_or"
- } else {
- "unwrap_or_else"
- };
utils::span_lint_and_sugg(
cx,
MANUAL_UNWRAP_OR, expr.span,
- &format!("this pattern reimplements `Option::{}`", &method),
+ "this pattern reimplements `Option::unwrap_or`",
"replace with",
format!(
- "{}.{}({}{})",
+ "{}.unwrap_or({})",
scrutinee_snippet,
- method,
- if eager_eval { "" } else { "|| " },
- reindented_none_body
+ reindented_none_body,
),
Applicability::MachineApplicable,
);
Lint {
name: "manual_unwrap_or",
group: "complexity",
- desc: "finds patterns that can be encoded more concisely with `Option::unwrap_or(_else)`",
+ desc: "finds patterns that can be encoded more concisely with `Option::unwrap_or`",
deprecation: None,
module: "manual_unwrap_or",
},
Some(1).unwrap_or(1 + 42);
// multiline case
- Some(1).unwrap_or_else(|| {
- let a = 1 + 42;
- let b = a + 42;
- b + 42
+ #[rustfmt::skip]
+ Some(1).unwrap_or({
+ 42 + 42
+ + 42 + 42 + 42
+ + 42 + 42 + 42
});
// string case
None => break,
};
}
+
+ // cases where the none arm isn't a constant expression
+ // are not linted due to potential ownership issues
+
+ // ownership issue example, don't lint
+ struct NonCopyable;
+ let mut option: Option<NonCopyable> = None;
+ match option {
+ Some(x) => x,
+ None => {
+ option = Some(NonCopyable);
+ // some more code ...
+ option.unwrap()
+ },
+ };
+
+ // ownership issue example, don't lint
+ let option: Option<&str> = None;
+ match option {
+ Some(s) => s,
+ None => &format!("{} {}!", "hello", "world"),
+ };
}
fn main() {}
};
// multiline case
+ #[rustfmt::skip]
match Some(1) {
Some(i) => i,
None => {
- let a = 1 + 42;
- let b = a + 42;
- b + 42
- },
+ 42 + 42
+ + 42 + 42 + 42
+ + 42 + 42 + 42
+ }
};
// string case
None => break,
};
}
+
+ // cases where the none arm isn't a constant expression
+ // are not linted due to potential ownership issues
+
+ // ownership issue example, don't lint
+ struct NonCopyable;
+ let mut option: Option<NonCopyable> = None;
+ match option {
+ Some(x) => x,
+ None => {
+ option = Some(NonCopyable);
+ // some more code ...
+ option.unwrap()
+ },
+ };
+
+ // ownership issue example, don't lint
+ let option: Option<&str> = None;
+ match option {
+ Some(s) => s,
+ None => &format!("{} {}!", "hello", "world"),
+ };
}
fn main() {}
LL | | };
| |_____^ help: replace with: `Some(1).unwrap_or(1 + 42)`
-error: this pattern reimplements `Option::unwrap_or_else`
- --> $DIR/manual_unwrap_or.rs:24:5
+error: this pattern reimplements `Option::unwrap_or`
+ --> $DIR/manual_unwrap_or.rs:25:5
|
LL | / match Some(1) {
LL | | Some(i) => i,
LL | | None => {
-LL | | let a = 1 + 42;
+LL | | 42 + 42
... |
-LL | | },
+LL | | }
LL | | };
| |_____^
|
help: replace with
|
-LL | Some(1).unwrap_or_else(|| {
-LL | let a = 1 + 42;
-LL | let b = a + 42;
-LL | b + 42
+LL | Some(1).unwrap_or({
+LL | 42 + 42
+LL | + 42 + 42 + 42
+LL | + 42 + 42 + 42
LL | });
|
error: this pattern reimplements `Option::unwrap_or`
- --> $DIR/manual_unwrap_or.rs:34:5
+ --> $DIR/manual_unwrap_or.rs:35:5
|
LL | / match Some("Bob") {
LL | | Some(i) => i,