2020-05-17 15:36:26 +00:00
mod bind_instead_of_map ;
2022-06-05 15:39:36 +00:00
mod bytecount ;
2022-06-05 17:05:11 +00:00
mod bytes_count_to_len ;
2021-02-11 14:04:38 +00:00
mod bytes_nth ;
2022-06-05 17:21:04 +00:00
mod case_sensitive_file_extension_comparisons ;
2021-03-25 18:29:11 +00:00
mod chars_cmp ;
mod chars_cmp_with_unwrap ;
mod chars_last_cmp ;
mod chars_last_cmp_with_unwrap ;
mod chars_next_cmp ;
mod chars_next_cmp_with_unwrap ;
2021-03-12 14:30:50 +00:00
mod clone_on_copy ;
mod clone_on_ref_ptr ;
2021-04-22 09:31:13 +00:00
mod cloned_instead_of_copied ;
2022-08-02 20:37:40 +00:00
mod collapsible_str_replace ;
2022-04-07 17:39:59 +00:00
mod err_expect ;
2021-03-12 14:30:50 +00:00
mod expect_fun_call ;
mod expect_used ;
2021-07-29 10:16:06 +00:00
mod extend_with_drain ;
2021-03-12 14:30:50 +00:00
mod filetype_is_file ;
mod filter_map ;
2021-02-11 14:04:38 +00:00
mod filter_map_identity ;
2021-03-12 14:30:50 +00:00
mod filter_map_next ;
mod filter_next ;
mod flat_map_identity ;
2021-04-22 09:31:13 +00:00
mod flat_map_option ;
2021-03-12 14:30:50 +00:00
mod from_iter_instead_of_collect ;
2022-06-05 17:44:09 +00:00
mod get_first ;
2022-05-20 20:33:31 +00:00
mod get_last_with_len ;
2021-03-12 14:30:50 +00:00
mod get_unwrap ;
mod implicit_clone ;
2019-10-16 19:54:20 +00:00
mod inefficient_to_string ;
2021-01-30 17:06:34 +00:00
mod inspect_for_each ;
2021-03-12 14:30:50 +00:00
mod into_iter_on_ref ;
2022-05-05 14:12:52 +00:00
mod is_digit_ascii_radix ;
2021-03-12 14:30:50 +00:00
mod iter_cloned_collect ;
mod iter_count ;
mod iter_next_slice ;
mod iter_nth ;
mod iter_nth_zero ;
2022-07-30 11:39:55 +00:00
mod iter_on_single_or_empty_collections ;
2022-01-17 12:29:07 +00:00
mod iter_overeager_cloned ;
2021-03-12 14:30:50 +00:00
mod iter_skip_next ;
2022-03-14 11:02:53 +00:00
mod iter_with_drain ;
2021-03-12 14:30:50 +00:00
mod iterator_step_by_zero ;
2022-06-05 19:20:47 +00:00
mod manual_ok_or ;
2019-09-04 12:06:28 +00:00
mod manual_saturating_arithmetic ;
2021-06-03 06:41:37 +00:00
mod manual_str_repeat ;
2022-06-05 19:45:04 +00:00
mod map_clone ;
2021-03-12 14:30:50 +00:00
mod map_collect_result_unit ;
2022-06-05 19:59:24 +00:00
mod map_err_ignore ;
2021-03-12 14:30:50 +00:00
mod map_flatten ;
2021-07-01 16:17:38 +00:00
mod map_identity ;
2021-03-12 14:30:50 +00:00
mod map_unwrap_or ;
2022-06-05 23:57:58 +00:00
mod mut_mutex_lock ;
2022-04-07 17:39:59 +00:00
mod needless_option_as_deref ;
2022-05-05 14:12:52 +00:00
mod needless_option_take ;
2022-04-25 14:12:48 +00:00
mod no_effect_replace ;
2022-07-10 21:37:38 +00:00
mod obfuscated_if_else ;
2021-03-12 14:30:50 +00:00
mod ok_expect ;
2022-06-06 00:09:55 +00:00
mod open_options ;
2021-03-12 14:30:50 +00:00
mod option_as_ref_deref ;
mod option_map_or_none ;
2019-01-31 01:15:29 +00:00
mod option_map_unwrap_or ;
2021-03-12 14:30:50 +00:00
mod or_fun_call ;
2022-03-24 13:50:04 +00:00
mod or_then_unwrap ;
2022-06-06 00:27:36 +00:00
mod path_buf_push_overwrite ;
2022-06-06 00:39:57 +00:00
mod range_zip_with_len ;
2022-06-06 00:49:03 +00:00
mod repeat_once ;
2021-03-12 14:30:50 +00:00
mod search_is_some ;
2021-03-25 18:29:11 +00:00
mod single_char_add_str ;
2021-03-12 14:30:50 +00:00
mod single_char_insert_string ;
mod single_char_pattern ;
mod single_char_push_string ;
mod skip_while_next ;
2022-06-06 01:07:29 +00:00
mod stable_sort_primitive ;
2021-12-06 11:33:31 +00:00
mod str_splitn ;
2021-03-12 14:30:50 +00:00
mod string_extend_chars ;
mod suspicious_map ;
2021-06-03 06:41:37 +00:00
mod suspicious_splitn ;
2021-03-12 14:30:50 +00:00
mod uninit_assumed_init ;
2022-06-06 01:41:33 +00:00
mod unit_hash ;
2019-01-31 01:15:29 +00:00
mod unnecessary_filter_map ;
2021-03-12 14:30:50 +00:00
mod unnecessary_fold ;
2021-12-17 12:40:22 +00:00
mod unnecessary_iter_cloned ;
2022-03-24 13:50:04 +00:00
mod unnecessary_join ;
2020-08-28 14:10:16 +00:00
mod unnecessary_lazy_eval ;
2022-06-06 03:22:58 +00:00
mod unnecessary_sort_by ;
2021-12-17 12:40:22 +00:00
mod unnecessary_to_owned ;
2021-08-12 09:16:25 +00:00
mod unwrap_or_else_default ;
2021-03-12 14:30:50 +00:00
mod unwrap_used ;
mod useless_asref ;
2021-03-25 18:29:11 +00:00
mod utils ;
2022-06-06 15:17:38 +00:00
mod vec_resize_to_zero ;
2022-06-06 15:58:30 +00:00
mod verbose_file_reads ;
2021-03-12 14:30:50 +00:00
mod wrong_self_convention ;
mod zst_offset ;
2019-01-31 01:15:29 +00:00
2020-05-17 15:36:26 +00:00
use bind_instead_of_map ::BindInsteadOfMap ;
2021-09-08 14:31:47 +00:00
use clippy_utils ::consts ::{ constant , Constant } ;
2021-03-25 18:29:11 +00:00
use clippy_utils ::diagnostics ::{ span_lint , span_lint_and_help } ;
use clippy_utils ::ty ::{ contains_adt_constructor , contains_ty , implements_trait , is_copy , is_type_diagnostic_item } ;
2022-06-05 15:39:36 +00:00
use clippy_utils ::{
contains_return , get_trait_def_id , is_trait_method , iter_input_pats , meets_msrv , msrvs , paths , return_ty ,
} ;
2018-07-19 08:00:54 +00:00
use if_chain ::if_chain ;
2020-01-06 16:39:50 +00:00
use rustc_hir as hir ;
2021-03-25 18:29:11 +00:00
use rustc_hir ::def ::Res ;
2021-04-08 15:50:13 +00:00
use rustc_hir ::{ Expr , ExprKind , PrimTy , QPath , TraitItem , TraitItemKind } ;
2021-03-25 18:29:11 +00:00
use rustc_lint ::{ LateContext , LateLintPass , LintContext } ;
2020-03-30 09:02:14 +00:00
use rustc_middle ::lint ::in_external_macro ;
2022-01-25 07:42:52 +00:00
use rustc_middle ::ty ::{ self , TraitRef , Ty } ;
2020-12-06 14:01:03 +00:00
use rustc_semver ::RustcVersion ;
use rustc_session ::{ declare_tool_lint , impl_lint_pass } ;
2021-04-08 15:50:13 +00:00
use rustc_span ::{ sym , Span } ;
2020-12-20 16:19:49 +00:00
use rustc_typeck ::hir_ty_to_ty ;
2015-08-11 18:53:50 +00:00
2021-04-22 09:31:13 +00:00
declare_clippy_lint! {
2021-07-29 10:16:06 +00:00
/// ### What it does
/// Checks for usages of `cloned()` on an `Iterator` or `Option` where
2021-04-22 09:31:13 +00:00
/// `copied()` could be used instead.
///
2021-07-29 10:16:06 +00:00
/// ### Why is this bad?
/// `copied()` is better because it guarantees that the type being cloned
2021-04-22 09:31:13 +00:00
/// implements `Copy`.
///
2021-07-29 10:16:06 +00:00
/// ### Example
2021-04-22 09:31:13 +00:00
/// ```rust
/// [1, 2, 3].iter().cloned();
/// ```
/// Use instead:
/// ```rust
/// [1, 2, 3].iter().copied();
/// ```
2021-12-06 11:33:31 +00:00
#[ clippy::version = " 1.53.0 " ]
2021-04-22 09:31:13 +00:00
pub CLONED_INSTEAD_OF_COPIED ,
pedantic ,
" used `cloned` where `copied` could be used instead "
}
2022-08-02 20:37:40 +00:00
declare_clippy_lint! {
/// ### What it does
/// Checks for consecutive calls to `str::replace` (2 or more)
/// that can be collapsed into a single call.
///
/// ### Why is this bad?
/// Consecutive `str::replace` calls scan the string multiple times
/// with repetitive code.
///
/// ### Example
/// ```rust
/// let hello = "hesuo worpd"
/// .replace('s', "l")
/// .replace("u", "l")
2022-08-08 20:31:53 +00:00
/// .replace('p', "l");
2022-08-02 20:37:40 +00:00
/// ```
/// Use instead:
/// ```rust
2022-08-14 16:33:55 +00:00
/// let hello = "hesuo worpd".replace(&['s', 'u', 'p'], "l");
2022-08-02 20:37:40 +00:00
/// ```
#[ clippy::version = " 1.64.0 " ]
pub COLLAPSIBLE_STR_REPLACE ,
perf ,
" collapse consecutive calls to str::replace (2 or more) into a single call "
}
2022-01-17 12:29:07 +00:00
declare_clippy_lint! {
/// ### What it does
/// Checks for usage of `_.cloned().<func>()` where call to `.cloned()` can be postponed.
///
/// ### Why is this bad?
/// It's often inefficient to clone all elements of an iterator, when eventually, only some
/// of them will be consumed.
///
2022-06-05 19:24:41 +00:00
/// ### Known Problems
/// This `lint` removes the side of effect of cloning items in the iterator.
/// A code that relies on that side-effect could fail.
///
2022-01-17 12:29:07 +00:00
/// ### Examples
/// ```rust
/// # let vec = vec!["string".to_string()];
/// vec.iter().cloned().take(10);
/// vec.iter().cloned().last();
2022-06-05 19:24:41 +00:00
/// ```
2022-01-17 12:29:07 +00:00
///
2022-06-05 19:24:41 +00:00
/// Use instead:
/// ```rust
/// # let vec = vec!["string".to_string()];
/// vec.iter().take(10).cloned();
2022-01-17 12:29:07 +00:00
/// vec.iter().last().cloned();
/// ```
2022-06-09 13:43:26 +00:00
#[ clippy::version = " 1.60.0 " ]
2022-01-17 12:29:07 +00:00
pub ITER_OVEREAGER_CLONED ,
perf ,
" using `cloned()` early with `Iterator::iter()` can lead to some performance inefficiencies "
}
2021-04-22 09:31:13 +00:00
declare_clippy_lint! {
2021-07-29 10:16:06 +00:00
/// ### What it does
/// Checks for usages of `Iterator::flat_map()` where `filter_map()` could be
2021-04-22 09:31:13 +00:00
/// used instead.
///
2021-07-29 10:16:06 +00:00
/// ### Why is this bad?
/// When applicable, `filter_map()` is more clear since it shows that
2021-04-22 09:31:13 +00:00
/// `Option` is used to produce 0 or 1 items.
///
2021-07-29 10:16:06 +00:00
/// ### Example
2021-04-22 09:31:13 +00:00
/// ```rust
/// let nums: Vec<i32> = ["1", "2", "whee!"].iter().flat_map(|x| x.parse().ok()).collect();
/// ```
/// Use instead:
/// ```rust
/// let nums: Vec<i32> = ["1", "2", "whee!"].iter().filter_map(|x| x.parse().ok()).collect();
/// ```
2021-12-06 11:33:31 +00:00
#[ clippy::version = " 1.53.0 " ]
2021-04-22 09:31:13 +00:00
pub FLAT_MAP_OPTION ,
pedantic ,
" used `flat_map` where `filter_map` could be used instead "
}
2018-03-28 13:24:26 +00:00
declare_clippy_lint! {
2021-07-29 10:16:06 +00:00
/// ### What it does
2022-08-15 18:30:30 +00:00
/// Checks for `.unwrap()` or `.unwrap_err()` calls on `Result`s and `.unwrap()` call on `Option`s.
2019-03-05 16:50:33 +00:00
///
2021-07-29 10:16:06 +00:00
/// ### Why is this bad?
/// It is better to handle the `None` or `Err` case,
2020-05-17 15:36:26 +00:00
/// or at least call `.expect(_)` with a more helpful message. Still, for a lot of
2019-03-05 16:50:33 +00:00
/// quick-and-dirty code, `unwrap` is a good choice, which is why this lint is
/// `Allow` by default.
///
2020-05-17 15:36:26 +00:00
/// `result.unwrap()` will let the thread panic on `Err` values.
/// Normally, you want to implement more sophisticated error handling,
2020-01-04 04:47:01 +00:00
/// and propagate errors upwards with `?` operator.
2019-03-05 16:50:33 +00:00
///
/// Even if you want to panic on errors, not all `Error`s implement good
2019-01-31 01:15:29 +00:00
/// messages on display. Therefore, it may be beneficial to look at the places
2019-03-05 16:50:33 +00:00
/// where they may get displayed. Activate this lint to do just that.
///
2021-07-29 10:16:06 +00:00
/// ### Examples
2019-03-05 16:50:33 +00:00
/// ```rust
2022-06-01 22:36:02 +00:00
/// # let option = Some(1);
/// # let result: Result<usize, ()> = Ok(1);
/// option.unwrap();
/// result.unwrap();
2019-08-03 19:24:50 +00:00
/// ```
///
2022-07-30 11:17:51 +00:00
/// Use instead:
2019-03-05 16:50:33 +00:00
/// ```rust
2022-06-01 22:36:02 +00:00
/// # let option = Some(1);
/// # let result: Result<usize, ()> = Ok(1);
/// option.expect("more helpful message");
/// result.expect("more helpful message");
2019-03-05 16:50:33 +00:00
/// ```
2022-07-28 20:08:48 +00:00
///
2022-07-30 11:17:51 +00:00
/// If [expect_used](#expect_used) is enabled, instead:
2022-07-28 20:27:50 +00:00
/// ```rust,ignore
/// # let option = Some(1);
/// # let result: Result<usize, ()> = Ok(1);
2022-07-28 20:08:48 +00:00
/// option?;
///
/// // or
///
/// result?;
/// ```
2021-12-06 11:33:31 +00:00
#[ clippy::version = " 1.45.0 " ]
2020-05-17 15:36:26 +00:00
pub UNWRAP_USED ,
2018-03-28 13:24:26 +00:00
restriction ,
2020-05-17 15:36:26 +00:00
" using `.unwrap()` on `Result` or `Option`, which should at least get a better message using `expect()` "
2016-02-05 23:13:29 +00:00
}
2015-12-14 21:16:56 +00:00
2019-10-15 19:33:07 +00:00
declare_clippy_lint! {
2021-07-29 10:16:06 +00:00
/// ### What it does
2022-08-15 18:30:30 +00:00
/// Checks for `.expect()` or `.expect_err()` calls on `Result`s and `.expect()` call on `Option`s.
2019-10-15 19:33:07 +00:00
///
2021-07-29 10:16:06 +00:00
/// ### Why is this bad?
/// Usually it is better to handle the `None` or `Err` case.
2020-05-17 15:36:26 +00:00
/// Still, for a lot of quick-and-dirty code, `expect` is a good choice, which is why
/// this lint is `Allow` by default.
2019-10-15 19:33:07 +00:00
///
2020-05-17 15:36:26 +00:00
/// `result.expect()` will let the thread panic on `Err`
/// values. Normally, you want to implement more sophisticated error handling,
/// and propagate errors upwards with `?` operator.
2019-10-15 19:33:07 +00:00
///
2021-07-29 10:16:06 +00:00
/// ### Examples
2020-05-17 15:36:26 +00:00
/// ```rust,ignore
2022-06-01 22:36:02 +00:00
/// # let option = Some(1);
/// # let result: Result<usize, ()> = Ok(1);
/// option.expect("one");
/// result.expect("one");
2019-10-15 19:33:07 +00:00
/// ```
///
2022-06-01 22:36:02 +00:00
/// Use instead:
/// ```rust,ignore
/// # let option = Some(1);
/// # let result: Result<usize, ()> = Ok(1);
/// option?;
2019-10-15 19:33:07 +00:00
///
2022-06-01 22:36:02 +00:00
/// // or
2019-10-15 19:33:07 +00:00
///
2022-06-01 22:36:02 +00:00
/// result?;
2019-10-15 19:33:07 +00:00
/// ```
2021-12-06 11:33:31 +00:00
#[ clippy::version = " 1.45.0 " ]
2020-05-17 15:36:26 +00:00
pub EXPECT_USED ,
2019-10-15 19:33:07 +00:00
restriction ,
2020-05-17 15:36:26 +00:00
" using `.expect()` on `Result` or `Option`, which might be better handled "
2019-10-15 19:33:07 +00:00
}
2018-03-28 13:24:26 +00:00
declare_clippy_lint! {
2021-07-29 10:16:06 +00:00
/// ### What it does
/// Checks for methods that should live in a trait
2019-03-05 16:50:33 +00:00
/// implementation of a `std` trait (see [llogiq's blog
/// post](http://llogiq.github.io/2015/07/30/traits.html) for further
/// information) instead of an inherent implementation.
///
2021-07-29 10:16:06 +00:00
/// ### Why is this bad?
/// Implementing the traits improve ergonomics for users of
2019-03-05 16:50:33 +00:00
/// the code, often with very little cost. Also people seeing a `mul(...)`
/// method
/// may expect `*` to work equally, so you should have good reason to disappoint
/// them.
///
2021-07-29 10:16:06 +00:00
/// ### Example
2020-01-30 22:44:37 +00:00
/// ```rust
2019-03-05 16:50:33 +00:00
/// struct X;
/// impl X {
/// fn add(&self, other: &X) -> X {
2020-01-30 22:44:37 +00:00
/// // ..
/// # X
2019-03-05 16:50:33 +00:00
/// }
/// }
/// ```
2021-12-06 11:33:31 +00:00
#[ clippy::version = " pre 1.29.0 " ]
2016-08-06 08:18:36 +00:00
pub SHOULD_IMPLEMENT_TRAIT ,
2018-03-28 13:24:26 +00:00
style ,
2016-02-05 23:13:29 +00:00
" defining a method that should be implementing a std trait "
}
2015-12-14 21:16:56 +00:00
2018-03-28 13:24:26 +00:00
declare_clippy_lint! {
2021-07-29 10:16:06 +00:00
/// ### What it does
/// Checks for methods with certain name prefixes and which
2019-03-05 16:50:33 +00:00
/// doesn't match how self is taken. The actual rules are:
///
2022-05-05 14:12:52 +00:00
/// |Prefix |Postfix |`self` taken | `self` type |
/// |-------|------------|-------------------------------|--------------|
/// |`as_` | none |`&self` or `&mut self` | any |
/// |`from_`| none | none | any |
/// |`into_`| none |`self` | any |
/// |`is_` | none |`&mut self` or `&self` or none | any |
/// |`to_` | `_mut` |`&mut self` | any |
/// |`to_` | not `_mut` |`self` | `Copy` |
/// |`to_` | not `_mut` |`&self` | not `Copy` |
2021-03-25 18:29:11 +00:00
///
2021-04-08 15:50:13 +00:00
/// Note: Clippy doesn't trigger methods with `to_` prefix in:
/// - Traits definition.
/// Clippy can not tell if a type that implements a trait is `Copy` or not.
/// - Traits implementation, when `&self` is taken.
/// The method signature is controlled by the trait and often `&self` is required for all types that implement the trait
/// (see e.g. the `std::string::ToString` trait).
///
2021-09-28 17:03:12 +00:00
/// Clippy allows `Pin<&Self>` and `Pin<&mut Self>` if `&self` and `&mut self` is required.
///
2021-03-25 18:29:11 +00:00
/// Please find more info here:
/// https://rust-lang.github.io/api-guidelines/naming.html#ad-hoc-conversions-follow-as_-to_-into_-conventions-c-conv
2019-03-05 16:50:33 +00:00
///
2021-07-29 10:16:06 +00:00
/// ### Why is this bad?
/// Consistency breeds readability. If you follow the
2019-03-05 16:50:33 +00:00
/// conventions, your users won't be surprised that they, e.g., need to supply a
/// mutable reference to a `as_..` function.
///
2021-07-29 10:16:06 +00:00
/// ### Example
2020-01-30 22:44:37 +00:00
/// ```rust
/// # struct X;
2019-03-05 16:50:33 +00:00
/// impl X {
2020-01-30 22:44:37 +00:00
/// fn as_str(self) -> &'static str {
/// // ..
/// # ""
2019-03-05 16:50:33 +00:00
/// }
/// }
/// ```
2021-12-06 11:33:31 +00:00
#[ clippy::version = " pre 1.29.0 " ]
2018-11-27 20:49:09 +00:00
pub WRONG_SELF_CONVENTION ,
style ,
" defining a method named with an established prefix (like \" into_ \" ) that takes `self` with the wrong convention "
2016-02-05 23:13:29 +00:00
}
2015-12-14 21:16:56 +00:00
2018-03-28 13:24:26 +00:00
declare_clippy_lint! {
2021-07-29 10:16:06 +00:00
/// ### What it does
/// Checks for usage of `ok().expect(..)`.
2019-03-05 16:50:33 +00:00
///
2021-07-29 10:16:06 +00:00
/// ### Why is this bad?
/// Because you usually call `expect()` on the `Result`
2019-03-05 16:50:33 +00:00
/// directly to get a better error message.
///
2021-07-29 10:16:06 +00:00
/// ### Known problems
/// The error type needs to implement `Debug`
2019-03-05 16:50:33 +00:00
///
2021-07-29 10:16:06 +00:00
/// ### Example
2020-01-30 22:44:37 +00:00
/// ```rust
/// # let x = Ok::<_, ()>(());
2020-06-09 14:36:01 +00:00
/// x.ok().expect("why did I do this again?");
2022-06-05 19:24:41 +00:00
/// ```
2020-06-09 14:36:01 +00:00
///
2022-06-05 19:24:41 +00:00
/// Use instead:
/// ```rust
/// # let x = Ok::<_, ()>(());
2020-06-09 14:36:01 +00:00
/// x.expect("why did I do this again?");
2019-03-05 16:50:33 +00:00
/// ```
2021-12-06 11:33:31 +00:00
#[ clippy::version = " pre 1.29.0 " ]
2018-11-27 20:49:09 +00:00
pub OK_EXPECT ,
style ,
" using `ok().expect()`, which gives worse error messages than calling `expect` directly on the Result "
2016-02-05 23:13:29 +00:00
}
2015-12-14 21:16:56 +00:00
2022-04-07 17:39:59 +00:00
declare_clippy_lint! {
/// ### What it does
/// Checks for `.err().expect()` calls on the `Result` type.
///
/// ### Why is this bad?
/// `.expect_err()` can be called directly to avoid the extra type conversion from `err()`.
///
/// ### Example
/// ```should_panic
/// let x: Result<u32, &str> = Ok(10);
/// x.err().expect("Testing err().expect()");
/// ```
/// Use instead:
/// ```should_panic
/// let x: Result<u32, &str> = Ok(10);
/// x.expect_err("Testing expect_err");
/// ```
2022-07-03 15:02:48 +00:00
#[ clippy::version = " 1.62.0 " ]
2022-04-07 17:39:59 +00:00
pub ERR_EXPECT ,
style ,
r # "using `.err().expect("")` when `.expect_err("")` can be used"#
}
2021-08-12 09:16:25 +00:00
declare_clippy_lint! {
/// ### What it does
/// Checks for usages of `_.unwrap_or_else(Default::default)` on `Option` and
/// `Result` values.
///
/// ### Why is this bad?
/// Readability, these can be written as `_.unwrap_or_default`, which is
/// simpler and more concise.
///
/// ### Examples
/// ```rust
/// # let x = Some(1);
/// x.unwrap_or_else(Default::default);
/// x.unwrap_or_else(u32::default);
2022-06-05 19:24:41 +00:00
/// ```
2021-08-12 09:16:25 +00:00
///
2022-06-05 19:24:41 +00:00
/// Use instead:
/// ```rust
/// # let x = Some(1);
2021-08-12 09:16:25 +00:00
/// x.unwrap_or_default();
/// ```
2021-12-06 11:33:31 +00:00
#[ clippy::version = " 1.56.0 " ]
2021-08-12 09:16:25 +00:00
pub UNWRAP_OR_ELSE_DEFAULT ,
style ,
" using `.unwrap_or_else(Default::default)`, which is more succinctly expressed as `.unwrap_or_default()` "
}
2018-03-28 13:24:26 +00:00
declare_clippy_lint! {
2021-07-29 10:16:06 +00:00
/// ### What it does
/// Checks for usage of `option.map(_).unwrap_or(_)` or `option.map(_).unwrap_or_else(_)` or
2020-05-17 15:36:26 +00:00
/// `result.map(_).unwrap_or_else(_)`.
2019-03-05 16:50:33 +00:00
///
2021-07-29 10:16:06 +00:00
/// ### Why is this bad?
/// Readability, these can be written more concisely (resp.) as
2020-05-17 15:36:26 +00:00
/// `option.map_or(_, _)`, `option.map_or_else(_, _)` and `result.map_or_else(_, _)`.
2019-03-05 16:50:33 +00:00
///
2021-07-29 10:16:06 +00:00
/// ### Known problems
/// The order of the arguments is not in execution order
2019-03-05 16:50:33 +00:00
///
2021-07-29 10:16:06 +00:00
/// ### Examples
2019-03-05 16:50:33 +00:00
/// ```rust
2022-06-01 22:36:02 +00:00
/// # let option = Some(1);
/// # let result: Result<usize, ()> = Ok(1);
/// # fn some_function(foo: ()) -> usize { 1 }
/// option.map(|a| a + 1).unwrap_or(0);
/// result.map(|a| a + 1).unwrap_or_else(some_function);
2019-03-05 16:50:33 +00:00
/// ```
///
2022-06-01 22:36:02 +00:00
/// Use instead:
2019-03-05 16:50:33 +00:00
/// ```rust
2022-06-01 22:36:02 +00:00
/// # let option = Some(1);
/// # let result: Result<usize, ()> = Ok(1);
2019-08-03 16:42:05 +00:00
/// # fn some_function(foo: ()) -> usize { 1 }
2022-06-01 22:36:02 +00:00
/// option.map_or(0, |a| a + 1);
/// result.map_or_else(some_function, |a| a + 1);
2019-03-05 16:50:33 +00:00
/// ```
2021-12-06 11:33:31 +00:00
#[ clippy::version = " 1.45.0 " ]
2020-05-17 15:36:26 +00:00
pub MAP_UNWRAP_OR ,
2018-11-27 20:49:09 +00:00
pedantic ,
2020-05-17 15:36:26 +00:00
" using `.map(f).unwrap_or(a)` or `.map(f).unwrap_or_else(func)`, which are more succinctly expressed as `map_or(a, f)` or `map_or_else(a, f)` "
2017-10-30 12:04:26 +00:00
}
2018-03-28 13:24:26 +00:00
declare_clippy_lint! {
2021-07-29 10:16:06 +00:00
/// ### What it does
/// Checks for usage of `_.map_or(None, _)`.
2019-03-05 16:50:33 +00:00
///
2021-07-29 10:16:06 +00:00
/// ### Why is this bad?
/// Readability, this can be written more concisely as
2019-03-05 16:50:33 +00:00
/// `_.and_then(_)`.
///
2021-07-29 10:16:06 +00:00
/// ### Known problems
/// The order of the arguments is not in execution order.
2019-03-05 16:50:33 +00:00
///
2021-07-29 10:16:06 +00:00
/// ### Example
2020-01-30 22:44:37 +00:00
/// ```rust
/// # let opt = Some(1);
2020-06-09 14:36:01 +00:00
/// opt.map_or(None, |a| Some(a + 1));
2022-06-05 19:24:41 +00:00
/// ```
2020-06-09 14:36:01 +00:00
///
2022-06-05 19:24:41 +00:00
/// Use instead:
/// ```rust
/// # let opt = Some(1);
2020-06-09 14:36:01 +00:00
/// opt.and_then(|a| Some(a + 1));
2019-03-05 16:50:33 +00:00
/// ```
2021-12-06 11:33:31 +00:00
#[ clippy::version = " pre 1.29.0 " ]
2018-11-27 20:49:09 +00:00
pub OPTION_MAP_OR_NONE ,
style ,
" using `Option.map_or(None, f)`, which is more succinctly expressed as `and_then(f)` "
2017-10-10 10:06:01 +00:00
}
2020-04-04 06:59:52 +00:00
declare_clippy_lint! {
2021-07-29 10:16:06 +00:00
/// ### What it does
/// Checks for usage of `_.map_or(None, Some)`.
2020-04-04 06:59:52 +00:00
///
2021-07-29 10:16:06 +00:00
/// ### Why is this bad?
/// Readability, this can be written more concisely as
2020-04-04 06:59:52 +00:00
/// `_.ok()`.
///
2021-07-29 10:16:06 +00:00
/// ### Example
2020-04-04 06:59:52 +00:00
/// ```rust
2020-04-05 00:20:23 +00:00
/// # let r: Result<u32, &str> = Ok(1);
2020-04-04 20:44:11 +00:00
/// assert_eq!(Some(1), r.map_or(None, Some));
2020-04-05 00:20:23 +00:00
/// ```
2020-04-04 20:44:11 +00:00
///
2022-06-05 19:24:41 +00:00
/// Use instead:
2020-04-05 00:20:23 +00:00
/// ```rust
/// # let r: Result<u32, &str> = Ok(1);
2020-04-04 20:44:11 +00:00
/// assert_eq!(Some(1), r.ok());
2020-04-04 06:59:52 +00:00
/// ```
2021-12-06 11:33:31 +00:00
#[ clippy::version = " 1.44.0 " ]
2020-04-04 06:59:52 +00:00
pub RESULT_MAP_OR_INTO_OPTION ,
style ,
" using `Result.map_or(None, Some)`, which is more succinctly expressed as `ok()` "
}
2019-08-15 03:53:11 +00:00
declare_clippy_lint! {
2021-07-29 10:16:06 +00:00
/// ### What it does
/// Checks for usage of `_.and_then(|x| Some(y))`, `_.and_then(|x| Ok(y))` or
2020-05-17 15:36:26 +00:00
/// `_.or_else(|x| Err(y))`.
2019-08-15 03:53:11 +00:00
///
2021-07-29 10:16:06 +00:00
/// ### Why is this bad?
/// Readability, this can be written more concisely as
2020-05-17 15:36:26 +00:00
/// `_.map(|x| y)` or `_.map_err(|x| y)`.
2019-08-15 03:53:11 +00:00
///
2021-07-29 10:16:06 +00:00
/// ### Example
2019-08-15 03:53:11 +00:00
/// ```rust
2020-05-17 15:36:26 +00:00
/// # fn opt() -> Option<&'static str> { Some("42") }
/// # fn res() -> Result<&'static str, &'static str> { Ok("42") }
/// let _ = opt().and_then(|s| Some(s.len()));
/// let _ = res().and_then(|s| if s.len() == 42 { Ok(10) } else { Ok(20) });
/// let _ = res().or_else(|s| if s.len() == 42 { Err(10) } else { Err(20) });
2019-08-15 03:53:11 +00:00
/// ```
///
/// The correct use would be:
///
/// ```rust
2020-05-17 15:36:26 +00:00
/// # fn opt() -> Option<&'static str> { Some("42") }
/// # fn res() -> Result<&'static str, &'static str> { Ok("42") }
/// let _ = opt().map(|s| s.len());
/// let _ = res().map(|s| if s.len() == 42 { 10 } else { 20 });
/// let _ = res().map_err(|s| if s.len() == 42 { 10 } else { 20 });
2019-08-15 03:53:11 +00:00
/// ```
2021-12-06 11:33:31 +00:00
#[ clippy::version = " 1.45.0 " ]
2020-05-17 15:36:26 +00:00
pub BIND_INSTEAD_OF_MAP ,
2019-08-15 03:53:11 +00:00
complexity ,
" using `Option.and_then(|x| Some(y))`, which is more succinctly expressed as `map(|x| y)` "
}
2018-03-28 13:24:26 +00:00
declare_clippy_lint! {
2021-07-29 10:16:06 +00:00
/// ### What it does
/// Checks for usage of `_.filter(_).next()`.
2019-03-05 16:50:33 +00:00
///
2021-07-29 10:16:06 +00:00
/// ### Why is this bad?
/// Readability, this can be written more concisely as
2019-03-05 16:50:33 +00:00
/// `_.find(_)`.
///
2021-07-29 10:16:06 +00:00
/// ### Example
2019-03-05 16:50:33 +00:00
/// ```rust
2019-08-02 06:13:54 +00:00
/// # let vec = vec![1];
/// vec.iter().filter(|x| **x == 0).next();
2019-03-05 16:50:33 +00:00
/// ```
2022-06-05 19:24:41 +00:00
///
/// Use instead:
2019-08-20 14:55:17 +00:00
/// ```rust
/// # let vec = vec![1];
/// vec.iter().find(|x| **x == 0);
/// ```
2021-12-06 11:33:31 +00:00
#[ clippy::version = " pre 1.29.0 " ]
2016-08-06 08:18:36 +00:00
pub FILTER_NEXT ,
2018-03-29 11:41:53 +00:00
complexity ,
2016-02-05 23:13:29 +00:00
" using `filter(p).next()`, which is more succinctly expressed as `.find(p)` "
}
2015-08-11 18:53:50 +00:00
2020-01-20 01:54:54 +00:00
declare_clippy_lint! {
2021-07-29 10:16:06 +00:00
/// ### What it does
/// Checks for usage of `_.skip_while(condition).next()`.
2020-01-20 01:54:54 +00:00
///
2021-07-29 10:16:06 +00:00
/// ### Why is this bad?
/// Readability, this can be written more concisely as
2020-01-20 01:54:54 +00:00
/// `_.find(!condition)`.
///
2021-07-29 10:16:06 +00:00
/// ### Example
2020-01-20 01:54:54 +00:00
/// ```rust
/// # let vec = vec![1];
/// vec.iter().skip_while(|x| **x == 0).next();
/// ```
2022-06-05 19:24:41 +00:00
///
/// Use instead:
2020-01-20 01:54:54 +00:00
/// ```rust
/// # let vec = vec![1];
/// vec.iter().find(|x| **x != 0);
/// ```
2021-12-06 11:33:31 +00:00
#[ clippy::version = " 1.42.0 " ]
2020-01-20 01:54:54 +00:00
pub SKIP_WHILE_NEXT ,
complexity ,
" using `skip_while(p).next()`, which is more succinctly expressed as `.find(!p)` "
}
2018-09-21 07:26:38 +00:00
declare_clippy_lint! {
2021-07-29 10:16:06 +00:00
/// ### What it does
/// Checks for usage of `_.map(_).flatten(_)` on `Iterator` and `Option`
2019-03-05 16:50:33 +00:00
///
2021-07-29 10:16:06 +00:00
/// ### Why is this bad?
/// Readability, this can be written more concisely as
2022-02-10 17:40:06 +00:00
/// `_.flat_map(_)` for `Iterator` or `_.and_then(_)` for `Option`
2019-03-05 16:50:33 +00:00
///
2021-07-29 10:16:06 +00:00
/// ### Example
2019-03-05 16:50:33 +00:00
/// ```rust
2019-08-03 16:42:05 +00:00
/// let vec = vec![vec![1]];
2022-02-10 17:40:06 +00:00
/// let opt = Some(5);
2020-06-09 14:36:01 +00:00
///
2019-08-03 16:42:05 +00:00
/// vec.iter().map(|x| x.iter()).flatten();
2022-02-10 17:40:06 +00:00
/// opt.map(|x| Some(x * 2)).flatten();
2022-06-05 19:24:41 +00:00
/// ```
2020-06-09 14:36:01 +00:00
///
2022-06-05 19:24:41 +00:00
/// Use instead:
/// ```rust
/// # let vec = vec![vec![1]];
/// # let opt = Some(5);
2020-06-09 14:36:01 +00:00
/// vec.iter().flat_map(|x| x.iter());
2022-02-10 17:40:06 +00:00
/// opt.and_then(|x| Some(x * 2));
2019-03-05 16:50:33 +00:00
/// ```
2021-12-06 11:33:31 +00:00
#[ clippy::version = " 1.31.0 " ]
2018-11-27 20:49:09 +00:00
pub MAP_FLATTEN ,
2021-12-06 11:33:31 +00:00
complexity ,
2018-11-27 20:49:09 +00:00
" using combinations of `flatten` and `map` which can usually be written as a single method call "
2018-09-21 07:26:38 +00:00
}
2021-01-30 17:06:34 +00:00
declare_clippy_lint! {
2021-07-29 10:16:06 +00:00
/// ### What it does
/// Checks for usage of `_.filter(_).map(_)` that can be written more simply
2021-01-30 17:06:34 +00:00
/// as `filter_map(_)`.
///
2021-07-29 10:16:06 +00:00
/// ### Why is this bad?
/// Redundant code in the `filter` and `map` operations is poor style and
2021-01-30 17:06:34 +00:00
/// less performant.
///
2021-07-29 10:16:06 +00:00
/// ### Example
2021-01-30 17:06:34 +00:00
/// ```rust
2022-06-07 00:28:16 +00:00
/// # #![allow(unused)]
2021-01-30 17:06:34 +00:00
/// (0_i32..10)
/// .filter(|n| n.checked_add(1).is_some())
/// .map(|n| n.checked_add(1).unwrap());
/// ```
///
2022-06-05 19:24:41 +00:00
/// Use instead:
2021-01-30 17:06:34 +00:00
/// ```rust
2022-06-07 00:28:16 +00:00
/// # #[allow(unused)]
2021-01-30 17:06:34 +00:00
/// (0_i32..10).filter_map(|n| n.checked_add(1));
/// ```
2021-12-06 11:33:31 +00:00
#[ clippy::version = " 1.51.0 " ]
2021-01-30 17:06:34 +00:00
pub MANUAL_FILTER_MAP ,
complexity ,
" using `_.filter(_).map(_)` in a way that can be written more simply as `filter_map(_)` "
}
declare_clippy_lint! {
2021-07-29 10:16:06 +00:00
/// ### What it does
/// Checks for usage of `_.find(_).map(_)` that can be written more simply
2021-01-30 17:06:34 +00:00
/// as `find_map(_)`.
///
2021-07-29 10:16:06 +00:00
/// ### Why is this bad?
/// Redundant code in the `find` and `map` operations is poor style and
2021-01-30 17:06:34 +00:00
/// less performant.
///
2021-07-29 10:16:06 +00:00
/// ### Example
2021-01-30 17:06:34 +00:00
/// ```rust
/// (0_i32..10)
/// .find(|n| n.checked_add(1).is_some())
/// .map(|n| n.checked_add(1).unwrap());
/// ```
///
2022-06-05 19:24:41 +00:00
/// Use instead:
2021-01-30 17:06:34 +00:00
/// ```rust
/// (0_i32..10).find_map(|n| n.checked_add(1));
/// ```
2021-12-06 11:33:31 +00:00
#[ clippy::version = " 1.51.0 " ]
2021-01-30 17:06:34 +00:00
pub MANUAL_FIND_MAP ,
complexity ,
" using `_.find(_).map(_)` in a way that can be written more simply as `find_map(_)` "
}
2019-04-27 22:06:35 +00:00
declare_clippy_lint! {
2021-07-29 10:16:06 +00:00
/// ### What it does
/// Checks for usage of `_.filter_map(_).next()`.
2019-04-27 22:06:35 +00:00
///
2021-07-29 10:16:06 +00:00
/// ### Why is this bad?
/// Readability, this can be written more concisely as
2020-10-09 10:45:29 +00:00
/// `_.find_map(_)`.
2019-04-27 22:06:35 +00:00
///
2021-07-29 10:16:06 +00:00
/// ### Example
2019-04-27 22:06:35 +00:00
/// ```rust
/// (0..3).filter_map(|x| if x == 2 { Some(x) } else { None }).next();
/// ```
/// Can be written as
///
/// ```rust
/// (0..3).find_map(|x| if x == 2 { Some(x) } else { None });
/// ```
2021-12-06 11:33:31 +00:00
#[ clippy::version = " 1.36.0 " ]
2019-04-27 22:06:35 +00:00
pub FILTER_MAP_NEXT ,
pedantic ,
" using combination of `filter_map` and `next` which can usually be written as a single method call "
}
2019-06-24 13:08:26 +00:00
declare_clippy_lint! {
2021-07-29 10:16:06 +00:00
/// ### What it does
/// Checks for usage of `flat_map(|x| x)`.
2019-06-24 13:08:26 +00:00
///
2021-07-29 10:16:06 +00:00
/// ### Why is this bad?
/// Readability, this can be written more concisely by using `flatten`.
2019-06-24 13:08:26 +00:00
///
2021-07-29 10:16:06 +00:00
/// ### Example
2019-06-24 13:08:26 +00:00
/// ```rust
2019-08-11 20:18:58 +00:00
/// # let iter = vec![vec![0]].into_iter();
/// iter.flat_map(|x| x);
2019-06-24 13:08:26 +00:00
/// ```
/// Can be written as
/// ```rust
2019-08-11 20:18:58 +00:00
/// # let iter = vec![vec![0]].into_iter();
/// iter.flatten();
2019-06-24 13:08:26 +00:00
/// ```
2021-12-06 11:33:31 +00:00
#[ clippy::version = " 1.39.0 " ]
2019-08-11 18:34:25 +00:00
pub FLAT_MAP_IDENTITY ,
2019-08-12 08:52:09 +00:00
complexity ,
2019-06-24 13:08:26 +00:00
" call to `flat_map` where `flatten` is sufficient "
}
2018-03-28 13:24:26 +00:00
declare_clippy_lint! {
2021-07-29 10:16:06 +00:00
/// ### What it does
/// Checks for an iterator or string search (such as `find()`,
2021-03-25 18:29:11 +00:00
/// `position()`, or `rposition()`) followed by a call to `is_some()` or `is_none()`.
2019-03-05 16:50:33 +00:00
///
2021-07-29 10:16:06 +00:00
/// ### Why is this bad?
/// Readability, this can be written more concisely as:
2021-03-25 18:29:11 +00:00
/// * `_.any(_)`, or `_.contains(_)` for `is_some()`,
/// * `!_.any(_)`, or `!_.contains(_)` for `is_none()`.
2019-03-05 16:50:33 +00:00
///
2021-07-29 10:16:06 +00:00
/// ### Example
2019-03-05 16:50:33 +00:00
/// ```rust
2022-06-07 00:28:16 +00:00
/// # #![allow(unused)]
2021-03-25 18:29:11 +00:00
/// let vec = vec![1];
2019-08-02 06:13:54 +00:00
/// vec.iter().find(|x| **x == 0).is_some();
2021-03-25 18:29:11 +00:00
///
2022-06-05 19:24:41 +00:00
/// "hello world".find("world").is_none();
2019-03-05 16:50:33 +00:00
/// ```
2022-06-05 19:24:41 +00:00
///
/// Use instead:
2019-08-20 14:55:17 +00:00
/// ```rust
2021-03-25 18:29:11 +00:00
/// let vec = vec![1];
2019-08-24 09:34:40 +00:00
/// vec.iter().any(|x| *x == 0);
2021-03-25 18:29:11 +00:00
///
2022-06-07 00:28:16 +00:00
/// # #[allow(unused)]
2022-06-05 19:24:41 +00:00
/// !"hello world".contains("world");
2019-08-20 14:55:17 +00:00
/// ```
2021-12-06 11:33:31 +00:00
#[ clippy::version = " pre 1.29.0 " ]
2018-11-27 20:49:09 +00:00
pub SEARCH_IS_SOME ,
complexity ,
2021-03-25 18:29:11 +00:00
" using an iterator or string search followed by `is_some()` or `is_none()`, which is more succinctly expressed as a call to `any()` or `contains()` (with negation in case of `is_none()`) "
2016-02-05 23:13:29 +00:00
}
2015-12-30 08:38:03 +00:00
2018-03-28 13:24:26 +00:00
declare_clippy_lint! {
2021-07-29 10:16:06 +00:00
/// ### What it does
/// Checks for usage of `.chars().next()` on a `str` to check
2019-03-05 16:50:33 +00:00
/// if it starts with a given char.
///
2021-07-29 10:16:06 +00:00
/// ### Why is this bad?
/// Readability, this can be written more concisely as
2019-03-05 16:50:33 +00:00
/// `_.starts_with(_)`.
///
2021-07-29 10:16:06 +00:00
/// ### Example
2019-03-05 16:50:33 +00:00
/// ```rust
2019-08-02 06:13:54 +00:00
/// let name = "foo";
2019-08-20 14:55:17 +00:00
/// if name.chars().next() == Some('_') {};
/// ```
2022-06-05 19:24:41 +00:00
///
/// Use instead:
2019-08-20 14:55:17 +00:00
/// ```rust
/// let name = "foo";
/// if name.starts_with('_') {};
2019-03-05 16:50:33 +00:00
/// ```
2021-12-06 11:33:31 +00:00
#[ clippy::version = " pre 1.29.0 " ]
2016-08-06 08:18:36 +00:00
pub CHARS_NEXT_CMP ,
2020-02-13 01:03:49 +00:00
style ,
2016-02-05 23:13:29 +00:00
" using `.chars().next()` to check if a string starts with a char "
}
2016-01-20 01:23:39 +00:00
2018-03-28 13:24:26 +00:00
declare_clippy_lint! {
2021-07-29 10:16:06 +00:00
/// ### What it does
/// Checks for calls to `.or(foo(..))`, `.unwrap_or(foo(..))`,
2019-03-05 16:50:33 +00:00
/// etc., and suggests to use `or_else`, `unwrap_or_else`, etc., or
/// `unwrap_or_default` instead.
///
2021-07-29 10:16:06 +00:00
/// ### Why is this bad?
/// The function will always be called and potentially
2019-03-05 16:50:33 +00:00
/// allocate an object acting as the default.
///
2021-07-29 10:16:06 +00:00
/// ### Known problems
/// If the function has side-effects, not calling it will
2019-03-05 16:50:33 +00:00
/// change the semantic of the program, but you shouldn't rely on that anyway.
///
2021-07-29 10:16:06 +00:00
/// ### Example
2019-03-05 16:50:33 +00:00
/// ```rust
2019-08-03 06:01:27 +00:00
/// # let foo = Some(String::new());
/// foo.unwrap_or(String::new());
2019-03-05 16:50:33 +00:00
/// ```
2022-06-01 22:36:02 +00:00
///
/// Use instead:
2019-03-05 16:50:33 +00:00
/// ```rust
2019-08-03 06:01:27 +00:00
/// # let foo = Some(String::new());
/// foo.unwrap_or_else(String::new);
2022-06-01 22:36:02 +00:00
///
/// // or
///
2019-08-03 06:01:27 +00:00
/// # let foo = Some(String::new());
/// foo.unwrap_or_default();
2019-03-05 16:50:33 +00:00
/// ```
2021-12-06 11:33:31 +00:00
#[ clippy::version = " pre 1.29.0 " ]
2016-08-06 08:18:36 +00:00
pub OR_FUN_CALL ,
2018-03-29 11:41:53 +00:00
perf ,
2016-08-06 08:18:36 +00:00
" using any `*or` method with a function call, which suggests `*or_else` "
2016-02-05 23:13:29 +00:00
}
2016-01-16 17:47:45 +00:00
2022-03-24 13:50:04 +00:00
declare_clippy_lint! {
/// ### What it does
/// Checks for `.or(…).unwrap()` calls to Options and Results.
///
/// ### Why is this bad?
/// You should use `.unwrap_or(…)` instead for clarity.
///
/// ### Example
/// ```rust
/// # let fallback = "fallback";
/// // Result
/// # type Error = &'static str;
/// # let result: Result<&str, Error> = Err("error");
/// let value = result.or::<Error>(Ok(fallback)).unwrap();
///
/// // Option
/// # let option: Option<&str> = None;
/// let value = option.or(Some(fallback)).unwrap();
/// ```
/// Use instead:
/// ```rust
/// # let fallback = "fallback";
/// // Result
/// # let result: Result<&str, &str> = Err("error");
/// let value = result.unwrap_or(fallback);
///
/// // Option
/// # let option: Option<&str> = None;
/// let value = option.unwrap_or(fallback);
/// ```
#[ clippy::version = " 1.61.0 " ]
pub OR_THEN_UNWRAP ,
complexity ,
" checks for `.or(…).unwrap()` calls to Options and Results. "
}
2018-05-28 19:00:45 +00:00
declare_clippy_lint! {
2021-07-29 10:16:06 +00:00
/// ### What it does
/// Checks for calls to `.expect(&format!(...))`, `.expect(foo(..))`,
2019-03-05 16:50:33 +00:00
/// etc., and suggests to use `unwrap_or_else` instead
///
2021-07-29 10:16:06 +00:00
/// ### Why is this bad?
/// The function will always be called.
2019-03-05 16:50:33 +00:00
///
2021-07-29 10:16:06 +00:00
/// ### Known problems
/// If the function has side-effects, not calling it will
2019-04-18 13:08:14 +00:00
/// change the semantics of the program, but you shouldn't rely on that anyway.
2019-03-05 16:50:33 +00:00
///
2021-07-29 10:16:06 +00:00
/// ### Example
2019-03-05 16:50:33 +00:00
/// ```rust
2019-08-03 06:01:27 +00:00
/// # let foo = Some(String::new());
/// # let err_code = "418";
/// # let err_msg = "I'm a teapot";
/// foo.expect(&format!("Err {}: {}", err_code, err_msg));
2022-06-01 22:36:02 +00:00
///
/// // or
///
2019-08-03 06:01:27 +00:00
/// # let foo = Some(String::new());
/// foo.expect(format!("Err {}: {}", err_code, err_msg).as_str());
2019-03-05 16:50:33 +00:00
/// ```
2022-06-01 22:36:02 +00:00
///
/// Use instead:
2019-03-05 16:50:33 +00:00
/// ```rust
2019-08-03 06:01:27 +00:00
/// # let foo = Some(String::new());
/// # let err_code = "418";
/// # let err_msg = "I'm a teapot";
/// foo.unwrap_or_else(|| panic!("Err {}: {}", err_code, err_msg));
2019-03-05 16:50:33 +00:00
/// ```
2021-12-06 11:33:31 +00:00
#[ clippy::version = " pre 1.29.0 " ]
2018-05-28 19:00:45 +00:00
pub EXPECT_FUN_CALL ,
perf ,
" using any `expect` method with a function call "
}
2018-03-28 13:24:26 +00:00
declare_clippy_lint! {
2021-07-29 10:16:06 +00:00
/// ### What it does
/// Checks for usage of `.clone()` on a `Copy` type.
2019-03-05 16:50:33 +00:00
///
2021-07-29 10:16:06 +00:00
/// ### Why is this bad?
/// The only reason `Copy` types implement `Clone` is for
2019-03-05 16:50:33 +00:00
/// generics, not for using the `clone` method on a concrete type.
///
2021-07-29 10:16:06 +00:00
/// ### Example
2019-03-05 16:50:33 +00:00
/// ```rust
2019-08-02 06:13:54 +00:00
/// 42u64.clone();
2019-03-05 16:50:33 +00:00
/// ```
2021-12-06 11:33:31 +00:00
#[ clippy::version = " pre 1.29.0 " ]
2016-08-06 08:18:36 +00:00
pub CLONE_ON_COPY ,
2018-03-28 13:24:26 +00:00
complexity ,
2016-08-06 08:18:36 +00:00
" using `clone` on a `Copy` type "
2016-02-05 23:13:29 +00:00
}
2016-02-02 21:35:01 +00:00
2018-03-28 13:24:26 +00:00
declare_clippy_lint! {
2021-07-29 10:16:06 +00:00
/// ### What it does
/// Checks for usage of `.clone()` on a ref-counted pointer,
2019-03-05 16:50:33 +00:00
/// (`Rc`, `Arc`, `rc::Weak`, or `sync::Weak`), and suggests calling Clone via unified
2019-01-31 01:15:29 +00:00
/// function syntax instead (e.g., `Rc::clone(foo)`).
2019-03-05 16:50:33 +00:00
///
2021-07-29 10:16:06 +00:00
/// ### Why is this bad?
/// Calling '.clone()' on an Rc, Arc, or Weak
2019-03-05 16:50:33 +00:00
/// can obscure the fact that only the pointer is being cloned, not the underlying
/// data.
///
2021-07-29 10:16:06 +00:00
/// ### Example
2019-03-05 16:50:33 +00:00
/// ```rust
2019-08-03 19:24:50 +00:00
/// # use std::rc::Rc;
/// let x = Rc::new(1);
2020-06-09 14:36:01 +00:00
///
2019-08-03 19:24:50 +00:00
/// x.clone();
2022-06-05 19:24:41 +00:00
/// ```
2020-06-09 14:36:01 +00:00
///
2022-06-05 19:24:41 +00:00
/// Use instead:
/// ```rust
/// # use std::rc::Rc;
/// # let x = Rc::new(1);
2020-06-09 14:36:01 +00:00
/// Rc::clone(&x);
2019-03-05 16:50:33 +00:00
/// ```
2021-12-06 11:33:31 +00:00
#[ clippy::version = " pre 1.29.0 " ]
2017-09-10 01:51:54 +00:00
pub CLONE_ON_REF_PTR ,
2018-03-28 13:24:26 +00:00
restriction ,
2017-09-10 01:51:54 +00:00
" using 'clone' on a ref-counted pointer "
}
2018-03-28 13:24:26 +00:00
declare_clippy_lint! {
2021-07-29 10:16:06 +00:00
/// ### What it does
/// Checks for usage of `.clone()` on an `&&T`.
2019-03-05 16:50:33 +00:00
///
2021-07-29 10:16:06 +00:00
/// ### Why is this bad?
/// Cloning an `&&T` copies the inner `&T`, instead of
2019-03-05 16:50:33 +00:00
/// cloning the underlying `T`.
///
2021-07-29 10:16:06 +00:00
/// ### Example
2019-03-05 16:50:33 +00:00
/// ```rust
/// fn main() {
/// let x = vec![1];
/// let y = &&x;
/// let z = y.clone();
/// println!("{:p} {:p}", *y, z); // prints out the same pointer
/// }
/// ```
2021-12-06 11:33:31 +00:00
#[ clippy::version = " pre 1.29.0 " ]
2016-08-06 08:18:36 +00:00
pub CLONE_DOUBLE_REF ,
2018-03-28 13:24:26 +00:00
correctness ,
2016-08-06 08:18:36 +00:00
" using `clone` on `&&T` "
2016-02-05 23:13:29 +00:00
}
2016-02-05 10:34:15 +00:00
2019-10-16 19:54:20 +00:00
declare_clippy_lint! {
2021-07-29 10:16:06 +00:00
/// ### What it does
/// Checks for usage of `.to_string()` on an `&&T` where
2019-10-16 19:54:20 +00:00
/// `T` implements `ToString` directly (like `&&str` or `&&String`).
///
2021-07-29 10:16:06 +00:00
/// ### Why is this bad?
/// This bypasses the specialized implementation of
2019-10-16 19:54:20 +00:00
/// `ToString` and instead goes through the more expensive string formatting
/// facilities.
///
2021-07-29 10:16:06 +00:00
/// ### Example
2019-10-16 19:54:20 +00:00
/// ```rust
/// // Generic implementation for `T: Display` is used (slow)
/// ["foo", "bar"].iter().map(|s| s.to_string());
///
/// // OK, the specialized impl is used
/// ["foo", "bar"].iter().map(|&s| s.to_string());
/// ```
2021-12-06 11:33:31 +00:00
#[ clippy::version = " 1.40.0 " ]
2019-10-16 19:54:20 +00:00
pub INEFFICIENT_TO_STRING ,
2020-04-03 03:00:12 +00:00
pedantic ,
2019-10-16 19:54:20 +00:00
" using `to_string` on `&&T` where `T: ToString` "
}
2018-03-28 13:24:26 +00:00
declare_clippy_lint! {
2021-07-29 10:16:06 +00:00
/// ### What it does
/// Checks for `new` not returning a type that contains `Self`.
2019-03-05 16:50:33 +00:00
///
2021-07-29 10:16:06 +00:00
/// ### Why is this bad?
/// As a convention, `new` methods are used to make a new
2019-03-05 16:50:33 +00:00
/// instance of a type.
///
2021-07-29 10:16:06 +00:00
/// ### Example
2020-08-28 14:10:16 +00:00
/// In an impl block:
2020-01-30 22:44:37 +00:00
/// ```rust
/// # struct Foo;
/// # struct NotAFoo;
2019-03-05 16:50:33 +00:00
/// impl Foo {
2020-01-30 22:44:37 +00:00
/// fn new() -> NotAFoo {
/// # NotAFoo
2019-03-05 16:50:33 +00:00
/// }
/// }
/// ```
2020-04-10 17:08:31 +00:00
///
/// ```rust
/// # struct Foo;
2020-08-28 14:10:16 +00:00
/// struct Bar(Foo);
2020-04-10 17:08:31 +00:00
/// impl Foo {
2020-08-28 14:10:16 +00:00
/// // Bad. The type name must contain `Self`
/// fn new() -> Bar {
/// # Bar(Foo)
2020-04-10 17:08:31 +00:00
/// }
/// }
/// ```
///
/// ```rust
/// # struct Foo;
2020-08-28 14:10:16 +00:00
/// # struct FooError;
2020-04-10 17:08:31 +00:00
/// impl Foo {
2020-08-28 14:10:16 +00:00
/// // Good. Return type contains `Self`
/// fn new() -> Result<Foo, FooError> {
/// # Ok(Foo)
2020-04-10 17:08:31 +00:00
/// }
/// }
/// ```
2020-08-28 14:10:16 +00:00
///
/// Or in a trait definition:
/// ```rust
/// pub trait Trait {
/// // Bad. The type name must contain `Self`
/// fn new();
/// }
/// ```
///
/// ```rust
/// pub trait Trait {
/// // Good. Return type contains `Self`
/// fn new() -> Self;
/// }
/// ```
2021-12-06 11:33:31 +00:00
#[ clippy::version = " pre 1.29.0 " ]
2016-08-06 08:18:36 +00:00
pub NEW_RET_NO_SELF ,
2020-04-09 17:38:20 +00:00
style ,
2020-04-10 17:08:31 +00:00
" not returning type containing `Self` in a `new` method "
2016-02-13 01:20:22 +00:00
}
2018-03-28 13:24:26 +00:00
declare_clippy_lint! {
2021-07-29 10:16:06 +00:00
/// ### What it does
/// Checks for string methods that receive a single-character
2019-01-31 01:15:29 +00:00
/// `str` as an argument, e.g., `_.split("x")`.
2019-03-05 16:50:33 +00:00
///
2021-07-29 10:16:06 +00:00
/// ### Why is this bad?
/// Performing these methods using a `char` is faster than
2019-03-05 16:50:33 +00:00
/// using a `str`.
///
2021-07-29 10:16:06 +00:00
/// ### Known problems
/// Does not catch multi-byte unicode characters.
2019-03-05 16:50:33 +00:00
///
2021-07-29 10:16:06 +00:00
/// ### Example
2020-06-09 14:36:01 +00:00
/// ```rust,ignore
/// _.split("x");
2022-06-05 19:24:41 +00:00
/// ```
2020-06-09 14:36:01 +00:00
///
2022-06-05 19:24:41 +00:00
/// Use instead:
/// ```rust,ignore
2020-06-09 14:36:01 +00:00
/// _.split('x');
2022-06-05 19:24:41 +00:00
/// ```
2021-12-06 11:33:31 +00:00
#[ clippy::version = " pre 1.29.0 " ]
2018-11-27 20:49:09 +00:00
pub SINGLE_CHAR_PATTERN ,
perf ,
2019-01-31 01:15:29 +00:00
" using a single-character str where a char could be used, e.g., `_.split( \" x \" )` "
2016-02-15 03:40:43 +00:00
}
2019-12-18 16:59:43 +00:00
declare_clippy_lint! {
2021-07-29 10:16:06 +00:00
/// ### What it does
/// Checks for calling `.step_by(0)` on iterators which panics.
2019-12-18 16:59:43 +00:00
///
2021-07-29 10:16:06 +00:00
/// ### Why is this bad?
/// This very much looks like an oversight. Use `panic!()` instead if you
2019-12-18 16:59:59 +00:00
/// actually intend to panic.
2019-12-18 16:59:43 +00:00
///
2021-07-29 10:16:06 +00:00
/// ### Example
2020-01-30 21:12:00 +00:00
/// ```rust,should_panic
2019-12-18 16:59:59 +00:00
/// for x in (0..100).step_by(0) {
/// //..
2019-12-18 16:59:43 +00:00
/// }
/// ```
2021-12-06 11:33:31 +00:00
#[ clippy::version = " pre 1.29.0 " ]
2019-12-18 16:59:43 +00:00
pub ITERATOR_STEP_BY_ZERO ,
correctness ,
2019-12-19 04:51:26 +00:00
" using `Iterator::step_by(0)`, which will panic at runtime "
2019-12-18 16:59:43 +00:00
}
2021-04-08 15:50:13 +00:00
declare_clippy_lint! {
2021-07-29 10:16:06 +00:00
/// ### What it does
/// Checks for indirect collection of populated `Option`
2021-04-08 15:50:13 +00:00
///
2021-07-29 10:16:06 +00:00
/// ### Why is this bad?
/// `Option` is like a collection of 0-1 things, so `flatten`
2021-04-08 15:50:13 +00:00
/// automatically does this without suspicious-looking `unwrap` calls.
///
2021-07-29 10:16:06 +00:00
/// ### Example
2021-04-08 15:50:13 +00:00
/// ```rust
/// let _ = std::iter::empty::<Option<i32>>().filter(Option::is_some).map(Option::unwrap);
/// ```
/// Use instead:
/// ```rust
/// let _ = std::iter::empty::<Option<i32>>().flatten();
/// ```
2021-12-06 11:33:31 +00:00
#[ clippy::version = " 1.53.0 " ]
2021-04-08 15:50:13 +00:00
pub OPTION_FILTER_MAP ,
complexity ,
" filtering `Option` for `Some` then force-unwrapping, which can be one type-safe operation "
}
2019-12-28 22:37:23 +00:00
declare_clippy_lint! {
2021-07-29 10:16:06 +00:00
/// ### What it does
/// Checks for the use of `iter.nth(0)`.
2019-12-28 22:37:23 +00:00
///
2021-07-29 10:16:06 +00:00
/// ### Why is this bad?
/// `iter.next()` is equivalent to
2020-02-02 22:19:16 +00:00
/// `iter.nth(0)`, as they both consume the next element,
/// but is more readable.
2019-12-28 22:37:23 +00:00
///
2021-07-29 10:16:06 +00:00
/// ### Example
2019-12-28 22:37:23 +00:00
/// ```rust
/// # use std::collections::HashSet;
/// # let mut s = HashSet::new();
/// # s.insert(1);
/// let x = s.iter().nth(0);
2022-06-05 19:24:41 +00:00
/// ```
2019-12-28 22:37:23 +00:00
///
2022-06-05 19:24:41 +00:00
/// Use instead:
/// ```rust
/// # use std::collections::HashSet;
2019-12-28 22:37:23 +00:00
/// # let mut s = HashSet::new();
/// # s.insert(1);
/// let x = s.iter().next();
/// ```
2021-12-06 11:33:31 +00:00
#[ clippy::version = " 1.42.0 " ]
2019-12-28 22:37:23 +00:00
pub ITER_NTH_ZERO ,
style ,
" replace `iter.nth(0)` with `iter.next()` "
}
2018-03-28 13:24:26 +00:00
declare_clippy_lint! {
2021-07-29 10:16:06 +00:00
/// ### What it does
/// Checks for use of `.iter().nth()` (and the related
2021-09-24 10:44:28 +00:00
/// `.iter_mut().nth()`) on standard library types with *O*(1) element access.
2019-03-05 16:50:33 +00:00
///
2021-07-29 10:16:06 +00:00
/// ### Why is this bad?
/// `.get()` and `.get_mut()` are more efficient and more
2019-03-05 16:50:33 +00:00
/// readable.
///
2021-07-29 10:16:06 +00:00
/// ### Example
2019-03-05 16:50:33 +00:00
/// ```rust
/// let some_vec = vec![0, 1, 2, 3];
/// let bad_vec = some_vec.iter().nth(3);
/// let bad_slice = &some_vec[..].iter().nth(3);
/// ```
/// The correct use would be:
/// ```rust
/// let some_vec = vec![0, 1, 2, 3];
/// let bad_vec = some_vec.get(3);
/// let bad_slice = &some_vec[..].get(3);
/// ```
2021-12-06 11:33:31 +00:00
#[ clippy::version = " pre 1.29.0 " ]
2016-06-16 09:02:00 +00:00
pub ITER_NTH ,
2018-03-28 13:24:26 +00:00
perf ,
2016-06-16 21:46:29 +00:00
" using `.iter().nth()` on a standard library type with O(1) element access "
2016-06-16 08:36:11 +00:00
}
2018-03-28 13:24:26 +00:00
declare_clippy_lint! {
2021-07-29 10:16:06 +00:00
/// ### What it does
/// Checks for use of `.skip(x).next()` on iterators.
2019-03-05 16:50:33 +00:00
///
2021-07-29 10:16:06 +00:00
/// ### Why is this bad?
/// `.nth(x)` is cleaner
2019-03-05 16:50:33 +00:00
///
2021-07-29 10:16:06 +00:00
/// ### Example
2019-03-05 16:50:33 +00:00
/// ```rust
/// let some_vec = vec![0, 1, 2, 3];
/// let bad_vec = some_vec.iter().skip(3).next();
/// let bad_slice = &some_vec[..].iter().skip(3).next();
/// ```
/// The correct use would be:
/// ```rust
/// let some_vec = vec![0, 1, 2, 3];
/// let bad_vec = some_vec.iter().nth(3);
/// let bad_slice = &some_vec[..].iter().nth(3);
/// ```
2021-12-06 11:33:31 +00:00
#[ clippy::version = " pre 1.29.0 " ]
2016-10-14 11:35:25 +00:00
pub ITER_SKIP_NEXT ,
2018-03-28 13:24:26 +00:00
style ,
2016-10-14 11:35:25 +00:00
" using `.skip(x).next()` on an iterator "
}
2022-03-14 11:02:53 +00:00
declare_clippy_lint! {
/// ### What it does
/// Checks for use of `.drain(..)` on `Vec` and `VecDeque` for iteration.
///
/// ### Why is this bad?
/// `.into_iter()` is simpler with better performance.
///
/// ### Example
/// ```rust
/// # use std::collections::HashSet;
/// let mut foo = vec![0, 1, 2, 3];
/// let bar: HashSet<usize> = foo.drain(..).collect();
/// ```
/// Use instead:
/// ```rust
/// # use std::collections::HashSet;
/// let foo = vec![0, 1, 2, 3];
/// let bar: HashSet<usize> = foo.into_iter().collect();
/// ```
#[ clippy::version = " 1.61.0 " ]
pub ITER_WITH_DRAIN ,
2022-03-24 13:50:04 +00:00
nursery ,
2022-03-14 11:02:53 +00:00
" replace `.drain(..)` with `.into_iter()` "
}
2022-05-20 20:33:31 +00:00
declare_clippy_lint! {
/// ### What it does
/// Checks for using `x.get(x.len() - 1)` instead of
/// `x.last()`.
///
/// ### Why is this bad?
/// Using `x.last()` is easier to read and has the same
/// result.
///
/// Note that using `x[x.len() - 1]` is semantically different from
/// `x.last()`. Indexing into the array will panic on out-of-bounds
/// accesses, while `x.get()` and `x.last()` will return `None`.
///
/// There is another lint (get_unwrap) that covers the case of using
/// `x.get(index).unwrap()` instead of `x[index]`.
///
/// ### Example
/// ```rust
/// let x = vec![2, 3, 5];
/// let last_element = x.get(x.len() - 1);
2022-06-05 19:24:41 +00:00
/// ```
2022-05-20 20:33:31 +00:00
///
2022-06-05 19:24:41 +00:00
/// Use instead:
/// ```rust
2022-05-20 20:33:31 +00:00
/// let x = vec![2, 3, 5];
/// let last_element = x.last();
/// ```
#[ clippy::version = " 1.37.0 " ]
pub GET_LAST_WITH_LEN ,
complexity ,
" Using `x.get(x.len() - 1)` when `x.last()` is correct and simpler "
}
2018-03-28 13:24:26 +00:00
declare_clippy_lint! {
2021-07-29 10:16:06 +00:00
/// ### What it does
/// Checks for use of `.get().unwrap()` (or
2019-03-05 16:50:33 +00:00
/// `.get_mut().unwrap`) on a standard library type which implements `Index`
///
2021-07-29 10:16:06 +00:00
/// ### Why is this bad?
/// Using the Index trait (`[]`) is more clear and more
2019-03-05 16:50:33 +00:00
/// concise.
///
2021-07-29 10:16:06 +00:00
/// ### Known problems
/// Not a replacement for error handling: Using either
2019-03-05 16:50:33 +00:00
/// `.unwrap()` or the Index trait (`[]`) carries the risk of causing a `panic`
/// if the value being accessed is `None`. If the use of `.get().unwrap()` is a
/// temporary placeholder for dealing with the `Option` type, then this does
/// not mitigate the need for error handling. If there is a chance that `.get()`
/// will be `None` in your program, then it is advisable that the `None` case
/// is handled in a future refactor instead of using `.unwrap()` or the Index
/// trait.
///
2021-07-29 10:16:06 +00:00
/// ### Example
2019-03-05 16:50:33 +00:00
/// ```rust
2019-03-05 22:23:50 +00:00
/// let mut some_vec = vec![0, 1, 2, 3];
2019-03-05 16:50:33 +00:00
/// let last = some_vec.get(3).unwrap();
/// *some_vec.get_mut(0).unwrap() = 1;
/// ```
/// The correct use would be:
/// ```rust
2019-03-05 22:23:50 +00:00
/// let mut some_vec = vec![0, 1, 2, 3];
2019-03-05 16:50:33 +00:00
/// let last = some_vec[3];
/// some_vec[0] = 1;
/// ```
2021-12-06 11:33:31 +00:00
#[ clippy::version = " pre 1.29.0 " ]
2016-11-01 06:30:13 +00:00
pub GET_UNWRAP ,
2019-03-09 18:12:22 +00:00
restriction ,
2016-11-01 06:30:13 +00:00
" using `.get().unwrap()` or `.get_mut().unwrap()` when using `[]` would work instead "
}
2021-07-01 16:17:38 +00:00
declare_clippy_lint! {
2021-07-29 10:16:06 +00:00
/// ### What it does
/// Checks for occurrences where one vector gets extended instead of append
2021-07-01 16:17:38 +00:00
///
2021-07-29 10:16:06 +00:00
/// ### Why is this bad?
/// Using `append` instead of `extend` is more concise and faster
2021-07-01 16:17:38 +00:00
///
2021-07-29 10:16:06 +00:00
/// ### Example
2021-07-01 16:17:38 +00:00
/// ```rust
/// let mut a = vec![1, 2, 3];
/// let mut b = vec![4, 5, 6];
///
/// a.extend(b.drain(..));
2022-06-05 19:24:41 +00:00
/// ```
///
/// Use instead:
/// ```rust
/// let mut a = vec![1, 2, 3];
/// let mut b = vec![4, 5, 6];
2021-07-01 16:17:38 +00:00
///
/// a.append(&mut b);
/// ```
2021-12-06 11:33:31 +00:00
#[ clippy::version = " 1.55.0 " ]
2021-07-29 10:16:06 +00:00
pub EXTEND_WITH_DRAIN ,
2021-07-01 16:17:38 +00:00
perf ,
2022-05-05 14:12:52 +00:00
" using vec.append(&mut vec) to move the full range of a vector to another "
2021-07-01 16:17:38 +00:00
}
2018-03-28 13:24:26 +00:00
declare_clippy_lint! {
2021-07-29 10:16:06 +00:00
/// ### What it does
/// Checks for the use of `.extend(s.chars())` where s is a
2019-03-05 16:50:33 +00:00
/// `&str` or `String`.
///
2021-07-29 10:16:06 +00:00
/// ### Why is this bad?
/// `.push_str(s)` is clearer
2019-03-05 16:50:33 +00:00
///
2021-07-29 10:16:06 +00:00
/// ### Example
2019-03-05 16:50:33 +00:00
/// ```rust
/// let abc = "abc";
/// let def = String::from("def");
/// let mut s = String::new();
/// s.extend(abc.chars());
/// s.extend(def.chars());
/// ```
/// The correct use would be:
/// ```rust
/// let abc = "abc";
/// let def = String::from("def");
/// let mut s = String::new();
/// s.push_str(abc);
2019-03-05 22:23:50 +00:00
/// s.push_str(&def);
2019-03-05 16:50:33 +00:00
/// ```
2021-12-06 11:33:31 +00:00
#[ clippy::version = " pre 1.29.0 " ]
2016-11-19 15:21:40 +00:00
pub STRING_EXTEND_CHARS ,
2018-03-28 13:24:26 +00:00
style ,
2016-11-19 15:36:23 +00:00
" using `x.extend(s.chars())` where s is a `&str` or `String` "
2016-11-19 15:21:40 +00:00
}
2018-03-28 13:24:26 +00:00
declare_clippy_lint! {
2021-07-29 10:16:06 +00:00
/// ### What it does
/// Checks for the use of `.cloned().collect()` on slice to
2019-03-05 16:50:33 +00:00
/// create a `Vec`.
///
2021-07-29 10:16:06 +00:00
/// ### Why is this bad?
/// `.to_vec()` is clearer
2019-03-05 16:50:33 +00:00
///
2021-07-29 10:16:06 +00:00
/// ### Example
2019-03-05 16:50:33 +00:00
/// ```rust
/// let s = [1, 2, 3, 4, 5];
/// let s2: Vec<isize> = s[..].iter().cloned().collect();
/// ```
/// The better use would be:
/// ```rust
/// let s = [1, 2, 3, 4, 5];
/// let s2: Vec<isize> = s.to_vec();
/// ```
2021-12-06 11:33:31 +00:00
#[ clippy::version = " pre 1.29.0 " ]
2017-02-12 09:03:09 +00:00
pub ITER_CLONED_COLLECT ,
2018-03-28 13:24:26 +00:00
style ,
2017-02-12 09:03:09 +00:00
" using `.cloned().collect()` on slice to create a `Vec` "
}
2016-10-14 11:35:25 +00:00
2018-03-28 13:24:26 +00:00
declare_clippy_lint! {
2021-07-29 10:16:06 +00:00
/// ### What it does
/// Checks for usage of `_.chars().last()` or
2020-06-09 14:36:01 +00:00
/// `_.chars().next_back()` on a `str` to check if it ends with a given char.
2019-03-05 16:50:33 +00:00
///
2021-07-29 10:16:06 +00:00
/// ### Why is this bad?
/// Readability, this can be written more concisely as
2019-03-05 16:50:33 +00:00
/// `_.ends_with(_)`.
///
2021-07-29 10:16:06 +00:00
/// ### Example
2020-01-30 22:44:37 +00:00
/// ```rust
/// # let name = "_";
2020-06-09 14:36:01 +00:00
/// name.chars().last() == Some('_') || name.chars().next_back() == Some('-');
2022-06-05 19:24:41 +00:00
/// ```
2020-06-09 14:36:01 +00:00
///
2022-06-05 19:24:41 +00:00
/// Use instead:
/// ```rust
/// # let name = "_";
2020-06-09 14:36:01 +00:00
/// name.ends_with('_') || name.ends_with('-');
2019-03-05 16:50:33 +00:00
/// ```
2021-12-06 11:33:31 +00:00
#[ clippy::version = " pre 1.29.0 " ]
2017-09-16 05:50:07 +00:00
pub CHARS_LAST_CMP ,
2018-03-28 13:24:26 +00:00
style ,
2017-09-16 05:50:07 +00:00
" using `.chars().last()` or `.chars().next_back()` to check if a string ends with a char "
}
2018-03-28 13:24:26 +00:00
declare_clippy_lint! {
2021-07-29 10:16:06 +00:00
/// ### What it does
/// Checks for usage of `.as_ref()` or `.as_mut()` where the
2019-03-05 16:50:33 +00:00
/// types before and after the call are the same.
///
2021-07-29 10:16:06 +00:00
/// ### Why is this bad?
/// The call is unnecessary.
2019-03-05 16:50:33 +00:00
///
2021-07-29 10:16:06 +00:00
/// ### Example
2019-03-05 16:50:33 +00:00
/// ```rust
2019-08-02 06:13:54 +00:00
/// # fn do_stuff(x: &[i32]) {}
2019-03-05 16:50:33 +00:00
/// let x: &[i32] = &[1, 2, 3, 4, 5];
/// do_stuff(x.as_ref());
/// ```
/// The correct use would be:
/// ```rust
2019-08-02 06:13:54 +00:00
/// # fn do_stuff(x: &[i32]) {}
2019-03-05 16:50:33 +00:00
/// let x: &[i32] = &[1, 2, 3, 4, 5];
/// do_stuff(x);
/// ```
2021-12-06 11:33:31 +00:00
#[ clippy::version = " pre 1.29.0 " ]
2017-10-20 15:39:20 +00:00
pub USELESS_ASREF ,
2018-03-28 13:24:26 +00:00
complexity ,
2017-10-20 15:39:20 +00:00
" using `as_ref` where the types before and after the call are the same "
}
2018-03-28 13:24:26 +00:00
declare_clippy_lint! {
2021-07-29 10:16:06 +00:00
/// ### What it does
/// Checks for using `fold` when a more succinct alternative exists.
2019-03-05 16:50:33 +00:00
/// Specifically, this checks for `fold`s which could be replaced by `any`, `all`,
/// `sum` or `product`.
///
2021-07-29 10:16:06 +00:00
/// ### Why is this bad?
/// Readability.
2019-03-05 16:50:33 +00:00
///
2021-07-29 10:16:06 +00:00
/// ### Example
2019-03-05 16:50:33 +00:00
/// ```rust
2022-06-07 00:28:16 +00:00
/// # #[allow(unused)]
2022-06-05 19:24:41 +00:00
/// (0..3).fold(false, |acc, x| acc || x > 2);
2019-03-05 16:50:33 +00:00
/// ```
2022-06-05 19:24:41 +00:00
///
/// Use instead:
2019-03-05 16:50:33 +00:00
/// ```rust
2022-06-05 19:24:41 +00:00
/// (0..3).any(|x| x > 2);
2019-03-05 16:50:33 +00:00
/// ```
2021-12-06 11:33:31 +00:00
#[ clippy::version = " pre 1.29.0 " ]
2018-01-17 20:21:29 +00:00
pub UNNECESSARY_FOLD ,
2018-03-28 13:24:26 +00:00
style ,
2018-01-17 21:54:09 +00:00
" using `fold` when a more succinct alternative exists "
2018-01-14 08:27:53 +00:00
}
2018-09-26 04:52:36 +00:00
declare_clippy_lint! {
2021-07-29 10:16:06 +00:00
/// ### What it does
2022-03-14 11:02:53 +00:00
/// Checks for `filter_map` calls that could be replaced by `filter` or `map`.
2019-03-05 16:50:33 +00:00
/// More specifically it checks if the closure provided is only performing one of the
/// filter or map operations and suggests the appropriate option.
///
2021-07-29 10:16:06 +00:00
/// ### Why is this bad?
/// Complexity. The intent is also clearer if only a single
2019-03-05 16:50:33 +00:00
/// operation is being performed.
///
2021-07-29 10:16:06 +00:00
/// ### Example
2019-03-05 16:50:33 +00:00
/// ```rust
/// let _ = (0..3).filter_map(|x| if x > 2 { Some(x) } else { None });
2020-06-09 14:36:01 +00:00
///
/// // As there is no transformation of the argument this could be written as:
2019-03-05 16:50:33 +00:00
/// let _ = (0..3).filter(|&x| x > 2);
/// ```
///
/// ```rust
2019-12-19 23:48:17 +00:00
/// let _ = (0..4).filter_map(|x| Some(x + 1));
2020-06-09 14:36:01 +00:00
///
/// // As there is no conditional check on the argument this could be written as:
2019-12-19 23:48:17 +00:00
/// let _ = (0..4).map(|x| x + 1);
2019-03-05 16:50:33 +00:00
/// ```
2021-12-06 11:33:31 +00:00
#[ clippy::version = " 1.31.0 " ]
2018-09-26 04:52:36 +00:00
pub UNNECESSARY_FILTER_MAP ,
complexity ,
" using `filter_map` when a more succinct alternative exists "
}
2022-03-14 11:02:53 +00:00
declare_clippy_lint! {
/// ### What it does
/// Checks for `find_map` calls that could be replaced by `find` or `map`. More
/// specifically it checks if the closure provided is only performing one of the
/// find or map operations and suggests the appropriate option.
///
/// ### Why is this bad?
/// Complexity. The intent is also clearer if only a single
/// operation is being performed.
///
/// ### Example
/// ```rust
/// let _ = (0..3).find_map(|x| if x > 2 { Some(x) } else { None });
///
/// // As there is no transformation of the argument this could be written as:
/// let _ = (0..3).find(|&x| x > 2);
/// ```
///
/// ```rust
/// let _ = (0..4).find_map(|x| Some(x + 1));
///
/// // As there is no conditional check on the argument this could be written as:
/// let _ = (0..4).map(|x| x + 1).next();
/// ```
#[ clippy::version = " 1.61.0 " ]
pub UNNECESSARY_FIND_MAP ,
complexity ,
" using `find_map` when a more succinct alternative exists "
}
2018-10-20 20:03:38 +00:00
declare_clippy_lint! {
2021-07-29 10:16:06 +00:00
/// ### What it does
/// Checks for `into_iter` calls on references which should be replaced by `iter`
2019-03-05 16:50:33 +00:00
/// or `iter_mut`.
///
2021-07-29 10:16:06 +00:00
/// ### Why is this bad?
/// Readability. Calling `into_iter` on a reference will not move out its
2019-03-05 16:50:33 +00:00
/// content into the resulting iterator, which is confusing. It is better just call `iter` or
/// `iter_mut` directly.
///
2021-07-29 10:16:06 +00:00
/// ### Example
2019-03-05 16:50:33 +00:00
/// ```rust
2022-06-07 00:28:16 +00:00
/// # let vec = vec![3, 4, 5];
/// (&vec).into_iter();
2022-06-05 19:24:41 +00:00
/// ```
2020-06-09 14:36:01 +00:00
///
2022-06-05 19:24:41 +00:00
/// Use instead:
/// ```rust
2022-06-07 00:28:16 +00:00
/// # let vec = vec![3, 4, 5];
/// (&vec).iter();
2019-03-05 16:50:33 +00:00
/// ```
2021-12-06 11:33:31 +00:00
#[ clippy::version = " 1.32.0 " ]
2018-10-20 20:03:38 +00:00
pub INTO_ITER_ON_REF ,
style ,
" using `.into_iter()` on a reference "
}
2019-08-15 20:56:16 +00:00
declare_clippy_lint! {
2021-07-29 10:16:06 +00:00
/// ### What it does
/// Checks for calls to `map` followed by a `count`.
2019-08-15 20:56:16 +00:00
///
2021-07-29 10:16:06 +00:00
/// ### Why is this bad?
/// It looks suspicious. Maybe `map` was confused with `filter`.
2021-10-07 09:21:30 +00:00
/// If the `map` call is intentional, this should be rewritten
/// using `inspect`. Or, if you intend to drive the iterator to
/// completion, you can just use `for_each` instead.
2019-08-15 20:56:16 +00:00
///
2021-07-29 10:16:06 +00:00
/// ### Example
2019-08-15 20:56:16 +00:00
/// ```rust
/// let _ = (0..3).map(|x| x + 2).count();
/// ```
2021-12-06 11:33:31 +00:00
#[ clippy::version = " 1.39.0 " ]
2019-08-15 20:56:16 +00:00
pub SUSPICIOUS_MAP ,
2021-07-01 16:17:38 +00:00
suspicious ,
2019-08-15 20:56:16 +00:00
" suspicious usage of map "
}
2019-08-31 18:25:28 +00:00
declare_clippy_lint! {
2021-07-29 10:16:06 +00:00
/// ### What it does
/// Checks for `MaybeUninit::uninit().assume_init()`.
2019-08-31 18:25:28 +00:00
///
2021-07-29 10:16:06 +00:00
/// ### Why is this bad?
/// For most types, this is undefined behavior.
2019-08-31 18:25:28 +00:00
///
2021-07-29 10:16:06 +00:00
/// ### Known problems
/// For now, we accept empty tuples and tuples / arrays
2019-08-31 18:25:28 +00:00
/// of `MaybeUninit`. There may be other types that allow uninitialized
/// data, but those are not yet rigorously defined.
///
2021-07-29 10:16:06 +00:00
/// ### Example
2019-08-31 18:25:28 +00:00
/// ```rust
/// // Beware the UB
/// use std::mem::MaybeUninit;
///
/// let _: usize = unsafe { MaybeUninit::uninit().assume_init() };
/// ```
///
/// Note that the following is OK:
///
/// ```rust
/// use std::mem::MaybeUninit;
///
/// let _: [MaybeUninit<bool>; 5] = unsafe {
/// MaybeUninit::uninit().assume_init()
/// };
/// ```
2021-12-06 11:33:31 +00:00
#[ clippy::version = " 1.39.0 " ]
2019-08-31 18:25:28 +00:00
pub UNINIT_ASSUMED_INIT ,
correctness ,
" `MaybeUninit::uninit().assume_init()` "
}
2019-09-04 07:08:48 +00:00
declare_clippy_lint! {
2021-07-29 10:16:06 +00:00
/// ### What it does
/// Checks for `.checked_add/sub(x).unwrap_or(MAX/MIN)`.
2019-09-04 07:08:48 +00:00
///
2021-07-29 10:16:06 +00:00
/// ### Why is this bad?
/// These can be written simply with `saturating_add/sub` methods.
2019-09-04 07:08:48 +00:00
///
2021-07-29 10:16:06 +00:00
/// ### Example
2019-09-04 07:08:48 +00:00
/// ```rust
2019-09-04 12:10:08 +00:00
/// # let y: u32 = 0;
/// # let x: u32 = 100;
2020-04-07 22:24:18 +00:00
/// let add = x.checked_add(y).unwrap_or(u32::MAX);
/// let sub = x.checked_sub(y).unwrap_or(u32::MIN);
2019-09-04 07:08:48 +00:00
/// ```
///
/// can be written using dedicated methods for saturating addition/subtraction as:
///
/// ```rust
2019-09-04 12:10:08 +00:00
/// # let y: u32 = 0;
/// # let x: u32 = 100;
/// let add = x.saturating_add(y);
/// let sub = x.saturating_sub(y);
2019-09-04 07:08:48 +00:00
/// ```
2021-12-06 11:33:31 +00:00
#[ clippy::version = " 1.39.0 " ]
2019-09-04 07:08:48 +00:00
pub MANUAL_SATURATING_ARITHMETIC ,
style ,
2022-05-21 11:24:00 +00:00
" `.checked_add/sub(x).unwrap_or(MAX/MIN)` "
2019-09-04 07:08:48 +00:00
}
2019-11-14 19:18:24 +00:00
declare_clippy_lint! {
2021-07-29 10:16:06 +00:00
/// ### What it does
/// Checks for `offset(_)`, `wrapping_`{`add`, `sub`}, etc. on raw pointers to
2019-11-14 19:18:24 +00:00
/// zero-sized types
///
2021-07-29 10:16:06 +00:00
/// ### Why is this bad?
/// This is a no-op, and likely unintended
2019-11-14 19:18:24 +00:00
///
2021-07-29 10:16:06 +00:00
/// ### Example
2020-01-30 22:44:37 +00:00
/// ```rust
2019-11-25 13:06:34 +00:00
/// unsafe { (&() as *const ()).offset(1) };
2019-11-14 19:18:24 +00:00
/// ```
2021-12-06 11:33:31 +00:00
#[ clippy::version = " 1.41.0 " ]
2019-11-14 19:18:24 +00:00
pub ZST_OFFSET ,
correctness ,
" Check for offset calculations on raw pointers to zero-sized types "
}
2020-01-02 05:12:23 +00:00
declare_clippy_lint! {
2021-07-29 10:16:06 +00:00
/// ### What it does
/// Checks for `FileType::is_file()`.
2020-01-02 05:12:23 +00:00
///
2021-07-29 10:16:06 +00:00
/// ### Why is this bad?
/// When people testing a file type with `FileType::is_file`
2020-01-02 05:12:23 +00:00
/// they are testing whether a path is something they can get bytes from. But
2020-01-05 12:25:07 +00:00
/// `is_file` doesn't cover special file types in unix-like systems, and doesn't cover
2020-01-02 05:12:23 +00:00
/// symlink in windows. Using `!FileType::is_dir()` is a better way to that intention.
///
2021-07-29 10:16:06 +00:00
/// ### Example
2020-01-30 22:44:37 +00:00
/// ```rust
/// # || {
2020-01-02 05:12:23 +00:00
/// let metadata = std::fs::metadata("foo.txt")?;
/// let filetype = metadata.file_type();
///
/// if filetype.is_file() {
/// // read file
/// }
2020-01-30 22:44:37 +00:00
/// # Ok::<_, std::io::Error>(())
/// # };
2020-01-02 05:12:23 +00:00
/// ```
///
2020-01-05 12:25:07 +00:00
/// should be written as:
2020-01-02 05:12:23 +00:00
///
2020-01-30 22:44:37 +00:00
/// ```rust
/// # || {
2020-01-02 05:12:23 +00:00
/// let metadata = std::fs::metadata("foo.txt")?;
/// let filetype = metadata.file_type();
///
/// if !filetype.is_dir() {
/// // read file
/// }
2020-01-30 22:44:37 +00:00
/// # Ok::<_, std::io::Error>(())
/// # };
2020-01-02 05:12:23 +00:00
/// ```
2021-12-06 11:33:31 +00:00
#[ clippy::version = " 1.42.0 " ]
2020-01-02 05:12:23 +00:00
pub FILETYPE_IS_FILE ,
2020-01-05 12:25:07 +00:00
restriction ,
" `FileType::is_file` is not recommended to test for readable file type "
2020-01-02 05:12:23 +00:00
}
2019-12-23 04:48:15 +00:00
declare_clippy_lint! {
2021-07-29 10:16:06 +00:00
/// ### What it does
/// Checks for usage of `_.as_ref().map(Deref::deref)` or it's aliases (such as String::as_str).
2019-12-23 04:48:15 +00:00
///
2021-07-29 10:16:06 +00:00
/// ### Why is this bad?
/// Readability, this can be written more concisely as
2020-10-09 10:45:29 +00:00
/// `_.as_deref()`.
2019-12-23 04:48:15 +00:00
///
2021-07-29 10:16:06 +00:00
/// ### Example
2020-01-30 22:44:37 +00:00
/// ```rust
/// # let opt = Some("".to_string());
/// opt.as_ref().map(String::as_str)
/// # ;
2019-12-23 04:48:15 +00:00
/// ```
/// Can be written as
2020-01-30 22:44:37 +00:00
/// ```rust
/// # let opt = Some("".to_string());
/// opt.as_deref()
/// # ;
2019-12-23 04:48:15 +00:00
/// ```
2021-12-06 11:33:31 +00:00
#[ clippy::version = " 1.42.0 " ]
2019-12-23 04:48:15 +00:00
pub OPTION_AS_REF_DEREF ,
complexity ,
" using `as_ref().map(Deref::deref)`, which is more succinctly expressed as `as_deref()` "
}
2020-06-09 14:36:01 +00:00
declare_clippy_lint! {
2021-07-29 10:16:06 +00:00
/// ### What it does
/// Checks for usage of `iter().next()` on a Slice or an Array
2020-06-09 14:36:01 +00:00
///
2021-07-29 10:16:06 +00:00
/// ### Why is this bad?
/// These can be shortened into `.get()`
2020-06-09 14:36:01 +00:00
///
2021-07-29 10:16:06 +00:00
/// ### Example
2020-06-09 14:36:01 +00:00
/// ```rust
/// # let a = [1, 2, 3];
/// # let b = vec![1, 2, 3];
/// a[2..].iter().next();
/// b.iter().next();
/// ```
/// should be written as:
/// ```rust
/// # let a = [1, 2, 3];
/// # let b = vec![1, 2, 3];
/// a.get(2);
/// b.get(0);
/// ```
2021-12-06 11:33:31 +00:00
#[ clippy::version = " 1.46.0 " ]
2020-06-09 14:36:01 +00:00
pub ITER_NEXT_SLICE ,
style ,
" using `.iter().next()` on a sliced array, which can be shortened to just `.get()` "
}
2020-08-28 14:10:16 +00:00
declare_clippy_lint! {
2021-07-29 10:16:06 +00:00
/// ### What it does
/// Warns when using `push_str`/`insert_str` with a single-character string literal
2020-11-05 13:29:48 +00:00
/// where `push`/`insert` with a `char` would work fine.
2020-08-28 14:10:16 +00:00
///
2021-07-29 10:16:06 +00:00
/// ### Why is this bad?
/// It's less clear that we are pushing a single character.
2020-08-28 14:10:16 +00:00
///
2021-07-29 10:16:06 +00:00
/// ### Example
2020-09-10 15:47:07 +00:00
/// ```rust
2022-06-05 19:24:41 +00:00
/// # let mut string = String::new();
2020-11-05 13:29:48 +00:00
/// string.insert_str(0, "R");
2020-08-28 14:10:16 +00:00
/// string.push_str("R");
/// ```
2022-06-05 19:24:41 +00:00
///
/// Use instead:
2020-09-10 15:47:07 +00:00
/// ```rust
2022-06-05 19:24:41 +00:00
/// # let mut string = String::new();
2020-11-05 13:29:48 +00:00
/// string.insert(0, 'R');
2020-08-28 14:10:16 +00:00
/// string.push('R');
/// ```
2021-12-06 11:33:31 +00:00
#[ clippy::version = " 1.49.0 " ]
2020-11-05 13:29:48 +00:00
pub SINGLE_CHAR_ADD_STR ,
2020-08-28 14:10:16 +00:00
style ,
2020-11-05 13:29:48 +00:00
" `push_str()` or `insert_str()` used with a single-character string literal as parameter "
2020-08-28 14:10:16 +00:00
}
declare_clippy_lint! {
2021-07-29 10:16:06 +00:00
/// ### What it does
/// As the counterpart to `or_fun_call`, this lint looks for unnecessary
2020-08-28 14:10:16 +00:00
/// lazily evaluated closures on `Option` and `Result`.
///
/// This lint suggests changing the following functions, when eager evaluation results in
/// simpler code:
/// - `unwrap_or_else` to `unwrap_or`
/// - `and_then` to `and`
/// - `or_else` to `or`
/// - `get_or_insert_with` to `get_or_insert`
/// - `ok_or_else` to `ok_or`
///
2021-07-29 10:16:06 +00:00
/// ### Why is this bad?
/// Using eager evaluation is shorter and simpler in some cases.
2020-08-28 14:10:16 +00:00
///
2021-07-29 10:16:06 +00:00
/// ### Known problems
/// It is possible, but not recommended for `Deref` and `Index` to have
2020-08-28 14:10:16 +00:00
/// side effects. Eagerly evaluating them can change the semantics of the program.
///
2021-07-29 10:16:06 +00:00
/// ### Example
2020-08-28 14:10:16 +00:00
/// ```rust
/// // example code where clippy issues a warning
/// let opt: Option<u32> = None;
///
/// opt.unwrap_or_else(|| 42);
/// ```
/// Use instead:
/// ```rust
/// let opt: Option<u32> = None;
///
/// opt.unwrap_or(42);
/// ```
2021-12-06 11:33:31 +00:00
#[ clippy::version = " 1.48.0 " ]
2020-08-28 14:10:16 +00:00
pub UNNECESSARY_LAZY_EVALUATIONS ,
style ,
" using unnecessary lazy evaluation, which can be replaced with simpler eager evaluation "
}
2020-11-05 13:29:48 +00:00
declare_clippy_lint! {
2021-07-29 10:16:06 +00:00
/// ### What it does
/// Checks for usage of `_.map(_).collect::<Result<(), _>()`.
2020-11-05 13:29:48 +00:00
///
2021-07-29 10:16:06 +00:00
/// ### Why is this bad?
/// Using `try_for_each` instead is more readable and idiomatic.
2020-11-05 13:29:48 +00:00
///
2021-07-29 10:16:06 +00:00
/// ### Example
2020-11-05 13:29:48 +00:00
/// ```rust
/// (0..3).map(|t| Err(t)).collect::<Result<(), _>>();
/// ```
/// Use instead:
/// ```rust
/// (0..3).try_for_each(|t| Err(t));
/// ```
2021-12-06 11:33:31 +00:00
#[ clippy::version = " 1.49.0 " ]
2020-11-05 13:29:48 +00:00
pub MAP_COLLECT_RESULT_UNIT ,
style ,
" using `.map(_).collect::<Result<(),_>()`, which can be replaced with `try_for_each` "
}
declare_clippy_lint! {
2021-07-29 10:16:06 +00:00
/// ### What it does
/// Checks for `from_iter()` function calls on types that implement the `FromIterator`
2020-11-05 13:29:48 +00:00
/// trait.
///
2021-07-29 10:16:06 +00:00
/// ### Why is this bad?
/// It is recommended style to use collect. See
2020-11-05 13:29:48 +00:00
/// [FromIterator documentation](https://doc.rust-lang.org/std/iter/trait.FromIterator.html)
///
2021-07-29 10:16:06 +00:00
/// ### Example
2020-11-05 13:29:48 +00:00
/// ```rust
/// let five_fives = std::iter::repeat(5).take(5);
///
/// let v = Vec::from_iter(five_fives);
///
/// assert_eq!(v, vec![5, 5, 5, 5, 5]);
/// ```
/// Use instead:
/// ```rust
/// let five_fives = std::iter::repeat(5).take(5);
///
/// let v: Vec<i32> = five_fives.collect();
///
/// assert_eq!(v, vec![5, 5, 5, 5, 5]);
/// ```
2021-12-06 11:33:31 +00:00
#[ clippy::version = " 1.49.0 " ]
2020-11-05 13:29:48 +00:00
pub FROM_ITER_INSTEAD_OF_COLLECT ,
2021-07-01 16:17:38 +00:00
pedantic ,
2020-11-05 13:29:48 +00:00
" use `.collect()` instead of `::from_iter()` "
}
2021-01-30 17:06:34 +00:00
declare_clippy_lint! {
2021-07-29 10:16:06 +00:00
/// ### What it does
/// Checks for usage of `inspect().for_each()`.
2021-01-30 17:06:34 +00:00
///
2021-07-29 10:16:06 +00:00
/// ### Why is this bad?
/// It is the same as performing the computation
2021-01-30 17:06:34 +00:00
/// inside `inspect` at the beginning of the closure in `for_each`.
///
2021-07-29 10:16:06 +00:00
/// ### Example
2021-01-30 17:06:34 +00:00
/// ```rust
/// [1,2,3,4,5].iter()
/// .inspect(|&x| println!("inspect the number: {}", x))
/// .for_each(|&x| {
/// assert!(x >= 0);
/// });
/// ```
/// Can be written as
/// ```rust
/// [1,2,3,4,5].iter()
/// .for_each(|&x| {
/// println!("inspect the number: {}", x);
/// assert!(x >= 0);
/// });
/// ```
2021-12-06 11:33:31 +00:00
#[ clippy::version = " 1.51.0 " ]
2021-01-30 17:06:34 +00:00
pub INSPECT_FOR_EACH ,
complexity ,
" using `.inspect().for_each()`, which can be replaced with `.for_each()` "
}
2021-02-11 14:04:38 +00:00
declare_clippy_lint! {
2021-07-29 10:16:06 +00:00
/// ### What it does
/// Checks for usage of `filter_map(|x| x)`.
2021-02-11 14:04:38 +00:00
///
2021-07-29 10:16:06 +00:00
/// ### Why is this bad?
/// Readability, this can be written more concisely by using `flatten`.
2021-02-11 14:04:38 +00:00
///
2021-07-29 10:16:06 +00:00
/// ### Example
2021-02-11 14:04:38 +00:00
/// ```rust
/// # let iter = vec![Some(1)].into_iter();
/// iter.filter_map(|x| x);
/// ```
/// Use instead:
/// ```rust
/// # let iter = vec![Some(1)].into_iter();
/// iter.flatten();
/// ```
2021-12-06 11:33:31 +00:00
#[ clippy::version = " 1.52.0 " ]
2021-02-11 14:04:38 +00:00
pub FILTER_MAP_IDENTITY ,
complexity ,
" call to `filter_map` where `flatten` is sufficient "
}
2021-07-01 16:17:38 +00:00
declare_clippy_lint! {
2021-07-29 10:16:06 +00:00
/// ### What it does
/// Checks for instances of `map(f)` where `f` is the identity function.
2021-07-01 16:17:38 +00:00
///
2021-07-29 10:16:06 +00:00
/// ### Why is this bad?
/// It can be written more concisely without the call to `map`.
2021-07-01 16:17:38 +00:00
///
2021-07-29 10:16:06 +00:00
/// ### Example
2021-07-01 16:17:38 +00:00
/// ```rust
/// let x = [1, 2, 3];
/// let y: Vec<_> = x.iter().map(|x| x).map(|x| 2*x).collect();
/// ```
/// Use instead:
/// ```rust
/// let x = [1, 2, 3];
/// let y: Vec<_> = x.iter().map(|x| 2*x).collect();
/// ```
2022-06-09 13:43:26 +00:00
#[ clippy::version = " 1.47.0 " ]
2021-07-01 16:17:38 +00:00
pub MAP_IDENTITY ,
complexity ,
" using iterator.map(|x| x) "
}
2021-02-11 14:04:38 +00:00
declare_clippy_lint! {
2021-07-29 10:16:06 +00:00
/// ### What it does
/// Checks for the use of `.bytes().nth()`.
2021-02-11 14:04:38 +00:00
///
2021-07-29 10:16:06 +00:00
/// ### Why is this bad?
/// `.as_bytes().get()` is more efficient and more
2021-02-11 14:04:38 +00:00
/// readable.
///
2021-07-29 10:16:06 +00:00
/// ### Example
2021-02-11 14:04:38 +00:00
/// ```rust
2022-06-07 00:28:16 +00:00
/// # #[allow(unused)]
2022-06-05 19:24:41 +00:00
/// "Hello".bytes().nth(3);
/// ```
2021-02-11 14:04:38 +00:00
///
2022-06-05 19:24:41 +00:00
/// Use instead:
/// ```rust
2022-06-07 00:28:16 +00:00
/// # #[allow(unused)]
2022-06-05 19:24:41 +00:00
/// "Hello".as_bytes().get(3);
2021-02-11 14:04:38 +00:00
/// ```
2021-12-06 11:33:31 +00:00
#[ clippy::version = " 1.52.0 " ]
2021-02-11 14:04:38 +00:00
pub BYTES_NTH ,
style ,
" replace `.bytes().nth()` with `.as_bytes().get()` "
}
2021-03-12 14:30:50 +00:00
declare_clippy_lint! {
2021-07-29 10:16:06 +00:00
/// ### What it does
/// Checks for the usage of `_.to_owned()`, `vec.to_vec()`, or similar when calling `_.clone()` would be clearer.
2021-03-12 14:30:50 +00:00
///
2021-07-29 10:16:06 +00:00
/// ### Why is this bad?
/// These methods do the same thing as `_.clone()` but may be confusing as
2021-03-12 14:30:50 +00:00
/// to why we are calling `to_vec` on something that is already a `Vec` or calling `to_owned` on something that is already owned.
///
2021-07-29 10:16:06 +00:00
/// ### Example
2021-03-12 14:30:50 +00:00
/// ```rust
/// let a = vec![1, 2, 3];
/// let b = a.to_vec();
/// let c = a.to_owned();
/// ```
/// Use instead:
/// ```rust
/// let a = vec![1, 2, 3];
/// let b = a.clone();
/// let c = a.clone();
/// ```
2021-12-06 11:33:31 +00:00
#[ clippy::version = " 1.52.0 " ]
2021-03-12 14:30:50 +00:00
pub IMPLICIT_CLONE ,
pedantic ,
" implicitly cloning a value by invoking a function on its dereferenced type "
}
declare_clippy_lint! {
2021-07-29 10:16:06 +00:00
/// ### What it does
/// Checks for the use of `.iter().count()`.
2021-03-12 14:30:50 +00:00
///
2021-07-29 10:16:06 +00:00
/// ### Why is this bad?
/// `.len()` is more efficient and more
2021-03-12 14:30:50 +00:00
/// readable.
///
2021-07-29 10:16:06 +00:00
/// ### Example
2021-03-12 14:30:50 +00:00
/// ```rust
2022-06-07 00:28:16 +00:00
/// # #![allow(unused)]
2021-03-12 14:30:50 +00:00
/// let some_vec = vec![0, 1, 2, 3];
///
2022-06-05 19:24:41 +00:00
/// some_vec.iter().count();
/// &some_vec[..].iter().count();
/// ```
2021-03-12 14:30:50 +00:00
///
2022-06-05 19:24:41 +00:00
/// Use instead:
/// ```rust
2021-03-12 14:30:50 +00:00
/// let some_vec = vec![0, 1, 2, 3];
2022-06-07 00:28:16 +00:00
///
2022-06-05 19:24:41 +00:00
/// some_vec.len();
/// &some_vec[..].len();
2021-03-12 14:30:50 +00:00
/// ```
2021-12-06 11:33:31 +00:00
#[ clippy::version = " 1.52.0 " ]
2021-03-12 14:30:50 +00:00
pub ITER_COUNT ,
complexity ,
" replace `.iter().count()` with `.len()` "
}
2021-06-03 06:41:37 +00:00
declare_clippy_lint! {
2021-07-29 10:16:06 +00:00
/// ### What it does
/// Checks for calls to [`splitn`]
2021-06-03 06:41:37 +00:00
/// (https://doc.rust-lang.org/std/primitive.str.html#method.splitn) and
/// related functions with either zero or one splits.
///
2021-07-29 10:16:06 +00:00
/// ### Why is this bad?
/// These calls don't actually split the value and are
2021-06-03 06:41:37 +00:00
/// likely to be intended as a different number.
///
2021-07-29 10:16:06 +00:00
/// ### Example
2021-06-03 06:41:37 +00:00
/// ```rust
2022-06-05 19:24:41 +00:00
/// # let s = "";
2021-06-03 06:41:37 +00:00
/// for x in s.splitn(1, ":") {
2022-06-05 19:24:41 +00:00
/// // ..
2021-06-03 06:41:37 +00:00
/// }
2022-06-05 19:24:41 +00:00
/// ```
2021-06-03 06:41:37 +00:00
///
2022-06-05 19:24:41 +00:00
/// Use instead:
/// ```rust
/// # let s = "";
2021-06-03 06:41:37 +00:00
/// for x in s.splitn(2, ":") {
2022-06-05 19:24:41 +00:00
/// // ..
2021-06-03 06:41:37 +00:00
/// }
/// ```
2021-12-06 11:33:31 +00:00
#[ clippy::version = " 1.54.0 " ]
2021-06-03 06:41:37 +00:00
pub SUSPICIOUS_SPLITN ,
correctness ,
" checks for `.splitn(0, ..)` and `.splitn(1, ..)` "
}
declare_clippy_lint! {
2021-07-29 10:16:06 +00:00
/// ### What it does
/// Checks for manual implementations of `str::repeat`
2021-06-03 06:41:37 +00:00
///
2021-07-29 10:16:06 +00:00
/// ### Why is this bad?
/// These are both harder to read, as well as less performant.
2021-06-03 06:41:37 +00:00
///
2021-07-29 10:16:06 +00:00
/// ### Example
2021-06-03 06:41:37 +00:00
/// ```rust
/// let x: String = std::iter::repeat('x').take(10).collect();
2022-06-05 19:24:41 +00:00
/// ```
2021-06-03 06:41:37 +00:00
///
2022-06-05 19:24:41 +00:00
/// Use instead:
/// ```rust
2021-06-03 06:41:37 +00:00
/// let x: String = "x".repeat(10);
/// ```
2021-12-06 11:33:31 +00:00
#[ clippy::version = " 1.54.0 " ]
2021-06-03 06:41:37 +00:00
pub MANUAL_STR_REPEAT ,
perf ,
" manual implementation of `str::repeat` "
}
2021-09-08 14:31:47 +00:00
declare_clippy_lint! {
2021-10-21 11:11:36 +00:00
/// ### What it does
/// Checks for usages of `str::splitn(2, _)`
2021-09-08 14:31:47 +00:00
///
2021-10-21 11:11:36 +00:00
/// ### Why is this bad?
/// `split_once` is both clearer in intent and slightly more efficient.
2021-09-08 14:31:47 +00:00
///
2021-10-21 11:11:36 +00:00
/// ### Example
2021-09-08 14:31:47 +00:00
/// ```rust,ignore
2022-05-05 14:12:52 +00:00
/// let s = "key=value=add";
/// let (key, value) = s.splitn(2, '=').next_tuple()?;
/// let value = s.splitn(2, '=').nth(1)?;
2021-09-08 14:31:47 +00:00
///
2022-05-05 14:12:52 +00:00
/// let mut parts = s.splitn(2, '=');
/// let key = parts.next()?;
/// let value = parts.next()?;
/// ```
2022-06-05 19:24:41 +00:00
///
2022-05-05 14:12:52 +00:00
/// Use instead:
/// ```rust,ignore
/// let s = "key=value=add";
/// let (key, value) = s.split_once('=')?;
/// let value = s.split_once('=')?.1;
///
/// let (key, value) = s.split_once('=')?;
2021-09-08 14:31:47 +00:00
/// ```
2022-05-05 14:12:52 +00:00
///
/// ### Limitations
/// The multiple statement variant currently only detects `iter.next()?`/`iter.next().unwrap()`
/// in two separate `let` statements that immediately follow the `splitn()`
2021-12-06 11:33:31 +00:00
#[ clippy::version = " 1.57.0 " ]
2021-09-08 14:31:47 +00:00
pub MANUAL_SPLIT_ONCE ,
complexity ,
" replace `.splitn(2, pat)` with `.split_once(pat)` "
}
2021-12-06 11:33:31 +00:00
declare_clippy_lint! {
/// ### What it does
/// Checks for usages of `str::splitn` (or `str::rsplitn`) where using `str::split` would be the same.
/// ### Why is this bad?
/// The function `split` is simpler and there is no performance difference in these cases, considering
/// that both functions return a lazy iterator.
/// ### Example
/// ```rust
/// let str = "key=value=add";
/// let _ = str.splitn(3, '=').next().unwrap();
/// ```
2022-06-05 19:24:41 +00:00
///
2021-12-06 11:33:31 +00:00
/// Use instead:
/// ```rust
/// let str = "key=value=add";
/// let _ = str.split('=').next().unwrap();
/// ```
2022-06-09 13:43:26 +00:00
#[ clippy::version = " 1.59.0 " ]
2021-12-06 11:33:31 +00:00
pub NEEDLESS_SPLITN ,
complexity ,
" usages of `str::splitn` that can be replaced with `str::split` "
}
2021-12-17 12:40:22 +00:00
declare_clippy_lint! {
/// ### What it does
/// Checks for unnecessary calls to [`ToOwned::to_owned`](https://doc.rust-lang.org/std/borrow/trait.ToOwned.html#tymethod.to_owned)
/// and other `to_owned`-like functions.
///
/// ### Why is this bad?
/// The unnecessary calls result in useless allocations.
///
2022-01-13 12:18:19 +00:00
/// ### Known problems
/// `unnecessary_to_owned` can falsely trigger if `IntoIterator::into_iter` is applied to an
/// owned copy of a resource and the resource is later used mutably. See
/// [#8148](https://github.com/rust-lang/rust-clippy/issues/8148).
///
2021-12-17 12:40:22 +00:00
/// ### Example
/// ```rust
/// let path = std::path::Path::new("x");
/// foo(&path.to_string_lossy().to_string());
/// fn foo(s: &str) {}
/// ```
/// Use instead:
/// ```rust
/// let path = std::path::Path::new("x");
/// foo(&path.to_string_lossy());
/// fn foo(s: &str) {}
/// ```
2022-06-09 13:43:26 +00:00
#[ clippy::version = " 1.59.0 " ]
2021-12-17 12:40:22 +00:00
pub UNNECESSARY_TO_OWNED ,
perf ,
" unnecessary calls to `to_owned`-like functions "
}
2022-03-24 13:50:04 +00:00
declare_clippy_lint! {
/// ### What it does
/// Checks for use of `.collect::<Vec<String>>().join("")` on iterators.
///
/// ### Why is this bad?
2022-04-07 17:39:59 +00:00
/// `.collect::<String>()` is more concise and might be more performant
2022-03-24 13:50:04 +00:00
///
/// ### Example
/// ```rust
/// let vector = vec!["hello", "world"];
/// let output = vector.iter().map(|item| item.to_uppercase()).collect::<Vec<String>>().join("");
/// println!("{}", output);
/// ```
/// The correct use would be:
/// ```rust
/// let vector = vec!["hello", "world"];
/// let output = vector.iter().map(|item| item.to_uppercase()).collect::<String>();
/// println!("{}", output);
/// ```
/// ### Known problems
2022-04-07 17:39:59 +00:00
/// While `.collect::<String>()` is sometimes more performant, there are cases where
2022-03-24 13:50:04 +00:00
/// using `.collect::<String>()` over `.collect::<Vec<String>>().join("")`
/// will prevent loop unrolling and will result in a negative performance impact.
2022-04-07 17:39:59 +00:00
///
2022-05-05 14:12:52 +00:00
/// Additionally, differences have been observed between aarch64 and x86_64 assembly output,
2022-04-07 17:39:59 +00:00
/// with aarch64 tending to producing faster assembly in more cases when using `.collect::<String>()`
2022-03-24 13:50:04 +00:00
#[ clippy::version = " 1.61.0 " ]
pub UNNECESSARY_JOIN ,
pedantic ,
" using `.collect::<Vec<String>>().join( \" \" )` on an iterator "
}
2022-04-07 17:39:59 +00:00
declare_clippy_lint! {
/// ### What it does
/// Checks for no-op uses of `Option::{as_deref, as_deref_mut}`,
/// for example, `Option<&T>::as_deref()` returns the same type.
///
/// ### Why is this bad?
/// Redundant code and improving readability.
///
/// ### Example
/// ```rust
/// let a = Some(&1);
/// let b = a.as_deref(); // goes from Option<&i32> to Option<&i32>
/// ```
2022-06-05 19:24:41 +00:00
///
/// Use instead:
2022-04-07 17:39:59 +00:00
/// ```rust
/// let a = Some(&1);
/// let b = a;
/// ```
#[ clippy::version = " 1.57.0 " ]
pub NEEDLESS_OPTION_AS_DEREF ,
complexity ,
" no-op use of `deref` or `deref_mut` method to `Option`. "
}
2022-05-05 14:12:52 +00:00
declare_clippy_lint! {
/// ### What it does
2022-06-30 19:14:38 +00:00
/// Finds usages of [`char::is_digit`](https://doc.rust-lang.org/stable/std/primitive.char.html#method.is_digit) that
/// can be replaced with [`is_ascii_digit`](https://doc.rust-lang.org/stable/std/primitive.char.html#method.is_ascii_digit) or
/// [`is_ascii_hexdigit`](https://doc.rust-lang.org/stable/std/primitive.char.html#method.is_ascii_hexdigit).
2022-05-05 14:12:52 +00:00
///
/// ### Why is this bad?
/// `is_digit(..)` is slower and requires specifying the radix.
///
/// ### Example
/// ```rust
/// let c: char = '6';
/// c.is_digit(10);
/// c.is_digit(16);
/// ```
/// Use instead:
/// ```rust
/// let c: char = '6';
/// c.is_ascii_digit();
/// c.is_ascii_hexdigit();
/// ```
2022-07-03 15:02:48 +00:00
#[ clippy::version = " 1.62.0 " ]
2022-05-05 14:12:52 +00:00
pub IS_DIGIT_ASCII_RADIX ,
style ,
" use of `char::is_digit(..)` with literal radix of 10 or 16 "
}
declare_clippy_lint! {
2022-06-19 14:15:14 +00:00
/// ### What it does
/// Checks for calling `take` function after `as_ref`.
2022-05-05 14:12:52 +00:00
///
/// ### Why is this bad?
2022-06-19 14:15:14 +00:00
/// Redundant code. `take` writes `None` to its argument.
/// In this case the modification is useless as it's a temporary that cannot be read from afterwards.
2022-05-05 14:12:52 +00:00
///
/// ### Example
/// ```rust
/// let x = Some(3);
/// x.as_ref().take();
/// ```
/// Use instead:
/// ```rust
/// let x = Some(3);
/// x.as_ref();
/// ```
2022-07-03 15:02:48 +00:00
#[ clippy::version = " 1.62.0 " ]
2022-05-05 14:12:52 +00:00
pub NEEDLESS_OPTION_TAKE ,
complexity ,
" using `.as_ref().take()` on a temporary value "
}
2022-04-25 14:12:48 +00:00
declare_clippy_lint! {
/// ### What it does
/// Checks for `replace` statements which have no effect.
///
/// ### Why is this bad?
/// It's either a mistake or confusing.
///
/// ### Example
/// ```rust
/// "1234".replace("12", "12");
/// "1234".replacen("12", "12", 1);
/// ```
2022-08-12 21:19:53 +00:00
#[ clippy::version = " 1.63.0 " ]
2022-04-25 14:12:48 +00:00
pub NO_EFFECT_REPLACE ,
suspicious ,
" replace with no effect "
}
2022-07-10 21:37:38 +00:00
declare_clippy_lint! {
/// ### What it does
/// Checks for usages of `.then_some(..).unwrap_or(..)`
///
/// ### Why is this bad?
/// This can be written more clearly with `if .. else ..`
///
/// ### Limitations
/// This lint currently only looks for usages of
/// `.then_some(..).unwrap_or(..)`, but will be expanded
/// to account for similar patterns.
///
/// ### Example
/// ```rust
/// let x = true;
/// x.then_some("a").unwrap_or("b");
/// ```
/// Use instead:
/// ```rust
/// let x = true;
/// if x { "a" } else { "b" };
/// ```
#[ clippy::version = " 1.64.0 " ]
pub OBFUSCATED_IF_ELSE ,
style ,
" use of `.then_some(..).unwrap_or(..)` can be written \
more clearly with ` if .. else .. ` "
}
2022-07-16 21:07:06 +00:00
declare_clippy_lint! {
/// ### What it does
///
2022-07-19 20:08:03 +00:00
/// Checks for calls to `iter`, `iter_mut` or `into_iter` on collections containing a single item
2022-07-16 21:07:06 +00:00
///
/// ### Why is this bad?
///
/// It is simpler to use the once function from the standard library:
///
/// ### Example
///
/// ```rust
/// let a = [123].iter();
/// let b = Some(123).into_iter();
/// ```
/// Use instead:
/// ```rust
/// use std::iter;
/// let a = iter::once(&123);
/// let b = iter::once(123);
/// ```
///
/// ### Known problems
///
/// The type of the resulting iterator might become incompatible with its usage
#[ clippy::version = " 1.64.0 " ]
2022-07-30 11:39:55 +00:00
pub ITER_ON_SINGLE_ITEMS ,
2022-07-16 21:07:06 +00:00
nursery ,
" Iterator for array of length 1 "
}
declare_clippy_lint! {
/// ### What it does
///
2022-07-19 20:08:03 +00:00
/// Checks for calls to `iter`, `iter_mut` or `into_iter` on empty collections
2022-07-16 21:07:06 +00:00
///
/// ### Why is this bad?
///
/// It is simpler to use the empty function from the standard library:
///
/// ### Example
///
/// ```rust
/// use std::{slice, option};
/// let a: slice::Iter<i32> = [].iter();
/// let f: option::IntoIter<i32> = None.into_iter();
/// ```
/// Use instead:
/// ```rust
/// use std::iter;
/// let a: iter::Empty<i32> = iter::empty();
/// let b: iter::Empty<i32> = iter::empty();
/// ```
///
/// ### Known problems
///
/// The type of the resulting iterator might become incompatible with its usage
#[ clippy::version = " 1.64.0 " ]
2022-07-30 11:39:55 +00:00
pub ITER_ON_EMPTY_COLLECTIONS ,
2022-07-16 21:07:06 +00:00
nursery ,
" Iterator for empty array "
}
2022-06-05 15:39:36 +00:00
declare_clippy_lint! {
/// ### What it does
/// Checks for naive byte counts
///
/// ### Why is this bad?
/// The [`bytecount`](https://crates.io/crates/bytecount)
/// crate has methods to count your bytes faster, especially for large slices.
///
/// ### Known problems
/// If you have predominantly small slices, the
/// `bytecount::count(..)` method may actually be slower. However, if you can
/// ensure that less than 2³²-1 matches arise, the `naive_count_32(..)` can be
/// faster in those cases.
///
/// ### Example
/// ```rust
/// # let vec = vec![1_u8];
/// let count = vec.iter().filter(|x| **x == 0u8).count();
/// ```
///
/// Use instead:
/// ```rust,ignore
/// # let vec = vec![1_u8];
/// let count = bytecount::count(&vec, 0u8);
/// ```
#[ clippy::version = " pre 1.29.0 " ]
pub NAIVE_BYTECOUNT ,
pedantic ,
" use of naive `<slice>.filter(|&x| x == y).count()` to count byte values "
}
2022-06-05 17:05:11 +00:00
declare_clippy_lint! {
/// ### What it does
/// It checks for `str::bytes().count()` and suggests replacing it with
/// `str::len()`.
///
/// ### Why is this bad?
/// `str::bytes().count()` is longer and may not be as performant as using
/// `str::len()`.
///
/// ### Example
/// ```rust
/// "hello".bytes().count();
/// String::from("hello").bytes().count();
/// ```
/// Use instead:
/// ```rust
/// "hello".len();
/// String::from("hello").len();
/// ```
#[ clippy::version = " 1.62.0 " ]
pub BYTES_COUNT_TO_LEN ,
complexity ,
" Using `bytes().count()` when `len()` performs the same functionality "
}
2022-06-05 17:21:04 +00:00
declare_clippy_lint! {
/// ### What it does
/// Checks for calls to `ends_with` with possible file extensions
/// and suggests to use a case-insensitive approach instead.
///
/// ### Why is this bad?
/// `ends_with` is case-sensitive and may not detect files with a valid extension.
///
/// ### Example
/// ```rust
/// fn is_rust_file(filename: &str) -> bool {
/// filename.ends_with(".rs")
/// }
/// ```
/// Use instead:
/// ```rust
/// fn is_rust_file(filename: &str) -> bool {
/// let filename = std::path::Path::new(filename);
/// filename.extension()
/// .map_or(false, |ext| ext.eq_ignore_ascii_case("rs"))
/// }
/// ```
#[ clippy::version = " 1.51.0 " ]
pub CASE_SENSITIVE_FILE_EXTENSION_COMPARISONS ,
pedantic ,
" Checks for calls to ends_with with case-sensitive file extensions "
}
2022-06-05 17:44:09 +00:00
declare_clippy_lint! {
/// ### What it does
/// Checks for using `x.get(0)` instead of
/// `x.first()`.
///
/// ### Why is this bad?
/// Using `x.first()` is easier to read and has the same
/// result.
///
/// ### Example
/// ```rust
/// let x = vec![2, 3, 5];
/// let first_element = x.get(0);
/// ```
///
/// Use instead:
/// ```rust
/// let x = vec![2, 3, 5];
/// let first_element = x.first();
/// ```
#[ clippy::version = " 1.63.0 " ]
pub GET_FIRST ,
style ,
" Using `x.get(0)` when `x.first()` is simpler "
}
2022-06-05 19:20:47 +00:00
declare_clippy_lint! {
/// ### What it does
///
/// Finds patterns that reimplement `Option::ok_or`.
///
/// ### Why is this bad?
///
/// Concise code helps focusing on behavior instead of boilerplate.
///
/// ### Examples
/// ```rust
/// let foo: Option<i32> = None;
/// foo.map_or(Err("error"), |v| Ok(v));
/// ```
///
/// Use instead:
/// ```rust
/// let foo: Option<i32> = None;
/// foo.ok_or("error");
/// ```
#[ clippy::version = " 1.49.0 " ]
pub MANUAL_OK_OR ,
pedantic ,
" finds patterns that can be encoded more concisely with `Option::ok_or` "
}
2022-06-05 19:45:04 +00:00
declare_clippy_lint! {
/// ### What it does
/// Checks for usage of `map(|x| x.clone())` or
/// dereferencing closures for `Copy` types, on `Iterator` or `Option`,
/// and suggests `cloned()` or `copied()` instead
///
/// ### Why is this bad?
/// Readability, this can be written more concisely
///
/// ### Example
/// ```rust
/// let x = vec![42, 43];
/// let y = x.iter();
/// let z = y.map(|i| *i);
/// ```
///
/// The correct use would be:
///
/// ```rust
/// let x = vec![42, 43];
/// let y = x.iter();
/// let z = y.cloned();
/// ```
#[ clippy::version = " pre 1.29.0 " ]
pub MAP_CLONE ,
style ,
" using `iterator.map(|x| x.clone())`, or dereferencing closures for `Copy` types "
}
2022-06-05 19:59:24 +00:00
declare_clippy_lint! {
/// ### What it does
/// Checks for instances of `map_err(|_| Some::Enum)`
///
/// ### Why is this bad?
/// This `map_err` throws away the original error rather than allowing the enum to contain and report the cause of the error
///
/// ### Example
/// Before:
/// ```rust
/// use std::fmt;
///
/// #[derive(Debug)]
/// enum Error {
/// Indivisible,
/// Remainder(u8),
/// }
///
/// impl fmt::Display for Error {
/// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
/// match self {
/// Error::Indivisible => write!(f, "could not divide input by three"),
/// Error::Remainder(remainder) => write!(
/// f,
/// "input is not divisible by three, remainder = {}",
/// remainder
/// ),
/// }
/// }
/// }
///
/// impl std::error::Error for Error {}
///
/// fn divisible_by_3(input: &str) -> Result<(), Error> {
/// input
/// .parse::<i32>()
/// .map_err(|_| Error::Indivisible)
/// .map(|v| v % 3)
/// .and_then(|remainder| {
/// if remainder == 0 {
/// Ok(())
/// } else {
/// Err(Error::Remainder(remainder as u8))
/// }
/// })
/// }
/// ```
///
/// After:
/// ```rust
/// use std::{fmt, num::ParseIntError};
///
/// #[derive(Debug)]
/// enum Error {
/// Indivisible(ParseIntError),
/// Remainder(u8),
/// }
///
/// impl fmt::Display for Error {
/// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
/// match self {
/// Error::Indivisible(_) => write!(f, "could not divide input by three"),
/// Error::Remainder(remainder) => write!(
/// f,
/// "input is not divisible by three, remainder = {}",
/// remainder
/// ),
/// }
/// }
/// }
///
/// impl std::error::Error for Error {
/// fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
/// match self {
/// Error::Indivisible(source) => Some(source),
/// _ => None,
/// }
/// }
/// }
///
/// fn divisible_by_3(input: &str) -> Result<(), Error> {
/// input
/// .parse::<i32>()
/// .map_err(Error::Indivisible)
/// .map(|v| v % 3)
/// .and_then(|remainder| {
/// if remainder == 0 {
/// Ok(())
/// } else {
/// Err(Error::Remainder(remainder as u8))
/// }
/// })
/// }
/// ```
#[ clippy::version = " 1.48.0 " ]
pub MAP_ERR_IGNORE ,
restriction ,
" `map_err` should not ignore the original error "
}
2022-06-05 23:57:58 +00:00
declare_clippy_lint! {
/// ### What it does
/// Checks for `&mut Mutex::lock` calls
///
/// ### Why is this bad?
/// `Mutex::lock` is less efficient than
/// calling `Mutex::get_mut`. In addition you also have a statically
/// guarantee that the mutex isn't locked, instead of just a runtime
/// guarantee.
///
/// ### Example
/// ```rust
/// use std::sync::{Arc, Mutex};
///
/// let mut value_rc = Arc::new(Mutex::new(42_u8));
/// let value_mutex = Arc::get_mut(&mut value_rc).unwrap();
///
/// let mut value = value_mutex.lock().unwrap();
/// *value += 1;
/// ```
/// Use instead:
/// ```rust
/// use std::sync::{Arc, Mutex};
///
/// let mut value_rc = Arc::new(Mutex::new(42_u8));
/// let value_mutex = Arc::get_mut(&mut value_rc).unwrap();
///
/// let value = value_mutex.get_mut().unwrap();
/// *value += 1;
/// ```
#[ clippy::version = " 1.49.0 " ]
pub MUT_MUTEX_LOCK ,
style ,
" `&mut Mutex::lock` does unnecessary locking "
}
2022-06-06 00:09:55 +00:00
declare_clippy_lint! {
/// ### What it does
/// Checks for duplicate open options as well as combinations
/// that make no sense.
///
/// ### Why is this bad?
/// In the best case, the code will be harder to read than
/// necessary. I don't know the worst case.
///
/// ### Example
/// ```rust
/// use std::fs::OpenOptions;
///
/// OpenOptions::new().read(true).truncate(true);
/// ```
#[ clippy::version = " pre 1.29.0 " ]
pub NONSENSICAL_OPEN_OPTIONS ,
correctness ,
" nonsensical combination of options for opening a file "
}
2022-06-06 00:27:36 +00:00
declare_clippy_lint! {
/// ### What it does
///* Checks for [push](https://doc.rust-lang.org/std/path/struct.PathBuf.html#method.push)
/// calls on `PathBuf` that can cause overwrites.
///
/// ### Why is this bad?
/// Calling `push` with a root path at the start can overwrite the
/// previous defined path.
///
/// ### Example
/// ```rust
/// use std::path::PathBuf;
///
/// let mut x = PathBuf::from("/foo");
/// x.push("/bar");
/// assert_eq!(x, PathBuf::from("/bar"));
/// ```
/// Could be written:
///
/// ```rust
/// use std::path::PathBuf;
///
/// let mut x = PathBuf::from("/foo");
/// x.push("bar");
/// assert_eq!(x, PathBuf::from("/foo/bar"));
/// ```
#[ clippy::version = " 1.36.0 " ]
pub PATH_BUF_PUSH_OVERWRITE ,
nursery ,
" calling `push` with file system root on `PathBuf` can overwrite it "
}
2022-06-06 00:39:57 +00:00
declare_clippy_lint! {
/// ### What it does
/// Checks for zipping a collection with the range of
/// `0.._.len()`.
///
/// ### Why is this bad?
/// The code is better expressed with `.enumerate()`.
///
/// ### Example
/// ```rust
/// # let x = vec![1];
/// let _ = x.iter().zip(0..x.len());
/// ```
///
/// Use instead:
/// ```rust
/// # let x = vec![1];
/// let _ = x.iter().enumerate();
/// ```
#[ clippy::version = " pre 1.29.0 " ]
pub RANGE_ZIP_WITH_LEN ,
complexity ,
" zipping iterator with a range when `enumerate()` would do "
}
2022-06-06 00:49:03 +00:00
declare_clippy_lint! {
/// ### What it does
/// Checks for usage of `.repeat(1)` and suggest the following method for each types.
/// - `.to_string()` for `str`
/// - `.clone()` for `String`
/// - `.to_vec()` for `slice`
///
/// The lint will evaluate constant expressions and values as arguments of `.repeat(..)` and emit a message if
/// they are equivalent to `1`. (Related discussion in [rust-clippy#7306](https://github.com/rust-lang/rust-clippy/issues/7306))
///
/// ### Why is this bad?
/// For example, `String.repeat(1)` is equivalent to `.clone()`. If cloning
/// the string is the intention behind this, `clone()` should be used.
///
/// ### Example
/// ```rust
/// fn main() {
/// let x = String::from("hello world").repeat(1);
/// }
/// ```
/// Use instead:
/// ```rust
/// fn main() {
/// let x = String::from("hello world").clone();
/// }
/// ```
#[ clippy::version = " 1.47.0 " ]
pub REPEAT_ONCE ,
complexity ,
" using `.repeat(1)` instead of `String.clone()`, `str.to_string()` or `slice.to_vec()` "
}
2022-06-06 01:07:29 +00:00
declare_clippy_lint! {
/// ### What it does
/// When sorting primitive values (integers, bools, chars, as well
/// as arrays, slices, and tuples of such items), it is typically better to
/// use an unstable sort than a stable sort.
///
/// ### Why is this bad?
/// Typically, using a stable sort consumes more memory and cpu cycles.
/// Because values which compare equal are identical, preserving their
/// relative order (the guarantee that a stable sort provides) means
/// nothing, while the extra costs still apply.
///
/// ### Known problems
///
/// As pointed out in
/// [issue #8241](https://github.com/rust-lang/rust-clippy/issues/8241),
/// a stable sort can instead be significantly faster for certain scenarios
/// (eg. when a sorted vector is extended with new data and resorted).
///
/// For more information and benchmarking results, please refer to the
/// issue linked above.
///
/// ### Example
/// ```rust
/// let mut vec = vec![2, 1, 3];
/// vec.sort();
/// ```
/// Use instead:
/// ```rust
/// let mut vec = vec![2, 1, 3];
/// vec.sort_unstable();
/// ```
#[ clippy::version = " 1.47.0 " ]
pub STABLE_SORT_PRIMITIVE ,
pedantic ,
" use of sort() when sort_unstable() is equivalent "
}
2022-06-06 01:41:33 +00:00
declare_clippy_lint! {
/// ### What it does
/// Detects `().hash(_)`.
///
/// ### Why is this bad?
/// Hashing a unit value doesn't do anything as the implementation of `Hash` for `()` is a no-op.
///
/// ### Example
/// ```rust
/// # use std::hash::Hash;
/// # use std::collections::hash_map::DefaultHasher;
/// # enum Foo { Empty, WithValue(u8) }
/// # use Foo::*;
/// # let mut state = DefaultHasher::new();
/// # let my_enum = Foo::Empty;
/// match my_enum {
/// Empty => ().hash(&mut state),
/// WithValue(x) => x.hash(&mut state),
/// }
/// ```
/// Use instead:
/// ```rust
/// # use std::hash::Hash;
/// # use std::collections::hash_map::DefaultHasher;
/// # enum Foo { Empty, WithValue(u8) }
/// # use Foo::*;
/// # let mut state = DefaultHasher::new();
/// # let my_enum = Foo::Empty;
/// match my_enum {
/// Empty => 0_u8.hash(&mut state),
/// WithValue(x) => x.hash(&mut state),
/// }
/// ```
#[ clippy::version = " 1.58.0 " ]
pub UNIT_HASH ,
correctness ,
" hashing a unit value, which does nothing "
}
2022-06-06 03:22:58 +00:00
declare_clippy_lint! {
/// ### What it does
/// Detects uses of `Vec::sort_by` passing in a closure
/// which compares the two arguments, either directly or indirectly.
///
/// ### Why is this bad?
/// It is more clear to use `Vec::sort_by_key` (or `Vec::sort` if
/// possible) than to use `Vec::sort_by` and a more complicated
/// closure.
///
/// ### Known problems
/// If the suggested `Vec::sort_by_key` uses Reverse and it isn't already
/// imported by a use statement, then it will need to be added manually.
///
/// ### Example
/// ```rust
/// # struct A;
/// # impl A { fn foo(&self) {} }
/// # let mut vec: Vec<A> = Vec::new();
/// vec.sort_by(|a, b| a.foo().cmp(&b.foo()));
/// ```
/// Use instead:
/// ```rust
/// # struct A;
/// # impl A { fn foo(&self) {} }
/// # let mut vec: Vec<A> = Vec::new();
/// vec.sort_by_key(|a| a.foo());
/// ```
#[ clippy::version = " 1.46.0 " ]
pub UNNECESSARY_SORT_BY ,
complexity ,
" Use of `Vec::sort_by` when `Vec::sort_by_key` or `Vec::sort` would be clearer "
}
2022-06-06 15:17:38 +00:00
declare_clippy_lint! {
/// ### What it does
/// Finds occurrences of `Vec::resize(0, an_int)`
///
/// ### Why is this bad?
/// This is probably an argument inversion mistake.
///
/// ### Example
/// ```rust
/// vec!(1, 2, 3, 4, 5).resize(0, 5)
/// ```
///
/// Use instead:
/// ```rust
/// vec!(1, 2, 3, 4, 5).clear()
/// ```
#[ clippy::version = " 1.46.0 " ]
pub VEC_RESIZE_TO_ZERO ,
correctness ,
" emptying a vector with `resize(0, an_int)` instead of `clear()` is probably an argument inversion mistake "
}
2022-06-06 15:58:30 +00:00
declare_clippy_lint! {
/// ### What it does
/// Checks for use of File::read_to_end and File::read_to_string.
///
/// ### Why is this bad?
/// `fs::{read, read_to_string}` provide the same functionality when `buf` is empty with fewer imports and no intermediate values.
/// See also: [fs::read docs](https://doc.rust-lang.org/std/fs/fn.read.html), [fs::read_to_string docs](https://doc.rust-lang.org/std/fs/fn.read_to_string.html)
///
/// ### Example
/// ```rust,no_run
/// # use std::io::Read;
/// # use std::fs::File;
/// let mut f = File::open("foo.txt").unwrap();
/// let mut bytes = Vec::new();
/// f.read_to_end(&mut bytes).unwrap();
/// ```
/// Can be written more concisely as
/// ```rust,no_run
/// # use std::fs;
/// let mut bytes = fs::read("foo.txt").unwrap();
/// ```
#[ clippy::version = " 1.44.0 " ]
pub VERBOSE_FILE_READS ,
restriction ,
" use of `File::read_to_end` or `File::read_to_string` "
}
2020-12-06 14:01:03 +00:00
pub struct Methods {
2021-06-03 06:41:37 +00:00
avoid_breaking_exported_api : bool ,
2020-12-06 14:01:03 +00:00
msrv : Option < RustcVersion > ,
2022-05-21 11:24:00 +00:00
allow_expect_in_tests : bool ,
allow_unwrap_in_tests : bool ,
2020-12-06 14:01:03 +00:00
}
impl Methods {
#[ must_use ]
2022-05-21 11:24:00 +00:00
pub fn new (
avoid_breaking_exported_api : bool ,
msrv : Option < RustcVersion > ,
allow_expect_in_tests : bool ,
allow_unwrap_in_tests : bool ,
) -> Self {
2021-06-03 06:41:37 +00:00
Self {
avoid_breaking_exported_api ,
msrv ,
2022-05-21 11:24:00 +00:00
allow_expect_in_tests ,
allow_unwrap_in_tests ,
2021-06-03 06:41:37 +00:00
}
2020-12-06 14:01:03 +00:00
}
}
impl_lint_pass! ( Methods = > [
2020-05-17 15:36:26 +00:00
UNWRAP_USED ,
EXPECT_USED ,
2019-04-08 20:43:55 +00:00
SHOULD_IMPLEMENT_TRAIT ,
WRONG_SELF_CONVENTION ,
OK_EXPECT ,
2021-08-12 09:16:25 +00:00
UNWRAP_OR_ELSE_DEFAULT ,
2020-05-17 15:36:26 +00:00
MAP_UNWRAP_OR ,
2020-04-04 06:59:52 +00:00
RESULT_MAP_OR_INTO_OPTION ,
2019-04-08 20:43:55 +00:00
OPTION_MAP_OR_NONE ,
2020-05-17 15:36:26 +00:00
BIND_INSTEAD_OF_MAP ,
2019-04-08 20:43:55 +00:00
OR_FUN_CALL ,
2022-03-24 13:50:04 +00:00
OR_THEN_UNWRAP ,
2019-04-08 20:43:55 +00:00
EXPECT_FUN_CALL ,
CHARS_NEXT_CMP ,
CHARS_LAST_CMP ,
CLONE_ON_COPY ,
CLONE_ON_REF_PTR ,
CLONE_DOUBLE_REF ,
2022-08-02 20:37:40 +00:00
COLLAPSIBLE_STR_REPLACE ,
2022-01-17 12:29:07 +00:00
ITER_OVEREAGER_CLONED ,
2021-04-22 09:31:13 +00:00
CLONED_INSTEAD_OF_COPIED ,
FLAT_MAP_OPTION ,
2019-10-16 19:54:20 +00:00
INEFFICIENT_TO_STRING ,
2019-04-08 20:43:55 +00:00
NEW_RET_NO_SELF ,
SINGLE_CHAR_PATTERN ,
2020-11-05 13:29:48 +00:00
SINGLE_CHAR_ADD_STR ,
2019-04-08 20:43:55 +00:00
SEARCH_IS_SOME ,
FILTER_NEXT ,
2020-01-20 01:54:54 +00:00
SKIP_WHILE_NEXT ,
2021-02-11 14:04:38 +00:00
FILTER_MAP_IDENTITY ,
2021-07-01 16:17:38 +00:00
MAP_IDENTITY ,
2021-01-30 17:06:34 +00:00
MANUAL_FILTER_MAP ,
MANUAL_FIND_MAP ,
2021-04-08 15:50:13 +00:00
OPTION_FILTER_MAP ,
2019-04-27 22:06:35 +00:00
FILTER_MAP_NEXT ,
2019-08-11 18:34:25 +00:00
FLAT_MAP_IDENTITY ,
2019-04-08 20:43:55 +00:00
MAP_FLATTEN ,
2019-12-18 16:59:43 +00:00
ITERATOR_STEP_BY_ZERO ,
2020-06-09 14:36:01 +00:00
ITER_NEXT_SLICE ,
2021-03-12 14:30:50 +00:00
ITER_COUNT ,
2019-04-08 20:43:55 +00:00
ITER_NTH ,
2019-12-28 22:37:23 +00:00
ITER_NTH_ZERO ,
2021-02-11 14:04:38 +00:00
BYTES_NTH ,
2019-04-08 20:43:55 +00:00
ITER_SKIP_NEXT ,
GET_UNWRAP ,
2022-05-20 20:33:31 +00:00
GET_LAST_WITH_LEN ,
2019-04-08 20:43:55 +00:00
STRING_EXTEND_CHARS ,
ITER_CLONED_COLLECT ,
2022-03-14 11:02:53 +00:00
ITER_WITH_DRAIN ,
2019-04-08 20:43:55 +00:00
USELESS_ASREF ,
UNNECESSARY_FOLD ,
UNNECESSARY_FILTER_MAP ,
2022-03-14 11:02:53 +00:00
UNNECESSARY_FIND_MAP ,
2019-04-08 20:43:55 +00:00
INTO_ITER_ON_REF ,
2019-08-15 20:56:16 +00:00
SUSPICIOUS_MAP ,
2019-08-31 18:25:28 +00:00
UNINIT_ASSUMED_INIT ,
2019-09-04 07:08:48 +00:00
MANUAL_SATURATING_ARITHMETIC ,
2019-11-14 19:18:24 +00:00
ZST_OFFSET ,
2020-01-02 05:12:23 +00:00
FILETYPE_IS_FILE ,
2019-12-23 04:48:15 +00:00
OPTION_AS_REF_DEREF ,
2020-08-28 14:10:16 +00:00
UNNECESSARY_LAZY_EVALUATIONS ,
2020-11-05 13:29:48 +00:00
MAP_COLLECT_RESULT_UNIT ,
FROM_ITER_INSTEAD_OF_COLLECT ,
2021-01-30 17:06:34 +00:00
INSPECT_FOR_EACH ,
2021-06-03 06:41:37 +00:00
IMPLICIT_CLONE ,
SUSPICIOUS_SPLITN ,
2021-07-01 16:17:38 +00:00
MANUAL_STR_REPEAT ,
2021-09-08 14:31:47 +00:00
EXTEND_WITH_DRAIN ,
2021-12-06 11:33:31 +00:00
MANUAL_SPLIT_ONCE ,
2021-12-17 12:40:22 +00:00
NEEDLESS_SPLITN ,
UNNECESSARY_TO_OWNED ,
2022-03-24 13:50:04 +00:00
UNNECESSARY_JOIN ,
2022-04-07 17:39:59 +00:00
ERR_EXPECT ,
NEEDLESS_OPTION_AS_DEREF ,
2022-05-05 14:12:52 +00:00
IS_DIGIT_ASCII_RADIX ,
NEEDLESS_OPTION_TAKE ,
2022-04-25 14:12:48 +00:00
NO_EFFECT_REPLACE ,
2022-07-10 21:37:38 +00:00
OBFUSCATED_IF_ELSE ,
2022-07-30 11:39:55 +00:00
ITER_ON_SINGLE_ITEMS ,
2022-06-05 15:39:36 +00:00
ITER_ON_EMPTY_COLLECTIONS ,
NAIVE_BYTECOUNT ,
2022-06-05 17:05:11 +00:00
BYTES_COUNT_TO_LEN ,
2022-06-05 17:21:04 +00:00
CASE_SENSITIVE_FILE_EXTENSION_COMPARISONS ,
2022-06-05 17:44:09 +00:00
GET_FIRST ,
2022-06-05 19:20:47 +00:00
MANUAL_OK_OR ,
2022-06-05 19:45:04 +00:00
MAP_CLONE ,
2022-06-05 19:59:24 +00:00
MAP_ERR_IGNORE ,
2022-06-05 23:57:58 +00:00
MUT_MUTEX_LOCK ,
2022-06-06 00:09:55 +00:00
NONSENSICAL_OPEN_OPTIONS ,
2022-06-06 00:27:36 +00:00
PATH_BUF_PUSH_OVERWRITE ,
2022-06-06 00:39:57 +00:00
RANGE_ZIP_WITH_LEN ,
2022-06-06 00:49:03 +00:00
REPEAT_ONCE ,
2022-06-06 01:07:29 +00:00
STABLE_SORT_PRIMITIVE ,
2022-06-06 01:41:33 +00:00
UNIT_HASH ,
2022-06-06 03:22:58 +00:00
UNNECESSARY_SORT_BY ,
2022-06-06 15:17:38 +00:00
VEC_RESIZE_TO_ZERO ,
2022-06-06 15:58:30 +00:00
VERBOSE_FILE_READS ,
2019-04-08 20:43:55 +00:00
] ) ;
2021-04-08 15:50:13 +00:00
/// Extracts a method call name, args, and `Span` of the method name.
2022-01-13 12:18:19 +00:00
fn method_call < ' tcx > ( recv : & ' tcx hir ::Expr < ' tcx > ) -> Option < ( & ' tcx str , & ' tcx [ hir ::Expr < ' tcx > ] , Span ) > {
2021-12-01 17:17:50 +00:00
if let ExprKind ::MethodCall ( path , args , _ ) = recv . kind {
2021-04-08 15:50:13 +00:00
if ! args . iter ( ) . any ( | e | e . span . from_expansion ( ) ) {
2022-01-13 12:18:19 +00:00
let name = path . ident . name . as_str ( ) ;
2021-12-01 17:17:50 +00:00
return Some ( ( name , args , path . ident . span ) ) ;
2021-04-08 15:50:13 +00:00
}
}
None
}
2020-06-25 20:41:36 +00:00
impl < ' tcx > LateLintPass < ' tcx > for Methods {
fn check_expr ( & mut self , cx : & LateContext < ' tcx > , expr : & ' tcx hir ::Expr < '_ > ) {
2021-12-06 11:33:31 +00:00
if expr . span . from_expansion ( ) {
2016-01-20 17:32:17 +00:00
return ;
}
2022-05-21 11:24:00 +00:00
self . check_methods ( cx , expr ) ;
2018-10-31 04:26:29 +00:00
2019-09-27 15:16:06 +00:00
match expr . kind {
2021-04-08 15:50:13 +00:00
hir ::ExprKind ::Call ( func , args ) = > {
2021-04-22 09:31:13 +00:00
from_iter_instead_of_collect ::check ( cx , expr , args , func ) ;
2020-11-05 13:29:48 +00:00
} ,
2021-12-01 17:17:50 +00:00
hir ::ExprKind ::MethodCall ( method_call , args , _ ) = > {
let method_span = method_call . ident . span ;
or_fun_call ::check ( cx , expr , method_span , method_call . ident . as_str ( ) , args ) ;
expect_fun_call ::check ( cx , expr , method_span , method_call . ident . as_str ( ) , args ) ;
2021-03-25 18:29:11 +00:00
clone_on_copy ::check ( cx , expr , method_call . ident . name , args ) ;
clone_on_ref_ptr ::check ( cx , expr , method_call . ident . name , args ) ;
inefficient_to_string ::check ( cx , expr , method_call . ident . name , args ) ;
single_char_add_str ::check ( cx , expr , args ) ;
2021-12-01 17:17:50 +00:00
into_iter_on_ref ::check ( cx , expr , method_span , method_call . ident . name , args ) ;
2021-03-25 18:29:11 +00:00
single_char_pattern ::check ( cx , expr , method_call . ident . name , args ) ;
2022-05-21 11:24:00 +00:00
unnecessary_to_owned ::check ( cx , expr , method_call . ident . name , args , self . msrv ) ;
2016-12-20 17:21:30 +00:00
} ,
2021-04-08 15:50:13 +00:00
hir ::ExprKind ::Binary ( op , lhs , rhs ) if op . node = = hir ::BinOpKind ::Eq | | op . node = = hir ::BinOpKind ::Ne = > {
2017-09-16 05:50:07 +00:00
let mut info = BinaryExprInfo {
2018-03-15 15:07:15 +00:00
expr ,
2017-09-16 05:50:07 +00:00
chain : lhs ,
other : rhs ,
2018-07-12 07:50:09 +00:00
eq : op . node = = hir ::BinOpKind ::Eq ,
2017-09-16 05:50:07 +00:00
} ;
lint_binary_expr_with_method_call ( cx , & mut info ) ;
2021-04-08 15:50:13 +00:00
} ,
2016-01-20 01:23:39 +00:00
_ = > ( ) ,
2015-08-11 18:53:50 +00:00
}
}
2015-08-24 16:13:02 +00:00
2020-08-28 14:10:16 +00:00
#[ allow(clippy::too_many_lines) ]
2020-06-25 20:41:36 +00:00
fn check_impl_item ( & mut self , cx : & LateContext < ' tcx > , impl_item : & ' tcx hir ::ImplItem < '_ > ) {
2019-08-10 03:58:52 +00:00
if in_external_macro ( cx . sess ( ) , impl_item . span ) {
2016-01-20 17:32:17 +00:00
return ;
}
2019-08-10 03:58:52 +00:00
let name = impl_item . ident . name . as_str ( ) ;
2021-10-21 17:41:47 +00:00
let parent = cx . tcx . hir ( ) . get_parent_item ( impl_item . hir_id ( ) ) ;
2019-06-18 09:15:47 +00:00
let item = cx . tcx . hir ( ) . expect_item ( parent ) ;
2021-01-30 16:47:51 +00:00
let self_ty = cx . tcx . type_of ( item . def_id ) ;
2020-12-20 16:19:49 +00:00
2021-03-25 18:29:11 +00:00
let implements_trait = matches! ( item . kind , hir ::ItemKind ::Impl ( hir ::Impl { of_trait : Some ( _ ) , .. } ) ) ;
2017-10-28 18:23:05 +00:00
if_chain! {
2020-03-16 15:00:16 +00:00
if let hir ::ImplItemKind ::Fn ( ref sig , id ) = impl_item . kind ;
2021-04-08 15:50:13 +00:00
if let Some ( first_arg ) = iter_input_pats ( sig . decl , cx . tcx . hir ( ) . body ( id ) ) . next ( ) ;
2019-08-10 04:00:27 +00:00
2021-01-30 22:25:03 +00:00
let method_sig = cx . tcx . fn_sig ( impl_item . def_id ) ;
2020-10-24 00:21:27 +00:00
let method_sig = cx . tcx . erase_late_bound_regions ( method_sig ) ;
2017-11-04 19:55:56 +00:00
Overhaul `TyS` and `Ty`.
Specifically, change `Ty` from this:
```
pub type Ty<'tcx> = &'tcx TyS<'tcx>;
```
to this
```
pub struct Ty<'tcx>(Interned<'tcx, TyS<'tcx>>);
```
There are two benefits to this.
- It's now a first class type, so we can define methods on it. This
means we can move a lot of methods away from `TyS`, leaving `TyS` as a
barely-used type, which is appropriate given that it's not meant to
be used directly.
- The uniqueness requirement is now explicit, via the `Interned` type.
E.g. the pointer-based `Eq` and `Hash` comes from `Interned`, rather
than via `TyS`, which wasn't obvious at all.
Much of this commit is boring churn. The interesting changes are in
these files:
- compiler/rustc_middle/src/arena.rs
- compiler/rustc_middle/src/mir/visit.rs
- compiler/rustc_middle/src/ty/context.rs
- compiler/rustc_middle/src/ty/mod.rs
Specifically:
- Most mentions of `TyS` are removed. It's very much a dumb struct now;
`Ty` has all the smarts.
- `TyS` now has `crate` visibility instead of `pub`.
- `TyS::make_for_test` is removed in favour of the static `BOOL_TY`,
which just works better with the new structure.
- The `Eq`/`Ord`/`Hash` impls are removed from `TyS`. `Interned`s impls
of `Eq`/`Hash` now suffice. `Ord` is now partly on `Interned`
(pointer-based, for the `Equal` case) and partly on `TyS`
(contents-based, for the other cases).
- There are many tedious sigil adjustments, i.e. adding or removing `*`
or `&`. They seem to be unavoidable.
2022-01-25 03:13:38 +00:00
let first_arg_ty = method_sig . inputs ( ) . iter ( ) . next ( ) ;
2019-08-10 04:00:27 +00:00
2019-08-23 12:20:55 +00:00
// check conventions w.r.t. conversion method names and predicates
if let Some ( first_arg_ty ) = first_arg_ty ;
then {
2021-03-25 18:29:11 +00:00
// if this impl block implements a trait, lint in trait definition instead
2021-07-28 22:07:32 +00:00
if ! implements_trait & & cx . access_levels . is_exported ( impl_item . def_id ) {
2020-08-28 14:10:16 +00:00
// check missing trait implementations
for method_config in & TRAIT_METHODS {
if name = = method_config . method_name & &
sig . decl . inputs . len ( ) = = method_config . param_count & &
2021-03-25 18:29:11 +00:00
method_config . output_type . matches ( & sig . decl . output ) & &
Overhaul `TyS` and `Ty`.
Specifically, change `Ty` from this:
```
pub type Ty<'tcx> = &'tcx TyS<'tcx>;
```
to this
```
pub struct Ty<'tcx>(Interned<'tcx, TyS<'tcx>>);
```
There are two benefits to this.
- It's now a first class type, so we can define methods on it. This
means we can move a lot of methods away from `TyS`, leaving `TyS` as a
barely-used type, which is appropriate given that it's not meant to
be used directly.
- The uniqueness requirement is now explicit, via the `Interned` type.
E.g. the pointer-based `Eq` and `Hash` comes from `Interned`, rather
than via `TyS`, which wasn't obvious at all.
Much of this commit is boring churn. The interesting changes are in
these files:
- compiler/rustc_middle/src/arena.rs
- compiler/rustc_middle/src/mir/visit.rs
- compiler/rustc_middle/src/ty/context.rs
- compiler/rustc_middle/src/ty/mod.rs
Specifically:
- Most mentions of `TyS` are removed. It's very much a dumb struct now;
`Ty` has all the smarts.
- `TyS` now has `crate` visibility instead of `pub`.
- `TyS::make_for_test` is removed in favour of the static `BOOL_TY`,
which just works better with the new structure.
- The `Eq`/`Ord`/`Hash` impls are removed from `TyS`. `Interned`s impls
of `Eq`/`Hash` now suffice. `Ord` is now partly on `Interned`
(pointer-based, for the `Equal` case) and partly on `TyS`
(contents-based, for the other cases).
- There are many tedious sigil adjustments, i.e. adding or removing `*`
or `&`. They seem to be unavoidable.
2022-01-25 03:13:38 +00:00
method_config . self_kind . matches ( cx , self_ty , * first_arg_ty ) & &
2020-08-28 14:10:16 +00:00
fn_header_equals ( method_config . fn_header , sig . header ) & &
2021-04-08 15:50:13 +00:00
method_config . lifetime_param_cond ( impl_item )
2020-08-28 14:10:16 +00:00
{
span_lint_and_help (
cx ,
SHOULD_IMPLEMENT_TRAIT ,
impl_item . span ,
& format! (
" method `{}` can be confused for the standard trait method `{}::{}` " ,
method_config . method_name ,
method_config . trait_name ,
method_config . method_name
) ,
None ,
& format! (
" consider implementing the trait `{}` or choosing a less ambiguous method name " ,
method_config . trait_name
)
) ;
2017-10-23 19:18:02 +00:00
}
2019-08-10 04:00:27 +00:00
}
2019-08-23 12:20:55 +00:00
}
2018-10-01 11:47:06 +00:00
2021-06-03 06:41:37 +00:00
if sig . decl . implicit_self . has_implicit_self ( )
& & ! ( self . avoid_breaking_exported_api
2021-07-28 22:07:32 +00:00
& & cx . access_levels . is_exported ( impl_item . def_id ) )
2021-06-03 06:41:37 +00:00
{
2021-05-20 10:30:31 +00:00
wrong_self_convention ::check (
cx ,
2021-12-30 14:10:43 +00:00
name ,
2021-05-20 10:30:31 +00:00
self_ty ,
Overhaul `TyS` and `Ty`.
Specifically, change `Ty` from this:
```
pub type Ty<'tcx> = &'tcx TyS<'tcx>;
```
to this
```
pub struct Ty<'tcx>(Interned<'tcx, TyS<'tcx>>);
```
There are two benefits to this.
- It's now a first class type, so we can define methods on it. This
means we can move a lot of methods away from `TyS`, leaving `TyS` as a
barely-used type, which is appropriate given that it's not meant to
be used directly.
- The uniqueness requirement is now explicit, via the `Interned` type.
E.g. the pointer-based `Eq` and `Hash` comes from `Interned`, rather
than via `TyS`, which wasn't obvious at all.
Much of this commit is boring churn. The interesting changes are in
these files:
- compiler/rustc_middle/src/arena.rs
- compiler/rustc_middle/src/mir/visit.rs
- compiler/rustc_middle/src/ty/context.rs
- compiler/rustc_middle/src/ty/mod.rs
Specifically:
- Most mentions of `TyS` are removed. It's very much a dumb struct now;
`Ty` has all the smarts.
- `TyS` now has `crate` visibility instead of `pub`.
- `TyS::make_for_test` is removed in favour of the static `BOOL_TY`,
which just works better with the new structure.
- The `Eq`/`Ord`/`Hash` impls are removed from `TyS`. `Interned`s impls
of `Eq`/`Hash` now suffice. `Ord` is now partly on `Interned`
(pointer-based, for the `Equal` case) and partly on `TyS`
(contents-based, for the other cases).
- There are many tedious sigil adjustments, i.e. adding or removing `*`
or `&`. They seem to be unavoidable.
2022-01-25 03:13:38 +00:00
* first_arg_ty ,
2021-05-20 10:30:31 +00:00
first_arg . pat . span ,
implements_trait ,
false
) ;
}
2016-08-08 15:09:36 +00:00
}
2017-10-23 19:18:02 +00:00
}
2018-10-03 03:11:56 +00:00
2021-03-25 18:29:11 +00:00
// if this impl block implements a trait, lint in trait definition instead
if implements_trait {
return ;
}
2020-03-16 15:00:16 +00:00
if let hir ::ImplItemKind ::Fn ( _ , _ ) = impl_item . kind {
2021-01-30 22:25:03 +00:00
let ret_ty = return_ty ( cx , impl_item . hir_id ( ) ) ;
2018-10-05 02:01:04 +00:00
2018-10-20 00:54:25 +00:00
// walk the return type and check for Self (this does not check associated types)
2021-03-25 18:29:11 +00:00
if let Some ( self_adt ) = self_ty . ty_adt_def ( ) {
2022-01-12 03:19:52 +00:00
if contains_adt_constructor ( ret_ty , self_adt ) {
2021-03-25 18:29:11 +00:00
return ;
}
2022-01-12 03:19:52 +00:00
} else if contains_ty ( ret_ty , self_ty ) {
2019-08-23 12:20:55 +00:00
return ;
2018-10-20 00:54:25 +00:00
}
2018-10-19 11:55:06 +00:00
2018-10-20 00:54:25 +00:00
// if return type is impl trait, check the associated types
2020-08-03 22:18:29 +00:00
if let ty ::Opaque ( def_id , _ ) = * ret_ty . kind ( ) {
2018-10-20 00:54:25 +00:00
// one of the associated types must be Self
2020-06-30 21:41:57 +00:00
for & ( predicate , _span ) in cx . tcx . explicit_item_bounds ( def_id ) {
2021-01-07 16:20:28 +00:00
if let ty ::PredicateKind ::Projection ( projection_predicate ) = predicate . kind ( ) . skip_binder ( ) {
2022-01-10 23:39:21 +00:00
let assoc_ty = match projection_predicate . term {
2022-01-27 14:12:45 +00:00
ty ::Term ::Ty ( ty ) = > ty ,
ty ::Term ::Const ( _c ) = > continue ,
2022-01-10 23:39:21 +00:00
} ;
2020-05-28 13:45:24 +00:00
// walk the associated type and check for Self
2021-03-25 18:29:11 +00:00
if let Some ( self_adt ) = self_ty . ty_adt_def ( ) {
2022-01-10 23:39:21 +00:00
if contains_adt_constructor ( assoc_ty , self_adt ) {
2021-03-25 18:29:11 +00:00
return ;
}
2022-01-10 23:39:21 +00:00
} else if contains_ty ( assoc_ty , self_ty ) {
2020-05-28 13:45:24 +00:00
return ;
}
2018-10-05 02:01:04 +00:00
}
}
}
2022-01-25 07:42:52 +00:00
if name = = " new " & & ret_ty ! = self_ty {
2018-11-27 20:14:15 +00:00
span_lint (
cx ,
NEW_RET_NO_SELF ,
2019-08-10 03:58:52 +00:00
impl_item . span ,
2018-11-27 20:14:15 +00:00
" methods called `new` usually return `Self` " ,
) ;
2018-10-03 10:55:31 +00:00
}
2018-10-03 03:11:56 +00:00
}
2015-08-24 16:13:02 +00:00
}
2020-08-28 14:10:16 +00:00
fn check_trait_item ( & mut self , cx : & LateContext < ' tcx > , item : & ' tcx TraitItem < '_ > ) {
2020-12-20 16:19:49 +00:00
if in_external_macro ( cx . tcx . sess , item . span ) {
return ;
}
if_chain! {
if let TraitItemKind ::Fn ( ref sig , _ ) = item . kind ;
2021-05-20 10:30:31 +00:00
if sig . decl . implicit_self . has_implicit_self ( ) ;
2020-12-20 16:19:49 +00:00
if let Some ( first_arg_ty ) = sig . decl . inputs . iter ( ) . next ( ) ;
2021-05-20 10:30:31 +00:00
2020-12-20 16:19:49 +00:00
then {
2021-04-08 15:50:13 +00:00
let first_arg_span = first_arg_ty . span ;
let first_arg_ty = hir_ty_to_ty ( cx . tcx , first_arg_ty ) ;
2021-09-16 04:12:56 +00:00
let self_ty = TraitRef ::identity ( cx . tcx , item . def_id . to_def_id ( ) ) . self_ty ( ) . skip_binder ( ) ;
2021-03-12 14:30:50 +00:00
wrong_self_convention ::check (
cx ,
2021-12-15 03:39:23 +00:00
item . ident . name . as_str ( ) ,
2021-03-12 14:30:50 +00:00
self_ty ,
first_arg_ty ,
2021-03-25 18:29:11 +00:00
first_arg_span ,
2021-04-08 15:50:13 +00:00
false ,
2021-03-25 18:29:11 +00:00
true
2021-03-12 14:30:50 +00:00
) ;
2020-12-20 16:19:49 +00:00
}
}
2020-08-28 14:10:16 +00:00
if_chain! {
2020-11-05 13:29:48 +00:00
if item . ident . name = = sym ::new ;
2020-08-28 14:10:16 +00:00
if let TraitItemKind ::Fn ( _ , _ ) = item . kind ;
2021-01-30 19:46:50 +00:00
let ret_ty = return_ty ( cx , item . hir_id ( ) ) ;
2021-09-16 04:12:56 +00:00
let self_ty = TraitRef ::identity ( cx . tcx , item . def_id . to_def_id ( ) ) . self_ty ( ) . skip_binder ( ) ;
2022-01-12 03:19:52 +00:00
if ! contains_ty ( ret_ty , self_ty ) ;
2020-08-28 14:10:16 +00:00
then {
span_lint (
cx ,
NEW_RET_NO_SELF ,
item . span ,
" methods called `new` usually return `Self` " ,
) ;
}
}
}
2020-12-06 14:01:03 +00:00
extract_msrv_attr! ( LateContext ) ;
2015-08-24 16:13:02 +00:00
}
2021-04-08 15:50:13 +00:00
2022-05-21 11:24:00 +00:00
impl Methods {
#[ allow(clippy::too_many_lines) ]
fn check_methods < ' tcx > ( & self , cx : & LateContext < ' tcx > , expr : & ' tcx Expr < '_ > ) {
if let Some ( ( name , [ recv , args @ .. ] , span ) ) = method_call ( expr ) {
match ( name , args ) {
( " add " | " offset " | " sub " | " wrapping_offset " | " wrapping_add " | " wrapping_sub " , [ _arg ] ) = > {
zst_offset ::check ( cx , expr , recv ) ;
} ,
( " and_then " , [ arg ] ) = > {
let biom_option_linted = bind_instead_of_map ::OptionAndThenSome ::check ( cx , expr , recv , arg ) ;
let biom_result_linted = bind_instead_of_map ::ResultAndThenOk ::check ( cx , expr , recv , arg ) ;
if ! biom_option_linted & & ! biom_result_linted {
unnecessary_lazy_eval ::check ( cx , expr , recv , arg , " and " ) ;
}
} ,
( " as_deref " | " as_deref_mut " , [ ] ) = > {
needless_option_as_deref ::check ( cx , expr , recv , name ) ;
} ,
( " as_mut " , [ ] ) = > useless_asref ::check ( cx , expr , " as_mut " , recv ) ,
( " as_ref " , [ ] ) = > useless_asref ::check ( cx , expr , " as_ref " , recv ) ,
( " assume_init " , [ ] ) = > uninit_assumed_init ::check ( cx , expr , recv ) ,
( " cloned " , [ ] ) = > cloned_instead_of_copied ::check ( cx , expr , recv , span , self . msrv ) ,
( " collect " , [ ] ) = > match method_call ( recv ) {
Some ( ( name @ ( " cloned " | " copied " ) , [ recv2 ] , _ ) ) = > {
iter_cloned_collect ::check ( cx , name , expr , recv2 ) ;
} ,
Some ( ( " map " , [ m_recv , m_arg ] , _ ) ) = > {
map_collect_result_unit ::check ( cx , expr , m_recv , m_arg , recv ) ;
} ,
Some ( ( " take " , [ take_self_arg , take_arg ] , _ ) ) = > {
if meets_msrv ( self . msrv , msrvs ::STR_REPEAT ) {
manual_str_repeat ::check ( cx , expr , recv , take_self_arg , take_arg ) ;
}
} ,
_ = > { } ,
} ,
2022-06-05 15:39:36 +00:00
( " count " , [ ] ) if is_trait_method ( cx , expr , sym ::Iterator ) = > match method_call ( recv ) {
2022-06-07 04:40:32 +00:00
Some ( ( " cloned " , [ recv2 ] , _ ) ) = > iter_overeager_cloned ::check ( cx , expr , recv , recv2 , true , false ) ,
2022-05-21 11:24:00 +00:00
Some ( ( name2 @ ( " into_iter " | " iter " | " iter_mut " ) , [ recv2 ] , _ ) ) = > {
iter_count ::check ( cx , expr , recv2 , name2 ) ;
} ,
Some ( ( " map " , [ _ , arg ] , _ ) ) = > suspicious_map ::check ( cx , expr , recv , arg ) ,
2022-06-05 15:39:36 +00:00
Some ( ( " filter " , [ recv2 , arg ] , _ ) ) = > bytecount ::check ( cx , expr , recv2 , arg ) ,
2022-06-05 17:05:11 +00:00
Some ( ( " bytes " , [ recv2 ] , _ ) ) = > bytes_count_to_len ::check ( cx , expr , recv , recv2 ) ,
2022-05-21 11:24:00 +00:00
_ = > { } ,
} ,
( " drain " , [ arg ] ) = > {
iter_with_drain ::check ( cx , expr , recv , span , arg ) ;
} ,
2022-06-05 17:21:04 +00:00
( " ends_with " , [ arg ] ) = > {
if let ExprKind ::MethodCall ( _ , _ , span ) = expr . kind {
2022-06-05 17:44:09 +00:00
case_sensitive_file_extension_comparisons ::check ( cx , expr , span , recv , arg ) ;
}
2022-06-05 17:21:04 +00:00
} ,
2022-05-21 11:24:00 +00:00
( " expect " , [ _ ] ) = > match method_call ( recv ) {
Some ( ( " ok " , [ recv ] , _ ) ) = > ok_expect ::check ( cx , expr , recv ) ,
Some ( ( " err " , [ recv ] , err_span ) ) = > err_expect ::check ( cx , expr , recv , self . msrv , span , err_span ) ,
2022-08-15 18:30:30 +00:00
_ = > expect_used ::check ( cx , expr , recv , false , self . allow_expect_in_tests ) ,
2022-05-21 11:24:00 +00:00
} ,
2022-08-15 18:30:30 +00:00
( " expect_err " , [ _ ] ) = > expect_used ::check ( cx , expr , recv , true , self . allow_expect_in_tests ) ,
2022-05-21 11:24:00 +00:00
( " extend " , [ arg ] ) = > {
string_extend_chars ::check ( cx , expr , recv , arg ) ;
extend_with_drain ::check ( cx , expr , recv , arg ) ;
} ,
( " filter_map " , [ arg ] ) = > {
unnecessary_filter_map ::check ( cx , expr , arg , name ) ;
filter_map_identity ::check ( cx , expr , arg , span ) ;
2021-12-06 11:33:31 +00:00
} ,
2022-05-21 11:24:00 +00:00
( " find_map " , [ arg ] ) = > {
unnecessary_filter_map ::check ( cx , expr , arg , name ) ;
2021-04-08 15:50:13 +00:00
} ,
2022-05-21 11:24:00 +00:00
( " flat_map " , [ arg ] ) = > {
flat_map_identity ::check ( cx , expr , arg , span ) ;
flat_map_option ::check ( cx , expr , arg , span ) ;
} ,
2022-06-07 04:40:32 +00:00
( " flatten " , [ ] ) = > match method_call ( recv ) {
2022-05-21 11:24:00 +00:00
Some ( ( " map " , [ recv , map_arg ] , map_span ) ) = > map_flatten ::check ( cx , expr , recv , map_arg , map_span ) ,
2022-06-07 04:40:32 +00:00
Some ( ( " cloned " , [ recv2 ] , _ ) ) = > iter_overeager_cloned ::check ( cx , expr , recv , recv2 , false , true ) ,
2022-05-21 11:24:00 +00:00
_ = > { } ,
} ,
( " fold " , [ init , acc ] ) = > unnecessary_fold ::check ( cx , expr , init , acc , span ) ,
( " for_each " , [ _ ] ) = > {
if let Some ( ( " inspect " , [ _ , _ ] , span2 ) ) = method_call ( recv ) {
inspect_for_each ::check ( cx , expr , span2 ) ;
2021-06-03 06:41:37 +00:00
}
} ,
2022-06-05 17:44:09 +00:00
( " get " , [ arg ] ) = > {
get_first ::check ( cx , expr , recv , arg ) ;
get_last_with_len ::check ( cx , expr , recv , arg ) ;
} ,
2022-05-21 11:24:00 +00:00
( " get_or_insert_with " , [ arg ] ) = > unnecessary_lazy_eval ::check ( cx , expr , recv , arg , " get_or_insert " ) ,
2022-06-06 01:41:33 +00:00
( " hash " , [ arg ] ) = > {
unit_hash ::check ( cx , expr , recv , arg ) ;
} ,
2022-05-21 11:24:00 +00:00
( " is_file " , [ ] ) = > filetype_is_file ::check ( cx , expr , recv ) ,
( " is_digit " , [ radix ] ) = > is_digit_ascii_radix ::check ( cx , expr , recv , radix , self . msrv ) ,
( " is_none " , [ ] ) = > check_is_some_is_none ( cx , expr , recv , false ) ,
( " is_some " , [ ] ) = > check_is_some_is_none ( cx , expr , recv , true ) ,
2022-07-30 11:39:55 +00:00
( " iter " | " iter_mut " | " into_iter " , [ ] ) = > {
iter_on_single_or_empty_collections ::check ( cx , expr , name , recv ) ;
} ,
2022-05-21 11:24:00 +00:00
( " join " , [ join_arg ] ) = > {
if let Some ( ( " collect " , _ , span ) ) = method_call ( recv ) {
unnecessary_join ::check ( cx , expr , recv , join_arg , span ) ;
}
2021-04-08 15:50:13 +00:00
} ,
2022-06-07 04:40:32 +00:00
( " last " , [ ] ) | ( " skip " , [ _ ] ) = > {
2022-05-21 11:24:00 +00:00
if let Some ( ( name2 , [ recv2 , args2 @ .. ] , _span2 ) ) = method_call ( recv ) {
if let ( " cloned " , [ ] ) = ( name2 , args2 ) {
2022-06-07 04:40:32 +00:00
iter_overeager_cloned ::check ( cx , expr , recv , recv2 , false , false ) ;
2022-05-21 11:24:00 +00:00
}
2022-01-17 12:29:07 +00:00
}
2022-05-21 11:24:00 +00:00
} ,
2022-06-05 23:57:58 +00:00
( " lock " , [ ] ) = > {
mut_mutex_lock ::check ( cx , expr , recv , span ) ;
} ,
2022-05-21 11:24:00 +00:00
( name @ ( " map " | " map_err " ) , [ m_arg ] ) = > {
2022-06-05 19:45:04 +00:00
if name = = " map " {
map_clone ::check ( cx , expr , recv , m_arg , self . msrv ) ;
2022-06-05 19:59:24 +00:00
} else {
map_err_ignore ::check ( cx , expr , m_arg ) ;
2022-06-05 19:45:04 +00:00
}
2022-05-21 11:24:00 +00:00
if let Some ( ( name , [ recv2 , args @ .. ] , span2 ) ) = method_call ( recv ) {
match ( name , args ) {
( " as_mut " , [ ] ) = > option_as_ref_deref ::check ( cx , expr , recv2 , m_arg , true , self . msrv ) ,
( " as_ref " , [ ] ) = > option_as_ref_deref ::check ( cx , expr , recv2 , m_arg , false , self . msrv ) ,
( " filter " , [ f_arg ] ) = > {
filter_map ::check ( cx , expr , recv2 , f_arg , span2 , recv , m_arg , span , false ) ;
} ,
( " find " , [ f_arg ] ) = > {
filter_map ::check ( cx , expr , recv2 , f_arg , span2 , recv , m_arg , span , true ) ;
} ,
_ = > { } ,
}
2021-04-08 15:50:13 +00:00
}
2022-05-21 11:24:00 +00:00
map_identity ::check ( cx , expr , recv , m_arg , name , span ) ;
} ,
2022-06-05 19:20:47 +00:00
( " map_or " , [ def , map ] ) = > {
option_map_or_none ::check ( cx , expr , recv , def , map ) ;
manual_ok_or ::check ( cx , expr , recv , def , map ) ;
} ,
2022-06-07 04:40:32 +00:00
( " next " , [ ] ) = > {
2022-05-21 11:24:00 +00:00
if let Some ( ( name2 , [ recv2 , args2 @ .. ] , _ ) ) = method_call ( recv ) {
match ( name2 , args2 ) {
2022-06-07 04:40:32 +00:00
( " cloned " , [ ] ) = > iter_overeager_cloned ::check ( cx , expr , recv , recv2 , false , false ) ,
2022-05-21 11:24:00 +00:00
( " filter " , [ arg ] ) = > filter_next ::check ( cx , expr , recv2 , arg ) ,
( " filter_map " , [ arg ] ) = > filter_map_next ::check ( cx , expr , recv2 , arg , self . msrv ) ,
( " iter " , [ ] ) = > iter_next_slice ::check ( cx , expr , recv2 ) ,
( " skip " , [ arg ] ) = > iter_skip_next ::check ( cx , expr , recv2 , arg ) ,
( " skip_while " , [ _ ] ) = > skip_while_next ::check ( cx , expr ) ,
_ = > { } ,
}
2021-04-08 15:50:13 +00:00
}
2022-05-21 11:24:00 +00:00
} ,
2022-06-07 04:40:32 +00:00
( " nth " , [ n_arg ] ) = > match method_call ( recv ) {
2022-05-21 11:24:00 +00:00
Some ( ( " bytes " , [ recv2 ] , _ ) ) = > bytes_nth ::check ( cx , expr , recv2 , n_arg ) ,
2022-06-07 04:40:32 +00:00
Some ( ( " cloned " , [ recv2 ] , _ ) ) = > iter_overeager_cloned ::check ( cx , expr , recv , recv2 , false , false ) ,
2022-05-21 11:24:00 +00:00
Some ( ( " iter " , [ recv2 ] , _ ) ) = > iter_nth ::check ( cx , expr , recv2 , recv , n_arg , false ) ,
Some ( ( " iter_mut " , [ recv2 ] , _ ) ) = > iter_nth ::check ( cx , expr , recv2 , recv , n_arg , true ) ,
_ = > iter_nth_zero ::check ( cx , expr , recv , n_arg ) ,
} ,
( " ok_or_else " , [ arg ] ) = > unnecessary_lazy_eval ::check ( cx , expr , recv , arg , " ok_or " ) ,
2022-06-06 00:09:55 +00:00
( " open " , [ _ ] ) = > {
open_options ::check ( cx , expr , recv ) ;
} ,
2022-05-21 11:24:00 +00:00
( " or_else " , [ arg ] ) = > {
if ! bind_instead_of_map ::ResultOrElseErrInfo ::check ( cx , expr , recv , arg ) {
unnecessary_lazy_eval ::check ( cx , expr , recv , arg , " or " ) ;
2022-01-17 12:29:07 +00:00
}
2022-05-21 11:24:00 +00:00
} ,
2022-06-06 00:27:36 +00:00
( " push " , [ arg ] ) = > {
path_buf_push_overwrite ::check ( cx , expr , arg ) ;
} ,
2022-06-06 15:58:30 +00:00
( " read_to_end " , [ _ ] ) = > {
verbose_file_reads ::check ( cx , expr , recv , verbose_file_reads ::READ_TO_END_MSG ) ;
} ,
( " read_to_string " , [ _ ] ) = > {
verbose_file_reads ::check ( cx , expr , recv , verbose_file_reads ::READ_TO_STRING_MSG ) ;
} ,
2022-06-06 00:49:03 +00:00
( " repeat " , [ arg ] ) = > {
repeat_once ::check ( cx , expr , recv , arg ) ;
} ,
2022-08-14 16:33:55 +00:00
( name @ ( " replace " | " replacen " ) , [ arg1 , arg2 ] | [ arg1 , arg2 , _ ] ) = > {
no_effect_replace ::check ( cx , expr , arg1 , arg2 ) ;
// Check for repeated `str::replace` calls to perform `collapsible_str_replace` lint
if name = = " replace " & & let Some ( ( " replace " , .. ) ) = method_call ( recv ) {
collapsible_str_replace ::check ( cx , expr , arg1 , arg2 ) ;
}
} ,
2022-06-06 15:17:38 +00:00
( " resize " , [ count_arg , default_arg ] ) = > {
vec_resize_to_zero ::check ( cx , expr , count_arg , default_arg , span ) ;
} ,
2022-06-06 01:07:29 +00:00
( " sort " , [ ] ) = > {
stable_sort_primitive ::check ( cx , expr , recv ) ;
} ,
2022-06-06 03:22:58 +00:00
( " sort_by " , [ arg ] ) = > {
unnecessary_sort_by ::check ( cx , expr , recv , arg , false ) ;
} ,
( " sort_unstable_by " , [ arg ] ) = > {
unnecessary_sort_by ::check ( cx , expr , recv , arg , true ) ;
} ,
2022-05-21 11:24:00 +00:00
( " splitn " | " rsplitn " , [ count_arg , pat_arg ] ) = > {
if let Some ( ( Constant ::Int ( count ) , _ ) ) = constant ( cx , cx . typeck_results ( ) , count_arg ) {
suspicious_splitn ::check ( cx , name , expr , recv , count ) ;
str_splitn ::check ( cx , name , expr , recv , pat_arg , count , self . msrv ) ;
}
} ,
( " splitn_mut " | " rsplitn_mut " , [ count_arg , _ ] ) = > {
if let Some ( ( Constant ::Int ( count ) , _ ) ) = constant ( cx , cx . typeck_results ( ) , count_arg ) {
suspicious_splitn ::check ( cx , name , expr , recv , count ) ;
}
} ,
( " step_by " , [ arg ] ) = > iterator_step_by_zero ::check ( cx , expr , arg ) ,
2022-06-07 04:40:32 +00:00
( " take " , [ _arg ] ) = > {
2022-05-21 11:24:00 +00:00
if let Some ( ( name2 , [ recv2 , args2 @ .. ] , _span2 ) ) = method_call ( recv ) {
if let ( " cloned " , [ ] ) = ( name2 , args2 ) {
2022-06-07 04:40:32 +00:00
iter_overeager_cloned ::check ( cx , expr , recv , recv2 , false , false ) ;
2022-05-21 11:24:00 +00:00
}
}
} ,
( " take " , [ ] ) = > needless_option_take ::check ( cx , expr , recv ) ,
2022-07-06 07:51:40 +00:00
( " then " , [ arg ] ) = > {
if ! meets_msrv ( self . msrv , msrvs ::BOOL_THEN_SOME ) {
return ;
}
unnecessary_lazy_eval ::check ( cx , expr , recv , arg , " then_some " ) ;
} ,
2022-05-21 11:24:00 +00:00
( " to_os_string " | " to_owned " | " to_path_buf " | " to_vec " , [ ] ) = > {
implicit_clone ::check ( cx , name , expr , recv ) ;
} ,
( " unwrap " , [ ] ) = > {
match method_call ( recv ) {
Some ( ( " get " , [ recv , get_arg ] , _ ) ) = > {
get_unwrap ::check ( cx , expr , recv , get_arg , false ) ;
} ,
Some ( ( " get_mut " , [ recv , get_arg ] , _ ) ) = > {
get_unwrap ::check ( cx , expr , recv , get_arg , true ) ;
} ,
Some ( ( " or " , [ recv , or_arg ] , or_span ) ) = > {
or_then_unwrap ::check ( cx , expr , recv , or_arg , or_span ) ;
} ,
_ = > { } ,
}
2022-08-15 18:30:30 +00:00
unwrap_used ::check ( cx , expr , recv , false , self . allow_unwrap_in_tests ) ;
2022-05-21 11:24:00 +00:00
} ,
2022-08-15 18:30:30 +00:00
( " unwrap_err " , [ ] ) = > unwrap_used ::check ( cx , expr , recv , true , self . allow_unwrap_in_tests ) ,
2022-05-21 11:24:00 +00:00
( " unwrap_or " , [ u_arg ] ) = > match method_call ( recv ) {
Some ( ( arith @ ( " checked_add " | " checked_sub " | " checked_mul " ) , [ lhs , rhs ] , _ ) ) = > {
manual_saturating_arithmetic ::check ( cx , expr , lhs , rhs , u_arg , & arith [ " checked_ " . len ( ) .. ] ) ;
2022-02-10 17:40:06 +00:00
} ,
2022-05-21 11:24:00 +00:00
Some ( ( " map " , [ m_recv , m_arg ] , span ) ) = > {
option_map_unwrap_or ::check ( cx , expr , m_recv , m_arg , recv , u_arg , span ) ;
2022-03-24 13:50:04 +00:00
} ,
2022-07-10 21:37:38 +00:00
Some ( ( " then_some " , [ t_recv , t_arg ] , _ ) ) = > {
obfuscated_if_else ::check ( cx , expr , t_recv , t_arg , u_arg ) ;
} ,
2022-02-10 17:40:06 +00:00
_ = > { } ,
2021-04-08 15:50:13 +00:00
} ,
2022-05-21 11:24:00 +00:00
( " unwrap_or_else " , [ u_arg ] ) = > match method_call ( recv ) {
Some ( ( " map " , [ recv , map_arg ] , _ ) )
if map_unwrap_or ::check ( cx , expr , recv , map_arg , u_arg , self . msrv ) = > { } ,
_ = > {
unwrap_or_else_default ::check ( cx , expr , recv , u_arg ) ;
unnecessary_lazy_eval ::check ( cx , expr , recv , u_arg , " unwrap_or " ) ;
} ,
2021-04-08 15:50:13 +00:00
} ,
2022-06-06 00:39:57 +00:00
( " zip " , [ arg ] ) = > {
if let ExprKind ::MethodCall ( name , [ iter_recv ] , _ ) = recv . kind
& & name . ident . name = = sym ::iter
{
range_zip_with_len ::check ( cx , expr , iter_recv , arg ) ;
}
} ,
2021-04-08 15:50:13 +00:00
_ = > { } ,
2022-05-21 11:24:00 +00:00
}
2021-04-08 15:50:13 +00:00
}
}
}
fn check_is_some_is_none ( cx : & LateContext < '_ > , expr : & Expr < '_ > , recv : & Expr < '_ > , is_some : bool ) {
2022-01-13 12:18:19 +00:00
if let Some ( ( name @ ( " find " | " position " | " rposition " ) , [ f_recv , arg ] , span ) ) = method_call ( recv ) {
2021-06-03 06:41:37 +00:00
search_is_some ::check ( cx , expr , name , is_some , f_recv , arg , recv , span ) ;
2021-04-08 15:50:13 +00:00
}
}
2021-03-12 14:30:50 +00:00
/// Used for `lint_binary_expr_with_method_call`.
#[ derive(Copy, Clone) ]
struct BinaryExprInfo < ' a > {
expr : & ' a hir ::Expr < ' a > ,
chain : & ' a hir ::Expr < ' a > ,
other : & ' a hir ::Expr < ' a > ,
eq : bool ,
}
2020-05-28 13:45:24 +00:00
2021-03-12 14:30:50 +00:00
/// Checks for the `CHARS_NEXT_CMP` and `CHARS_LAST_CMP` lints.
fn lint_binary_expr_with_method_call ( cx : & LateContext < '_ > , info : & mut BinaryExprInfo < '_ > ) {
macro_rules ! lint_with_both_lhs_and_rhs {
2021-03-25 18:29:11 +00:00
( $func :expr , $cx :expr , $info :ident ) = > {
2021-03-12 14:30:50 +00:00
if ! $func ( $cx , $info ) {
::std ::mem ::swap ( & mut $info . chain , & mut $info . other ) ;
if $func ( $cx , $info ) {
2020-05-28 13:45:24 +00:00
return ;
}
}
2021-03-12 14:30:50 +00:00
} ;
2016-01-18 12:11:07 +00:00
}
2021-03-25 18:29:11 +00:00
lint_with_both_lhs_and_rhs! ( chars_next_cmp ::check , cx , info ) ;
lint_with_both_lhs_and_rhs! ( chars_last_cmp ::check , cx , info ) ;
lint_with_both_lhs_and_rhs! ( chars_next_cmp_with_unwrap ::check , cx , info ) ;
lint_with_both_lhs_and_rhs! ( chars_last_cmp_with_unwrap ::check , cx , info ) ;
2016-02-15 03:40:43 +00:00
}
2020-04-08 10:57:58 +00:00
const FN_HEADER : hir ::FnHeader = hir ::FnHeader {
unsafety : hir ::Unsafety ::Normal ,
constness : hir ::Constness ::NotConst ,
asyncness : hir ::IsAsync ::NotAsync ,
abi : rustc_target ::spec ::abi ::Abi ::Rust ,
} ;
2020-08-28 14:10:16 +00:00
struct ShouldImplTraitCase {
trait_name : & 'static str ,
method_name : & 'static str ,
param_count : usize ,
fn_header : hir ::FnHeader ,
// implicit self kind expected (none, self, &self, ...)
self_kind : SelfKind ,
// checks against the output type
output_type : OutType ,
// certain methods with explicit lifetimes can't implement the equivalent trait method
lint_explicit_lifetime : bool ,
}
impl ShouldImplTraitCase {
const fn new (
trait_name : & 'static str ,
method_name : & 'static str ,
param_count : usize ,
fn_header : hir ::FnHeader ,
self_kind : SelfKind ,
output_type : OutType ,
lint_explicit_lifetime : bool ,
) -> ShouldImplTraitCase {
ShouldImplTraitCase {
trait_name ,
method_name ,
param_count ,
fn_header ,
self_kind ,
output_type ,
lint_explicit_lifetime ,
}
}
fn lifetime_param_cond ( & self , impl_item : & hir ::ImplItem < '_ > ) -> bool {
self . lint_explicit_lifetime
| | ! impl_item . generics . params . iter ( ) . any ( | p | {
matches! (
p . kind ,
hir ::GenericParamKind ::Lifetime {
kind : hir ::LifetimeParamKind ::Explicit
}
)
} )
}
}
2018-05-30 16:24:44 +00:00
#[ rustfmt::skip ]
2020-08-28 14:10:16 +00:00
const TRAIT_METHODS : [ ShouldImplTraitCase ; 30 ] = [
ShouldImplTraitCase ::new ( " std::ops::Add " , " add " , 2 , FN_HEADER , SelfKind ::Value , OutType ::Any , true ) ,
ShouldImplTraitCase ::new ( " std::convert::AsMut " , " as_mut " , 1 , FN_HEADER , SelfKind ::RefMut , OutType ::Ref , true ) ,
ShouldImplTraitCase ::new ( " std::convert::AsRef " , " as_ref " , 1 , FN_HEADER , SelfKind ::Ref , OutType ::Ref , true ) ,
ShouldImplTraitCase ::new ( " std::ops::BitAnd " , " bitand " , 2 , FN_HEADER , SelfKind ::Value , OutType ::Any , true ) ,
ShouldImplTraitCase ::new ( " std::ops::BitOr " , " bitor " , 2 , FN_HEADER , SelfKind ::Value , OutType ::Any , true ) ,
ShouldImplTraitCase ::new ( " std::ops::BitXor " , " bitxor " , 2 , FN_HEADER , SelfKind ::Value , OutType ::Any , true ) ,
ShouldImplTraitCase ::new ( " std::borrow::Borrow " , " borrow " , 1 , FN_HEADER , SelfKind ::Ref , OutType ::Ref , true ) ,
ShouldImplTraitCase ::new ( " std::borrow::BorrowMut " , " borrow_mut " , 1 , FN_HEADER , SelfKind ::RefMut , OutType ::Ref , true ) ,
ShouldImplTraitCase ::new ( " std::clone::Clone " , " clone " , 1 , FN_HEADER , SelfKind ::Ref , OutType ::Any , true ) ,
ShouldImplTraitCase ::new ( " std::cmp::Ord " , " cmp " , 2 , FN_HEADER , SelfKind ::Ref , OutType ::Any , true ) ,
// FIXME: default doesn't work
ShouldImplTraitCase ::new ( " std::default::Default " , " default " , 0 , FN_HEADER , SelfKind ::No , OutType ::Any , true ) ,
ShouldImplTraitCase ::new ( " std::ops::Deref " , " deref " , 1 , FN_HEADER , SelfKind ::Ref , OutType ::Ref , true ) ,
ShouldImplTraitCase ::new ( " std::ops::DerefMut " , " deref_mut " , 1 , FN_HEADER , SelfKind ::RefMut , OutType ::Ref , true ) ,
ShouldImplTraitCase ::new ( " std::ops::Div " , " div " , 2 , FN_HEADER , SelfKind ::Value , OutType ::Any , true ) ,
ShouldImplTraitCase ::new ( " std::ops::Drop " , " drop " , 1 , FN_HEADER , SelfKind ::RefMut , OutType ::Unit , true ) ,
ShouldImplTraitCase ::new ( " std::cmp::PartialEq " , " eq " , 2 , FN_HEADER , SelfKind ::Ref , OutType ::Bool , true ) ,
ShouldImplTraitCase ::new ( " std::iter::FromIterator " , " from_iter " , 1 , FN_HEADER , SelfKind ::No , OutType ::Any , true ) ,
ShouldImplTraitCase ::new ( " std::str::FromStr " , " from_str " , 1 , FN_HEADER , SelfKind ::No , OutType ::Any , true ) ,
ShouldImplTraitCase ::new ( " std::hash::Hash " , " hash " , 2 , FN_HEADER , SelfKind ::Ref , OutType ::Unit , true ) ,
ShouldImplTraitCase ::new ( " std::ops::Index " , " index " , 2 , FN_HEADER , SelfKind ::Ref , OutType ::Ref , true ) ,
ShouldImplTraitCase ::new ( " std::ops::IndexMut " , " index_mut " , 2 , FN_HEADER , SelfKind ::RefMut , OutType ::Ref , true ) ,
ShouldImplTraitCase ::new ( " std::iter::IntoIterator " , " into_iter " , 1 , FN_HEADER , SelfKind ::Value , OutType ::Any , true ) ,
ShouldImplTraitCase ::new ( " std::ops::Mul " , " mul " , 2 , FN_HEADER , SelfKind ::Value , OutType ::Any , true ) ,
ShouldImplTraitCase ::new ( " std::ops::Neg " , " neg " , 1 , FN_HEADER , SelfKind ::Value , OutType ::Any , true ) ,
ShouldImplTraitCase ::new ( " std::iter::Iterator " , " next " , 1 , FN_HEADER , SelfKind ::RefMut , OutType ::Any , false ) ,
ShouldImplTraitCase ::new ( " std::ops::Not " , " not " , 1 , FN_HEADER , SelfKind ::Value , OutType ::Any , true ) ,
ShouldImplTraitCase ::new ( " std::ops::Rem " , " rem " , 2 , FN_HEADER , SelfKind ::Value , OutType ::Any , true ) ,
ShouldImplTraitCase ::new ( " std::ops::Shl " , " shl " , 2 , FN_HEADER , SelfKind ::Value , OutType ::Any , true ) ,
ShouldImplTraitCase ::new ( " std::ops::Shr " , " shr " , 2 , FN_HEADER , SelfKind ::Value , OutType ::Any , true ) ,
ShouldImplTraitCase ::new ( " std::ops::Sub " , " sub " , 2 , FN_HEADER , SelfKind ::Value , OutType ::Any , true ) ,
2016-01-30 12:39:16 +00:00
] ;
2015-08-24 16:13:02 +00:00
2022-05-21 11:24:00 +00:00
#[ derive(Clone, Copy, PartialEq, Eq, Debug) ]
2015-08-24 16:13:02 +00:00
enum SelfKind {
2016-02-01 11:51:33 +00:00
Value ,
Ref ,
RefMut ,
No ,
2015-08-24 16:13:02 +00:00
}
impl SelfKind {
2020-06-25 20:41:36 +00:00
fn matches < ' a > ( self , cx : & LateContext < ' a > , parent_ty : Ty < ' a > , ty : Ty < ' a > ) -> bool {
2022-05-23 15:48:17 +00:00
fn matches_value < ' a > ( cx : & LateContext < ' a > , parent_ty : Ty < ' a > , ty : Ty < ' a > ) -> bool {
2019-08-10 04:01:15 +00:00
if ty = = parent_ty {
true
} else if ty . is_box ( ) {
ty . boxed_ty ( ) = = parent_ty
2020-04-10 17:03:34 +00:00
} else if is_type_diagnostic_item ( cx , ty , sym ::Rc ) | | is_type_diagnostic_item ( cx , ty , sym ::Arc ) {
2020-08-03 22:18:29 +00:00
if let ty ::Adt ( _ , substs ) = ty . kind ( ) {
2019-08-10 04:01:15 +00:00
substs . types ( ) . next ( ) . map_or ( false , | t | t = = parent_ty )
} else {
false
}
} else {
false
2017-01-04 04:40:42 +00:00
}
2019-08-10 04:01:15 +00:00
}
2020-06-25 20:41:36 +00:00
fn matches_ref < ' a > ( cx : & LateContext < ' a > , mutability : hir ::Mutability , parent_ty : Ty < ' a > , ty : Ty < ' a > ) -> bool {
2020-08-03 22:18:29 +00:00
if let ty ::Ref ( _ , t , m ) = * ty . kind ( ) {
2019-08-10 04:00:27 +00:00
return m = = mutability & & t = = parent_ty ;
2017-06-06 17:26:50 +00:00
}
2019-08-10 04:00:27 +00:00
let trait_path = match mutability {
2019-12-21 18:38:45 +00:00
hir ::Mutability ::Not = > & paths ::ASREF_TRAIT ,
hir ::Mutability ::Mut = > & paths ::ASMUT_TRAIT ,
2019-08-10 04:00:27 +00:00
} ;
2019-08-22 03:03:26 +00:00
let trait_def_id = match get_trait_def_id ( cx , trait_path ) {
Some ( did ) = > did ,
None = > return false ,
} ;
2019-08-10 04:00:27 +00:00
implements_trait ( cx , ty , trait_def_id , & [ parent_ty . into ( ) ] )
}
2022-01-13 12:18:19 +00:00
fn matches_none < ' a > ( cx : & LateContext < ' a > , parent_ty : Ty < ' a > , ty : Ty < ' a > ) -> bool {
! matches_value ( cx , parent_ty , ty )
& & ! matches_ref ( cx , hir ::Mutability ::Not , parent_ty , ty )
& & ! matches_ref ( cx , hir ::Mutability ::Mut , parent_ty , ty )
}
2019-08-10 04:00:27 +00:00
match self {
2020-04-10 17:03:34 +00:00
Self ::Value = > matches_value ( cx , parent_ty , ty ) ,
2019-12-21 18:38:45 +00:00
Self ::Ref = > matches_ref ( cx , hir ::Mutability ::Not , parent_ty , ty ) | | ty = = parent_ty & & is_copy ( cx , ty ) ,
Self ::RefMut = > matches_ref ( cx , hir ::Mutability ::Mut , parent_ty , ty ) ,
2022-01-13 12:18:19 +00:00
Self ::No = > matches_none ( cx , parent_ty , ty ) ,
2015-08-24 16:13:02 +00:00
}
}
2015-09-01 16:52:48 +00:00
2019-09-18 06:37:41 +00:00
#[ must_use ]
2018-05-31 18:15:48 +00:00
fn description ( self ) -> & 'static str {
match self {
2021-03-25 18:29:11 +00:00
Self ::Value = > " `self` by value " ,
Self ::Ref = > " `self` by reference " ,
Self ::RefMut = > " `self` by mutable reference " ,
Self ::No = > " no `self` " ,
2015-09-01 16:52:48 +00:00
}
}
2015-08-24 16:13:02 +00:00
}
#[ derive(Clone, Copy) ]
enum OutType {
2016-02-01 11:51:33 +00:00
Unit ,
Bool ,
Any ,
Ref ,
2015-08-24 16:13:02 +00:00
}
impl OutType {
2021-03-25 18:29:11 +00:00
fn matches ( self , ty : & hir ::FnRetTy < '_ > ) -> bool {
let is_unit = | ty : & hir ::Ty < '_ > | matches! ( ty . kind , hir ::TyKind ::Tup ( & [ ] ) ) ;
2015-08-24 16:13:02 +00:00
match ( self , ty ) {
2020-02-17 09:36:17 +00:00
( Self ::Unit , & hir ::FnRetTy ::DefaultReturn ( _ ) ) = > true ,
2021-04-08 15:50:13 +00:00
( Self ::Unit , & hir ::FnRetTy ::Return ( ty ) ) if is_unit ( ty ) = > true ,
( Self ::Bool , & hir ::FnRetTy ::Return ( ty ) ) if is_bool ( ty ) = > true ,
( Self ::Any , & hir ::FnRetTy ::Return ( ty ) ) if ! is_unit ( ty ) = > true ,
( Self ::Ref , & hir ::FnRetTy ::Return ( ty ) ) = > matches! ( ty . kind , hir ::TyKind ::Rptr ( _ , _ ) ) ,
2016-01-04 04:26:12 +00:00
_ = > false ,
2015-08-24 16:13:02 +00:00
}
}
}
2019-12-30 04:02:10 +00:00
fn is_bool ( ty : & hir ::Ty < '_ > ) -> bool {
2021-03-25 18:29:11 +00:00
if let hir ::TyKind ::Path ( QPath ::Resolved ( _ , path ) ) = ty . kind {
matches! ( path . res , Res ::PrimTy ( PrimTy ::Bool ) )
2016-06-05 18:46:42 +00:00
} else {
false
2015-08-24 16:13:02 +00:00
}
2015-08-11 18:53:50 +00:00
}
2019-09-08 09:03:45 +00:00
2020-04-08 10:57:58 +00:00
fn fn_header_equals ( expected : hir ::FnHeader , actual : hir ::FnHeader ) -> bool {
expected . constness = = actual . constness
& & expected . unsafety = = actual . unsafety
& & expected . asyncness = = actual . asyncness
}