2020-05-17 15:36:26 +00:00
mod bind_instead_of_map ;
2021-02-11 14:04:38 +00:00
mod bytes_nth ;
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-03-29 17:19:16 +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 ;
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-04-02 21:01:07 +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-01-17 12:29:07 +00:00
mod iter_overeager_cloned ;
2021-03-12 14:30:50 +00:00
mod iter_skip_next ;
2022-02-12 19:14:04 +00:00
mod iter_with_drain ;
2021-03-12 14:30:50 +00:00
mod iterator_step_by_zero ;
2019-09-04 12:06:28 +00:00
mod manual_saturating_arithmetic ;
2021-06-03 06:41:37 +00:00
mod manual_str_repeat ;
2021-03-12 14:30:50 +00:00
mod map_collect_result_unit ;
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-04-06 14:35:49 +00:00
mod needless_option_as_deref ;
2022-04-08 18:07:19 +00:00
mod needless_option_take ;
2021-03-12 14:30:50 +00:00
mod ok_expect ;
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-18 20:11:54 +00:00
mod or_then_unwrap ;
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 ;
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 ;
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 12:18:18 +00:00
mod unnecessary_join ;
2020-08-28 14:10:16 +00:00
mod unnecessary_lazy_eval ;
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 ;
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 } ;
2021-12-06 11:33:31 +00:00
use clippy_utils ::{ contains_return , get_trait_def_id , 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-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.
///
/// ### Examples
/// ```rust
/// # let vec = vec!["string".to_string()];
///
/// // Bad
/// vec.iter().cloned().take(10);
///
/// // Good
/// vec.iter().take(10).cloned();
///
/// // Bad
/// vec.iter().cloned().last();
///
/// // Good
/// vec.iter().last().cloned();
///
/// ```
/// ### 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.
///
#[ clippy::version = " 1.59.0 " ]
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
/// Checks for `.unwrap()` calls on `Option`s and on `Result`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
2020-05-17 15:36:26 +00:00
/// # let opt = Some(1);
///
/// // Bad
/// opt.unwrap();
///
/// // Good
/// opt.expect("more helpful message");
2019-08-03 19:24:50 +00:00
/// ```
///
2020-05-17 15:36:26 +00:00
/// // or
2019-08-03 19:24:50 +00:00
///
2019-03-05 16:50:33 +00:00
/// ```rust
2020-05-17 15:36:26 +00:00
/// # let res: Result<usize, ()> = Ok(1);
///
/// // Bad
/// res.unwrap();
///
/// // Good
2019-08-03 19:24:50 +00:00
/// res.expect("more helpful message");
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 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
/// Checks for `.expect()` calls on `Option`s and `Result`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
/// # let opt = Some(1);
2019-10-15 19:33:07 +00:00
///
2020-05-17 15:36:26 +00:00
/// // Bad
2019-10-15 19:33:07 +00:00
/// opt.expect("one");
///
2020-05-17 15:36:26 +00:00
/// // Good
2019-10-15 19:33:07 +00:00
/// let opt = Some(1);
/// opt?;
/// ```
///
2020-05-17 15:36:26 +00:00
/// // or
2019-10-15 19:33:07 +00:00
///
/// ```rust
2020-05-17 15:36:26 +00:00
/// # let res: Result<usize, ()> = Ok(1);
2019-10-15 19:33:07 +00:00
///
2020-05-17 15:36:26 +00:00
/// // Bad
/// res.expect("one");
2019-10-15 19:33:07 +00:00
///
2020-05-17 15:36:26 +00:00
/// // Good
2019-10-15 19:33:07 +00:00
/// res?;
2019-10-16 17:43:26 +00:00
/// # Ok::<(), ()>(())
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:
///
2021-03-25 18:29:11 +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 |`&self` or none | any |
/// |`to_` | `_mut` |`&mut self` | any |
/// |`to_` | not `_mut` |`self` | `Copy` |
/// |`to_` | not `_mut` |`&self` | not `Copy` |
///
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
///
/// // Bad
/// x.ok().expect("why did I do this again?");
///
/// // Good
/// 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-03-29 17:19:16 +00:00
declare_clippy_lint! {
/// ### What it does
/// Checks for `.err().expect()` calls on the `Result` type.
///
/// ### Why is this bad?
2022-04-06 17:24:49 +00:00
/// `.expect_err()` can be called directly to avoid the extra type conversion from `err()`.
2022-03-29 17:19:16 +00:00
///
/// ### 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");
/// ```
#[ clippy::version = " 1.61.0 " ]
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);
///
/// // Bad
/// x.unwrap_or_else(Default::default);
/// x.unwrap_or_else(u32::default);
///
/// // Good
/// 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
2019-08-03 16:42:05 +00:00
/// # let x = Some(1);
2019-03-05 16:50:33 +00:00
///
2020-05-17 15:36:26 +00:00
/// // Bad
/// x.map(|a| a + 1).unwrap_or(0);
2019-03-05 16:50:33 +00:00
///
2020-05-17 15:36:26 +00:00
/// // Good
/// x.map_or(0, |a| a + 1);
2019-03-05 16:50:33 +00:00
/// ```
///
2020-05-17 15:36:26 +00:00
/// // or
2019-03-05 16:50:33 +00:00
///
/// ```rust
2019-08-03 16:42:05 +00:00
/// # let x: Result<usize, ()> = Ok(1);
/// # fn some_function(foo: ()) -> usize { 1 }
2020-05-17 15:36:26 +00:00
///
/// // Bad
2019-08-03 16:42:05 +00:00
/// x.map(|a| a + 1).unwrap_or_else(some_function);
2020-05-17 15:36:26 +00:00
///
/// // Good
/// x.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
///
/// // Bad
/// opt.map_or(None, |a| Some(a + 1));
///
/// // Good
/// 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-05 00:20:23 +00:00
/// Bad:
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
///
2020-04-05 00:20:23 +00:00
/// Good:
/// ```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
/// ```
2019-08-20 14:55:17 +00:00
/// Could be written as
/// ```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();
/// ```
/// Could be written as
/// ```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
///
/// // Bad
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();
2020-06-09 14:36:01 +00:00
///
/// // Good
/// 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
/// Bad:
/// ```rust
/// (0_i32..10)
/// .filter(|n| n.checked_add(1).is_some())
/// .map(|n| n.checked_add(1).unwrap());
/// ```
///
/// Good:
/// ```rust
/// (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
/// Bad:
/// ```rust
/// (0_i32..10)
/// .find(|n| n.checked_add(1).is_some())
/// .map(|n| n.checked_add(1).unwrap());
/// ```
///
/// Good:
/// ```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
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
///
/// let _ = "hello world".find("world").is_none();
2019-03-05 16:50:33 +00:00
/// ```
2019-08-20 14:55:17 +00:00
/// Could be written as
/// ```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
///
/// let _ = !"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('_') {};
/// ```
/// Could be written as
/// ```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
/// ```
/// this can instead be written:
/// ```rust
2019-08-03 06:01:27 +00:00
/// # let foo = Some(String::new());
/// foo.unwrap_or_else(String::new);
2019-03-05 16:50:33 +00:00
/// ```
/// or
/// ```rust
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-18 20:11:54 +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));
2019-03-05 16:50:33 +00:00
/// ```
/// or
/// ```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).as_str());
2019-03-05 16:50:33 +00:00
/// ```
/// this can instead be written:
/// ```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
///
/// // Bad
2019-08-03 19:24:50 +00:00
/// x.clone();
2020-06-09 14:36:01 +00:00
///
/// // Good
/// 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
/// // Bad
/// _.split("x");
///
/// // Good
/// _.split('x');
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;
/// // Bad
/// # let mut s = HashSet::new();
/// # s.insert(1);
/// let x = s.iter().nth(0);
///
/// // Good
/// # 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-02-12 19:14:04 +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-15 08:46:49 +00:00
nursery ,
2022-02-12 19:14:04 +00:00
" replace `.drain(..)` with `.into_iter()` "
}
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];
///
/// // Bad
/// a.extend(b.drain(..));
///
/// // Good
/// 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-04-15 18:25:55 +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
///
/// // Bad
/// name.chars().last() == Some('_') || name.chars().next_back() == Some('-');
///
/// // Good
/// 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
/// let _ = (0..3).fold(false, |acc, x| acc || x > 2);
/// ```
/// This could be written as:
/// ```rust
/// let _ = (0..3).any(|x| x > 2);
/// ```
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-01 00:17:45 +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-01 00:17:45 +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
2020-06-09 14:36:01 +00:00
/// // Bad
2019-03-05 16:50:33 +00:00
/// let _ = (&vec![3, 4, 5]).into_iter();
2020-06-09 14:36:01 +00:00
///
/// // Good
/// let _ = (&vec![3, 4, 5]).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 ,
" `.chcked_add/sub(x).unwrap_or(MAX/MIN)` "
}
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
2020-08-28 14:10:16 +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");
/// ```
/// Could be written as
2020-09-10 15:47:07 +00:00
/// ```rust
2020-08-28 14:10:16 +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
/// use std::iter::FromIterator;
///
/// 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();
/// ```
2021-12-06 11:33:31 +00:00
#[ clippy::version = " 1.52.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
/// // Bad
/// let _ = "Hello".bytes().nth(3);
///
/// // Good
/// let _ = "Hello".as_bytes().get(3);
/// ```
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
/// // Bad
/// let some_vec = vec![0, 1, 2, 3];
/// let _ = some_vec.iter().count();
/// let _ = &some_vec[..].iter().count();
///
/// // Good
/// let some_vec = vec![0, 1, 2, 3];
/// let _ = some_vec.len();
/// let _ = &some_vec[..].len();
/// ```
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
/// // Bad
/// let s = "";
/// for x in s.splitn(1, ":") {
/// // use x
/// }
///
/// // Good
/// let s = "";
/// for x in s.splitn(2, ":") {
/// // use x
/// }
/// ```
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
/// // Bad
/// let x: String = std::iter::repeat('x').take(10).collect();
///
/// // Good
/// 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
/// // Bad
/// let (key, value) = _.splitn(2, '=').next_tuple()?;
/// let value = _.splitn(2, '=').nth(1)?;
///
/// // Good
/// let (key, value) = _.split_once('=')?;
/// let value = _.split_once('=')?.1;
/// ```
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
/// // Bad
/// let str = "key=value=add";
/// let _ = str.splitn(3, '=').next().unwrap();
/// ```
/// Use instead:
/// ```rust
/// // Good
/// let str = "key=value=add";
/// let _ = str.split('=').next().unwrap();
/// ```
#[ clippy::version = " 1.58.0 " ]
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) {}
/// ```
#[ clippy::version = " 1.58.0 " ]
pub UNNECESSARY_TO_OWNED ,
perf ,
" unnecessary calls to `to_owned`-like functions "
}
2022-03-24 12:18:18 +00:00
declare_clippy_lint! {
/// ### What it does
/// Checks for use of `.collect::<Vec<String>>().join("")` on iterators.
///
/// ### Why is this bad?
2022-04-06 13:59:38 +00:00
/// `.collect::<String>()` is more concise and might be more performant
2022-03-24 12:18:18 +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-06 13:59:38 +00:00
/// While `.collect::<String>()` is sometimes more performant, there are cases where
2022-03-24 12:18:18 +00:00
/// using `.collect::<String>()` over `.collect::<Vec<String>>().join("")`
/// will prevent loop unrolling and will result in a negative performance impact.
2022-04-06 13:59:38 +00:00
///
2022-04-15 18:25:55 +00:00
/// Additionally, differences have been observed between aarch64 and x86_64 assembly output,
2022-04-06 13:59:38 +00:00
/// with aarch64 tending to producing faster assembly in more cases when using `.collect::<String>()`
2022-03-24 12:18:18 +00:00
#[ clippy::version = " 1.61.0 " ]
pub UNNECESSARY_JOIN ,
pedantic ,
" using `.collect::<Vec<String>>().join( \" \" )` on an iterator "
}
2022-04-06 14:35:49 +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>
/// ```
/// Could be written as:
/// ```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-04-02 21:01:07 +00:00
declare_clippy_lint! {
/// ### What it does
/// 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).
///
/// ### 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();
/// ```
#[ clippy::version = " 1.61.0 " ]
pub IS_DIGIT_ASCII_RADIX ,
style ,
" use of `char::is_digit(..)` with literal radix of 10 or 16 "
}
2022-04-08 18:07:19 +00:00
declare_clippy_lint! {
///
/// ### Why is this bad?
///
/// ### Example
/// ```rust
2022-04-12 17:34:55 +00:00
/// let x = Some(3);
/// x.as_ref().take();
2022-04-08 18:07:19 +00:00
/// ```
/// Use instead:
/// ```rust
2022-04-12 17:34:55 +00:00
/// let x = Some(3);
/// x.as_ref();
2022-04-08 18:07:19 +00:00
/// ```
#[ clippy::version = " 1.61.0 " ]
pub NEEDLESS_OPTION_TAKE ,
2022-04-08 19:59:59 +00:00
complexity ,
2022-04-08 18:07:19 +00:00
" using `.as_ref().take()` on a temporary value "
}
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 > ,
}
impl Methods {
#[ must_use ]
2021-06-03 06:41:37 +00:00
pub fn new ( avoid_breaking_exported_api : bool , msrv : Option < RustcVersion > ) -> Self {
Self {
avoid_breaking_exported_api ,
msrv ,
}
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-18 20:11:54 +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-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 ,
STRING_EXTEND_CHARS ,
ITER_CLONED_COLLECT ,
2022-02-12 19:14:04 +00:00
ITER_WITH_DRAIN ,
2019-04-08 20:43:55 +00:00
USELESS_ASREF ,
UNNECESSARY_FOLD ,
UNNECESSARY_FILTER_MAP ,
2022-03-01 00:17:45 +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 12:18:18 +00:00
UNNECESSARY_JOIN ,
2022-03-29 17:19:16 +00:00
ERR_EXPECT ,
2022-04-06 14:35:49 +00:00
NEEDLESS_OPTION_AS_DEREF ,
2022-04-02 21:01:07 +00:00
IS_DIGIT_ASCII_RADIX ,
2022-04-08 18:07:19 +00:00
NEEDLESS_OPTION_TAKE ,
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 ;
}
2021-04-08 15:50:13 +00:00
check_methods ( cx , expr , self . msrv . as_ref ( ) ) ;
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-04-12 13:55:48 +00:00
unnecessary_to_owned ::check ( cx , expr , method_call . ident . name , args , self . msrv . as_ref ( ) ) ;
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
#[ allow(clippy::too_many_lines) ]
fn check_methods < ' tcx > ( cx : & LateContext < ' tcx > , expr : & ' tcx Expr < '_ > , msrv : Option < & RustcVersion > ) {
2022-01-13 12:18:19 +00:00
if let Some ( ( name , [ recv , args @ .. ] , span ) ) = method_call ( expr ) {
2021-04-08 15:50:13 +00:00
match ( name , args ) {
2021-07-01 16:17:38 +00:00
( " add " | " offset " | " sub " | " wrapping_offset " | " wrapping_add " | " wrapping_sub " , [ _arg ] ) = > {
2021-06-03 06:41:37 +00:00
zst_offset ::check ( cx , expr , recv ) ;
2021-04-08 15:50:13 +00:00
} ,
( " 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 " ) ;
}
} ,
2022-04-06 14:35:49 +00:00
( " as_deref " | " as_deref_mut " , [ ] ) = > {
needless_option_as_deref ::check ( cx , expr , recv , name ) ;
} ,
2021-04-08 15:50:13 +00:00
( " 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 ) ,
2021-04-27 14:55:11 +00:00
( " cloned " , [ ] ) = > cloned_instead_of_copied ::check ( cx , expr , recv , span , msrv ) ,
2022-01-13 12:18:19 +00:00
( " collect " , [ ] ) = > match method_call ( recv ) {
2021-12-06 11:33:31 +00:00
Some ( ( name @ ( " cloned " | " copied " ) , [ recv2 ] , _ ) ) = > {
iter_cloned_collect ::check ( cx , name , expr , recv2 ) ;
} ,
2021-04-08 15:50:13 +00:00
Some ( ( " map " , [ m_recv , m_arg ] , _ ) ) = > {
map_collect_result_unit ::check ( cx , expr , m_recv , m_arg , recv ) ;
} ,
2021-06-03 06:41:37 +00:00
Some ( ( " take " , [ take_self_arg , take_arg ] , _ ) ) = > {
if meets_msrv ( msrv , & msrvs ::STR_REPEAT ) {
manual_str_repeat ::check ( cx , expr , recv , take_self_arg , take_arg ) ;
}
} ,
2021-04-08 15:50:13 +00:00
_ = > { } ,
} ,
2022-01-17 12:29:07 +00:00
( name @ " count " , args @ [ ] ) = > match method_call ( recv ) {
Some ( ( " cloned " , [ recv2 ] , _ ) ) = > iter_overeager_cloned ::check ( cx , expr , recv2 , name , args ) ,
Some ( ( name2 @ ( " into_iter " | " iter " | " iter_mut " ) , [ recv2 ] , _ ) ) = > {
iter_count ::check ( cx , expr , recv2 , name2 ) ;
2021-04-08 15:50:13 +00:00
} ,
Some ( ( " map " , [ _ , arg ] , _ ) ) = > suspicious_map ::check ( cx , expr , recv , arg ) ,
_ = > { } ,
} ,
2022-02-12 19:14:04 +00:00
( " drain " , [ arg ] ) = > {
iter_with_drain ::check ( cx , expr , recv , span , arg ) ;
} ,
2022-01-13 12:18:19 +00:00
( " expect " , [ _ ] ) = > match method_call ( recv ) {
2021-04-08 15:50:13 +00:00
Some ( ( " ok " , [ recv ] , _ ) ) = > ok_expect ::check ( cx , expr , recv ) ,
2022-03-29 17:19:16 +00:00
Some ( ( " err " , [ recv ] , err_span ) ) = > err_expect ::check ( cx , expr , recv , msrv , span , err_span ) ,
2021-04-08 15:50:13 +00:00
_ = > expect_used ::check ( cx , expr , recv ) ,
} ,
2021-07-01 16:17:38 +00:00
( " extend " , [ arg ] ) = > {
string_extend_chars ::check ( cx , expr , recv , arg ) ;
2021-07-29 10:16:06 +00:00
extend_with_drain ::check ( cx , expr , recv , arg ) ;
2021-07-01 16:17:38 +00:00
} ,
2021-04-08 15:50:13 +00:00
( " filter_map " , [ arg ] ) = > {
2022-03-01 00:17:45 +00:00
unnecessary_filter_map ::check ( cx , expr , arg , name ) ;
2021-04-08 15:50:13 +00:00
filter_map_identity ::check ( cx , expr , arg , span ) ;
} ,
2022-03-01 00:17:45 +00:00
( " find_map " , [ arg ] ) = > {
unnecessary_filter_map ::check ( cx , expr , arg , name ) ;
} ,
2021-04-22 09:31:13 +00:00
( " flat_map " , [ arg ] ) = > {
flat_map_identity ::check ( cx , expr , arg , span ) ;
flat_map_option ::check ( cx , expr , arg , span ) ;
2021-04-08 15:50:13 +00:00
} ,
2022-01-17 12:29:07 +00:00
( name @ " flatten " , args @ [ ] ) = > match method_call ( recv ) {
2022-03-21 06:11:22 +00:00
Some ( ( " map " , [ recv , map_arg ] , map_span ) ) = > map_flatten ::check ( cx , expr , recv , map_arg , map_span ) ,
2022-01-17 12:29:07 +00:00
Some ( ( " cloned " , [ recv2 ] , _ ) ) = > iter_overeager_cloned ::check ( cx , expr , recv2 , name , args ) ,
_ = > { } ,
2021-04-08 15:50:13 +00:00
} ,
( " fold " , [ init , acc ] ) = > unnecessary_fold ::check ( cx , expr , init , acc , span ) ,
( " for_each " , [ _ ] ) = > {
2022-01-13 12:18:19 +00:00
if let Some ( ( " inspect " , [ _ , _ ] , span2 ) ) = method_call ( recv ) {
2021-04-08 15:50:13 +00:00
inspect_for_each ::check ( cx , expr , span2 ) ;
}
} ,
( " get_or_insert_with " , [ arg ] ) = > unnecessary_lazy_eval ::check ( cx , expr , recv , arg , " get_or_insert " ) ,
( " is_file " , [ ] ) = > filetype_is_file ::check ( cx , expr , recv ) ,
2022-04-02 21:01:07 +00:00
( " is_digit " , [ radix ] ) = > is_digit_ascii_radix ::check ( cx , expr , recv , radix , msrv ) ,
2021-04-08 15:50:13 +00:00
( " is_none " , [ ] ) = > check_is_some_is_none ( cx , expr , recv , false ) ,
( " is_some " , [ ] ) = > check_is_some_is_none ( cx , expr , recv , true ) ,
2022-03-24 12:18:18 +00:00
( " join " , [ join_arg ] ) = > {
if let Some ( ( " collect " , _ , span ) ) = method_call ( recv ) {
unnecessary_join ::check ( cx , expr , recv , join_arg , span ) ;
}
} ,
2022-01-17 12:29:07 +00:00
( " last " , args @ [ ] ) | ( " skip " , args @ [ _ ] ) = > {
if let Some ( ( name2 , [ recv2 , args2 @ .. ] , _span2 ) ) = method_call ( recv ) {
if let ( " cloned " , [ ] ) = ( name2 , args2 ) {
iter_overeager_cloned ::check ( cx , expr , recv2 , name , args ) ;
}
}
} ,
2022-03-01 04:47:55 +00:00
( name @ ( " map " | " map_err " ) , [ m_arg ] ) = > {
2022-01-13 12:18:19 +00:00
if let Some ( ( name , [ recv2 , args @ .. ] , span2 ) ) = method_call ( recv ) {
2021-04-08 15:50:13 +00:00
match ( name , args ) {
( " as_mut " , [ ] ) = > option_as_ref_deref ::check ( cx , expr , recv2 , m_arg , true , msrv ) ,
( " as_ref " , [ ] ) = > option_as_ref_deref ::check ( cx , expr , recv2 , m_arg , false , msrv ) ,
( " filter " , [ f_arg ] ) = > {
2021-06-03 06:41:37 +00:00
filter_map ::check ( cx , expr , recv2 , f_arg , span2 , recv , m_arg , span , false ) ;
2021-04-08 15:50:13 +00:00
} ,
( " find " , [ f_arg ] ) = > filter_map ::check ( cx , expr , recv2 , f_arg , span2 , recv , m_arg , span , true ) ,
_ = > { } ,
}
}
2022-03-01 04:47:55 +00:00
map_identity ::check ( cx , expr , recv , m_arg , name , span ) ;
2021-04-08 15:50:13 +00:00
} ,
( " map_or " , [ def , map ] ) = > option_map_or_none ::check ( cx , expr , recv , def , map ) ,
2022-01-17 12:29:07 +00:00
( name @ " next " , args @ [ ] ) = > {
if let Some ( ( name2 , [ recv2 , args2 @ .. ] , _ ) ) = method_call ( recv ) {
match ( name2 , args2 ) {
( " cloned " , [ ] ) = > iter_overeager_cloned ::check ( cx , expr , recv2 , name , args ) ,
( " filter " , [ arg ] ) = > filter_next ::check ( cx , expr , recv2 , arg ) ,
( " filter_map " , [ arg ] ) = > filter_map_next ::check ( cx , expr , recv2 , arg , msrv ) ,
( " iter " , [ ] ) = > iter_next_slice ::check ( cx , expr , recv2 ) ,
( " skip " , [ arg ] ) = > iter_skip_next ::check ( cx , expr , recv2 , arg ) ,
2021-04-08 15:50:13 +00:00
( " skip_while " , [ _ ] ) = > skip_while_next ::check ( cx , expr ) ,
_ = > { } ,
}
}
} ,
2022-01-17 12:29:07 +00:00
( " nth " , args @ [ n_arg ] ) = > match method_call ( recv ) {
2021-04-08 15:50:13 +00:00
Some ( ( " bytes " , [ recv2 ] , _ ) ) = > bytes_nth ::check ( cx , expr , recv2 , n_arg ) ,
2022-01-17 12:29:07 +00:00
Some ( ( " cloned " , [ recv2 ] , _ ) ) = > iter_overeager_cloned ::check ( cx , expr , recv2 , name , args ) ,
2021-04-08 15:50:13 +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 " ) ,
( " or_else " , [ arg ] ) = > {
if ! bind_instead_of_map ::ResultOrElseErrInfo ::check ( cx , expr , recv , arg ) {
unnecessary_lazy_eval ::check ( cx , expr , recv , arg , " or " ) ;
}
} ,
2021-09-08 14:31:47 +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 ) ;
2022-04-04 15:30:38 +00:00
str_splitn ::check ( cx , name , expr , recv , pat_arg , count , msrv ) ;
2021-09-08 14:31:47 +00:00
}
} ,
( " 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 ) ;
}
2021-06-03 06:41:37 +00:00
} ,
2021-04-08 15:50:13 +00:00
( " step_by " , [ arg ] ) = > iterator_step_by_zero ::check ( cx , expr , arg ) ,
2022-01-17 12:29:07 +00:00
( " take " , args @ [ _arg ] ) = > {
if let Some ( ( name2 , [ recv2 , args2 @ .. ] , _span2 ) ) = method_call ( recv ) {
if let ( " cloned " , [ ] ) = ( name2 , args2 ) {
iter_overeager_cloned ::check ( cx , expr , recv2 , name , args ) ;
}
}
} ,
2022-04-08 18:07:19 +00:00
( " take " , [ ] ) = > needless_option_take ::check ( cx , expr , recv ) ,
2021-04-22 09:31:13 +00:00
( " to_os_string " | " to_owned " | " to_path_buf " | " to_vec " , [ ] ) = > {
2022-01-17 12:29:07 +00:00
implicit_clone ::check ( cx , name , expr , recv ) ;
2021-04-22 09:31:13 +00:00
} ,
2022-02-10 17:40:06 +00:00
( " 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 ) ;
} ,
2022-03-18 20:11:54 +00:00
Some ( ( " or " , [ recv , or_arg ] , or_span ) ) = > {
or_then_unwrap ::check ( cx , expr , recv , or_arg , or_span ) ;
} ,
2022-02-10 17:40:06 +00:00
_ = > { } ,
}
unwrap_used ::check ( cx , expr , recv ) ;
2021-04-08 15:50:13 +00:00
} ,
2022-01-13 12:18:19 +00:00
( " unwrap_or " , [ u_arg ] ) = > match method_call ( recv ) {
2021-04-08 15:50:13 +00:00
Some ( ( arith @ ( " checked_add " | " checked_sub " | " checked_mul " ) , [ lhs , rhs ] , _ ) ) = > {
manual_saturating_arithmetic ::check ( cx , expr , lhs , rhs , u_arg , & arith [ " checked_ " . len ( ) .. ] ) ;
} ,
Some ( ( " map " , [ m_recv , m_arg ] , span ) ) = > {
2021-06-03 06:41:37 +00:00
option_map_unwrap_or ::check ( cx , expr , m_recv , m_arg , recv , u_arg , span ) ;
2021-04-08 15:50:13 +00:00
} ,
_ = > { } ,
} ,
2022-01-13 12:18:19 +00:00
( " unwrap_or_else " , [ u_arg ] ) = > match method_call ( recv ) {
2021-04-08 15:50:13 +00:00
Some ( ( " map " , [ recv , map_arg ] , _ ) ) if map_unwrap_or ::check ( cx , expr , recv , map_arg , u_arg , msrv ) = > { } ,
2021-08-12 09:16:25 +00:00
_ = > {
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
} ,
_ = > { } ,
}
}
}
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
2017-01-05 02:01:53 +00:00
#[ derive(Clone, Copy, PartialEq, 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 {
fn matches_value < ' a > ( cx : & LateContext < ' a > , parent_ty : Ty < '_ > , ty : Ty < '_ > ) -> 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
}