@@ -110,6 +110,7 @@ mod unit_hash;
110
110
mod unnecessary_fallible_conversions;
111
111
mod unnecessary_filter_map;
112
112
mod unnecessary_fold;
113
+ mod unnecessary_get_then_check;
113
114
mod unnecessary_iter_cloned;
114
115
mod unnecessary_join;
115
116
mod unnecessary_lazy_eval;
@@ -4011,6 +4012,35 @@ declare_clippy_lint! {
4011
4012
r#"creating a `CStr` through functions when `c""` literals can be used"#
4012
4013
}
4013
4014
4015
+ declare_clippy_lint ! {
4016
+ /// ### What it does
4017
+ /// Checks the usage of `.get().is_some()` or `.get().is_none()` on std map types.
4018
+ ///
4019
+ /// ### Why is this bad?
4020
+ /// It can be done in one call with `.contains()`/`.contains_keys()`.
4021
+ ///
4022
+ /// ### Example
4023
+ /// ```no_run
4024
+ /// # use std::collections::HashSet;
4025
+ /// let s: HashSet<String> = HashSet::new();
4026
+ /// if s.get("a").is_some() {
4027
+ /// // code
4028
+ /// }
4029
+ /// ```
4030
+ /// Use instead:
4031
+ /// ```no_run
4032
+ /// # use std::collections::HashSet;
4033
+ /// let s: HashSet<String> = HashSet::new();
4034
+ /// if s.contains("a") {
4035
+ /// // code
4036
+ /// }
4037
+ /// ```
4038
+ #[ clippy:: version = "1.78.0" ]
4039
+ pub UNNECESSARY_GET_THEN_CHECK ,
4040
+ suspicious,
4041
+ "calling `.get().is_some()` or `.get().is_none()` instead of `.contains()` or `.contains_key()`"
4042
+ }
4043
+
4014
4044
pub struct Methods {
4015
4045
avoid_breaking_exported_api : bool ,
4016
4046
msrv : Msrv ,
@@ -4171,6 +4201,7 @@ impl_lint_pass!(Methods => [
4171
4201
OPTION_AS_REF_CLONED ,
4172
4202
UNNECESSARY_RESULT_MAP_OR_ELSE ,
4173
4203
MANUAL_C_STR_LITERALS ,
4204
+ UNNECESSARY_GET_THEN_CHECK ,
4174
4205
] ) ;
4175
4206
4176
4207
/// Extracts a method call name, args, and `Span` of the method name.
@@ -4587,8 +4618,8 @@ impl Methods {
4587
4618
} ,
4588
4619
( "is_file" , [ ] ) => filetype_is_file:: check ( cx, expr, recv) ,
4589
4620
( "is_digit" , [ radix] ) => is_digit_ascii_radix:: check ( cx, expr, recv, radix, & self . msrv ) ,
4590
- ( "is_none" , [ ] ) => check_is_some_is_none ( cx, expr, recv, false ) ,
4591
- ( "is_some" , [ ] ) => check_is_some_is_none ( cx, expr, recv, true ) ,
4621
+ ( "is_none" , [ ] ) => check_is_some_is_none ( cx, expr, recv, call_span , false ) ,
4622
+ ( "is_some" , [ ] ) => check_is_some_is_none ( cx, expr, recv, call_span , true ) ,
4592
4623
( "iter" | "iter_mut" | "into_iter" , [ ] ) => {
4593
4624
iter_on_single_or_empty_collections:: check ( cx, expr, name, recv) ;
4594
4625
} ,
@@ -4899,9 +4930,15 @@ impl Methods {
4899
4930
}
4900
4931
}
4901
4932
4902
- fn check_is_some_is_none ( cx : & LateContext < ' _ > , expr : & Expr < ' _ > , recv : & Expr < ' _ > , is_some : bool ) {
4903
- if let Some ( ( name @ ( "find" | "position" | "rposition" ) , f_recv, [ arg] , span, _) ) = method_call ( recv) {
4904
- search_is_some:: check ( cx, expr, name, is_some, f_recv, arg, recv, span) ;
4933
+ fn check_is_some_is_none ( cx : & LateContext < ' _ > , expr : & Expr < ' _ > , recv : & Expr < ' _ > , call_span : Span , is_some : bool ) {
4934
+ match method_call ( recv) {
4935
+ Some ( ( name @ ( "find" | "position" | "rposition" ) , f_recv, [ arg] , span, _) ) => {
4936
+ search_is_some:: check ( cx, expr, name, is_some, f_recv, arg, recv, span) ;
4937
+ } ,
4938
+ Some ( ( "get" , f_recv, [ arg] , _, _) ) => {
4939
+ unnecessary_get_then_check:: check ( cx, call_span, recv, f_recv, arg, is_some) ;
4940
+ } ,
4941
+ _ => { } ,
4905
4942
}
4906
4943
}
4907
4944
0 commit comments