Skip to content

Commit a5907a5

Browse files
committed
Introduce option_take_on_temporary lints
This lint checks if Option::take() is used on a temporary value (a value that is not of type &mut Option and that is not a Place expression) to suggest omitting take()
1 parent a63308b commit a5907a5

7 files changed

+53
-0
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3504,6 +3504,7 @@ Released 2018-09-13
35043504
[`option_map_or_none`]: https://rust-lang.github.io/rust-clippy/master/index.html#option_map_or_none
35053505
[`option_map_unit_fn`]: https://rust-lang.github.io/rust-clippy/master/index.html#option_map_unit_fn
35063506
[`option_option`]: https://rust-lang.github.io/rust-clippy/master/index.html#option_option
3507+
[`option_take_on_temporary`]: https://rust-lang.github.io/rust-clippy/master/index.html#option_take_on_temporary
35073508
[`or_fun_call`]: https://rust-lang.github.io/rust-clippy/master/index.html#or_fun_call
35083509
[`or_then_unwrap`]: https://rust-lang.github.io/rust-clippy/master/index.html#or_then_unwrap
35093510
[`out_of_bounds_indexing`]: https://rust-lang.github.io/rust-clippy/master/index.html#out_of_bounds_indexing

clippy_lints/src/lib.register_all.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,7 @@ store.register_group(true, "clippy::all", Some("clippy_all"), vec![
188188
LintId::of(methods::OPTION_AS_REF_DEREF),
189189
LintId::of(methods::OPTION_FILTER_MAP),
190190
LintId::of(methods::OPTION_MAP_OR_NONE),
191+
LintId::of(methods::OPTION_TAKE_ON_TEMPORARY),
191192
LintId::of(methods::OR_FUN_CALL),
192193
LintId::of(methods::OR_THEN_UNWRAP),
193194
LintId::of(methods::RESULT_MAP_OR_INTO_OPTION),

clippy_lints/src/lib.register_lints.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,7 @@ store.register_lints(&[
327327
methods::OPTION_AS_REF_DEREF,
328328
methods::OPTION_FILTER_MAP,
329329
methods::OPTION_MAP_OR_NONE,
330+
methods::OPTION_TAKE_ON_TEMPORARY,
330331
methods::OR_FUN_CALL,
331332
methods::OR_THEN_UNWRAP,
332333
methods::RESULT_MAP_OR_INTO_OPTION,

clippy_lints/src/lib.register_suspicious.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ store.register_group(true, "clippy::suspicious", Some("clippy_suspicious"), vec!
2222
LintId::of(loops::EMPTY_LOOP),
2323
LintId::of(loops::FOR_LOOPS_OVER_FALLIBLES),
2424
LintId::of(loops::MUT_RANGE_BOUND),
25+
LintId::of(methods::OPTION_TAKE_ON_TEMPORARY),
2526
LintId::of(methods::SUSPICIOUS_MAP),
2627
LintId::of(mut_key::MUTABLE_KEY_TYPE),
2728
LintId::of(octal_escapes::OCTAL_ESCAPES),

clippy_lints/src/methods/mod.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ mod ok_expect;
4646
mod option_as_ref_deref;
4747
mod option_map_or_none;
4848
mod option_map_unwrap_or;
49+
mod option_take_on_temporary;
4950
mod or_fun_call;
5051
mod or_then_unwrap;
5152
mod search_is_some;
@@ -2131,6 +2132,24 @@ declare_clippy_lint! {
21312132
"no-op use of `deref` or `deref_mut` method to `Option`."
21322133
}
21332134

2135+
declare_clippy_lint! {
2136+
///
2137+
/// ### Why is this bad?
2138+
///
2139+
/// ### Example
2140+
/// ```rust
2141+
/// // example code where clippy issues a warning
2142+
/// ```
2143+
/// Use instead:
2144+
/// ```rust
2145+
/// // example code which does not raise clippy warning
2146+
/// ```
2147+
#[clippy::version = "1.61.0"]
2148+
pub OPTION_TAKE_ON_TEMPORARY,
2149+
suspicious,
2150+
"using `.as_ref().take()` on a temporary value"
2151+
}
2152+
21342153
pub struct Methods {
21352154
avoid_breaking_exported_api: bool,
21362155
msrv: Option<RustcVersion>,
@@ -2219,6 +2238,7 @@ impl_lint_pass!(Methods => [
22192238
UNNECESSARY_JOIN,
22202239
ERR_EXPECT,
22212240
NEEDLESS_OPTION_AS_DEREF,
2241+
OPTION_TAKE_ON_TEMPORARY,
22222242
]);
22232243

22242244
/// Extracts a method call name, args, and `Span` of the method name.
@@ -2595,6 +2615,7 @@ fn check_methods<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, msrv: Optio
25952615
}
25962616
}
25972617
},
2618+
("take", []) => option_take_on_temporary::check(cx, expr, recv),
25982619
("to_os_string" | "to_owned" | "to_path_buf" | "to_vec", []) => {
25992620
implicit_clone::check(cx, name, expr, recv);
26002621
},
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
use clippy_utils::diagnostics::span_lint;
2+
use clippy_utils::ty::is_type_diagnostic_item;
3+
use rustc_hir::Expr;
4+
use rustc_lint::LateContext;
5+
use rustc_span::sym::Result as sym_result;
6+
7+
use super::OPTION_TAKE_ON_TEMPORARY;
8+
9+
pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, recv: &'tcx Expr<'_>) {
10+
if_chain! {
11+
if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym_result);
12+
let result_type = cx.typeck_results().expr_ty(recv);
13+
14+
then {
15+
span_lint(
16+
cx,
17+
OPTION_TAKE_ON_TEMPORARY,
18+
expr.span,
19+
"Format test"
20+
);
21+
}
22+
};
23+
}

tests/ui/option_take_on_temporary.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
fn main() {
2+
println!("Testing option_take_on_temporary");
3+
let x = Some(3);
4+
let y = x.as_ref().take();
5+
}

0 commit comments

Comments
 (0)