-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Suggest Option::map_or
(_else) for if let Some { y } else { x }
#5301
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
+760
−228
Merged
Changes from all commits
Commits
Show all changes
14 commits
Select commit
Hold shift + click to select a range
bf48a2d
Lint for if let Some(x) = ... instead of Option::map_or
JarredAllen 82f8d4d
Stop linting on macros and correctly use braces for constructs
JarredAllen b85796f
Properly parenthesize to avoid operator precedence errors
JarredAllen 88c8afd
Handle ref, mut, &, and &mut on the option
JarredAllen f73b455
Refactoring
JarredAllen 7c4de9d
Refactoring pt. 2
JarredAllen 5e20475
Don't lint if contains a macro
JarredAllen 5150277
Used clippy to clean itself
JarredAllen 93f0f5d
Last few tweaks
JarredAllen ccb9998
Fix compile error from library change
JarredAllen 6ce9812
Clean existing lint code to match new lint
JarredAllen 6e2d55c
Update compile-test to follow new lint
JarredAllen 1c32263
Formatted updates to lints
JarredAllen c8f700e
Fixed compile errors
JarredAllen File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,267 @@ | ||
use crate::utils; | ||
use crate::utils::sugg::Sugg; | ||
use crate::utils::{match_type, paths, span_lint_and_sugg}; | ||
use if_chain::if_chain; | ||
|
||
use rustc_errors::Applicability; | ||
use rustc_hir::intravisit::{NestedVisitorMap, Visitor}; | ||
use rustc_hir::{Arm, BindingAnnotation, Block, Expr, ExprKind, MatchSource, Mutability, PatKind, UnOp}; | ||
use rustc_lint::{LateContext, LateLintPass}; | ||
use rustc_middle::hir::map::Map; | ||
use rustc_session::{declare_lint_pass, declare_tool_lint}; | ||
|
||
declare_clippy_lint! { | ||
/// **What it does:** | ||
/// Lints usage of `if let Some(v) = ... { y } else { x }` which is more | ||
/// idiomatically done with `Option::map_or` (if the else bit is a simple | ||
/// expression) or `Option::map_or_else` (if the else bit is a longer | ||
/// block). | ||
/// | ||
/// **Why is this bad?** | ||
/// Using the dedicated functions of the Option type is clearer and | ||
/// more concise than an if let expression. | ||
/// | ||
/// **Known problems:** | ||
/// This lint uses whether the block is just an expression or if it has | ||
/// more statements to decide whether to use `Option::map_or` or | ||
/// `Option::map_or_else`. If you have a single expression which calls | ||
/// an expensive function, then it would be more efficient to use | ||
/// `Option::map_or_else`, but this lint would suggest `Option::map_or`. | ||
/// | ||
/// Also, this lint uses a deliberately conservative metric for checking | ||
/// if the inside of either body contains breaks or continues which will | ||
/// cause it to not suggest a fix if either block contains a loop with | ||
/// continues or breaks contained within the loop. | ||
/// | ||
/// **Example:** | ||
/// | ||
/// ```rust | ||
/// # let optional: Option<u32> = Some(0); | ||
/// # fn do_complicated_function() -> u32 { 5 }; | ||
/// let _ = if let Some(foo) = optional { | ||
/// foo | ||
/// } else { | ||
/// 5 | ||
/// }; | ||
/// let _ = if let Some(foo) = optional { | ||
/// foo | ||
/// } else { | ||
/// let y = do_complicated_function(); | ||
/// y*y | ||
/// }; | ||
/// ``` | ||
/// | ||
/// should be | ||
/// | ||
/// ```rust | ||
/// # let optional: Option<u32> = Some(0); | ||
/// # fn do_complicated_function() -> u32 { 5 }; | ||
/// let _ = optional.map_or(5, |foo| foo); | ||
/// let _ = optional.map_or_else(||{ | ||
/// let y = do_complicated_function(); | ||
/// y*y | ||
/// }, |foo| foo); | ||
/// ``` | ||
pub OPTION_IF_LET_ELSE, | ||
pedantic, | ||
"reimplementation of Option::map_or" | ||
} | ||
|
||
declare_lint_pass!(OptionIfLetElse => [OPTION_IF_LET_ELSE]); | ||
|
||
/// Returns true iff the given expression is the result of calling `Result::ok` | ||
fn is_result_ok(cx: &LateContext<'_>, expr: &'_ Expr<'_>) -> bool { | ||
if let ExprKind::MethodCall(ref path, _, &[ref receiver], _) = &expr.kind { | ||
path.ident.name.to_ident_string() == "ok" && match_type(cx, &cx.tables().expr_ty(&receiver), &paths::RESULT) | ||
} else { | ||
false | ||
} | ||
} | ||
|
||
/// A struct containing information about occurences of the | ||
/// `if let Some(..) = .. else` construct that this lint detects. | ||
struct OptionIfLetElseOccurence { | ||
option: String, | ||
method_sugg: String, | ||
some_expr: String, | ||
none_expr: String, | ||
wrap_braces: bool, | ||
} | ||
|
||
struct ReturnBreakContinueMacroVisitor { | ||
seen_return_break_continue: bool, | ||
} | ||
impl ReturnBreakContinueMacroVisitor { | ||
fn new() -> ReturnBreakContinueMacroVisitor { | ||
ReturnBreakContinueMacroVisitor { | ||
seen_return_break_continue: false, | ||
} | ||
} | ||
} | ||
impl<'tcx> Visitor<'tcx> for ReturnBreakContinueMacroVisitor { | ||
type Map = Map<'tcx>; | ||
fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> { | ||
NestedVisitorMap::None | ||
} | ||
|
||
fn visit_expr(&mut self, ex: &'tcx Expr<'tcx>) { | ||
if self.seen_return_break_continue { | ||
// No need to look farther if we've already seen one of them | ||
return; | ||
} | ||
match &ex.kind { | ||
ExprKind::Ret(..) | ExprKind::Break(..) | ExprKind::Continue(..) => { | ||
self.seen_return_break_continue = true; | ||
}, | ||
// Something special could be done here to handle while or for loop | ||
// desugaring, as this will detect a break if there's a while loop | ||
// or a for loop inside the expression. | ||
_ => { | ||
if utils::in_macro(ex.span) { | ||
self.seen_return_break_continue = true; | ||
} else { | ||
rustc_hir::intravisit::walk_expr(self, ex); | ||
} | ||
}, | ||
} | ||
} | ||
} | ||
|
||
fn contains_return_break_continue_macro(expression: &Expr<'_>) -> bool { | ||
let mut recursive_visitor = ReturnBreakContinueMacroVisitor::new(); | ||
recursive_visitor.visit_expr(expression); | ||
recursive_visitor.seen_return_break_continue | ||
} | ||
|
||
/// Extracts the body of a given arm. If the arm contains only an expression, | ||
/// then it returns the expression. Otherwise, it returns the entire block | ||
fn extract_body_from_arm<'a>(arm: &'a Arm<'a>) -> Option<&'a Expr<'a>> { | ||
if let ExprKind::Block( | ||
Block { | ||
stmts: statements, | ||
expr: Some(expr), | ||
.. | ||
}, | ||
_, | ||
) = &arm.body.kind | ||
{ | ||
if let [] = statements { | ||
Some(&expr) | ||
} else { | ||
Some(&arm.body) | ||
} | ||
} else { | ||
None | ||
} | ||
} | ||
|
||
/// If this is the else body of an if/else expression, then we need to wrap | ||
/// it in curcly braces. Otherwise, we don't. | ||
fn should_wrap_in_braces(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { | ||
utils::get_enclosing_block(cx, expr.hir_id).map_or(false, |parent| { | ||
if let Some(Expr { | ||
kind: | ||
ExprKind::Match( | ||
_, | ||
arms, | ||
MatchSource::IfDesugar { | ||
contains_else_clause: true, | ||
} | ||
| MatchSource::IfLetDesugar { | ||
contains_else_clause: true, | ||
}, | ||
), | ||
.. | ||
}) = parent.expr | ||
{ | ||
expr.hir_id == arms[1].body.hir_id | ||
} else { | ||
false | ||
} | ||
}) | ||
} | ||
|
||
fn format_option_in_sugg(cx: &LateContext<'_>, cond_expr: &Expr<'_>, as_ref: bool, as_mut: bool) -> String { | ||
format!( | ||
"{}{}", | ||
Sugg::hir(cx, cond_expr, "..").maybe_par(), | ||
if as_mut { | ||
".as_mut()" | ||
} else if as_ref { | ||
".as_ref()" | ||
} else { | ||
"" | ||
} | ||
) | ||
} | ||
|
||
/// If this expression is the option if let/else construct we're detecting, then | ||
/// this function returns an `OptionIfLetElseOccurence` struct with details if | ||
/// this construct is found, or None if this construct is not found. | ||
fn detect_option_if_let_else(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<OptionIfLetElseOccurence> { | ||
if_chain! { | ||
if !utils::in_macro(expr.span); // Don't lint macros, because it behaves weirdly | ||
if let ExprKind::Match(cond_expr, arms, MatchSource::IfLetDesugar{contains_else_clause: true}) = &expr.kind; | ||
if arms.len() == 2; | ||
if !is_result_ok(cx, cond_expr); // Don't lint on Result::ok because a different lint does it already | ||
if let PatKind::TupleStruct(struct_qpath, &[inner_pat], _) = &arms[0].pat.kind; | ||
if utils::match_qpath(struct_qpath, &paths::OPTION_SOME); | ||
if let PatKind::Binding(bind_annotation, _, id, _) = &inner_pat.kind; | ||
if !contains_return_break_continue_macro(arms[0].body); | ||
if !contains_return_break_continue_macro(arms[1].body); | ||
then { | ||
let capture_mut = if bind_annotation == &BindingAnnotation::Mutable { "mut " } else { "" }; | ||
let some_body = extract_body_from_arm(&arms[0])?; | ||
let none_body = extract_body_from_arm(&arms[1])?; | ||
let method_sugg = match &none_body.kind { | ||
ExprKind::Block(..) => "map_or_else", | ||
_ => "map_or", | ||
}; | ||
let capture_name = id.name.to_ident_string(); | ||
let wrap_braces = should_wrap_in_braces(cx, expr); | ||
let (as_ref, as_mut) = match &cond_expr.kind { | ||
ExprKind::AddrOf(_, Mutability::Not, _) => (true, false), | ||
ExprKind::AddrOf(_, Mutability::Mut, _) => (false, true), | ||
_ => (bind_annotation == &BindingAnnotation::Ref, bind_annotation == &BindingAnnotation::RefMut), | ||
}; | ||
let cond_expr = match &cond_expr.kind { | ||
// Pointer dereferencing happens automatically, so we can omit it in the suggestion | ||
ExprKind::Unary(UnOp::UnDeref, expr) | ExprKind::AddrOf(_, _, expr) => expr, | ||
_ => cond_expr, | ||
}; | ||
Some(OptionIfLetElseOccurence { | ||
option: format_option_in_sugg(cx, cond_expr, as_ref, as_mut), | ||
method_sugg: method_sugg.to_string(), | ||
some_expr: format!("|{}{}| {}", capture_mut, capture_name, Sugg::hir(cx, some_body, "..")), | ||
none_expr: format!("{}{}", if method_sugg == "map_or" { "" } else { "|| " }, Sugg::hir(cx, none_body, "..")), | ||
wrap_braces, | ||
}) | ||
} else { | ||
None | ||
} | ||
} | ||
} | ||
|
||
impl<'a> LateLintPass<'a> for OptionIfLetElse { | ||
fn check_expr(&mut self, cx: &LateContext<'a>, expr: &Expr<'_>) { | ||
if let Some(detection) = detect_option_if_let_else(cx, expr) { | ||
span_lint_and_sugg( | ||
cx, | ||
OPTION_IF_LET_ELSE, | ||
expr.span, | ||
format!("use Option::{} instead of an if let/else", detection.method_sugg).as_str(), | ||
"try", | ||
format!( | ||
"{}{}.{}({}, {}){}", | ||
if detection.wrap_braces { "{ " } else { "" }, | ||
detection.option, | ||
detection.method_sugg, | ||
detection.none_expr, | ||
detection.some_expr, | ||
if detection.wrap_braces { " }" } else { "" }, | ||
), | ||
Applicability::MaybeIncorrect, | ||
); | ||
} | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
// run-rustfix | ||
#![warn(clippy::option_if_let_else)] | ||
|
||
fn bad1(string: Option<&str>) -> (bool, &str) { | ||
string.map_or((false, "hello"), |x| (true, x)) | ||
} | ||
|
||
fn else_if_option(string: Option<&str>) -> Option<(bool, &str)> { | ||
if string.is_none() { | ||
None | ||
} else { string.map_or(Some((false, "")), |x| Some((true, x))) } | ||
} | ||
|
||
fn unop_bad(string: &Option<&str>, mut num: Option<i32>) { | ||
let _ = string.map_or(0, |s| s.len()); | ||
let _ = num.as_ref().map_or(&0, |s| s); | ||
let _ = num.as_mut().map_or(&mut 0, |s| { | ||
*s += 1; | ||
s | ||
}); | ||
let _ = num.as_ref().map_or(&0, |s| s); | ||
let _ = num.map_or(0, |mut s| { | ||
s += 1; | ||
s | ||
}); | ||
let _ = num.as_mut().map_or(&mut 0, |s| { | ||
*s += 1; | ||
s | ||
}); | ||
} | ||
|
||
fn longer_body(arg: Option<u32>) -> u32 { | ||
arg.map_or(13, |x| { | ||
let y = x * x; | ||
y * y | ||
}) | ||
} | ||
|
||
fn test_map_or_else(arg: Option<u32>) { | ||
let _ = arg.map_or_else(|| { | ||
let mut y = 1; | ||
y = (y + 2 / y) / 2; | ||
y = (y + 2 / y) / 2; | ||
y | ||
}, |x| x * x * x * x); | ||
} | ||
|
||
fn negative_tests(arg: Option<u32>) -> u32 { | ||
let _ = if let Some(13) = arg { "unlucky" } else { "lucky" }; | ||
for _ in 0..10 { | ||
let _ = if let Some(x) = arg { | ||
x | ||
} else { | ||
continue; | ||
}; | ||
} | ||
let _ = if let Some(x) = arg { | ||
return x; | ||
} else { | ||
5 | ||
}; | ||
7 | ||
} | ||
|
||
fn main() { | ||
let optional = Some(5); | ||
let _ = optional.map_or(5, |x| x + 2); | ||
let _ = bad1(None); | ||
let _ = else_if_option(None); | ||
unop_bad(&None, None); | ||
let _ = longer_body(None); | ||
test_map_or_else(None); | ||
let _ = negative_tests(None); | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
// run-rustfix | ||
#![warn(clippy::option_if_let_else)] | ||
|
||
fn bad1(string: Option<&str>) -> (bool, &str) { | ||
if let Some(x) = string { | ||
(true, x) | ||
} else { | ||
(false, "hello") | ||
} | ||
} | ||
|
||
fn else_if_option(string: Option<&str>) -> Option<(bool, &str)> { | ||
if string.is_none() { | ||
None | ||
} else if let Some(x) = string { | ||
Some((true, x)) | ||
} else { | ||
Some((false, "")) | ||
} | ||
} | ||
|
||
fn unop_bad(string: &Option<&str>, mut num: Option<i32>) { | ||
let _ = if let Some(s) = *string { s.len() } else { 0 }; | ||
let _ = if let Some(s) = &num { s } else { &0 }; | ||
let _ = if let Some(s) = &mut num { | ||
*s += 1; | ||
s | ||
} else { | ||
&mut 0 | ||
}; | ||
let _ = if let Some(ref s) = num { s } else { &0 }; | ||
let _ = if let Some(mut s) = num { | ||
s += 1; | ||
s | ||
} else { | ||
0 | ||
}; | ||
let _ = if let Some(ref mut s) = num { | ||
*s += 1; | ||
s | ||
} else { | ||
&mut 0 | ||
}; | ||
} | ||
|
||
fn longer_body(arg: Option<u32>) -> u32 { | ||
if let Some(x) = arg { | ||
let y = x * x; | ||
y * y | ||
} else { | ||
13 | ||
} | ||
} | ||
|
||
fn test_map_or_else(arg: Option<u32>) { | ||
let _ = if let Some(x) = arg { | ||
x * x * x * x | ||
} else { | ||
let mut y = 1; | ||
y = (y + 2 / y) / 2; | ||
y = (y + 2 / y) / 2; | ||
y | ||
}; | ||
} | ||
|
||
fn negative_tests(arg: Option<u32>) -> u32 { | ||
let _ = if let Some(13) = arg { "unlucky" } else { "lucky" }; | ||
for _ in 0..10 { | ||
let _ = if let Some(x) = arg { | ||
x | ||
} else { | ||
continue; | ||
}; | ||
} | ||
let _ = if let Some(x) = arg { | ||
return x; | ||
} else { | ||
5 | ||
}; | ||
7 | ||
} | ||
|
||
fn main() { | ||
let optional = Some(5); | ||
let _ = if let Some(x) = optional { x + 2 } else { 5 }; | ||
let _ = bad1(None); | ||
let _ = else_if_option(None); | ||
unop_bad(&None, None); | ||
let _ = longer_body(None); | ||
test_map_or_else(None); | ||
let _ = negative_tests(None); | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,151 @@ | ||
error: use Option::map_or instead of an if let/else | ||
--> $DIR/option_if_let_else.rs:5:5 | ||
| | ||
LL | / if let Some(x) = string { | ||
LL | | (true, x) | ||
LL | | } else { | ||
LL | | (false, "hello") | ||
LL | | } | ||
| |_____^ help: try: `string.map_or((false, "hello"), |x| (true, x))` | ||
| | ||
= note: `-D clippy::option-if-let-else` implied by `-D warnings` | ||
|
||
error: use Option::map_or instead of an if let/else | ||
--> $DIR/option_if_let_else.rs:15:12 | ||
| | ||
LL | } else if let Some(x) = string { | ||
| ____________^ | ||
LL | | Some((true, x)) | ||
LL | | } else { | ||
LL | | Some((false, "")) | ||
LL | | } | ||
| |_____^ help: try: `{ string.map_or(Some((false, "")), |x| Some((true, x))) }` | ||
|
||
error: use Option::map_or instead of an if let/else | ||
--> $DIR/option_if_let_else.rs:23:13 | ||
| | ||
LL | let _ = if let Some(s) = *string { s.len() } else { 0 }; | ||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `string.map_or(0, |s| s.len())` | ||
|
||
error: use Option::map_or instead of an if let/else | ||
--> $DIR/option_if_let_else.rs:24:13 | ||
| | ||
LL | let _ = if let Some(s) = &num { s } else { &0 }; | ||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `num.as_ref().map_or(&0, |s| s)` | ||
|
||
error: use Option::map_or instead of an if let/else | ||
--> $DIR/option_if_let_else.rs:25:13 | ||
| | ||
LL | let _ = if let Some(s) = &mut num { | ||
| _____________^ | ||
LL | | *s += 1; | ||
LL | | s | ||
LL | | } else { | ||
LL | | &mut 0 | ||
LL | | }; | ||
| |_____^ | ||
| | ||
help: try | ||
| | ||
LL | let _ = num.as_mut().map_or(&mut 0, |s| { | ||
LL | *s += 1; | ||
LL | s | ||
LL | }); | ||
| | ||
|
||
error: use Option::map_or instead of an if let/else | ||
--> $DIR/option_if_let_else.rs:31:13 | ||
| | ||
LL | let _ = if let Some(ref s) = num { s } else { &0 }; | ||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `num.as_ref().map_or(&0, |s| s)` | ||
|
||
error: use Option::map_or instead of an if let/else | ||
--> $DIR/option_if_let_else.rs:32:13 | ||
| | ||
LL | let _ = if let Some(mut s) = num { | ||
| _____________^ | ||
LL | | s += 1; | ||
LL | | s | ||
LL | | } else { | ||
LL | | 0 | ||
LL | | }; | ||
| |_____^ | ||
| | ||
help: try | ||
| | ||
LL | let _ = num.map_or(0, |mut s| { | ||
LL | s += 1; | ||
LL | s | ||
LL | }); | ||
| | ||
|
||
error: use Option::map_or instead of an if let/else | ||
--> $DIR/option_if_let_else.rs:38:13 | ||
| | ||
LL | let _ = if let Some(ref mut s) = num { | ||
| _____________^ | ||
LL | | *s += 1; | ||
LL | | s | ||
LL | | } else { | ||
LL | | &mut 0 | ||
LL | | }; | ||
| |_____^ | ||
| | ||
help: try | ||
| | ||
LL | let _ = num.as_mut().map_or(&mut 0, |s| { | ||
LL | *s += 1; | ||
LL | s | ||
LL | }); | ||
| | ||
|
||
error: use Option::map_or instead of an if let/else | ||
--> $DIR/option_if_let_else.rs:47:5 | ||
| | ||
LL | / if let Some(x) = arg { | ||
LL | | let y = x * x; | ||
LL | | y * y | ||
LL | | } else { | ||
LL | | 13 | ||
LL | | } | ||
| |_____^ | ||
| | ||
help: try | ||
| | ||
LL | arg.map_or(13, |x| { | ||
LL | let y = x * x; | ||
LL | y * y | ||
LL | }) | ||
| | ||
|
||
error: use Option::map_or_else instead of an if let/else | ||
--> $DIR/option_if_let_else.rs:56:13 | ||
| | ||
LL | let _ = if let Some(x) = arg { | ||
| _____________^ | ||
LL | | x * x * x * x | ||
LL | | } else { | ||
LL | | let mut y = 1; | ||
... | | ||
LL | | y | ||
LL | | }; | ||
| |_____^ | ||
| | ||
help: try | ||
| | ||
LL | let _ = arg.map_or_else(|| { | ||
LL | let mut y = 1; | ||
LL | y = (y + 2 / y) / 2; | ||
LL | y = (y + 2 / y) / 2; | ||
LL | y | ||
LL | }, |x| x * x * x * x); | ||
| | ||
|
||
error: use Option::map_or instead of an if let/else | ||
--> $DIR/option_if_let_else.rs:85:13 | ||
| | ||
LL | let _ = if let Some(x) = optional { x + 2 } else { 5 }; | ||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `optional.map_or(5, |x| x + 2)` | ||
|
||
error: aborting due to 11 previous errors | ||
|
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.