mirror of
https://github.com/rust-lang/rust-clippy
synced 2024-11-14 17:07:17 +00:00
Merge remote-tracking branch 'upstream/master' into rustup
This commit is contained in:
commit
18d37a5d25
61 changed files with 1132 additions and 218 deletions
29
README.md
29
README.md
|
@ -182,7 +182,7 @@ cargo clippy -- -W clippy::lint_name
|
|||
```
|
||||
|
||||
This also works with lint groups. For example you
|
||||
can run Clippy with warnings for all lints enabled:
|
||||
can run Clippy with warnings for all lints enabled:
|
||||
```terminal
|
||||
cargo clippy -- -W clippy::pedantic
|
||||
```
|
||||
|
@ -194,6 +194,33 @@ cargo clippy -- -A clippy::all -W clippy::useless_format -W clippy::...
|
|||
```
|
||||
Note that if you've run clippy before, this may only take effect after you've modified a file or ran `cargo clean`.
|
||||
|
||||
### Specifying the minimum supported Rust version
|
||||
|
||||
Projects that intend to support old versions of Rust can disable lints pertaining to newer features by
|
||||
specifying the minimum supported Rust version (MSRV) in the clippy configuration file.
|
||||
|
||||
```toml
|
||||
msrv = "1.30.0"
|
||||
```
|
||||
|
||||
The MSRV can also be specified as an inner attribute, like below.
|
||||
|
||||
```rust
|
||||
#![feature(custom_inner_attributes)]
|
||||
#![clippy::msrv = "1.30.0"]
|
||||
|
||||
fn main() {
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
You can also omit the patch version when specifying the MSRV, so `msrv = 1.30`
|
||||
is equivalent to `msrv = 1.30.0`.
|
||||
|
||||
Note: `custom_inner_attributes` is an unstable feature so it has to be enabled explicitly.
|
||||
|
||||
Lints that recognize this configuration option can be found [here](https://rust-lang.github.io/rust-clippy/master/index.html#msrv)
|
||||
|
||||
## Contributing
|
||||
|
||||
If you want to contribute to Clippy, you can find more information in [CONTRIBUTING.md](https://github.com/rust-lang/rust-clippy/blob/master/CONTRIBUTING.md).
|
||||
|
|
|
@ -5,7 +5,6 @@ use crate::utils::{
|
|||
span_lint_and_sugg, span_lint_and_then, without_block_comments,
|
||||
};
|
||||
use if_chain::if_chain;
|
||||
use rustc_span::lev_distance::find_best_match_for_name;
|
||||
use rustc_ast::{AttrKind, AttrStyle, Attribute, Lit, LitKind, MetaItemKind, NestedMetaItem};
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::{
|
||||
|
@ -15,6 +14,7 @@ use rustc_lint::{CheckLintNameResult, EarlyContext, EarlyLintPass, LateContext,
|
|||
use rustc_middle::lint::in_external_macro;
|
||||
use rustc_middle::ty;
|
||||
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||
use rustc_span::lev_distance::find_best_match_for_name;
|
||||
use rustc_span::source_map::Span;
|
||||
use rustc_span::sym;
|
||||
use rustc_span::symbol::{Symbol, SymbolStr};
|
||||
|
|
|
@ -51,26 +51,6 @@ declare_deprecated_lint! {
|
|||
"`Vec::as_mut_slice` has been stabilized in 1.7"
|
||||
}
|
||||
|
||||
declare_deprecated_lint! {
|
||||
/// **What it does:** Nothing. This lint has been deprecated.
|
||||
///
|
||||
/// **Deprecation reason:** This used to check for `.to_string()` method calls on values
|
||||
/// of type `&str`. This is not unidiomatic and with specialization coming, `to_string` could be
|
||||
/// specialized to be as efficient as `to_owned`.
|
||||
pub STR_TO_STRING,
|
||||
"using `str::to_string` is common even today and specialization will likely happen soon"
|
||||
}
|
||||
|
||||
declare_deprecated_lint! {
|
||||
/// **What it does:** Nothing. This lint has been deprecated.
|
||||
///
|
||||
/// **Deprecation reason:** This used to check for `.to_string()` method calls on values
|
||||
/// of type `String`. This is not unidiomatic and with specialization coming, `to_string` could be
|
||||
/// specialized to be as efficient as `clone`.
|
||||
pub STRING_TO_STRING,
|
||||
"using `string::to_string` is common even today and specialization will likely happen soon"
|
||||
}
|
||||
|
||||
declare_deprecated_lint! {
|
||||
/// **What it does:** Nothing. This lint has been deprecated.
|
||||
///
|
||||
|
|
|
@ -92,13 +92,8 @@ impl<'tcx> LateLintPass<'tcx> for FutureNotSend {
|
|||
|db| {
|
||||
cx.tcx.infer_ctxt().enter(|infcx| {
|
||||
for FulfillmentError { obligation, .. } in send_errors {
|
||||
infcx.maybe_note_obligation_cause_for_async_await(
|
||||
db,
|
||||
&obligation,
|
||||
);
|
||||
if let Trait(trait_pred, _) =
|
||||
obligation.predicate.skip_binders()
|
||||
{
|
||||
infcx.maybe_note_obligation_cause_for_async_await(db, &obligation);
|
||||
if let Trait(trait_pred, _) = obligation.predicate.skip_binders() {
|
||||
db.note(&format!(
|
||||
"`{}` doesn't implement `{}`",
|
||||
trait_pred.self_ty(),
|
||||
|
|
|
@ -44,6 +44,7 @@ extern crate rustc_target;
|
|||
extern crate rustc_trait_selection;
|
||||
extern crate rustc_typeck;
|
||||
|
||||
use crate::utils::parse_msrv;
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_lint::LintId;
|
||||
use rustc_session::Session;
|
||||
|
@ -440,14 +441,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
|
|||
"clippy::unstable_as_mut_slice",
|
||||
"`Vec::as_mut_slice` has been stabilized in 1.7",
|
||||
);
|
||||
store.register_removed(
|
||||
"clippy::str_to_string",
|
||||
"using `str::to_string` is common even today and specialization will likely happen soon",
|
||||
);
|
||||
store.register_removed(
|
||||
"clippy::string_to_string",
|
||||
"using `string::to_string` is common even today and specialization will likely happen soon",
|
||||
);
|
||||
store.register_removed(
|
||||
"clippy::misaligned_transmute",
|
||||
"this lint has been split into cast_ptr_alignment and transmute_ptr_to_ptr",
|
||||
|
@ -839,6 +832,8 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
|
|||
&strings::STRING_ADD_ASSIGN,
|
||||
&strings::STRING_FROM_UTF8_AS_BYTES,
|
||||
&strings::STRING_LIT_AS_BYTES,
|
||||
&strings::STRING_TO_STRING,
|
||||
&strings::STR_TO_STRING,
|
||||
&suspicious_trait_impl::SUSPICIOUS_ARITHMETIC_IMPL,
|
||||
&suspicious_trait_impl::SUSPICIOUS_OP_ASSIGN_IMPL,
|
||||
&swap::ALMOST_SWAPPED,
|
||||
|
@ -933,7 +928,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
|
|||
&zero_div_zero::ZERO_DIVIDED_BY_ZERO,
|
||||
]);
|
||||
// end register lints, do not remove this comment, it’s used in `update_lints`
|
||||
|
||||
store.register_late_pass(|| box await_holding_invalid::AwaitHolding);
|
||||
store.register_late_pass(|| box serde_api::SerdeAPI);
|
||||
store.register_late_pass(|| box utils::internal_lints::CompilerLintFunctions::new());
|
||||
|
@ -969,7 +963,23 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
|
|||
store.register_late_pass(|| box strings::StringAdd);
|
||||
store.register_late_pass(|| box implicit_return::ImplicitReturn);
|
||||
store.register_late_pass(|| box implicit_saturating_sub::ImplicitSaturatingSub);
|
||||
store.register_late_pass(|| box methods::Methods);
|
||||
|
||||
let parsed_msrv = conf.msrv.as_ref().and_then(|s| {
|
||||
parse_msrv(s, None, None).or_else(|| {
|
||||
sess.err(&format!("error reading Clippy's configuration file. `{}` is not a valid Rust version", s));
|
||||
None
|
||||
})
|
||||
});
|
||||
|
||||
let msrv = parsed_msrv.clone();
|
||||
store.register_late_pass(move || box methods::Methods::new(msrv.clone()));
|
||||
let msrv = parsed_msrv.clone();
|
||||
store.register_late_pass(move || box matches::Matches::new(msrv.clone()));
|
||||
let msrv = parsed_msrv.clone();
|
||||
store.register_early_pass(move || box manual_non_exhaustive::ManualNonExhaustive::new(msrv.clone()));
|
||||
let msrv = parsed_msrv;
|
||||
store.register_late_pass(move || box manual_strip::ManualStrip::new(msrv.clone()));
|
||||
|
||||
store.register_late_pass(|| box map_clone::MapClone);
|
||||
store.register_late_pass(|| box map_err_ignore::MapErrIgnore);
|
||||
store.register_late_pass(|| box shadow::Shadow);
|
||||
|
@ -983,7 +993,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
|
|||
store.register_late_pass(|| box types::Casts);
|
||||
let type_complexity_threshold = conf.type_complexity_threshold;
|
||||
store.register_late_pass(move || box types::TypeComplexity::new(type_complexity_threshold));
|
||||
store.register_late_pass(|| box matches::Matches::default());
|
||||
store.register_late_pass(|| box minmax::MinMaxPass);
|
||||
store.register_late_pass(|| box open_options::OpenOptions);
|
||||
store.register_late_pass(|| box zero_div_zero::ZeroDiv);
|
||||
|
@ -1144,7 +1153,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
|
|||
store.register_late_pass(|| box if_let_mutex::IfLetMutex);
|
||||
store.register_late_pass(|| box mut_mutex_lock::MutMutexLock);
|
||||
store.register_late_pass(|| box match_on_vec_items::MatchOnVecItems);
|
||||
store.register_early_pass(|| box manual_non_exhaustive::ManualNonExhaustive);
|
||||
store.register_late_pass(|| box manual_async_fn::ManualAsyncFn);
|
||||
store.register_early_pass(|| box redundant_field_names::RedundantFieldNames);
|
||||
store.register_late_pass(|| box vec_resize_to_zero::VecResizeToZero);
|
||||
|
@ -1166,13 +1174,14 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
|
|||
store.register_late_pass(|| box manual_ok_or::ManualOkOr);
|
||||
store.register_late_pass(|| box float_equality_without_abs::FloatEqualityWithoutAbs);
|
||||
store.register_late_pass(|| box async_yields_async::AsyncYieldsAsync);
|
||||
store.register_late_pass(|| box manual_strip::ManualStrip);
|
||||
store.register_late_pass(|| box utils::internal_lints::MatchTypeOnDiagItem);
|
||||
let disallowed_methods = conf.disallowed_methods.iter().cloned().collect::<FxHashSet<_>>();
|
||||
store.register_late_pass(move || box disallowed_method::DisallowedMethod::new(&disallowed_methods));
|
||||
store.register_early_pass(|| box asm_syntax::InlineAsmX86AttSyntax);
|
||||
store.register_early_pass(|| box asm_syntax::InlineAsmX86IntelSyntax);
|
||||
store.register_late_pass(|| box undropped_manually_drops::UndroppedManuallyDrops);
|
||||
store.register_late_pass(|| box strings::StrToString);
|
||||
store.register_late_pass(|| box strings::StringToString);
|
||||
|
||||
|
||||
store.register_group(true, "clippy::restriction", Some("clippy_restriction"), vec![
|
||||
|
@ -1215,6 +1224,8 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
|
|||
LintId::of(&shadow::SHADOW_REUSE),
|
||||
LintId::of(&shadow::SHADOW_SAME),
|
||||
LintId::of(&strings::STRING_ADD),
|
||||
LintId::of(&strings::STRING_TO_STRING),
|
||||
LintId::of(&strings::STR_TO_STRING),
|
||||
LintId::of(&types::RC_BUFFER),
|
||||
LintId::of(&unwrap_in_result::UNWRAP_IN_RESULT),
|
||||
LintId::of(&verbose_file_reads::VERBOSE_FILE_READS),
|
||||
|
@ -1930,14 +1941,6 @@ fn register_removed_non_tool_lints(store: &mut rustc_lint::LintStore) {
|
|||
"unstable_as_mut_slice",
|
||||
"`Vec::as_mut_slice` has been stabilized in 1.7",
|
||||
);
|
||||
store.register_removed(
|
||||
"str_to_string",
|
||||
"using `str::to_string` is common even today and specialization will likely happen soon",
|
||||
);
|
||||
store.register_removed(
|
||||
"string_to_string",
|
||||
"using `string::to_string` is common even today and specialization will likely happen soon",
|
||||
);
|
||||
store.register_removed(
|
||||
"misaligned_transmute",
|
||||
"this lint has been split into cast_ptr_alignment and transmute_ptr_to_ptr",
|
||||
|
|
|
@ -2950,7 +2950,7 @@ fn check_needless_collect_indirect_usage<'tcx>(expr: &'tcx Expr<'_>, cx: &LateCo
|
|||
for ref stmt in block.stmts {
|
||||
if_chain! {
|
||||
if let StmtKind::Local(
|
||||
Local { pat: Pat { kind: PatKind::Binding(_, _, ident, .. ), .. },
|
||||
Local { pat: Pat { hir_id: pat_id, kind: PatKind::Binding(_, _, ident, .. ), .. },
|
||||
init: Some(ref init_expr), .. }
|
||||
) = stmt.kind;
|
||||
if let ExprKind::MethodCall(ref method_name, _, &[ref iter_source], ..) = init_expr.kind;
|
||||
|
@ -2964,6 +2964,16 @@ fn check_needless_collect_indirect_usage<'tcx>(expr: &'tcx Expr<'_>, cx: &LateCo
|
|||
if let Some(iter_calls) = detect_iter_and_into_iters(block, *ident);
|
||||
if iter_calls.len() == 1;
|
||||
then {
|
||||
let mut used_count_visitor = UsedCountVisitor {
|
||||
cx,
|
||||
id: *pat_id,
|
||||
count: 0,
|
||||
};
|
||||
walk_block(&mut used_count_visitor, block);
|
||||
if used_count_visitor.count > 1 {
|
||||
return;
|
||||
}
|
||||
|
||||
// Suggest replacing iter_call with iter_replacement, and removing stmt
|
||||
let iter_call = &iter_calls[0];
|
||||
span_lint_and_then(
|
||||
|
@ -3087,6 +3097,28 @@ impl<'tcx> Visitor<'tcx> for IterFunctionVisitor {
|
|||
}
|
||||
}
|
||||
|
||||
struct UsedCountVisitor<'a, 'tcx> {
|
||||
cx: &'a LateContext<'tcx>,
|
||||
id: HirId,
|
||||
count: usize,
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> Visitor<'tcx> for UsedCountVisitor<'a, 'tcx> {
|
||||
type Map = Map<'tcx>;
|
||||
|
||||
fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
|
||||
if same_var(self.cx, expr, self.id) {
|
||||
self.count += 1;
|
||||
} else {
|
||||
walk_expr(self, expr);
|
||||
}
|
||||
}
|
||||
|
||||
fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
|
||||
NestedVisitorMap::OnlyBodies(self.cx.tcx.hir())
|
||||
}
|
||||
}
|
||||
|
||||
/// Detect the occurrences of calls to `iter` or `into_iter` for the
|
||||
/// given identifier
|
||||
fn detect_iter_and_into_iters<'tcx>(block: &'tcx Block<'tcx>, identifier: Ident) -> Option<Vec<IterFunction>> {
|
||||
|
|
|
@ -1,11 +1,20 @@
|
|||
use crate::utils::{snippet_opt, span_lint_and_then};
|
||||
use crate::utils::{meets_msrv, snippet_opt, span_lint_and_then};
|
||||
use if_chain::if_chain;
|
||||
use rustc_ast::ast::{Attribute, Item, ItemKind, StructField, Variant, VariantData, VisibilityKind};
|
||||
use rustc_attr as attr;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_lint::{EarlyContext, EarlyLintPass};
|
||||
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||
use rustc_session::{declare_tool_lint, impl_lint_pass};
|
||||
use rustc_span::{sym, Span};
|
||||
use semver::{Version, VersionReq};
|
||||
|
||||
const MANUAL_NON_EXHAUSTIVE_MSRV: Version = Version {
|
||||
major: 1,
|
||||
minor: 40,
|
||||
patch: 0,
|
||||
pre: Vec::new(),
|
||||
build: Vec::new(),
|
||||
};
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// **What it does:** Checks for manual implementations of the non-exhaustive pattern.
|
||||
|
@ -55,10 +64,26 @@ declare_clippy_lint! {
|
|||
"manual implementations of the non-exhaustive pattern can be simplified using #[non_exhaustive]"
|
||||
}
|
||||
|
||||
declare_lint_pass!(ManualNonExhaustive => [MANUAL_NON_EXHAUSTIVE]);
|
||||
#[derive(Clone)]
|
||||
pub struct ManualNonExhaustive {
|
||||
msrv: Option<VersionReq>,
|
||||
}
|
||||
|
||||
impl ManualNonExhaustive {
|
||||
#[must_use]
|
||||
pub fn new(msrv: Option<VersionReq>) -> Self {
|
||||
Self { msrv }
|
||||
}
|
||||
}
|
||||
|
||||
impl_lint_pass!(ManualNonExhaustive => [MANUAL_NON_EXHAUSTIVE]);
|
||||
|
||||
impl EarlyLintPass for ManualNonExhaustive {
|
||||
fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
|
||||
if !meets_msrv(self.msrv.as_ref(), &MANUAL_NON_EXHAUSTIVE_MSRV) {
|
||||
return;
|
||||
}
|
||||
|
||||
match &item.kind {
|
||||
ItemKind::Enum(def, _) => {
|
||||
check_manual_non_exhaustive_enum(cx, item, &def.variants);
|
||||
|
@ -73,6 +98,8 @@ impl EarlyLintPass for ManualNonExhaustive {
|
|||
_ => {},
|
||||
}
|
||||
}
|
||||
|
||||
extract_msrv_attr!(EarlyContext);
|
||||
}
|
||||
|
||||
fn check_manual_non_exhaustive_enum(cx: &EarlyContext<'_>, item: &Item, variants: &[Variant]) {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use crate::consts::{constant, Constant};
|
||||
use crate::utils::usage::mutated_variables;
|
||||
use crate::utils::{
|
||||
eq_expr_value, higher, match_def_path, multispan_sugg, paths, qpath_res, snippet, span_lint_and_then,
|
||||
eq_expr_value, higher, match_def_path, meets_msrv, multispan_sugg, paths, qpath_res, snippet, span_lint_and_then,
|
||||
};
|
||||
|
||||
use if_chain::if_chain;
|
||||
|
@ -10,12 +10,21 @@ use rustc_hir::def::Res;
|
|||
use rustc_hir::intravisit::{walk_expr, NestedVisitorMap, Visitor};
|
||||
use rustc_hir::BinOpKind;
|
||||
use rustc_hir::{BorrowKind, Expr, ExprKind};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_lint::{LateContext, LateLintPass, LintContext};
|
||||
use rustc_middle::hir::map::Map;
|
||||
use rustc_middle::ty;
|
||||
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||
use rustc_session::{declare_tool_lint, impl_lint_pass};
|
||||
use rustc_span::source_map::Spanned;
|
||||
use rustc_span::Span;
|
||||
use semver::{Version, VersionReq};
|
||||
|
||||
const MANUAL_STRIP_MSRV: Version = Version {
|
||||
major: 1,
|
||||
minor: 45,
|
||||
patch: 0,
|
||||
pre: Vec::new(),
|
||||
build: Vec::new(),
|
||||
};
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// **What it does:**
|
||||
|
@ -51,7 +60,18 @@ declare_clippy_lint! {
|
|||
"suggests using `strip_{prefix,suffix}` over `str::{starts,ends}_with` and slicing"
|
||||
}
|
||||
|
||||
declare_lint_pass!(ManualStrip => [MANUAL_STRIP]);
|
||||
pub struct ManualStrip {
|
||||
msrv: Option<VersionReq>,
|
||||
}
|
||||
|
||||
impl ManualStrip {
|
||||
#[must_use]
|
||||
pub fn new(msrv: Option<VersionReq>) -> Self {
|
||||
Self { msrv }
|
||||
}
|
||||
}
|
||||
|
||||
impl_lint_pass!(ManualStrip => [MANUAL_STRIP]);
|
||||
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
enum StripKind {
|
||||
|
@ -61,6 +81,10 @@ enum StripKind {
|
|||
|
||||
impl<'tcx> LateLintPass<'tcx> for ManualStrip {
|
||||
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
|
||||
if !meets_msrv(self.msrv.as_ref(), &MANUAL_STRIP_MSRV) {
|
||||
return;
|
||||
}
|
||||
|
||||
if_chain! {
|
||||
if let Some((cond, then, _)) = higher::if_block(&expr);
|
||||
if let ExprKind::MethodCall(_, _, [target_arg, pattern], _) = cond.kind;
|
||||
|
@ -114,6 +138,8 @@ impl<'tcx> LateLintPass<'tcx> for ManualStrip {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
extract_msrv_attr!(LateContext);
|
||||
}
|
||||
|
||||
// Returns `Some(arg)` if `expr` matches `arg.len()` and `None` otherwise.
|
||||
|
|
|
@ -3,8 +3,8 @@ use crate::utils::sugg::Sugg;
|
|||
use crate::utils::usage::is_unused;
|
||||
use crate::utils::{
|
||||
expr_block, get_arg_name, get_parent_expr, in_macro, indent_of, is_allowed, is_expn_of, is_refutable,
|
||||
is_type_diagnostic_item, is_wild, match_qpath, match_type, match_var, multispan_sugg, remove_blocks, snippet,
|
||||
snippet_block, snippet_with_applicability, span_lint_and_help, span_lint_and_note, span_lint_and_sugg,
|
||||
is_type_diagnostic_item, is_wild, match_qpath, match_type, match_var, meets_msrv, multispan_sugg, remove_blocks,
|
||||
snippet, snippet_block, snippet_with_applicability, span_lint_and_help, span_lint_and_note, span_lint_and_sugg,
|
||||
span_lint_and_then,
|
||||
};
|
||||
use crate::utils::{paths, search_same, SpanlessEq, SpanlessHash};
|
||||
|
@ -23,6 +23,7 @@ use rustc_middle::ty::{self, Ty, TyS};
|
|||
use rustc_session::{declare_tool_lint, impl_lint_pass};
|
||||
use rustc_span::source_map::{Span, Spanned};
|
||||
use rustc_span::{sym, Symbol};
|
||||
use semver::{Version, VersionReq};
|
||||
use std::cmp::Ordering;
|
||||
use std::collections::hash_map::Entry;
|
||||
use std::collections::Bound;
|
||||
|
@ -411,8 +412,8 @@ declare_clippy_lint! {
|
|||
}
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// **What it does:** Lint for redundant pattern matching over `Result` or
|
||||
/// `Option`
|
||||
/// **What it does:** Lint for redundant pattern matching over `Result`, `Option` or
|
||||
/// `std::task::Poll`
|
||||
///
|
||||
/// **Why is this bad?** It's more concise and clear to just use the proper
|
||||
/// utility function
|
||||
|
@ -422,10 +423,13 @@ declare_clippy_lint! {
|
|||
/// **Example:**
|
||||
///
|
||||
/// ```rust
|
||||
/// # use std::task::Poll;
|
||||
/// if let Ok(_) = Ok::<i32, i32>(42) {}
|
||||
/// if let Err(_) = Err::<i32, i32>(42) {}
|
||||
/// if let None = None::<()> {}
|
||||
/// if let Some(_) = Some(42) {}
|
||||
/// if let Poll::Pending = Poll::Pending::<()> {}
|
||||
/// if let Poll::Ready(_) = Poll::Ready(42) {}
|
||||
/// match Ok::<i32, i32>(42) {
|
||||
/// Ok(_) => true,
|
||||
/// Err(_) => false,
|
||||
|
@ -435,10 +439,13 @@ declare_clippy_lint! {
|
|||
/// The more idiomatic use would be:
|
||||
///
|
||||
/// ```rust
|
||||
/// # use std::task::Poll;
|
||||
/// if Ok::<i32, i32>(42).is_ok() {}
|
||||
/// if Err::<i32, i32>(42).is_err() {}
|
||||
/// if None::<()>.is_none() {}
|
||||
/// if Some(42).is_some() {}
|
||||
/// if Poll::Pending::<()>.is_pending() {}
|
||||
/// if Poll::Ready(42).is_ready() {}
|
||||
/// Ok::<i32, i32>(42).is_ok();
|
||||
/// ```
|
||||
pub REDUNDANT_PATTERN_MATCHING,
|
||||
|
@ -521,9 +528,20 @@ declare_clippy_lint! {
|
|||
|
||||
#[derive(Default)]
|
||||
pub struct Matches {
|
||||
msrv: Option<VersionReq>,
|
||||
infallible_destructuring_match_linted: bool,
|
||||
}
|
||||
|
||||
impl Matches {
|
||||
#[must_use]
|
||||
pub fn new(msrv: Option<VersionReq>) -> Self {
|
||||
Self {
|
||||
msrv,
|
||||
..Matches::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl_lint_pass!(Matches => [
|
||||
SINGLE_MATCH,
|
||||
MATCH_REF_PATS,
|
||||
|
@ -543,6 +561,14 @@ impl_lint_pass!(Matches => [
|
|||
MATCH_SAME_ARMS,
|
||||
]);
|
||||
|
||||
const MATCH_LIKE_MATCHES_MACRO_MSRV: Version = Version {
|
||||
major: 1,
|
||||
minor: 42,
|
||||
patch: 0,
|
||||
pre: Vec::new(),
|
||||
build: Vec::new(),
|
||||
};
|
||||
|
||||
impl<'tcx> LateLintPass<'tcx> for Matches {
|
||||
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
|
||||
if in_external_macro(cx.sess(), expr.span) || in_macro(expr.span) {
|
||||
|
@ -550,7 +576,12 @@ impl<'tcx> LateLintPass<'tcx> for Matches {
|
|||
}
|
||||
|
||||
redundant_pattern_match::check(cx, expr);
|
||||
if !check_match_like_matches(cx, expr) {
|
||||
|
||||
if meets_msrv(self.msrv.as_ref(), &MATCH_LIKE_MATCHES_MACRO_MSRV) {
|
||||
if !check_match_like_matches(cx, expr) {
|
||||
lint_match_arms(cx, expr);
|
||||
}
|
||||
} else {
|
||||
lint_match_arms(cx, expr);
|
||||
}
|
||||
|
||||
|
@ -634,6 +665,8 @@ impl<'tcx> LateLintPass<'tcx> for Matches {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
extract_msrv_attr!(LateContext);
|
||||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
|
@ -1538,6 +1571,8 @@ mod redundant_pattern_match {
|
|||
"is_err()"
|
||||
} else if match_qpath(path, &paths::OPTION_SOME) {
|
||||
"is_some()"
|
||||
} else if match_qpath(path, &paths::POLL_READY) {
|
||||
"is_ready()"
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
@ -1545,7 +1580,15 @@ mod redundant_pattern_match {
|
|||
return;
|
||||
}
|
||||
},
|
||||
PatKind::Path(ref path) if match_qpath(path, &paths::OPTION_NONE) => "is_none()",
|
||||
PatKind::Path(ref path) => {
|
||||
if match_qpath(path, &paths::OPTION_NONE) {
|
||||
"is_none()"
|
||||
} else if match_qpath(path, &paths::POLL_PENDING) {
|
||||
"is_pending()"
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
},
|
||||
_ => return,
|
||||
};
|
||||
|
||||
|
@ -1628,6 +1671,17 @@ mod redundant_pattern_match {
|
|||
"is_some()",
|
||||
"is_none()",
|
||||
)
|
||||
.or_else(|| {
|
||||
find_good_method_for_match(
|
||||
arms,
|
||||
path_left,
|
||||
path_right,
|
||||
&paths::POLL_READY,
|
||||
&paths::POLL_PENDING,
|
||||
"is_ready()",
|
||||
"is_pending()",
|
||||
)
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ use rustc_lint::{LateContext, LateLintPass, Lint, LintContext};
|
|||
use rustc_middle::hir::map::Map;
|
||||
use rustc_middle::lint::in_external_macro;
|
||||
use rustc_middle::ty::{self, TraitRef, Ty, TyS};
|
||||
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||
use rustc_session::{declare_tool_lint, impl_lint_pass};
|
||||
use rustc_span::source_map::Span;
|
||||
use rustc_span::symbol::{sym, SymbolStr};
|
||||
|
||||
|
@ -30,10 +30,11 @@ use crate::utils::usage::mutated_variables;
|
|||
use crate::utils::{
|
||||
contains_ty, get_arg_name, get_parent_expr, get_trait_def_id, has_iter_method, higher, implements_trait, in_macro,
|
||||
is_copy, is_expn_of, is_type_diagnostic_item, iter_input_pats, last_path_segment, match_def_path, match_qpath,
|
||||
match_trait_method, match_type, match_var, method_calls, method_chain_args, paths, remove_blocks, return_ty,
|
||||
single_segment_path, snippet, snippet_with_applicability, snippet_with_macro_callsite, span_lint,
|
||||
match_trait_method, match_type, match_var, meets_msrv, method_calls, method_chain_args, paths, remove_blocks,
|
||||
return_ty, single_segment_path, snippet, snippet_with_applicability, snippet_with_macro_callsite, span_lint,
|
||||
span_lint_and_help, span_lint_and_sugg, span_lint_and_then, sugg, walk_ptrs_ty_depth, SpanlessEq,
|
||||
};
|
||||
use semver::{Version, VersionReq};
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// **What it does:** Checks for `.unwrap()` calls on `Option`s and on `Result`s.
|
||||
|
@ -1404,7 +1405,18 @@ declare_clippy_lint! {
|
|||
"use `.collect()` instead of `::from_iter()`"
|
||||
}
|
||||
|
||||
declare_lint_pass!(Methods => [
|
||||
pub struct Methods {
|
||||
msrv: Option<VersionReq>,
|
||||
}
|
||||
|
||||
impl Methods {
|
||||
#[must_use]
|
||||
pub fn new(msrv: Option<VersionReq>) -> Self {
|
||||
Self { msrv }
|
||||
}
|
||||
}
|
||||
|
||||
impl_lint_pass!(Methods => [
|
||||
UNWRAP_USED,
|
||||
EXPECT_USED,
|
||||
SHOULD_IMPLEMENT_TRAIT,
|
||||
|
@ -1531,8 +1543,12 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
|
|||
check_pointer_offset(cx, expr, arg_lists[0])
|
||||
},
|
||||
["is_file", ..] => lint_filetype_is_file(cx, expr, arg_lists[0]),
|
||||
["map", "as_ref"] => lint_option_as_ref_deref(cx, expr, arg_lists[1], arg_lists[0], false),
|
||||
["map", "as_mut"] => lint_option_as_ref_deref(cx, expr, arg_lists[1], arg_lists[0], true),
|
||||
["map", "as_ref"] => {
|
||||
lint_option_as_ref_deref(cx, expr, arg_lists[1], arg_lists[0], false, self.msrv.as_ref())
|
||||
},
|
||||
["map", "as_mut"] => {
|
||||
lint_option_as_ref_deref(cx, expr, arg_lists[1], arg_lists[0], true, self.msrv.as_ref())
|
||||
},
|
||||
["unwrap_or_else", ..] => unnecessary_lazy_eval::lint(cx, expr, arg_lists[0], "unwrap_or"),
|
||||
["get_or_insert_with", ..] => unnecessary_lazy_eval::lint(cx, expr, arg_lists[0], "get_or_insert"),
|
||||
["ok_or_else", ..] => unnecessary_lazy_eval::lint(cx, expr, arg_lists[0], "ok_or"),
|
||||
|
@ -1738,6 +1754,8 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
extract_msrv_attr!(LateContext);
|
||||
}
|
||||
|
||||
/// Checks for the `OR_FUN_CALL` lint.
|
||||
|
@ -3453,6 +3471,14 @@ fn lint_suspicious_map(cx: &LateContext<'_>, expr: &hir::Expr<'_>) {
|
|||
);
|
||||
}
|
||||
|
||||
const OPTION_AS_REF_DEREF_MSRV: Version = Version {
|
||||
major: 1,
|
||||
minor: 40,
|
||||
patch: 0,
|
||||
pre: Vec::new(),
|
||||
build: Vec::new(),
|
||||
};
|
||||
|
||||
/// lint use of `_.as_ref().map(Deref::deref)` for `Option`s
|
||||
fn lint_option_as_ref_deref<'tcx>(
|
||||
cx: &LateContext<'tcx>,
|
||||
|
@ -3460,7 +3486,12 @@ fn lint_option_as_ref_deref<'tcx>(
|
|||
as_ref_args: &[hir::Expr<'_>],
|
||||
map_args: &[hir::Expr<'_>],
|
||||
is_mut: bool,
|
||||
msrv: Option<&VersionReq>,
|
||||
) {
|
||||
if !meets_msrv(msrv, &OPTION_AS_REF_DEREF_MSRV) {
|
||||
return;
|
||||
}
|
||||
|
||||
let same_mutability = |m| (is_mut && m == &hir::Mutability::Mut) || (!is_mut && m == &hir::Mutability::Not);
|
||||
|
||||
let option_ty = cx.typeck_results().expr_ty(&as_ref_args[0]);
|
||||
|
|
|
@ -2,6 +2,7 @@ use rustc_errors::Applicability;
|
|||
use rustc_hir::{BinOpKind, BorrowKind, Expr, ExprKind, LangItem, QPath};
|
||||
use rustc_lint::{LateContext, LateLintPass, LintContext};
|
||||
use rustc_middle::lint::in_external_macro;
|
||||
use rustc_middle::ty;
|
||||
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||
use rustc_span::source_map::Spanned;
|
||||
use rustc_span::sym;
|
||||
|
@ -11,7 +12,7 @@ use if_chain::if_chain;
|
|||
use crate::utils::SpanlessEq;
|
||||
use crate::utils::{
|
||||
get_parent_expr, is_allowed, is_type_diagnostic_item, match_function_call, method_calls, paths, span_lint,
|
||||
span_lint_and_sugg,
|
||||
span_lint_and_help, span_lint_and_sugg,
|
||||
};
|
||||
|
||||
declare_clippy_lint! {
|
||||
|
@ -289,3 +290,100 @@ impl<'tcx> LateLintPass<'tcx> for StringLitAsBytes {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// **What it does:** This lint checks for `.to_string()` method calls on values of type `&str`.
|
||||
///
|
||||
/// **Why is this bad?** The `to_string` method is also used on other types to convert them to a string.
|
||||
/// When called on a `&str` it turns the `&str` into the owned variant `String`, which can be better
|
||||
/// expressed with `.to_owned()`.
|
||||
///
|
||||
/// **Known problems:** None.
|
||||
///
|
||||
/// **Example:**
|
||||
///
|
||||
/// ```rust
|
||||
/// // example code where clippy issues a warning
|
||||
/// let _ = "str".to_string();
|
||||
/// ```
|
||||
/// Use instead:
|
||||
/// ```rust
|
||||
/// // example code which does not raise clippy warning
|
||||
/// let _ = "str".to_owned();
|
||||
/// ```
|
||||
pub STR_TO_STRING,
|
||||
restriction,
|
||||
"using `to_string()` on a `&str`, which should be `to_owned()`"
|
||||
}
|
||||
|
||||
declare_lint_pass!(StrToString => [STR_TO_STRING]);
|
||||
|
||||
impl LateLintPass<'_> for StrToString {
|
||||
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'_>) {
|
||||
if_chain! {
|
||||
if let ExprKind::MethodCall(path, _, args, _) = &expr.kind;
|
||||
if path.ident.name == sym!(to_string);
|
||||
let ty = cx.typeck_results().expr_ty(&args[0]);
|
||||
if let ty::Ref(_, ty, ..) = ty.kind();
|
||||
if *ty.kind() == ty::Str;
|
||||
then {
|
||||
span_lint_and_help(
|
||||
cx,
|
||||
STR_TO_STRING,
|
||||
expr.span,
|
||||
"`to_string()` called on a `&str`",
|
||||
None,
|
||||
"consider using `.to_owned()`",
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// **What it does:** This lint checks for `.to_string()` method calls on values of type `String`.
|
||||
///
|
||||
/// **Why is this bad?** The `to_string` method is also used on other types to convert them to a string.
|
||||
/// When called on a `String` it only clones the `String`, which can be better expressed with `.clone()`.
|
||||
/// **Known problems:** None.
|
||||
///
|
||||
/// **Example:**
|
||||
///
|
||||
/// ```rust
|
||||
/// // example code where clippy issues a warning
|
||||
/// let msg = String::from("Hello World");
|
||||
/// let _ = msg.to_string();
|
||||
/// ```
|
||||
/// Use instead:
|
||||
/// ```rust
|
||||
/// // example code which does not raise clippy warning
|
||||
/// let msg = String::from("Hello World");
|
||||
/// let _ = msg.clone();
|
||||
/// ```
|
||||
pub STRING_TO_STRING,
|
||||
restriction,
|
||||
"using `to_string()` on a `String`, which should be `clone()`"
|
||||
}
|
||||
|
||||
declare_lint_pass!(StringToString => [STRING_TO_STRING]);
|
||||
|
||||
impl LateLintPass<'_> for StringToString {
|
||||
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'_>) {
|
||||
if_chain! {
|
||||
if let ExprKind::MethodCall(path, _, args, _) = &expr.kind;
|
||||
if path.ident.name == sym!(to_string);
|
||||
let ty = cx.typeck_results().expr_ty(&args[0]);
|
||||
if is_type_diagnostic_item(cx, ty, sym!(string_type));
|
||||
then {
|
||||
span_lint_and_help(
|
||||
cx,
|
||||
STRING_TO_STRING,
|
||||
expr.span,
|
||||
"`to_string()` called on a `String`",
|
||||
None,
|
||||
"consider using `.clone()`",
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ use if_chain::if_chain;
|
|||
use rustc_ast::{FloatTy, IntTy, LitFloatType, LitIntType, LitKind, UintTy};
|
||||
use rustc_errors::{Applicability, DiagnosticBuilder};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::Res;
|
||||
use rustc_hir::intravisit::{walk_body, walk_expr, walk_ty, FnKind, NestedVisitorMap, Visitor};
|
||||
use rustc_hir::{
|
||||
BinOpKind, Block, Body, Expr, ExprKind, FnDecl, FnRetTy, FnSig, GenericArg, GenericBounds, GenericParamKind, HirId,
|
||||
|
@ -1632,7 +1633,14 @@ impl<'tcx> LateLintPass<'tcx> for Casts {
|
|||
if expr.span.from_expansion() {
|
||||
return;
|
||||
}
|
||||
if let ExprKind::Cast(ref ex, _) = expr.kind {
|
||||
if let ExprKind::Cast(ref ex, cast_to) = expr.kind {
|
||||
if let TyKind::Path(QPath::Resolved(_, path)) = cast_to.kind {
|
||||
if let Res::Def(_, def_id) = path.res {
|
||||
if cx.tcx.has_attr(def_id, sym::cfg) || cx.tcx.has_attr(def_id, sym::cfg_attr) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
let (cast_from, cast_to) = (cx.typeck_results().expr_ty(ex), cx.typeck_results().expr_ty(expr));
|
||||
lint_fn_to_numeric_cast(cx, expr, ex, cast_from, cast_to);
|
||||
if let Some(lit) = get_numeric_literal(ex) {
|
||||
|
@ -1711,7 +1719,7 @@ fn show_unnecessary_cast(cx: &LateContext<'_>, expr: &Expr<'_>, literal_str: &st
|
|||
expr.span,
|
||||
&format!("casting {} literal to `{}` is unnecessary", literal_kind_name, cast_to),
|
||||
"try",
|
||||
format!("{}_{}", literal_str, cast_to),
|
||||
format!("{}_{}", literal_str.trim_end_matches('.'), cast_to),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ pub const BUILTIN_ATTRIBUTES: &[(&str, DeprecationStatus)] = &[
|
|||
DeprecationStatus::Replaced("cognitive_complexity"),
|
||||
),
|
||||
("dump", DeprecationStatus::None),
|
||||
("msrv", DeprecationStatus::None),
|
||||
];
|
||||
|
||||
pub struct LimitStack {
|
||||
|
@ -123,6 +124,24 @@ fn parse_attrs<F: FnMut(u64)>(sess: &Session, attrs: &[ast::Attribute], name: &'
|
|||
}
|
||||
}
|
||||
|
||||
pub fn get_unique_inner_attr(sess: &Session, attrs: &[ast::Attribute], name: &'static str) -> Option<ast::Attribute> {
|
||||
let mut unique_attr = None;
|
||||
for attr in get_attr(sess, attrs, name) {
|
||||
match attr.style {
|
||||
ast::AttrStyle::Inner if unique_attr.is_none() => unique_attr = Some(attr.clone()),
|
||||
ast::AttrStyle::Inner => {
|
||||
sess.struct_span_err(attr.span, &format!("`{}` is defined multiple times", name))
|
||||
.span_note(unique_attr.as_ref().unwrap().span, "first definition found here")
|
||||
.emit();
|
||||
},
|
||||
ast::AttrStyle::Outer => {
|
||||
sess.span_err(attr.span, &format!("`{}` cannot be an outer attribute", name));
|
||||
},
|
||||
}
|
||||
}
|
||||
unique_attr
|
||||
}
|
||||
|
||||
/// Return true if the attributes contain any of `proc_macro`,
|
||||
/// `proc_macro_derive` or `proc_macro_attribute`, false otherwise
|
||||
pub fn is_proc_macro(sess: &Session, attrs: &[ast::Attribute]) -> bool {
|
||||
|
|
|
@ -106,6 +106,8 @@ macro_rules! define_Conf {
|
|||
|
||||
pub use self::helpers::Conf;
|
||||
define_Conf! {
|
||||
/// Lint: MANUAL_NON_EXHAUSTIVE, MANUAL_STRIP, OPTION_AS_REF_DEREF, MATCH_LIKE_MATCHES_MACRO. The minimum rust version that the project supports
|
||||
(msrv, "msrv": Option<String>, None),
|
||||
/// Lint: BLACKLISTED_NAME. The list of blacklisted names to lint about. NB: `bar` is not here since it has legitimate uses
|
||||
(blacklisted_names, "blacklisted_names": Vec<String>, ["foo", "baz", "quux"].iter().map(ToString::to_string).collect()),
|
||||
/// Lint: COGNITIVE_COMPLEXITY. The maximum cognitive complexity a function can have
|
||||
|
|
|
@ -51,6 +51,7 @@ use rustc_lint::{LateContext, Level, Lint, LintContext};
|
|||
use rustc_middle::hir::map::Map;
|
||||
use rustc_middle::ty::subst::{GenericArg, GenericArgKind};
|
||||
use rustc_middle::ty::{self, layout::IntegerExt, Ty, TyCtxt, TypeFoldable};
|
||||
use rustc_session::Session;
|
||||
use rustc_span::hygiene::{ExpnKind, MacroKind};
|
||||
use rustc_span::source_map::original_sp;
|
||||
use rustc_span::sym as rustc_sym;
|
||||
|
@ -58,10 +59,54 @@ use rustc_span::symbol::{self, kw, Symbol};
|
|||
use rustc_span::{BytePos, Pos, Span, DUMMY_SP};
|
||||
use rustc_target::abi::Integer;
|
||||
use rustc_trait_selection::traits::query::normalize::AtExt;
|
||||
use semver::{Version, VersionReq};
|
||||
use smallvec::SmallVec;
|
||||
|
||||
use crate::consts::{constant, Constant};
|
||||
|
||||
pub fn parse_msrv(msrv: &str, sess: Option<&Session>, span: Option<Span>) -> Option<VersionReq> {
|
||||
if let Ok(version) = VersionReq::parse(msrv) {
|
||||
return Some(version);
|
||||
} else if let Some(sess) = sess {
|
||||
if let Some(span) = span {
|
||||
sess.span_err(span, &format!("`{}` is not a valid Rust version", msrv));
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
pub fn meets_msrv(msrv: Option<&VersionReq>, lint_msrv: &Version) -> bool {
|
||||
msrv.map_or(true, |msrv| !msrv.matches(lint_msrv))
|
||||
}
|
||||
|
||||
macro_rules! extract_msrv_attr {
|
||||
(LateContext) => {
|
||||
extract_msrv_attr!(@LateContext, ());
|
||||
};
|
||||
(EarlyContext) => {
|
||||
extract_msrv_attr!(@EarlyContext);
|
||||
};
|
||||
(@$context:ident$(, $call:tt)?) => {
|
||||
fn enter_lint_attrs(&mut self, cx: &rustc_lint::$context<'tcx>, attrs: &'tcx [rustc_ast::ast::Attribute]) {
|
||||
use $crate::utils::get_unique_inner_attr;
|
||||
match get_unique_inner_attr(cx.sess$($call)?, attrs, "msrv") {
|
||||
Some(msrv_attr) => {
|
||||
if let Some(msrv) = msrv_attr.value_str() {
|
||||
self.msrv = $crate::utils::parse_msrv(
|
||||
&msrv.to_string(),
|
||||
Some(cx.sess$($call)?),
|
||||
Some(msrv_attr.span),
|
||||
);
|
||||
} else {
|
||||
cx.sess$($call)?.span_err(msrv_attr.span, "bad clippy attribute");
|
||||
}
|
||||
},
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// Returns `true` if the two spans come from differing expansions (i.e., one is
|
||||
/// from a macro and one isn't).
|
||||
#[must_use]
|
||||
|
|
|
@ -90,6 +90,8 @@ pub const PATH_BUF: [&str; 3] = ["std", "path", "PathBuf"];
|
|||
pub const PATH_BUF_AS_PATH: [&str; 4] = ["std", "path", "PathBuf", "as_path"];
|
||||
pub const PATH_TO_PATH_BUF: [&str; 4] = ["std", "path", "Path", "to_path_buf"];
|
||||
pub const POLL: [&str; 4] = ["core", "task", "poll", "Poll"];
|
||||
pub const POLL_PENDING: [&str; 5] = ["core", "task", "poll", "Poll", "Pending"];
|
||||
pub const POLL_READY: [&str; 5] = ["core", "task", "poll", "Poll", "Ready"];
|
||||
pub const PTR_EQ: [&str; 3] = ["core", "ptr", "eq"];
|
||||
pub const PTR_NULL: [&str; 3] = ["core", "ptr", "null"];
|
||||
pub const PTR_NULL_MUT: [&str; 3] = ["core", "ptr", "null_mut"];
|
||||
|
|
1
tests/ui-toml/invalid_min_rust_version/clippy.toml
Normal file
1
tests/ui-toml/invalid_min_rust_version/clippy.toml
Normal file
|
@ -0,0 +1 @@
|
|||
msrv = "invalid.version"
|
|
@ -0,0 +1,3 @@
|
|||
#![allow(clippy::redundant_clone)]
|
||||
|
||||
fn main() {}
|
|
@ -0,0 +1,4 @@
|
|||
error: error reading Clippy's configuration file. `invalid.version` is not a valid Rust version
|
||||
|
||||
error: aborting due to previous error
|
||||
|
1
tests/ui-toml/min_rust_version/clippy.toml
Normal file
1
tests/ui-toml/min_rust_version/clippy.toml
Normal file
|
@ -0,0 +1 @@
|
|||
msrv = "1.0.0"
|
68
tests/ui-toml/min_rust_version/min_rust_version.rs
Normal file
68
tests/ui-toml/min_rust_version/min_rust_version.rs
Normal file
|
@ -0,0 +1,68 @@
|
|||
#![allow(clippy::redundant_clone)]
|
||||
#![warn(clippy::manual_non_exhaustive)]
|
||||
|
||||
use std::ops::Deref;
|
||||
|
||||
mod enums {
|
||||
enum E {
|
||||
A,
|
||||
B,
|
||||
#[doc(hidden)]
|
||||
_C,
|
||||
}
|
||||
|
||||
// user forgot to remove the marker
|
||||
#[non_exhaustive]
|
||||
enum Ep {
|
||||
A,
|
||||
B,
|
||||
#[doc(hidden)]
|
||||
_C,
|
||||
}
|
||||
}
|
||||
|
||||
fn option_as_ref_deref() {
|
||||
let mut opt = Some(String::from("123"));
|
||||
|
||||
let _ = opt.as_ref().map(String::as_str);
|
||||
let _ = opt.as_ref().map(|x| x.as_str());
|
||||
let _ = opt.as_mut().map(String::as_mut_str);
|
||||
let _ = opt.as_mut().map(|x| x.as_mut_str());
|
||||
}
|
||||
|
||||
fn match_like_matches() {
|
||||
let _y = match Some(5) {
|
||||
Some(0) => true,
|
||||
_ => false,
|
||||
};
|
||||
}
|
||||
|
||||
fn match_same_arms() {
|
||||
match (1, 2, 3) {
|
||||
(1, .., 3) => 42,
|
||||
(.., 3) => 42, //~ ERROR match arms have same body
|
||||
_ => 0,
|
||||
};
|
||||
}
|
||||
|
||||
fn match_same_arms2() {
|
||||
let _ = match Some(42) {
|
||||
Some(_) => 24,
|
||||
None => 24, //~ ERROR match arms have same body
|
||||
};
|
||||
}
|
||||
|
||||
fn manual_strip_msrv() {
|
||||
let s = "hello, world!";
|
||||
if s.starts_with("hello, ") {
|
||||
assert_eq!(s["hello, ".len()..].to_uppercase(), "WORLD!");
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
option_as_ref_deref();
|
||||
match_like_matches();
|
||||
match_same_arms();
|
||||
match_same_arms2();
|
||||
manual_strip_msrv();
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
error: error reading Clippy's configuration file `$DIR/clippy.toml`: unknown field `foobar`, expected one of `blacklisted-names`, `cognitive-complexity-threshold`, `cyclomatic-complexity-threshold`, `doc-valid-idents`, `too-many-arguments-threshold`, `type-complexity-threshold`, `single-char-binding-names-threshold`, `too-large-for-stack`, `enum-variant-name-threshold`, `enum-variant-size-threshold`, `verbose-bit-mask-threshold`, `literal-representation-threshold`, `trivial-copy-size-limit`, `pass-by-value-size-limit`, `too-many-lines-threshold`, `array-size-threshold`, `vec-box-size-threshold`, `max-trait-bounds`, `max-struct-bools`, `max-fn-params-bools`, `warn-on-all-wildcard-imports`, `disallowed-methods`, `third-party` at line 5 column 1
|
||||
error: error reading Clippy's configuration file `$DIR/clippy.toml`: unknown field `foobar`, expected one of `msrv`, `blacklisted-names`, `cognitive-complexity-threshold`, `cyclomatic-complexity-threshold`, `doc-valid-idents`, `too-many-arguments-threshold`, `type-complexity-threshold`, `single-char-binding-names-threshold`, `too-large-for-stack`, `enum-variant-name-threshold`, `enum-variant-size-threshold`, `verbose-bit-mask-threshold`, `literal-representation-threshold`, `trivial-copy-size-limit`, `pass-by-value-size-limit`, `too-many-lines-threshold`, `array-size-threshold`, `vec-box-size-threshold`, `max-trait-bounds`, `max-struct-bools`, `max-fn-params-bools`, `warn-on-all-wildcard-imports`, `disallowed-methods`, `third-party` at line 5 column 1
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
|
@ -1,7 +1,19 @@
|
|||
#[warn(clippy::as_conversions)]
|
||||
// aux-build:macro_rules.rs
|
||||
|
||||
#![warn(clippy::as_conversions)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate macro_rules;
|
||||
|
||||
fn with_external_macro() {
|
||||
as_conv_with_arg!(0u32 as u64);
|
||||
as_conv!();
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let i = 0u32 as u64;
|
||||
|
||||
let j = &i as *const u64 as *mut u64;
|
||||
|
||||
with_external_macro();
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
error: using a potentially dangerous silent `as` conversion
|
||||
--> $DIR/as_conversions.rs:4:13
|
||||
--> $DIR/as_conversions.rs:14:13
|
||||
|
|
||||
LL | let i = 0u32 as u64;
|
||||
| ^^^^^^^^^^^
|
||||
|
@ -8,7 +8,7 @@ LL | let i = 0u32 as u64;
|
|||
= help: consider using a safe wrapper for this conversion
|
||||
|
||||
error: using a potentially dangerous silent `as` conversion
|
||||
--> $DIR/as_conversions.rs:6:13
|
||||
--> $DIR/as_conversions.rs:16:13
|
||||
|
|
||||
LL | let j = &i as *const u64 as *mut u64;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
@ -16,7 +16,7 @@ LL | let j = &i as *const u64 as *mut u64;
|
|||
= help: consider using a safe wrapper for this conversion
|
||||
|
||||
error: using a potentially dangerous silent `as` conversion
|
||||
--> $DIR/as_conversions.rs:6:13
|
||||
--> $DIR/as_conversions.rs:16:13
|
||||
|
|
||||
LL | let j = &i as *const u64 as *mut u64;
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
|
|
@ -70,3 +70,17 @@ macro_rules! ref_arg_function {
|
|||
fn fun_example(ref _x: usize) {}
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! as_conv_with_arg {
|
||||
(0u32 as u64) => {
|
||||
()
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! as_conv {
|
||||
() => {
|
||||
0u32 as u64
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
#[warn(clippy::str_to_string)]
|
||||
#[warn(clippy::string_to_string)]
|
||||
#[warn(clippy::unstable_as_slice)]
|
||||
#[warn(clippy::unstable_as_mut_slice)]
|
||||
#[warn(clippy::misaligned_transmute)]
|
||||
|
|
|
@ -1,88 +1,76 @@
|
|||
error: lint `clippy::str_to_string` has been removed: `using `str::to_string` is common even today and specialization will likely happen soon`
|
||||
--> $DIR/deprecated.rs:1:8
|
||||
|
|
||||
LL | #[warn(clippy::str_to_string)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: `-D renamed-and-removed-lints` implied by `-D warnings`
|
||||
|
||||
error: lint `clippy::string_to_string` has been removed: `using `string::to_string` is common even today and specialization will likely happen soon`
|
||||
--> $DIR/deprecated.rs:2:8
|
||||
|
|
||||
LL | #[warn(clippy::string_to_string)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: lint `clippy::unstable_as_slice` has been removed: ``Vec::as_slice` has been stabilized in 1.7`
|
||||
--> $DIR/deprecated.rs:3:8
|
||||
--> $DIR/deprecated.rs:1:8
|
||||
|
|
||||
LL | #[warn(clippy::unstable_as_slice)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: `-D renamed-and-removed-lints` implied by `-D warnings`
|
||||
|
||||
error: lint `clippy::unstable_as_mut_slice` has been removed: ``Vec::as_mut_slice` has been stabilized in 1.7`
|
||||
--> $DIR/deprecated.rs:4:8
|
||||
--> $DIR/deprecated.rs:2:8
|
||||
|
|
||||
LL | #[warn(clippy::unstable_as_mut_slice)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: lint `clippy::misaligned_transmute` has been removed: `this lint has been split into cast_ptr_alignment and transmute_ptr_to_ptr`
|
||||
--> $DIR/deprecated.rs:5:8
|
||||
--> $DIR/deprecated.rs:3:8
|
||||
|
|
||||
LL | #[warn(clippy::misaligned_transmute)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: lint `clippy::unused_collect` has been removed: ``collect` has been marked as #[must_use] in rustc and that covers all cases of this lint`
|
||||
--> $DIR/deprecated.rs:6:8
|
||||
--> $DIR/deprecated.rs:4:8
|
||||
|
|
||||
LL | #[warn(clippy::unused_collect)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: lint `clippy::invalid_ref` has been removed: `superseded by rustc lint `invalid_value``
|
||||
--> $DIR/deprecated.rs:7:8
|
||||
--> $DIR/deprecated.rs:5:8
|
||||
|
|
||||
LL | #[warn(clippy::invalid_ref)]
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: lint `clippy::into_iter_on_array` has been removed: `this lint has been uplifted to rustc and is now called `array_into_iter``
|
||||
--> $DIR/deprecated.rs:8:8
|
||||
--> $DIR/deprecated.rs:6:8
|
||||
|
|
||||
LL | #[warn(clippy::into_iter_on_array)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: lint `clippy::unused_label` has been removed: `this lint has been uplifted to rustc and is now called `unused_labels``
|
||||
--> $DIR/deprecated.rs:9:8
|
||||
--> $DIR/deprecated.rs:7:8
|
||||
|
|
||||
LL | #[warn(clippy::unused_label)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: lint `clippy::regex_macro` has been removed: `the regex! macro has been removed from the regex crate in 2018`
|
||||
--> $DIR/deprecated.rs:10:8
|
||||
--> $DIR/deprecated.rs:8:8
|
||||
|
|
||||
LL | #[warn(clippy::regex_macro)]
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: lint `clippy::drop_bounds` has been removed: `this lint has been uplifted to rustc and is now called `drop_bounds``
|
||||
--> $DIR/deprecated.rs:11:8
|
||||
--> $DIR/deprecated.rs:9:8
|
||||
|
|
||||
LL | #[warn(clippy::drop_bounds)]
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: lint `clippy::temporary_cstring_as_ptr` has been removed: `this lint has been uplifted to rustc and is now called `temporary_cstring_as_ptr``
|
||||
--> $DIR/deprecated.rs:12:8
|
||||
--> $DIR/deprecated.rs:10:8
|
||||
|
|
||||
LL | #[warn(clippy::temporary_cstring_as_ptr)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: lint `clippy::panic_params` has been removed: `this lint has been uplifted to rustc and is now called `panic_fmt``
|
||||
--> $DIR/deprecated.rs:13:8
|
||||
--> $DIR/deprecated.rs:11:8
|
||||
|
|
||||
LL | #[warn(clippy::panic_params)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: lint `clippy::str_to_string` has been removed: `using `str::to_string` is common even today and specialization will likely happen soon`
|
||||
error: lint `clippy::unstable_as_slice` has been removed: ``Vec::as_slice` has been stabilized in 1.7`
|
||||
--> $DIR/deprecated.rs:1:8
|
||||
|
|
||||
LL | #[warn(clippy::str_to_string)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
LL | #[warn(clippy::unstable_as_slice)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 14 previous errors
|
||||
error: aborting due to 12 previous errors
|
||||
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
#[warn(str_to_string)]
|
||||
#[warn(string_to_string)]
|
||||
#[warn(unstable_as_slice)]
|
||||
#[warn(unstable_as_mut_slice)]
|
||||
#[warn(misaligned_transmute)]
|
||||
|
|
|
@ -1,40 +1,28 @@
|
|||
error: lint `str_to_string` has been removed: `using `str::to_string` is common even today and specialization will likely happen soon`
|
||||
--> $DIR/deprecated_old.rs:1:8
|
||||
|
|
||||
LL | #[warn(str_to_string)]
|
||||
| ^^^^^^^^^^^^^
|
||||
|
|
||||
= note: `-D renamed-and-removed-lints` implied by `-D warnings`
|
||||
|
||||
error: lint `string_to_string` has been removed: `using `string::to_string` is common even today and specialization will likely happen soon`
|
||||
--> $DIR/deprecated_old.rs:2:8
|
||||
|
|
||||
LL | #[warn(string_to_string)]
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
||||
error: lint `unstable_as_slice` has been removed: ``Vec::as_slice` has been stabilized in 1.7`
|
||||
--> $DIR/deprecated_old.rs:3:8
|
||||
--> $DIR/deprecated_old.rs:1:8
|
||||
|
|
||||
LL | #[warn(unstable_as_slice)]
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: `-D renamed-and-removed-lints` implied by `-D warnings`
|
||||
|
||||
error: lint `unstable_as_mut_slice` has been removed: ``Vec::as_mut_slice` has been stabilized in 1.7`
|
||||
--> $DIR/deprecated_old.rs:4:8
|
||||
--> $DIR/deprecated_old.rs:2:8
|
||||
|
|
||||
LL | #[warn(unstable_as_mut_slice)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: lint `misaligned_transmute` has been removed: `this lint has been split into cast_ptr_alignment and transmute_ptr_to_ptr`
|
||||
--> $DIR/deprecated_old.rs:5:8
|
||||
--> $DIR/deprecated_old.rs:3:8
|
||||
|
|
||||
LL | #[warn(misaligned_transmute)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: lint `str_to_string` has been removed: `using `str::to_string` is common even today and specialization will likely happen soon`
|
||||
error: lint `unstable_as_slice` has been removed: ``Vec::as_slice` has been stabilized in 1.7`
|
||||
--> $DIR/deprecated_old.rs:1:8
|
||||
|
|
||||
LL | #[warn(str_to_string)]
|
||||
| ^^^^^^^^^^^^^
|
||||
LL | #[warn(unstable_as_slice)]
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
|
|
51
tests/ui/min_rust_version_attr.rs
Normal file
51
tests/ui/min_rust_version_attr.rs
Normal file
|
@ -0,0 +1,51 @@
|
|||
#![allow(clippy::redundant_clone)]
|
||||
#![feature(custom_inner_attributes)]
|
||||
#![clippy::msrv = "1.0.0"]
|
||||
|
||||
use std::ops::Deref;
|
||||
|
||||
fn option_as_ref_deref() {
|
||||
let mut opt = Some(String::from("123"));
|
||||
|
||||
let _ = opt.as_ref().map(String::as_str);
|
||||
let _ = opt.as_ref().map(|x| x.as_str());
|
||||
let _ = opt.as_mut().map(String::as_mut_str);
|
||||
let _ = opt.as_mut().map(|x| x.as_mut_str());
|
||||
}
|
||||
|
||||
fn match_like_matches() {
|
||||
let _y = match Some(5) {
|
||||
Some(0) => true,
|
||||
_ => false,
|
||||
};
|
||||
}
|
||||
|
||||
fn match_same_arms() {
|
||||
match (1, 2, 3) {
|
||||
(1, .., 3) => 42,
|
||||
(.., 3) => 42, //~ ERROR match arms have same body
|
||||
_ => 0,
|
||||
};
|
||||
}
|
||||
|
||||
fn match_same_arms2() {
|
||||
let _ = match Some(42) {
|
||||
Some(_) => 24,
|
||||
None => 24, //~ ERROR match arms have same body
|
||||
};
|
||||
}
|
||||
|
||||
fn manual_strip_msrv() {
|
||||
let s = "hello, world!";
|
||||
if s.starts_with("hello, ") {
|
||||
assert_eq!(s["hello, ".len()..].to_uppercase(), "WORLD!");
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
option_as_ref_deref();
|
||||
match_like_matches();
|
||||
match_same_arms();
|
||||
match_same_arms2();
|
||||
manual_strip_msrv();
|
||||
}
|
4
tests/ui/min_rust_version_invalid_attr.rs
Normal file
4
tests/ui/min_rust_version_invalid_attr.rs
Normal file
|
@ -0,0 +1,4 @@
|
|||
#![feature(custom_inner_attributes)]
|
||||
#![clippy::msrv = "invalid.version"]
|
||||
|
||||
fn main() {}
|
8
tests/ui/min_rust_version_invalid_attr.stderr
Normal file
8
tests/ui/min_rust_version_invalid_attr.stderr
Normal file
|
@ -0,0 +1,8 @@
|
|||
error: `invalid.version` is not a valid Rust version
|
||||
--> $DIR/min_rust_version_invalid_attr.rs:2:1
|
||||
|
|
||||
LL | #![clippy::msrv = "invalid.version"]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
11
tests/ui/min_rust_version_multiple_inner_attr.rs
Normal file
11
tests/ui/min_rust_version_multiple_inner_attr.rs
Normal file
|
@ -0,0 +1,11 @@
|
|||
#![feature(custom_inner_attributes)]
|
||||
#![clippy::msrv = "1.40"]
|
||||
#![clippy::msrv = "=1.35.0"]
|
||||
#![clippy::msrv = "1.10.1"]
|
||||
|
||||
mod foo {
|
||||
#![clippy::msrv = "1"]
|
||||
#![clippy::msrv = "1.0.0"]
|
||||
}
|
||||
|
||||
fn main() {}
|
38
tests/ui/min_rust_version_multiple_inner_attr.stderr
Normal file
38
tests/ui/min_rust_version_multiple_inner_attr.stderr
Normal file
|
@ -0,0 +1,38 @@
|
|||
error: `msrv` is defined multiple times
|
||||
--> $DIR/min_rust_version_multiple_inner_attr.rs:3:1
|
||||
|
|
||||
LL | #![clippy::msrv = "=1.35.0"]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: first definition found here
|
||||
--> $DIR/min_rust_version_multiple_inner_attr.rs:2:1
|
||||
|
|
||||
LL | #![clippy::msrv = "1.40"]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: `msrv` is defined multiple times
|
||||
--> $DIR/min_rust_version_multiple_inner_attr.rs:4:1
|
||||
|
|
||||
LL | #![clippy::msrv = "1.10.1"]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: first definition found here
|
||||
--> $DIR/min_rust_version_multiple_inner_attr.rs:2:1
|
||||
|
|
||||
LL | #![clippy::msrv = "1.40"]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: `msrv` is defined multiple times
|
||||
--> $DIR/min_rust_version_multiple_inner_attr.rs:8:5
|
||||
|
|
||||
LL | #![clippy::msrv = "1.0.0"]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: first definition found here
|
||||
--> $DIR/min_rust_version_multiple_inner_attr.rs:7:5
|
||||
|
|
||||
LL | #![clippy::msrv = "1"]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
14
tests/ui/min_rust_version_no_patch.rs
Normal file
14
tests/ui/min_rust_version_no_patch.rs
Normal file
|
@ -0,0 +1,14 @@
|
|||
#![allow(clippy::redundant_clone)]
|
||||
#![feature(custom_inner_attributes)]
|
||||
#![clippy::msrv = "^1.0"]
|
||||
|
||||
fn manual_strip_msrv() {
|
||||
let s = "hello, world!";
|
||||
if s.starts_with("hello, ") {
|
||||
assert_eq!(s["hello, ".len()..].to_uppercase(), "WORLD!");
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
manual_strip_msrv()
|
||||
}
|
4
tests/ui/min_rust_version_outer_attr.rs
Normal file
4
tests/ui/min_rust_version_outer_attr.rs
Normal file
|
@ -0,0 +1,4 @@
|
|||
#![feature(custom_inner_attributes)]
|
||||
|
||||
#[clippy::msrv = "invalid.version"]
|
||||
fn main() {}
|
8
tests/ui/min_rust_version_outer_attr.stderr
Normal file
8
tests/ui/min_rust_version_outer_attr.stderr
Normal file
|
@ -0,0 +1,8 @@
|
|||
error: `msrv` cannot be an outer attribute
|
||||
--> $DIR/min_rust_version_outer_attr.rs:3:1
|
||||
|
|
||||
LL | #[clippy::msrv = "invalid.version"]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
|
@ -22,4 +22,24 @@ fn main() {
|
|||
let sample = vec![a.clone(), "b".to_string(), "c".to_string()];
|
||||
let non_copy_contains = sample.into_iter().collect::<Vec<_>>();
|
||||
non_copy_contains.contains(&a);
|
||||
|
||||
// Fix #5991
|
||||
let vec_a = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
|
||||
let vec_b = vec_a.iter().collect::<Vec<_>>();
|
||||
if vec_b.len() > 3 {}
|
||||
let other_vec = vec![1, 3, 12, 4, 16, 2];
|
||||
let we_got_the_same_numbers = other_vec.iter().filter(|item| vec_b.contains(item)).collect::<Vec<_>>();
|
||||
|
||||
// Fix #6297
|
||||
let sample = [1; 5];
|
||||
let multiple_indirect = sample.iter().collect::<Vec<_>>();
|
||||
let sample2 = vec![2, 3];
|
||||
if multiple_indirect.is_empty() {
|
||||
// do something
|
||||
} else {
|
||||
let found = sample2
|
||||
.iter()
|
||||
.filter(|i| multiple_indirect.iter().any(|s| **s % **i == 0))
|
||||
.collect::<Vec<_>>();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,13 +2,7 @@
|
|||
|
||||
#![warn(clippy::all)]
|
||||
#![warn(clippy::redundant_pattern_matching)]
|
||||
#![allow(
|
||||
clippy::unit_arg,
|
||||
unused_must_use,
|
||||
clippy::needless_bool,
|
||||
clippy::match_like_matches_macro,
|
||||
deprecated
|
||||
)]
|
||||
#![allow(unused_must_use, clippy::needless_bool, clippy::match_like_matches_macro)]
|
||||
|
||||
fn main() {
|
||||
if None::<()>.is_none() {}
|
||||
|
|
|
@ -2,13 +2,7 @@
|
|||
|
||||
#![warn(clippy::all)]
|
||||
#![warn(clippy::redundant_pattern_matching)]
|
||||
#![allow(
|
||||
clippy::unit_arg,
|
||||
unused_must_use,
|
||||
clippy::needless_bool,
|
||||
clippy::match_like_matches_macro,
|
||||
deprecated
|
||||
)]
|
||||
#![allow(unused_must_use, clippy::needless_bool, clippy::match_like_matches_macro)]
|
||||
|
||||
fn main() {
|
||||
if let None = None::<()> {}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
error: redundant pattern matching, consider using `is_none()`
|
||||
--> $DIR/redundant_pattern_matching_option.rs:14:12
|
||||
--> $DIR/redundant_pattern_matching_option.rs:8:12
|
||||
|
|
||||
LL | if let None = None::<()> {}
|
||||
| -------^^^^------------- help: try this: `if None::<()>.is_none()`
|
||||
|
@ -7,43 +7,43 @@ LL | if let None = None::<()> {}
|
|||
= note: `-D clippy::redundant-pattern-matching` implied by `-D warnings`
|
||||
|
||||
error: redundant pattern matching, consider using `is_some()`
|
||||
--> $DIR/redundant_pattern_matching_option.rs:16:12
|
||||
--> $DIR/redundant_pattern_matching_option.rs:10:12
|
||||
|
|
||||
LL | if let Some(_) = Some(42) {}
|
||||
| -------^^^^^^^----------- help: try this: `if Some(42).is_some()`
|
||||
|
||||
error: redundant pattern matching, consider using `is_some()`
|
||||
--> $DIR/redundant_pattern_matching_option.rs:18:12
|
||||
--> $DIR/redundant_pattern_matching_option.rs:12:12
|
||||
|
|
||||
LL | if let Some(_) = Some(42) {
|
||||
| -------^^^^^^^----------- help: try this: `if Some(42).is_some()`
|
||||
|
||||
error: redundant pattern matching, consider using `is_some()`
|
||||
--> $DIR/redundant_pattern_matching_option.rs:24:15
|
||||
--> $DIR/redundant_pattern_matching_option.rs:18:15
|
||||
|
|
||||
LL | while let Some(_) = Some(42) {}
|
||||
| ----------^^^^^^^----------- help: try this: `while Some(42).is_some()`
|
||||
|
||||
error: redundant pattern matching, consider using `is_none()`
|
||||
--> $DIR/redundant_pattern_matching_option.rs:26:15
|
||||
--> $DIR/redundant_pattern_matching_option.rs:20:15
|
||||
|
|
||||
LL | while let None = Some(42) {}
|
||||
| ----------^^^^----------- help: try this: `while Some(42).is_none()`
|
||||
|
||||
error: redundant pattern matching, consider using `is_none()`
|
||||
--> $DIR/redundant_pattern_matching_option.rs:28:15
|
||||
--> $DIR/redundant_pattern_matching_option.rs:22:15
|
||||
|
|
||||
LL | while let None = None::<()> {}
|
||||
| ----------^^^^------------- help: try this: `while None::<()>.is_none()`
|
||||
|
||||
error: redundant pattern matching, consider using `is_some()`
|
||||
--> $DIR/redundant_pattern_matching_option.rs:31:15
|
||||
--> $DIR/redundant_pattern_matching_option.rs:25:15
|
||||
|
|
||||
LL | while let Some(_) = v.pop() {
|
||||
| ----------^^^^^^^---------- help: try this: `while v.pop().is_some()`
|
||||
|
||||
error: redundant pattern matching, consider using `is_some()`
|
||||
--> $DIR/redundant_pattern_matching_option.rs:39:5
|
||||
--> $DIR/redundant_pattern_matching_option.rs:33:5
|
||||
|
|
||||
LL | / match Some(42) {
|
||||
LL | | Some(_) => true,
|
||||
|
@ -52,7 +52,7 @@ LL | | };
|
|||
| |_____^ help: try this: `Some(42).is_some()`
|
||||
|
||||
error: redundant pattern matching, consider using `is_none()`
|
||||
--> $DIR/redundant_pattern_matching_option.rs:44:5
|
||||
--> $DIR/redundant_pattern_matching_option.rs:38:5
|
||||
|
|
||||
LL | / match None::<()> {
|
||||
LL | | Some(_) => false,
|
||||
|
@ -61,7 +61,7 @@ LL | | };
|
|||
| |_____^ help: try this: `None::<()>.is_none()`
|
||||
|
||||
error: redundant pattern matching, consider using `is_none()`
|
||||
--> $DIR/redundant_pattern_matching_option.rs:49:13
|
||||
--> $DIR/redundant_pattern_matching_option.rs:43:13
|
||||
|
|
||||
LL | let _ = match None::<()> {
|
||||
| _____________^
|
||||
|
@ -71,49 +71,49 @@ LL | | };
|
|||
| |_____^ help: try this: `None::<()>.is_none()`
|
||||
|
||||
error: redundant pattern matching, consider using `is_some()`
|
||||
--> $DIR/redundant_pattern_matching_option.rs:55:20
|
||||
--> $DIR/redundant_pattern_matching_option.rs:49:20
|
||||
|
|
||||
LL | let x = if let Some(_) = opt { true } else { false };
|
||||
| -------^^^^^^^------ help: try this: `if opt.is_some()`
|
||||
|
||||
error: redundant pattern matching, consider using `is_some()`
|
||||
--> $DIR/redundant_pattern_matching_option.rs:60:20
|
||||
--> $DIR/redundant_pattern_matching_option.rs:54:20
|
||||
|
|
||||
LL | let _ = if let Some(_) = gen_opt() {
|
||||
| -------^^^^^^^------------ help: try this: `if gen_opt().is_some()`
|
||||
|
||||
error: redundant pattern matching, consider using `is_none()`
|
||||
--> $DIR/redundant_pattern_matching_option.rs:62:19
|
||||
--> $DIR/redundant_pattern_matching_option.rs:56:19
|
||||
|
|
||||
LL | } else if let None = gen_opt() {
|
||||
| -------^^^^------------ help: try this: `if gen_opt().is_none()`
|
||||
|
||||
error: redundant pattern matching, consider using `is_some()`
|
||||
--> $DIR/redundant_pattern_matching_option.rs:83:12
|
||||
--> $DIR/redundant_pattern_matching_option.rs:77:12
|
||||
|
|
||||
LL | if let Some(_) = Some(42) {}
|
||||
| -------^^^^^^^----------- help: try this: `if Some(42).is_some()`
|
||||
|
||||
error: redundant pattern matching, consider using `is_none()`
|
||||
--> $DIR/redundant_pattern_matching_option.rs:85:12
|
||||
--> $DIR/redundant_pattern_matching_option.rs:79:12
|
||||
|
|
||||
LL | if let None = None::<()> {}
|
||||
| -------^^^^------------- help: try this: `if None::<()>.is_none()`
|
||||
|
||||
error: redundant pattern matching, consider using `is_some()`
|
||||
--> $DIR/redundant_pattern_matching_option.rs:87:15
|
||||
--> $DIR/redundant_pattern_matching_option.rs:81:15
|
||||
|
|
||||
LL | while let Some(_) = Some(42) {}
|
||||
| ----------^^^^^^^----------- help: try this: `while Some(42).is_some()`
|
||||
|
||||
error: redundant pattern matching, consider using `is_none()`
|
||||
--> $DIR/redundant_pattern_matching_option.rs:89:15
|
||||
--> $DIR/redundant_pattern_matching_option.rs:83:15
|
||||
|
|
||||
LL | while let None = None::<()> {}
|
||||
| ----------^^^^------------- help: try this: `while None::<()>.is_none()`
|
||||
|
||||
error: redundant pattern matching, consider using `is_some()`
|
||||
--> $DIR/redundant_pattern_matching_option.rs:91:5
|
||||
--> $DIR/redundant_pattern_matching_option.rs:85:5
|
||||
|
|
||||
LL | / match Some(42) {
|
||||
LL | | Some(_) => true,
|
||||
|
@ -122,7 +122,7 @@ LL | | };
|
|||
| |_____^ help: try this: `Some(42).is_some()`
|
||||
|
||||
error: redundant pattern matching, consider using `is_none()`
|
||||
--> $DIR/redundant_pattern_matching_option.rs:96:5
|
||||
--> $DIR/redundant_pattern_matching_option.rs:90:5
|
||||
|
|
||||
LL | / match None::<()> {
|
||||
LL | | Some(_) => false,
|
||||
|
|
73
tests/ui/redundant_pattern_matching_poll.fixed
Normal file
73
tests/ui/redundant_pattern_matching_poll.fixed
Normal file
|
@ -0,0 +1,73 @@
|
|||
// run-rustfix
|
||||
|
||||
#![warn(clippy::all)]
|
||||
#![warn(clippy::redundant_pattern_matching)]
|
||||
#![allow(unused_must_use, clippy::needless_bool, clippy::match_like_matches_macro)]
|
||||
|
||||
use std::task::Poll::{self, Pending, Ready};
|
||||
|
||||
fn main() {
|
||||
if Pending::<()>.is_pending() {}
|
||||
|
||||
if Ready(42).is_ready() {}
|
||||
|
||||
if Ready(42).is_ready() {
|
||||
foo();
|
||||
} else {
|
||||
bar();
|
||||
}
|
||||
|
||||
while Ready(42).is_ready() {}
|
||||
|
||||
while Ready(42).is_pending() {}
|
||||
|
||||
while Pending::<()>.is_pending() {}
|
||||
|
||||
if Pending::<i32>.is_pending() {}
|
||||
|
||||
if Ready(42).is_ready() {}
|
||||
|
||||
Ready(42).is_ready();
|
||||
|
||||
Pending::<()>.is_pending();
|
||||
|
||||
let _ = Pending::<()>.is_pending();
|
||||
|
||||
let poll = Ready(false);
|
||||
let x = if poll.is_ready() { true } else { false };
|
||||
takes_poll(x);
|
||||
|
||||
poll_const();
|
||||
|
||||
let _ = if gen_poll().is_ready() {
|
||||
1
|
||||
} else if gen_poll().is_pending() {
|
||||
2
|
||||
} else {
|
||||
3
|
||||
};
|
||||
}
|
||||
|
||||
fn gen_poll() -> Poll<()> {
|
||||
Pending
|
||||
}
|
||||
|
||||
fn takes_poll(_: bool) {}
|
||||
|
||||
fn foo() {}
|
||||
|
||||
fn bar() {}
|
||||
|
||||
const fn poll_const() {
|
||||
if Ready(42).is_ready() {}
|
||||
|
||||
if Pending::<()>.is_pending() {}
|
||||
|
||||
while Ready(42).is_ready() {}
|
||||
|
||||
while Pending::<()>.is_pending() {}
|
||||
|
||||
Ready(42).is_ready();
|
||||
|
||||
Pending::<()>.is_pending();
|
||||
}
|
88
tests/ui/redundant_pattern_matching_poll.rs
Normal file
88
tests/ui/redundant_pattern_matching_poll.rs
Normal file
|
@ -0,0 +1,88 @@
|
|||
// run-rustfix
|
||||
|
||||
#![warn(clippy::all)]
|
||||
#![warn(clippy::redundant_pattern_matching)]
|
||||
#![allow(unused_must_use, clippy::needless_bool, clippy::match_like_matches_macro)]
|
||||
|
||||
use std::task::Poll::{self, Pending, Ready};
|
||||
|
||||
fn main() {
|
||||
if let Pending = Pending::<()> {}
|
||||
|
||||
if let Ready(_) = Ready(42) {}
|
||||
|
||||
if let Ready(_) = Ready(42) {
|
||||
foo();
|
||||
} else {
|
||||
bar();
|
||||
}
|
||||
|
||||
while let Ready(_) = Ready(42) {}
|
||||
|
||||
while let Pending = Ready(42) {}
|
||||
|
||||
while let Pending = Pending::<()> {}
|
||||
|
||||
if Pending::<i32>.is_pending() {}
|
||||
|
||||
if Ready(42).is_ready() {}
|
||||
|
||||
match Ready(42) {
|
||||
Ready(_) => true,
|
||||
Pending => false,
|
||||
};
|
||||
|
||||
match Pending::<()> {
|
||||
Ready(_) => false,
|
||||
Pending => true,
|
||||
};
|
||||
|
||||
let _ = match Pending::<()> {
|
||||
Ready(_) => false,
|
||||
Pending => true,
|
||||
};
|
||||
|
||||
let poll = Ready(false);
|
||||
let x = if let Ready(_) = poll { true } else { false };
|
||||
takes_poll(x);
|
||||
|
||||
poll_const();
|
||||
|
||||
let _ = if let Ready(_) = gen_poll() {
|
||||
1
|
||||
} else if let Pending = gen_poll() {
|
||||
2
|
||||
} else {
|
||||
3
|
||||
};
|
||||
}
|
||||
|
||||
fn gen_poll() -> Poll<()> {
|
||||
Pending
|
||||
}
|
||||
|
||||
fn takes_poll(_: bool) {}
|
||||
|
||||
fn foo() {}
|
||||
|
||||
fn bar() {}
|
||||
|
||||
const fn poll_const() {
|
||||
if let Ready(_) = Ready(42) {}
|
||||
|
||||
if let Pending = Pending::<()> {}
|
||||
|
||||
while let Ready(_) = Ready(42) {}
|
||||
|
||||
while let Pending = Pending::<()> {}
|
||||
|
||||
match Ready(42) {
|
||||
Ready(_) => true,
|
||||
Pending => false,
|
||||
};
|
||||
|
||||
match Pending::<()> {
|
||||
Ready(_) => false,
|
||||
Pending => true,
|
||||
};
|
||||
}
|
128
tests/ui/redundant_pattern_matching_poll.stderr
Normal file
128
tests/ui/redundant_pattern_matching_poll.stderr
Normal file
|
@ -0,0 +1,128 @@
|
|||
error: redundant pattern matching, consider using `is_pending()`
|
||||
--> $DIR/redundant_pattern_matching_poll.rs:10:12
|
||||
|
|
||||
LL | if let Pending = Pending::<()> {}
|
||||
| -------^^^^^^^---------------- help: try this: `if Pending::<()>.is_pending()`
|
||||
|
|
||||
= note: `-D clippy::redundant-pattern-matching` implied by `-D warnings`
|
||||
|
||||
error: redundant pattern matching, consider using `is_ready()`
|
||||
--> $DIR/redundant_pattern_matching_poll.rs:12:12
|
||||
|
|
||||
LL | if let Ready(_) = Ready(42) {}
|
||||
| -------^^^^^^^^------------ help: try this: `if Ready(42).is_ready()`
|
||||
|
||||
error: redundant pattern matching, consider using `is_ready()`
|
||||
--> $DIR/redundant_pattern_matching_poll.rs:14:12
|
||||
|
|
||||
LL | if let Ready(_) = Ready(42) {
|
||||
| -------^^^^^^^^------------ help: try this: `if Ready(42).is_ready()`
|
||||
|
||||
error: redundant pattern matching, consider using `is_ready()`
|
||||
--> $DIR/redundant_pattern_matching_poll.rs:20:15
|
||||
|
|
||||
LL | while let Ready(_) = Ready(42) {}
|
||||
| ----------^^^^^^^^------------ help: try this: `while Ready(42).is_ready()`
|
||||
|
||||
error: redundant pattern matching, consider using `is_pending()`
|
||||
--> $DIR/redundant_pattern_matching_poll.rs:22:15
|
||||
|
|
||||
LL | while let Pending = Ready(42) {}
|
||||
| ----------^^^^^^^------------ help: try this: `while Ready(42).is_pending()`
|
||||
|
||||
error: redundant pattern matching, consider using `is_pending()`
|
||||
--> $DIR/redundant_pattern_matching_poll.rs:24:15
|
||||
|
|
||||
LL | while let Pending = Pending::<()> {}
|
||||
| ----------^^^^^^^---------------- help: try this: `while Pending::<()>.is_pending()`
|
||||
|
||||
error: redundant pattern matching, consider using `is_ready()`
|
||||
--> $DIR/redundant_pattern_matching_poll.rs:30:5
|
||||
|
|
||||
LL | / match Ready(42) {
|
||||
LL | | Ready(_) => true,
|
||||
LL | | Pending => false,
|
||||
LL | | };
|
||||
| |_____^ help: try this: `Ready(42).is_ready()`
|
||||
|
||||
error: redundant pattern matching, consider using `is_pending()`
|
||||
--> $DIR/redundant_pattern_matching_poll.rs:35:5
|
||||
|
|
||||
LL | / match Pending::<()> {
|
||||
LL | | Ready(_) => false,
|
||||
LL | | Pending => true,
|
||||
LL | | };
|
||||
| |_____^ help: try this: `Pending::<()>.is_pending()`
|
||||
|
||||
error: redundant pattern matching, consider using `is_pending()`
|
||||
--> $DIR/redundant_pattern_matching_poll.rs:40:13
|
||||
|
|
||||
LL | let _ = match Pending::<()> {
|
||||
| _____________^
|
||||
LL | | Ready(_) => false,
|
||||
LL | | Pending => true,
|
||||
LL | | };
|
||||
| |_____^ help: try this: `Pending::<()>.is_pending()`
|
||||
|
||||
error: redundant pattern matching, consider using `is_ready()`
|
||||
--> $DIR/redundant_pattern_matching_poll.rs:46:20
|
||||
|
|
||||
LL | let x = if let Ready(_) = poll { true } else { false };
|
||||
| -------^^^^^^^^------- help: try this: `if poll.is_ready()`
|
||||
|
||||
error: redundant pattern matching, consider using `is_ready()`
|
||||
--> $DIR/redundant_pattern_matching_poll.rs:51:20
|
||||
|
|
||||
LL | let _ = if let Ready(_) = gen_poll() {
|
||||
| -------^^^^^^^^------------- help: try this: `if gen_poll().is_ready()`
|
||||
|
||||
error: redundant pattern matching, consider using `is_pending()`
|
||||
--> $DIR/redundant_pattern_matching_poll.rs:53:19
|
||||
|
|
||||
LL | } else if let Pending = gen_poll() {
|
||||
| -------^^^^^^^------------- help: try this: `if gen_poll().is_pending()`
|
||||
|
||||
error: redundant pattern matching, consider using `is_ready()`
|
||||
--> $DIR/redundant_pattern_matching_poll.rs:71:12
|
||||
|
|
||||
LL | if let Ready(_) = Ready(42) {}
|
||||
| -------^^^^^^^^------------ help: try this: `if Ready(42).is_ready()`
|
||||
|
||||
error: redundant pattern matching, consider using `is_pending()`
|
||||
--> $DIR/redundant_pattern_matching_poll.rs:73:12
|
||||
|
|
||||
LL | if let Pending = Pending::<()> {}
|
||||
| -------^^^^^^^---------------- help: try this: `if Pending::<()>.is_pending()`
|
||||
|
||||
error: redundant pattern matching, consider using `is_ready()`
|
||||
--> $DIR/redundant_pattern_matching_poll.rs:75:15
|
||||
|
|
||||
LL | while let Ready(_) = Ready(42) {}
|
||||
| ----------^^^^^^^^------------ help: try this: `while Ready(42).is_ready()`
|
||||
|
||||
error: redundant pattern matching, consider using `is_pending()`
|
||||
--> $DIR/redundant_pattern_matching_poll.rs:77:15
|
||||
|
|
||||
LL | while let Pending = Pending::<()> {}
|
||||
| ----------^^^^^^^---------------- help: try this: `while Pending::<()>.is_pending()`
|
||||
|
||||
error: redundant pattern matching, consider using `is_ready()`
|
||||
--> $DIR/redundant_pattern_matching_poll.rs:79:5
|
||||
|
|
||||
LL | / match Ready(42) {
|
||||
LL | | Ready(_) => true,
|
||||
LL | | Pending => false,
|
||||
LL | | };
|
||||
| |_____^ help: try this: `Ready(42).is_ready()`
|
||||
|
||||
error: redundant pattern matching, consider using `is_pending()`
|
||||
--> $DIR/redundant_pattern_matching_poll.rs:84:5
|
||||
|
|
||||
LL | / match Pending::<()> {
|
||||
LL | | Ready(_) => false,
|
||||
LL | | Pending => true,
|
||||
LL | | };
|
||||
| |_____^ help: try this: `Pending::<()>.is_pending()`
|
||||
|
||||
error: aborting due to 18 previous errors
|
||||
|
|
@ -3,7 +3,6 @@
|
|||
#![warn(clippy::all)]
|
||||
#![warn(clippy::redundant_pattern_matching)]
|
||||
#![allow(
|
||||
clippy::unit_arg,
|
||||
unused_must_use,
|
||||
clippy::needless_bool,
|
||||
clippy::match_like_matches_macro,
|
|
@ -3,7 +3,6 @@
|
|||
#![warn(clippy::all)]
|
||||
#![warn(clippy::redundant_pattern_matching)]
|
||||
#![allow(
|
||||
clippy::unit_arg,
|
||||
unused_must_use,
|
||||
clippy::needless_bool,
|
||||
clippy::match_like_matches_macro,
|
|
@ -1,5 +1,5 @@
|
|||
error: redundant pattern matching, consider using `is_ok()`
|
||||
--> $DIR/redundant_pattern_matching.rs:16:12
|
||||
--> $DIR/redundant_pattern_matching_result.rs:15:12
|
||||
|
|
||||
LL | if let Ok(_) = &result {}
|
||||
| -------^^^^^---------- help: try this: `if result.is_ok()`
|
||||
|
@ -7,31 +7,31 @@ LL | if let Ok(_) = &result {}
|
|||
= note: `-D clippy::redundant-pattern-matching` implied by `-D warnings`
|
||||
|
||||
error: redundant pattern matching, consider using `is_ok()`
|
||||
--> $DIR/redundant_pattern_matching.rs:18:12
|
||||
--> $DIR/redundant_pattern_matching_result.rs:17:12
|
||||
|
|
||||
LL | if let Ok(_) = Ok::<i32, i32>(42) {}
|
||||
| -------^^^^^--------------------- help: try this: `if Ok::<i32, i32>(42).is_ok()`
|
||||
|
||||
error: redundant pattern matching, consider using `is_err()`
|
||||
--> $DIR/redundant_pattern_matching.rs:20:12
|
||||
--> $DIR/redundant_pattern_matching_result.rs:19:12
|
||||
|
|
||||
LL | if let Err(_) = Err::<i32, i32>(42) {}
|
||||
| -------^^^^^^---------------------- help: try this: `if Err::<i32, i32>(42).is_err()`
|
||||
|
||||
error: redundant pattern matching, consider using `is_ok()`
|
||||
--> $DIR/redundant_pattern_matching.rs:22:15
|
||||
--> $DIR/redundant_pattern_matching_result.rs:21:15
|
||||
|
|
||||
LL | while let Ok(_) = Ok::<i32, i32>(10) {}
|
||||
| ----------^^^^^--------------------- help: try this: `while Ok::<i32, i32>(10).is_ok()`
|
||||
|
||||
error: redundant pattern matching, consider using `is_err()`
|
||||
--> $DIR/redundant_pattern_matching.rs:24:15
|
||||
--> $DIR/redundant_pattern_matching_result.rs:23:15
|
||||
|
|
||||
LL | while let Err(_) = Ok::<i32, i32>(10) {}
|
||||
| ----------^^^^^^--------------------- help: try this: `while Ok::<i32, i32>(10).is_err()`
|
||||
|
||||
error: redundant pattern matching, consider using `is_ok()`
|
||||
--> $DIR/redundant_pattern_matching.rs:34:5
|
||||
--> $DIR/redundant_pattern_matching_result.rs:33:5
|
||||
|
|
||||
LL | / match Ok::<i32, i32>(42) {
|
||||
LL | | Ok(_) => true,
|
||||
|
@ -40,7 +40,7 @@ LL | | };
|
|||
| |_____^ help: try this: `Ok::<i32, i32>(42).is_ok()`
|
||||
|
||||
error: redundant pattern matching, consider using `is_err()`
|
||||
--> $DIR/redundant_pattern_matching.rs:39:5
|
||||
--> $DIR/redundant_pattern_matching_result.rs:38:5
|
||||
|
|
||||
LL | / match Ok::<i32, i32>(42) {
|
||||
LL | | Ok(_) => false,
|
||||
|
@ -49,7 +49,7 @@ LL | | };
|
|||
| |_____^ help: try this: `Ok::<i32, i32>(42).is_err()`
|
||||
|
||||
error: redundant pattern matching, consider using `is_err()`
|
||||
--> $DIR/redundant_pattern_matching.rs:44:5
|
||||
--> $DIR/redundant_pattern_matching_result.rs:43:5
|
||||
|
|
||||
LL | / match Err::<i32, i32>(42) {
|
||||
LL | | Ok(_) => false,
|
||||
|
@ -58,7 +58,7 @@ LL | | };
|
|||
| |_____^ help: try this: `Err::<i32, i32>(42).is_err()`
|
||||
|
||||
error: redundant pattern matching, consider using `is_ok()`
|
||||
--> $DIR/redundant_pattern_matching.rs:49:5
|
||||
--> $DIR/redundant_pattern_matching_result.rs:48:5
|
||||
|
|
||||
LL | / match Err::<i32, i32>(42) {
|
||||
LL | | Ok(_) => true,
|
||||
|
@ -67,73 +67,73 @@ LL | | };
|
|||
| |_____^ help: try this: `Err::<i32, i32>(42).is_ok()`
|
||||
|
||||
error: redundant pattern matching, consider using `is_ok()`
|
||||
--> $DIR/redundant_pattern_matching.rs:54:20
|
||||
--> $DIR/redundant_pattern_matching_result.rs:53:20
|
||||
|
|
||||
LL | let _ = if let Ok(_) = Ok::<usize, ()>(4) { true } else { false };
|
||||
| -------^^^^^--------------------- help: try this: `if Ok::<usize, ()>(4).is_ok()`
|
||||
|
||||
error: redundant pattern matching, consider using `is_ok()`
|
||||
--> $DIR/redundant_pattern_matching.rs:60:20
|
||||
--> $DIR/redundant_pattern_matching_result.rs:59:20
|
||||
|
|
||||
LL | let _ = if let Ok(_) = gen_res() {
|
||||
| -------^^^^^------------ help: try this: `if gen_res().is_ok()`
|
||||
|
||||
error: redundant pattern matching, consider using `is_err()`
|
||||
--> $DIR/redundant_pattern_matching.rs:62:19
|
||||
--> $DIR/redundant_pattern_matching_result.rs:61:19
|
||||
|
|
||||
LL | } else if let Err(_) = gen_res() {
|
||||
| -------^^^^^^------------ help: try this: `if gen_res().is_err()`
|
||||
|
||||
error: redundant pattern matching, consider using `is_some()`
|
||||
--> $DIR/redundant_pattern_matching.rs:85:19
|
||||
--> $DIR/redundant_pattern_matching_result.rs:84:19
|
||||
|
|
||||
LL | while let Some(_) = r#try!(result_opt()) {}
|
||||
| ----------^^^^^^^----------------------- help: try this: `while r#try!(result_opt()).is_some()`
|
||||
|
||||
error: redundant pattern matching, consider using `is_some()`
|
||||
--> $DIR/redundant_pattern_matching.rs:86:16
|
||||
--> $DIR/redundant_pattern_matching_result.rs:85:16
|
||||
|
|
||||
LL | if let Some(_) = r#try!(result_opt()) {}
|
||||
| -------^^^^^^^----------------------- help: try this: `if r#try!(result_opt()).is_some()`
|
||||
|
||||
error: redundant pattern matching, consider using `is_some()`
|
||||
--> $DIR/redundant_pattern_matching.rs:92:12
|
||||
--> $DIR/redundant_pattern_matching_result.rs:91:12
|
||||
|
|
||||
LL | if let Some(_) = m!() {}
|
||||
| -------^^^^^^^------- help: try this: `if m!().is_some()`
|
||||
|
||||
error: redundant pattern matching, consider using `is_some()`
|
||||
--> $DIR/redundant_pattern_matching.rs:93:15
|
||||
--> $DIR/redundant_pattern_matching_result.rs:92:15
|
||||
|
|
||||
LL | while let Some(_) = m!() {}
|
||||
| ----------^^^^^^^------- help: try this: `while m!().is_some()`
|
||||
|
||||
error: redundant pattern matching, consider using `is_ok()`
|
||||
--> $DIR/redundant_pattern_matching.rs:111:12
|
||||
--> $DIR/redundant_pattern_matching_result.rs:110:12
|
||||
|
|
||||
LL | if let Ok(_) = Ok::<i32, i32>(42) {}
|
||||
| -------^^^^^--------------------- help: try this: `if Ok::<i32, i32>(42).is_ok()`
|
||||
|
||||
error: redundant pattern matching, consider using `is_err()`
|
||||
--> $DIR/redundant_pattern_matching.rs:113:12
|
||||
--> $DIR/redundant_pattern_matching_result.rs:112:12
|
||||
|
|
||||
LL | if let Err(_) = Err::<i32, i32>(42) {}
|
||||
| -------^^^^^^---------------------- help: try this: `if Err::<i32, i32>(42).is_err()`
|
||||
|
||||
error: redundant pattern matching, consider using `is_ok()`
|
||||
--> $DIR/redundant_pattern_matching.rs:115:15
|
||||
--> $DIR/redundant_pattern_matching_result.rs:114:15
|
||||
|
|
||||
LL | while let Ok(_) = Ok::<i32, i32>(10) {}
|
||||
| ----------^^^^^--------------------- help: try this: `while Ok::<i32, i32>(10).is_ok()`
|
||||
|
||||
error: redundant pattern matching, consider using `is_err()`
|
||||
--> $DIR/redundant_pattern_matching.rs:117:15
|
||||
--> $DIR/redundant_pattern_matching_result.rs:116:15
|
||||
|
|
||||
LL | while let Err(_) = Ok::<i32, i32>(10) {}
|
||||
| ----------^^^^^^--------------------- help: try this: `while Ok::<i32, i32>(10).is_err()`
|
||||
|
||||
error: redundant pattern matching, consider using `is_ok()`
|
||||
--> $DIR/redundant_pattern_matching.rs:119:5
|
||||
--> $DIR/redundant_pattern_matching_result.rs:118:5
|
||||
|
|
||||
LL | / match Ok::<i32, i32>(42) {
|
||||
LL | | Ok(_) => true,
|
||||
|
@ -142,7 +142,7 @@ LL | | };
|
|||
| |_____^ help: try this: `Ok::<i32, i32>(42).is_ok()`
|
||||
|
||||
error: redundant pattern matching, consider using `is_err()`
|
||||
--> $DIR/redundant_pattern_matching.rs:124:5
|
||||
--> $DIR/redundant_pattern_matching_result.rs:123:5
|
||||
|
|
||||
LL | / match Err::<i32, i32>(42) {
|
||||
LL | | Ok(_) => false,
|
7
tests/ui/str_to_string.rs
Normal file
7
tests/ui/str_to_string.rs
Normal file
|
@ -0,0 +1,7 @@
|
|||
#![warn(clippy::str_to_string)]
|
||||
|
||||
fn main() {
|
||||
let hello = "hello world".to_string();
|
||||
let msg = &hello[..];
|
||||
msg.to_string();
|
||||
}
|
19
tests/ui/str_to_string.stderr
Normal file
19
tests/ui/str_to_string.stderr
Normal file
|
@ -0,0 +1,19 @@
|
|||
error: `to_string()` called on a `&str`
|
||||
--> $DIR/str_to_string.rs:4:17
|
||||
|
|
||||
LL | let hello = "hello world".to_string();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: `-D clippy::str-to-string` implied by `-D warnings`
|
||||
= help: consider using `.to_owned()`
|
||||
|
||||
error: `to_string()` called on a `&str`
|
||||
--> $DIR/str_to_string.rs:6:5
|
||||
|
|
||||
LL | msg.to_string();
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: consider using `.to_owned()`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
7
tests/ui/string_to_string.rs
Normal file
7
tests/ui/string_to_string.rs
Normal file
|
@ -0,0 +1,7 @@
|
|||
#![warn(clippy::string_to_string)]
|
||||
#![allow(clippy::redundant_clone)]
|
||||
|
||||
fn main() {
|
||||
let mut message = String::from("Hello");
|
||||
let mut v = message.to_string();
|
||||
}
|
11
tests/ui/string_to_string.stderr
Normal file
11
tests/ui/string_to_string.stderr
Normal file
|
@ -0,0 +1,11 @@
|
|||
error: `to_string()` called on a `String`
|
||||
--> $DIR/string_to_string.rs:6:17
|
||||
|
|
||||
LL | let mut v = message.to_string();
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: `-D clippy::string-to-string` implied by `-D warnings`
|
||||
= help: consider using `.clone()`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
#![warn(clippy::temporary_assignment)]
|
||||
#![allow(const_item_mutation)]
|
||||
|
||||
use std::ops::{Deref, DerefMut};
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
error: assignment to temporary
|
||||
--> $DIR/temporary_assignment.rs:48:5
|
||||
--> $DIR/temporary_assignment.rs:47:5
|
||||
|
|
||||
LL | Struct { field: 0 }.field = 1;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
@ -7,7 +7,7 @@ LL | Struct { field: 0 }.field = 1;
|
|||
= note: `-D clippy::temporary-assignment` implied by `-D warnings`
|
||||
|
||||
error: assignment to temporary
|
||||
--> $DIR/temporary_assignment.rs:49:5
|
||||
--> $DIR/temporary_assignment.rs:48:5
|
||||
|
|
||||
LL | / MultiStruct {
|
||||
LL | | structure: Struct { field: 0 },
|
||||
|
@ -17,13 +17,13 @@ LL | | .field = 1;
|
|||
| |______________^
|
||||
|
||||
error: assignment to temporary
|
||||
--> $DIR/temporary_assignment.rs:54:5
|
||||
--> $DIR/temporary_assignment.rs:53:5
|
||||
|
|
||||
LL | ArrayStruct { array: [0] }.array[0] = 1;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: assignment to temporary
|
||||
--> $DIR/temporary_assignment.rs:55:5
|
||||
--> $DIR/temporary_assignment.rs:54:5
|
||||
|
|
||||
LL | (0, 0).0 = 1;
|
||||
| ^^^^^^^^^^^^
|
||||
|
|
|
@ -20,4 +20,7 @@ fn main() {
|
|||
foo!(a, i32);
|
||||
foo!(b, f32);
|
||||
foo!(c, f64);
|
||||
|
||||
// do not lint cast to cfg-dependant type
|
||||
1 as std::os::raw::c_char;
|
||||
}
|
||||
|
|
|
@ -11,6 +11,8 @@ fn main() {
|
|||
let _ = -100_f32;
|
||||
let _ = -100_f64;
|
||||
let _ = -100_f64;
|
||||
100_f32;
|
||||
100_f64;
|
||||
// Should not trigger
|
||||
#[rustfmt::skip]
|
||||
let v = vec!(1);
|
||||
|
|
|
@ -11,6 +11,8 @@ fn main() {
|
|||
let _ = -100 as f32;
|
||||
let _ = -100 as f64;
|
||||
let _ = -100_i32 as f64;
|
||||
100. as f32;
|
||||
100. as f64;
|
||||
// Should not trigger
|
||||
#[rustfmt::skip]
|
||||
let v = vec!(1);
|
||||
|
|
|
@ -36,59 +36,71 @@ error: casting integer literal to `f64` is unnecessary
|
|||
LL | let _ = -100_i32 as f64;
|
||||
| ^^^^^^^^^^^^^^^ help: try: `-100_f64`
|
||||
|
||||
error: casting float literal to `f32` is unnecessary
|
||||
--> $DIR/unnecessary_cast_fixable.rs:14:5
|
||||
|
|
||||
LL | 100. as f32;
|
||||
| ^^^^^^^^^^^ help: try: `100_f32`
|
||||
|
||||
error: casting float literal to `f64` is unnecessary
|
||||
--> $DIR/unnecessary_cast_fixable.rs:15:5
|
||||
|
|
||||
LL | 100. as f64;
|
||||
| ^^^^^^^^^^^ help: try: `100_f64`
|
||||
|
||||
error: casting integer literal to `u32` is unnecessary
|
||||
--> $DIR/unnecessary_cast_fixable.rs:25:5
|
||||
--> $DIR/unnecessary_cast_fixable.rs:27:5
|
||||
|
|
||||
LL | 1 as u32;
|
||||
| ^^^^^^^^ help: try: `1_u32`
|
||||
|
||||
error: casting integer literal to `i32` is unnecessary
|
||||
--> $DIR/unnecessary_cast_fixable.rs:26:5
|
||||
--> $DIR/unnecessary_cast_fixable.rs:28:5
|
||||
|
|
||||
LL | 0x10 as i32;
|
||||
| ^^^^^^^^^^^ help: try: `0x10_i32`
|
||||
|
||||
error: casting integer literal to `usize` is unnecessary
|
||||
--> $DIR/unnecessary_cast_fixable.rs:27:5
|
||||
--> $DIR/unnecessary_cast_fixable.rs:29:5
|
||||
|
|
||||
LL | 0b10 as usize;
|
||||
| ^^^^^^^^^^^^^ help: try: `0b10_usize`
|
||||
|
||||
error: casting integer literal to `u16` is unnecessary
|
||||
--> $DIR/unnecessary_cast_fixable.rs:28:5
|
||||
--> $DIR/unnecessary_cast_fixable.rs:30:5
|
||||
|
|
||||
LL | 0o73 as u16;
|
||||
| ^^^^^^^^^^^ help: try: `0o73_u16`
|
||||
|
||||
error: casting integer literal to `u32` is unnecessary
|
||||
--> $DIR/unnecessary_cast_fixable.rs:29:5
|
||||
--> $DIR/unnecessary_cast_fixable.rs:31:5
|
||||
|
|
||||
LL | 1_000_000_000 as u32;
|
||||
| ^^^^^^^^^^^^^^^^^^^^ help: try: `1_000_000_000_u32`
|
||||
|
||||
error: casting float literal to `f64` is unnecessary
|
||||
--> $DIR/unnecessary_cast_fixable.rs:31:5
|
||||
--> $DIR/unnecessary_cast_fixable.rs:33:5
|
||||
|
|
||||
LL | 1.0 as f64;
|
||||
| ^^^^^^^^^^ help: try: `1.0_f64`
|
||||
|
||||
error: casting float literal to `f32` is unnecessary
|
||||
--> $DIR/unnecessary_cast_fixable.rs:32:5
|
||||
--> $DIR/unnecessary_cast_fixable.rs:34:5
|
||||
|
|
||||
LL | 0.5 as f32;
|
||||
| ^^^^^^^^^^ help: try: `0.5_f32`
|
||||
|
||||
error: casting integer literal to `i32` is unnecessary
|
||||
--> $DIR/unnecessary_cast_fixable.rs:36:13
|
||||
--> $DIR/unnecessary_cast_fixable.rs:38:13
|
||||
|
|
||||
LL | let _ = -1 as i32;
|
||||
| ^^^^^^^^^ help: try: `-1_i32`
|
||||
|
||||
error: casting float literal to `f32` is unnecessary
|
||||
--> $DIR/unnecessary_cast_fixable.rs:37:13
|
||||
--> $DIR/unnecessary_cast_fixable.rs:39:13
|
||||
|
|
||||
LL | let _ = -1.0 as f32;
|
||||
| ^^^^^^^^^^^ help: try: `-1.0_f32`
|
||||
|
||||
error: aborting due to 15 previous errors
|
||||
error: aborting due to 17 previous errors
|
||||
|
||||
|
|
|
@ -7,7 +7,8 @@
|
|||
dead_code,
|
||||
clippy::single_match,
|
||||
clippy::wildcard_in_or_patterns,
|
||||
clippy::unnested_or_patterns, clippy::diverging_sub_expression
|
||||
clippy::unnested_or_patterns,
|
||||
clippy::diverging_sub_expression
|
||||
)]
|
||||
|
||||
use std::io::ErrorKind;
|
||||
|
|
|
@ -7,7 +7,8 @@
|
|||
dead_code,
|
||||
clippy::single_match,
|
||||
clippy::wildcard_in_or_patterns,
|
||||
clippy::unnested_or_patterns, clippy::diverging_sub_expression
|
||||
clippy::unnested_or_patterns,
|
||||
clippy::diverging_sub_expression
|
||||
)]
|
||||
|
||||
use std::io::ErrorKind;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
error: wildcard match will miss any future added variants
|
||||
--> $DIR/wildcard_enum_match_arm.rs:38:9
|
||||
--> $DIR/wildcard_enum_match_arm.rs:39:9
|
||||
|
|
||||
LL | _ => eprintln!("Not red"),
|
||||
| ^ help: try this: `Color::Green | Color::Blue | Color::Rgb(..) | Color::Cyan`
|
||||
|
@ -11,25 +11,25 @@ LL | #![deny(clippy::wildcard_enum_match_arm)]
|
|||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: wildcard match will miss any future added variants
|
||||
--> $DIR/wildcard_enum_match_arm.rs:42:9
|
||||
--> $DIR/wildcard_enum_match_arm.rs:43:9
|
||||
|
|
||||
LL | _not_red => eprintln!("Not red"),
|
||||
| ^^^^^^^^ help: try this: `_not_red @ Color::Green | _not_red @ Color::Blue | _not_red @ Color::Rgb(..) | _not_red @ Color::Cyan`
|
||||
|
||||
error: wildcard match will miss any future added variants
|
||||
--> $DIR/wildcard_enum_match_arm.rs:46:9
|
||||
--> $DIR/wildcard_enum_match_arm.rs:47:9
|
||||
|
|
||||
LL | not_red => format!("{:?}", not_red),
|
||||
| ^^^^^^^ help: try this: `not_red @ Color::Green | not_red @ Color::Blue | not_red @ Color::Rgb(..) | not_red @ Color::Cyan`
|
||||
|
||||
error: wildcard match will miss any future added variants
|
||||
--> $DIR/wildcard_enum_match_arm.rs:62:9
|
||||
--> $DIR/wildcard_enum_match_arm.rs:63:9
|
||||
|
|
||||
LL | _ => "No red",
|
||||
| ^ help: try this: `Color::Red | Color::Green | Color::Blue | Color::Rgb(..) | Color::Cyan`
|
||||
|
||||
error: match on non-exhaustive enum doesn't explicitly match all known variants
|
||||
--> $DIR/wildcard_enum_match_arm.rs:79:9
|
||||
--> $DIR/wildcard_enum_match_arm.rs:80:9
|
||||
|
|
||||
LL | _ => {},
|
||||
| ^ help: try this: `std::io::ErrorKind::PermissionDenied | std::io::ErrorKind::ConnectionRefused | std::io::ErrorKind::ConnectionReset | std::io::ErrorKind::ConnectionAborted | std::io::ErrorKind::NotConnected | std::io::ErrorKind::AddrInUse | std::io::ErrorKind::AddrNotAvailable | std::io::ErrorKind::BrokenPipe | std::io::ErrorKind::AlreadyExists | std::io::ErrorKind::WouldBlock | std::io::ErrorKind::InvalidInput | std::io::ErrorKind::InvalidData | std::io::ErrorKind::TimedOut | std::io::ErrorKind::WriteZero | std::io::ErrorKind::Interrupted | std::io::ErrorKind::Other | std::io::ErrorKind::UnexpectedEof | _`
|
||||
|
|
7
util/dev
7
util/dev
|
@ -1,7 +0,0 @@
|
|||
#!/bin/sh
|
||||
CARGO_TARGET_DIR=$(pwd)/target/
|
||||
export CARGO_TARGET_DIR
|
||||
|
||||
echo 'Deprecated! `util/dev` usage is deprecated, please use `cargo dev` instead.'
|
||||
|
||||
cd clippy_dev && cargo run -- "$@"
|
Loading…
Reference in a new issue