Merge remote-tracking branch 'upstream/master' into rustup
This commit is contained in:
3
.github/workflows/clippy_bors.yml
vendored
3
.github/workflows/clippy_bors.yml
vendored
@@ -240,7 +240,8 @@ jobs:
|
|||||||
- 'Geal/nom'
|
- 'Geal/nom'
|
||||||
- 'rust-lang/stdarch'
|
- 'rust-lang/stdarch'
|
||||||
- 'serde-rs/serde'
|
- 'serde-rs/serde'
|
||||||
- 'chronotope/chrono'
|
# FIXME: chrono currently cannot be compiled with `--all-targets`
|
||||||
|
# - 'chronotope/chrono'
|
||||||
- 'hyperium/hyper'
|
- 'hyperium/hyper'
|
||||||
- 'rust-random/rand'
|
- 'rust-random/rand'
|
||||||
- 'rust-lang/futures-rs'
|
- 'rust-lang/futures-rs'
|
||||||
|
|||||||
@@ -1352,6 +1352,7 @@ Released 2018-09-13
|
|||||||
[`bad_bit_mask`]: https://rust-lang.github.io/rust-clippy/master/index.html#bad_bit_mask
|
[`bad_bit_mask`]: https://rust-lang.github.io/rust-clippy/master/index.html#bad_bit_mask
|
||||||
[`bind_instead_of_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#bind_instead_of_map
|
[`bind_instead_of_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#bind_instead_of_map
|
||||||
[`blacklisted_name`]: https://rust-lang.github.io/rust-clippy/master/index.html#blacklisted_name
|
[`blacklisted_name`]: https://rust-lang.github.io/rust-clippy/master/index.html#blacklisted_name
|
||||||
|
[`blanket_clippy_restriction_lints`]: https://rust-lang.github.io/rust-clippy/master/index.html#blanket_clippy_restriction_lints
|
||||||
[`blocks_in_if_conditions`]: https://rust-lang.github.io/rust-clippy/master/index.html#blocks_in_if_conditions
|
[`blocks_in_if_conditions`]: https://rust-lang.github.io/rust-clippy/master/index.html#blocks_in_if_conditions
|
||||||
[`bool_comparison`]: https://rust-lang.github.io/rust-clippy/master/index.html#bool_comparison
|
[`bool_comparison`]: https://rust-lang.github.io/rust-clippy/master/index.html#bool_comparison
|
||||||
[`borrow_interior_mutable_const`]: https://rust-lang.github.io/rust-clippy/master/index.html#borrow_interior_mutable_const
|
[`borrow_interior_mutable_const`]: https://rust-lang.github.io/rust-clippy/master/index.html#borrow_interior_mutable_const
|
||||||
@@ -1508,6 +1509,7 @@ Released 2018-09-13
|
|||||||
[`map_clone`]: https://rust-lang.github.io/rust-clippy/master/index.html#map_clone
|
[`map_clone`]: https://rust-lang.github.io/rust-clippy/master/index.html#map_clone
|
||||||
[`map_entry`]: https://rust-lang.github.io/rust-clippy/master/index.html#map_entry
|
[`map_entry`]: https://rust-lang.github.io/rust-clippy/master/index.html#map_entry
|
||||||
[`map_flatten`]: https://rust-lang.github.io/rust-clippy/master/index.html#map_flatten
|
[`map_flatten`]: https://rust-lang.github.io/rust-clippy/master/index.html#map_flatten
|
||||||
|
[`map_identity`]: https://rust-lang.github.io/rust-clippy/master/index.html#map_identity
|
||||||
[`map_unwrap_or`]: https://rust-lang.github.io/rust-clippy/master/index.html#map_unwrap_or
|
[`map_unwrap_or`]: https://rust-lang.github.io/rust-clippy/master/index.html#map_unwrap_or
|
||||||
[`match_as_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#match_as_ref
|
[`match_as_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#match_as_ref
|
||||||
[`match_bool`]: https://rust-lang.github.io/rust-clippy/master/index.html#match_bool
|
[`match_bool`]: https://rust-lang.github.io/rust-clippy/master/index.html#match_bool
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
use crate::reexport::Name;
|
use crate::reexport::Name;
|
||||||
use crate::utils::{
|
use crate::utils::{
|
||||||
first_line_of_span, is_present_in_source, match_def_path, paths, snippet_opt, span_lint, span_lint_and_sugg,
|
first_line_of_span, is_present_in_source, match_def_path, paths, snippet_opt, span_lint, span_lint_and_help,
|
||||||
span_lint_and_then, without_block_comments,
|
span_lint_and_sugg, span_lint_and_then, without_block_comments,
|
||||||
};
|
};
|
||||||
use if_chain::if_chain;
|
use if_chain::if_chain;
|
||||||
use rustc_ast::ast::{AttrKind, AttrStyle, Attribute, Lit, LitKind, MetaItemKind, NestedMetaItem};
|
use rustc_ast::ast::{AttrKind, AttrStyle, Attribute, Lit, LitKind, MetaItemKind, NestedMetaItem};
|
||||||
@@ -17,7 +17,7 @@ use rustc_middle::lint::in_external_macro;
|
|||||||
use rustc_middle::ty;
|
use rustc_middle::ty;
|
||||||
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||||
use rustc_span::source_map::Span;
|
use rustc_span::source_map::Span;
|
||||||
use rustc_span::symbol::Symbol;
|
use rustc_span::symbol::{Symbol, SymbolStr};
|
||||||
use semver::Version;
|
use semver::Version;
|
||||||
|
|
||||||
static UNIX_SYSTEMS: &[&str] = &[
|
static UNIX_SYSTEMS: &[&str] = &[
|
||||||
@@ -182,6 +182,29 @@ declare_clippy_lint! {
|
|||||||
"unknown_lints for scoped Clippy lints"
|
"unknown_lints for scoped Clippy lints"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
declare_clippy_lint! {
|
||||||
|
/// **What it does:** Checks for `warn`/`deny`/`forbid` attributes targeting the whole clippy::restriction category.
|
||||||
|
///
|
||||||
|
/// **Why is this bad?** Restriction lints sometimes are in contrast with other lints or even go against idiomatic rust.
|
||||||
|
/// These lints should only be enabled on a lint-by-lint basis and with careful consideration.
|
||||||
|
///
|
||||||
|
/// **Known problems:** None.
|
||||||
|
///
|
||||||
|
/// **Example:**
|
||||||
|
/// Bad:
|
||||||
|
/// ```rust
|
||||||
|
/// #![deny(clippy::restriction)]
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// Good:
|
||||||
|
/// ```rust
|
||||||
|
/// #![deny(clippy::as_conversions)]
|
||||||
|
/// ```
|
||||||
|
pub BLANKET_CLIPPY_RESTRICTION_LINTS,
|
||||||
|
style,
|
||||||
|
"enabling the complete restriction group"
|
||||||
|
}
|
||||||
|
|
||||||
declare_clippy_lint! {
|
declare_clippy_lint! {
|
||||||
/// **What it does:** Checks for `#[cfg_attr(rustfmt, rustfmt_skip)]` and suggests to replace it
|
/// **What it does:** Checks for `#[cfg_attr(rustfmt, rustfmt_skip)]` and suggests to replace it
|
||||||
/// with `#[rustfmt::skip]`.
|
/// with `#[rustfmt::skip]`.
|
||||||
@@ -249,15 +272,17 @@ declare_lint_pass!(Attributes => [
|
|||||||
DEPRECATED_SEMVER,
|
DEPRECATED_SEMVER,
|
||||||
USELESS_ATTRIBUTE,
|
USELESS_ATTRIBUTE,
|
||||||
UNKNOWN_CLIPPY_LINTS,
|
UNKNOWN_CLIPPY_LINTS,
|
||||||
|
BLANKET_CLIPPY_RESTRICTION_LINTS,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
impl<'tcx> LateLintPass<'tcx> for Attributes {
|
impl<'tcx> LateLintPass<'tcx> for Attributes {
|
||||||
fn check_attribute(&mut self, cx: &LateContext<'tcx>, attr: &'tcx Attribute) {
|
fn check_attribute(&mut self, cx: &LateContext<'tcx>, attr: &'tcx Attribute) {
|
||||||
if let Some(items) = &attr.meta_item_list() {
|
if let Some(items) = &attr.meta_item_list() {
|
||||||
if let Some(ident) = attr.ident() {
|
if let Some(ident) = attr.ident() {
|
||||||
match &*ident.as_str() {
|
let ident = &*ident.as_str();
|
||||||
|
match ident {
|
||||||
"allow" | "warn" | "deny" | "forbid" => {
|
"allow" | "warn" | "deny" | "forbid" => {
|
||||||
check_clippy_lint_names(cx, items);
|
check_clippy_lint_names(cx, ident, items);
|
||||||
},
|
},
|
||||||
_ => {},
|
_ => {},
|
||||||
}
|
}
|
||||||
@@ -363,38 +388,43 @@ impl<'tcx> LateLintPass<'tcx> for Attributes {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::single_match_else)]
|
fn check_clippy_lint_names(cx: &LateContext<'_>, ident: &str, items: &[NestedMetaItem]) {
|
||||||
fn check_clippy_lint_names(cx: &LateContext<'_>, items: &[NestedMetaItem]) {
|
fn extract_name(lint: &NestedMetaItem) -> Option<SymbolStr> {
|
||||||
let lint_store = cx.lints();
|
|
||||||
for lint in items {
|
|
||||||
if_chain! {
|
if_chain! {
|
||||||
if let Some(meta_item) = lint.meta_item();
|
if let Some(meta_item) = lint.meta_item();
|
||||||
if meta_item.path.segments.len() > 1;
|
if meta_item.path.segments.len() > 1;
|
||||||
if let tool_name = meta_item.path.segments[0].ident;
|
if let tool_name = meta_item.path.segments[0].ident;
|
||||||
if tool_name.as_str() == "clippy";
|
if tool_name.as_str() == "clippy";
|
||||||
let name = meta_item.path.segments.last().unwrap().ident.name;
|
let lint_name = meta_item.path.segments.last().unwrap().ident.name;
|
||||||
if let CheckLintNameResult::Tool(Err((None, _))) = lint_store.check_lint_name(
|
|
||||||
&name.as_str(),
|
|
||||||
Some(tool_name.name),
|
|
||||||
);
|
|
||||||
then {
|
then {
|
||||||
|
return Some(lint_name.as_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
let lint_store = cx.lints();
|
||||||
|
for lint in items {
|
||||||
|
if let Some(lint_name) = extract_name(lint) {
|
||||||
|
if let CheckLintNameResult::Tool(Err((None, _))) =
|
||||||
|
lint_store.check_lint_name(&lint_name, Some(sym!(clippy)))
|
||||||
|
{
|
||||||
span_lint_and_then(
|
span_lint_and_then(
|
||||||
cx,
|
cx,
|
||||||
UNKNOWN_CLIPPY_LINTS,
|
UNKNOWN_CLIPPY_LINTS,
|
||||||
lint.span(),
|
lint.span(),
|
||||||
&format!("unknown clippy lint: clippy::{}", name),
|
&format!("unknown clippy lint: clippy::{}", lint_name),
|
||||||
|diag| {
|
|diag| {
|
||||||
let name_lower = name.as_str().to_lowercase();
|
let name_lower = lint_name.to_lowercase();
|
||||||
let symbols = lint_store.get_lints().iter().map(
|
let symbols = lint_store
|
||||||
|l| Symbol::intern(&l.name_lower())
|
.get_lints()
|
||||||
).collect::<Vec<_>>();
|
.iter()
|
||||||
let sugg = find_best_match_for_name(
|
.map(|l| Symbol::intern(&l.name_lower()))
|
||||||
symbols.iter(),
|
.collect::<Vec<_>>();
|
||||||
&format!("clippy::{}", name_lower),
|
let sugg = find_best_match_for_name(symbols.iter(), &format!("clippy::{}", name_lower), None);
|
||||||
None,
|
if lint_name.chars().any(char::is_uppercase)
|
||||||
);
|
&& lint_store.find_lints(&format!("clippy::{}", name_lower)).is_ok()
|
||||||
if name.as_str().chars().any(char::is_uppercase)
|
{
|
||||||
&& lint_store.find_lints(&format!("clippy::{}", name_lower)).is_ok() {
|
|
||||||
diag.span_suggestion(
|
diag.span_suggestion(
|
||||||
lint.span(),
|
lint.span(),
|
||||||
"lowercase the lint name",
|
"lowercase the lint name",
|
||||||
@@ -409,10 +439,19 @@ fn check_clippy_lint_names(cx: &LateContext<'_>, items: &[NestedMetaItem]) {
|
|||||||
Applicability::MachineApplicable,
|
Applicability::MachineApplicable,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
);
|
||||||
|
} else if lint_name == "restriction" && ident != "allow" {
|
||||||
|
span_lint_and_help(
|
||||||
|
cx,
|
||||||
|
BLANKET_CLIPPY_RESTRICTION_LINTS,
|
||||||
|
lint.span(),
|
||||||
|
"restriction lints are not meant to be all enabled",
|
||||||
|
None,
|
||||||
|
"try enabling only the lints you really need",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ declare_clippy_lint! {
|
|||||||
/// non-async-aware MutexGuard.
|
/// non-async-aware MutexGuard.
|
||||||
///
|
///
|
||||||
/// **Why is this bad?** The Mutex types found in syd::sync and parking_lot
|
/// **Why is this bad?** The Mutex types found in syd::sync and parking_lot
|
||||||
/// are not designed to operator in an async context across await points.
|
/// are not designed to operate in an async context across await points.
|
||||||
///
|
///
|
||||||
/// There are two potential solutions. One is to use an asynx-aware Mutex
|
/// There are two potential solutions. One is to use an asynx-aware Mutex
|
||||||
/// type. Many asynchronous foundation crates provide such a Mutex type. The
|
/// type. Many asynchronous foundation crates provide such a Mutex type. The
|
||||||
|
|||||||
@@ -153,5 +153,13 @@ declare_deprecated_lint! {
|
|||||||
///
|
///
|
||||||
/// **Deprecation reason:** Associated-constants are now preferred.
|
/// **Deprecation reason:** Associated-constants are now preferred.
|
||||||
pub REPLACE_CONSTS,
|
pub REPLACE_CONSTS,
|
||||||
"associated-constants `MIN`/`MAX` of integers are prefer to `{min,max}_value()` and module constants"
|
"associated-constants `MIN`/`MAX` of integers are prefered to `{min,max}_value()` and module constants"
|
||||||
|
}
|
||||||
|
|
||||||
|
declare_deprecated_lint! {
|
||||||
|
/// **What it does:** Nothing. This lint has been deprecated.
|
||||||
|
///
|
||||||
|
/// **Deprecation reason:** The regex! macro does not exist anymore.
|
||||||
|
pub REGEX_MACRO,
|
||||||
|
"the regex! macro has been removed from the regex crate in 2018"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -73,9 +73,10 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing {
|
|||||||
fn lint_deref(cx: &LateContext<'_>, method_name: &str, call_expr: &Expr<'_>, var_span: Span, expr_span: Span) {
|
fn lint_deref(cx: &LateContext<'_>, method_name: &str, call_expr: &Expr<'_>, var_span: Span, expr_span: Span) {
|
||||||
match method_name {
|
match method_name {
|
||||||
"deref" => {
|
"deref" => {
|
||||||
if cx.tcx.lang_items().deref_trait().map_or(false, |id| {
|
let impls_deref_trait = cx.tcx.lang_items().deref_trait().map_or(false, |id| {
|
||||||
implements_trait(cx, cx.tables().expr_ty(&call_expr), id, &[])
|
implements_trait(cx, cx.tables().expr_ty(&call_expr), id, &[])
|
||||||
}) {
|
});
|
||||||
|
if impls_deref_trait {
|
||||||
span_lint_and_sugg(
|
span_lint_and_sugg(
|
||||||
cx,
|
cx,
|
||||||
EXPLICIT_DEREF_METHODS,
|
EXPLICIT_DEREF_METHODS,
|
||||||
@@ -88,9 +89,10 @@ fn lint_deref(cx: &LateContext<'_>, method_name: &str, call_expr: &Expr<'_>, var
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"deref_mut" => {
|
"deref_mut" => {
|
||||||
if cx.tcx.lang_items().deref_mut_trait().map_or(false, |id| {
|
let impls_deref_mut_trait = cx.tcx.lang_items().deref_mut_trait().map_or(false, |id| {
|
||||||
implements_trait(cx, cx.tables().expr_ty(&call_expr), id, &[])
|
implements_trait(cx, cx.tables().expr_ty(&call_expr), id, &[])
|
||||||
}) {
|
});
|
||||||
|
if impls_deref_mut_trait {
|
||||||
span_lint_and_sugg(
|
span_lint_and_sugg(
|
||||||
cx,
|
cx,
|
||||||
EXPLICIT_DEREF_METHODS,
|
EXPLICIT_DEREF_METHODS,
|
||||||
|
|||||||
@@ -229,6 +229,7 @@ mod main_recursion;
|
|||||||
mod manual_async_fn;
|
mod manual_async_fn;
|
||||||
mod manual_non_exhaustive;
|
mod manual_non_exhaustive;
|
||||||
mod map_clone;
|
mod map_clone;
|
||||||
|
mod map_identity;
|
||||||
mod map_unit_fn;
|
mod map_unit_fn;
|
||||||
mod match_on_vec_items;
|
mod match_on_vec_items;
|
||||||
mod matches;
|
mod matches;
|
||||||
@@ -459,7 +460,11 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
|
|||||||
);
|
);
|
||||||
store.register_removed(
|
store.register_removed(
|
||||||
"clippy::replace_consts",
|
"clippy::replace_consts",
|
||||||
"associated-constants `MIN`/`MAX` of integers are prefer to `{min,max}_value()` and module constants",
|
"associated-constants `MIN`/`MAX` of integers are prefered to `{min,max}_value()` and module constants",
|
||||||
|
);
|
||||||
|
store.register_removed(
|
||||||
|
"clippy::regex_macro",
|
||||||
|
"the regex! macro has been removed from the regex crate in 2018",
|
||||||
);
|
);
|
||||||
// end deprecated lints, do not remove this comment, it’s used in `update_lints`
|
// end deprecated lints, do not remove this comment, it’s used in `update_lints`
|
||||||
|
|
||||||
@@ -473,6 +478,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
|
|||||||
&assign_ops::ASSIGN_OP_PATTERN,
|
&assign_ops::ASSIGN_OP_PATTERN,
|
||||||
&assign_ops::MISREFACTORED_ASSIGN_OP,
|
&assign_ops::MISREFACTORED_ASSIGN_OP,
|
||||||
&atomic_ordering::INVALID_ATOMIC_ORDERING,
|
&atomic_ordering::INVALID_ATOMIC_ORDERING,
|
||||||
|
&attrs::BLANKET_CLIPPY_RESTRICTION_LINTS,
|
||||||
&attrs::DEPRECATED_CFG_ATTR,
|
&attrs::DEPRECATED_CFG_ATTR,
|
||||||
&attrs::DEPRECATED_SEMVER,
|
&attrs::DEPRECATED_SEMVER,
|
||||||
&attrs::EMPTY_LINE_AFTER_OUTER_ATTR,
|
&attrs::EMPTY_LINE_AFTER_OUTER_ATTR,
|
||||||
@@ -608,6 +614,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
|
|||||||
&manual_async_fn::MANUAL_ASYNC_FN,
|
&manual_async_fn::MANUAL_ASYNC_FN,
|
||||||
&manual_non_exhaustive::MANUAL_NON_EXHAUSTIVE,
|
&manual_non_exhaustive::MANUAL_NON_EXHAUSTIVE,
|
||||||
&map_clone::MAP_CLONE,
|
&map_clone::MAP_CLONE,
|
||||||
|
&map_identity::MAP_IDENTITY,
|
||||||
&map_unit_fn::OPTION_MAP_UNIT_FN,
|
&map_unit_fn::OPTION_MAP_UNIT_FN,
|
||||||
&map_unit_fn::RESULT_MAP_UNIT_FN,
|
&map_unit_fn::RESULT_MAP_UNIT_FN,
|
||||||
&match_on_vec_items::MATCH_ON_VEC_ITEMS,
|
&match_on_vec_items::MATCH_ON_VEC_ITEMS,
|
||||||
@@ -752,7 +759,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
|
|||||||
&reference::DEREF_ADDROF,
|
&reference::DEREF_ADDROF,
|
||||||
&reference::REF_IN_DEREF,
|
&reference::REF_IN_DEREF,
|
||||||
®ex::INVALID_REGEX,
|
®ex::INVALID_REGEX,
|
||||||
®ex::REGEX_MACRO,
|
|
||||||
®ex::TRIVIAL_REGEX,
|
®ex::TRIVIAL_REGEX,
|
||||||
&returns::NEEDLESS_RETURN,
|
&returns::NEEDLESS_RETURN,
|
||||||
&returns::UNUSED_UNIT,
|
&returns::UNUSED_UNIT,
|
||||||
@@ -1057,6 +1063,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
|
|||||||
});
|
});
|
||||||
store.register_early_pass(|| box unnested_or_patterns::UnnestedOrPatterns);
|
store.register_early_pass(|| box unnested_or_patterns::UnnestedOrPatterns);
|
||||||
store.register_late_pass(|| box macro_use::MacroUseImports::default());
|
store.register_late_pass(|| box macro_use::MacroUseImports::default());
|
||||||
|
store.register_late_pass(|| box map_identity::MapIdentity);
|
||||||
|
|
||||||
store.register_group(true, "clippy::restriction", Some("clippy_restriction"), vec![
|
store.register_group(true, "clippy::restriction", Some("clippy_restriction"), vec![
|
||||||
LintId::of(&arithmetic::FLOAT_ARITHMETIC),
|
LintId::of(&arithmetic::FLOAT_ARITHMETIC),
|
||||||
@@ -1186,6 +1193,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
|
|||||||
LintId::of(&assign_ops::ASSIGN_OP_PATTERN),
|
LintId::of(&assign_ops::ASSIGN_OP_PATTERN),
|
||||||
LintId::of(&assign_ops::MISREFACTORED_ASSIGN_OP),
|
LintId::of(&assign_ops::MISREFACTORED_ASSIGN_OP),
|
||||||
LintId::of(&atomic_ordering::INVALID_ATOMIC_ORDERING),
|
LintId::of(&atomic_ordering::INVALID_ATOMIC_ORDERING),
|
||||||
|
LintId::of(&attrs::BLANKET_CLIPPY_RESTRICTION_LINTS),
|
||||||
LintId::of(&attrs::DEPRECATED_CFG_ATTR),
|
LintId::of(&attrs::DEPRECATED_CFG_ATTR),
|
||||||
LintId::of(&attrs::DEPRECATED_SEMVER),
|
LintId::of(&attrs::DEPRECATED_SEMVER),
|
||||||
LintId::of(&attrs::MISMATCHED_TARGET_OS),
|
LintId::of(&attrs::MISMATCHED_TARGET_OS),
|
||||||
@@ -1273,6 +1281,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
|
|||||||
LintId::of(&manual_async_fn::MANUAL_ASYNC_FN),
|
LintId::of(&manual_async_fn::MANUAL_ASYNC_FN),
|
||||||
LintId::of(&manual_non_exhaustive::MANUAL_NON_EXHAUSTIVE),
|
LintId::of(&manual_non_exhaustive::MANUAL_NON_EXHAUSTIVE),
|
||||||
LintId::of(&map_clone::MAP_CLONE),
|
LintId::of(&map_clone::MAP_CLONE),
|
||||||
|
LintId::of(&map_identity::MAP_IDENTITY),
|
||||||
LintId::of(&map_unit_fn::OPTION_MAP_UNIT_FN),
|
LintId::of(&map_unit_fn::OPTION_MAP_UNIT_FN),
|
||||||
LintId::of(&map_unit_fn::RESULT_MAP_UNIT_FN),
|
LintId::of(&map_unit_fn::RESULT_MAP_UNIT_FN),
|
||||||
LintId::of(&matches::INFALLIBLE_DESTRUCTURING_MATCH),
|
LintId::of(&matches::INFALLIBLE_DESTRUCTURING_MATCH),
|
||||||
@@ -1374,7 +1383,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
|
|||||||
LintId::of(&reference::DEREF_ADDROF),
|
LintId::of(&reference::DEREF_ADDROF),
|
||||||
LintId::of(&reference::REF_IN_DEREF),
|
LintId::of(&reference::REF_IN_DEREF),
|
||||||
LintId::of(®ex::INVALID_REGEX),
|
LintId::of(®ex::INVALID_REGEX),
|
||||||
LintId::of(®ex::REGEX_MACRO),
|
|
||||||
LintId::of(®ex::TRIVIAL_REGEX),
|
LintId::of(®ex::TRIVIAL_REGEX),
|
||||||
LintId::of(&returns::NEEDLESS_RETURN),
|
LintId::of(&returns::NEEDLESS_RETURN),
|
||||||
LintId::of(&returns::UNUSED_UNIT),
|
LintId::of(&returns::UNUSED_UNIT),
|
||||||
@@ -1437,6 +1445,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
|
|||||||
store.register_group(true, "clippy::style", Some("clippy_style"), vec![
|
store.register_group(true, "clippy::style", Some("clippy_style"), vec![
|
||||||
LintId::of(&assertions_on_constants::ASSERTIONS_ON_CONSTANTS),
|
LintId::of(&assertions_on_constants::ASSERTIONS_ON_CONSTANTS),
|
||||||
LintId::of(&assign_ops::ASSIGN_OP_PATTERN),
|
LintId::of(&assign_ops::ASSIGN_OP_PATTERN),
|
||||||
|
LintId::of(&attrs::BLANKET_CLIPPY_RESTRICTION_LINTS),
|
||||||
LintId::of(&attrs::UNKNOWN_CLIPPY_LINTS),
|
LintId::of(&attrs::UNKNOWN_CLIPPY_LINTS),
|
||||||
LintId::of(&bit_mask::VERBOSE_BIT_MASK),
|
LintId::of(&bit_mask::VERBOSE_BIT_MASK),
|
||||||
LintId::of(&blacklisted_name::BLACKLISTED_NAME),
|
LintId::of(&blacklisted_name::BLACKLISTED_NAME),
|
||||||
@@ -1510,7 +1519,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
|
|||||||
LintId::of(&redundant_field_names::REDUNDANT_FIELD_NAMES),
|
LintId::of(&redundant_field_names::REDUNDANT_FIELD_NAMES),
|
||||||
LintId::of(&redundant_pattern_matching::REDUNDANT_PATTERN_MATCHING),
|
LintId::of(&redundant_pattern_matching::REDUNDANT_PATTERN_MATCHING),
|
||||||
LintId::of(&redundant_static_lifetimes::REDUNDANT_STATIC_LIFETIMES),
|
LintId::of(&redundant_static_lifetimes::REDUNDANT_STATIC_LIFETIMES),
|
||||||
LintId::of(®ex::REGEX_MACRO),
|
|
||||||
LintId::of(®ex::TRIVIAL_REGEX),
|
LintId::of(®ex::TRIVIAL_REGEX),
|
||||||
LintId::of(&returns::NEEDLESS_RETURN),
|
LintId::of(&returns::NEEDLESS_RETURN),
|
||||||
LintId::of(&returns::UNUSED_UNIT),
|
LintId::of(&returns::UNUSED_UNIT),
|
||||||
@@ -1550,6 +1558,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
|
|||||||
LintId::of(&loops::EXPLICIT_COUNTER_LOOP),
|
LintId::of(&loops::EXPLICIT_COUNTER_LOOP),
|
||||||
LintId::of(&loops::MUT_RANGE_BOUND),
|
LintId::of(&loops::MUT_RANGE_BOUND),
|
||||||
LintId::of(&loops::WHILE_LET_LOOP),
|
LintId::of(&loops::WHILE_LET_LOOP),
|
||||||
|
LintId::of(&map_identity::MAP_IDENTITY),
|
||||||
LintId::of(&map_unit_fn::OPTION_MAP_UNIT_FN),
|
LintId::of(&map_unit_fn::OPTION_MAP_UNIT_FN),
|
||||||
LintId::of(&map_unit_fn::RESULT_MAP_UNIT_FN),
|
LintId::of(&map_unit_fn::RESULT_MAP_UNIT_FN),
|
||||||
LintId::of(&matches::MATCH_AS_REF),
|
LintId::of(&matches::MATCH_AS_REF),
|
||||||
|
|||||||
126
clippy_lints/src/map_identity.rs
Normal file
126
clippy_lints/src/map_identity.rs
Normal file
@@ -0,0 +1,126 @@
|
|||||||
|
use crate::utils::{
|
||||||
|
is_adjusted, is_type_diagnostic_item, match_path, match_trait_method, match_var, paths, remove_blocks,
|
||||||
|
span_lint_and_sugg,
|
||||||
|
};
|
||||||
|
use if_chain::if_chain;
|
||||||
|
use rustc_errors::Applicability;
|
||||||
|
use rustc_hir::{Body, Expr, ExprKind, Pat, PatKind, QPath, StmtKind};
|
||||||
|
use rustc_lint::{LateContext, LateLintPass};
|
||||||
|
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||||
|
|
||||||
|
declare_clippy_lint! {
|
||||||
|
/// **What it does:** Checks for instances of `map(f)` where `f` is the identity function.
|
||||||
|
///
|
||||||
|
/// **Why is this bad?** It can be written more concisely without the call to `map`.
|
||||||
|
///
|
||||||
|
/// **Known problems:** None.
|
||||||
|
///
|
||||||
|
/// **Example:**
|
||||||
|
///
|
||||||
|
/// ```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();
|
||||||
|
/// ```
|
||||||
|
pub MAP_IDENTITY,
|
||||||
|
complexity,
|
||||||
|
"using iterator.map(|x| x)"
|
||||||
|
}
|
||||||
|
|
||||||
|
declare_lint_pass!(MapIdentity => [MAP_IDENTITY]);
|
||||||
|
|
||||||
|
impl<'tcx> LateLintPass<'tcx> for MapIdentity {
|
||||||
|
fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
|
||||||
|
if expr.span.from_expansion() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if_chain! {
|
||||||
|
if let Some([caller, func]) = get_map_argument(cx, expr);
|
||||||
|
if is_expr_identity_function(cx, func);
|
||||||
|
then {
|
||||||
|
span_lint_and_sugg(
|
||||||
|
cx,
|
||||||
|
MAP_IDENTITY,
|
||||||
|
expr.span.trim_start(caller.span).unwrap(),
|
||||||
|
"unnecessary map of the identity function",
|
||||||
|
"remove the call to `map`",
|
||||||
|
String::new(),
|
||||||
|
Applicability::MachineApplicable
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the arguments passed into map() if the expression is a method call to
|
||||||
|
/// map(). Otherwise, returns None.
|
||||||
|
fn get_map_argument<'a>(cx: &LateContext<'_>, expr: &'a Expr<'a>) -> Option<&'a [Expr<'a>]> {
|
||||||
|
if_chain! {
|
||||||
|
if let ExprKind::MethodCall(ref method, _, ref args, _) = expr.kind;
|
||||||
|
if args.len() == 2 && method.ident.as_str() == "map";
|
||||||
|
let caller_ty = cx.tables().expr_ty(&args[0]);
|
||||||
|
if match_trait_method(cx, expr, &paths::ITERATOR)
|
||||||
|
|| is_type_diagnostic_item(cx, caller_ty, sym!(result_type))
|
||||||
|
|| is_type_diagnostic_item(cx, caller_ty, sym!(option_type));
|
||||||
|
then {
|
||||||
|
Some(args)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Checks if an expression represents the identity function
|
||||||
|
/// Only examines closures and `std::convert::identity`
|
||||||
|
fn is_expr_identity_function(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
|
||||||
|
match expr.kind {
|
||||||
|
ExprKind::Closure(_, _, body_id, _, _) => is_body_identity_function(cx, cx.tcx.hir().body(body_id)),
|
||||||
|
ExprKind::Path(QPath::Resolved(_, ref path)) => match_path(path, &paths::STD_CONVERT_IDENTITY),
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Checks if a function's body represents the identity function
|
||||||
|
/// Looks for bodies of the form `|x| x`, `|x| return x`, `|x| { return x }` or `|x| {
|
||||||
|
/// return x; }`
|
||||||
|
fn is_body_identity_function(cx: &LateContext<'_>, func: &Body<'_>) -> bool {
|
||||||
|
let params = func.params;
|
||||||
|
let body = remove_blocks(&func.value);
|
||||||
|
|
||||||
|
// if there's less/more than one parameter, then it is not the identity function
|
||||||
|
if params.len() != 1 {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
match body.kind {
|
||||||
|
ExprKind::Path(QPath::Resolved(None, _)) => match_expr_param(cx, body, params[0].pat),
|
||||||
|
ExprKind::Ret(Some(ref ret_val)) => match_expr_param(cx, ret_val, params[0].pat),
|
||||||
|
ExprKind::Block(ref block, _) => {
|
||||||
|
if_chain! {
|
||||||
|
if block.stmts.len() == 1;
|
||||||
|
if let StmtKind::Semi(ref expr) | StmtKind::Expr(ref expr) = block.stmts[0].kind;
|
||||||
|
if let ExprKind::Ret(Some(ref ret_val)) = expr.kind;
|
||||||
|
then {
|
||||||
|
match_expr_param(cx, ret_val, params[0].pat)
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns true iff an expression returns the same thing as a parameter's pattern
|
||||||
|
fn match_expr_param(cx: &LateContext<'_>, expr: &Expr<'_>, pat: &Pat<'_>) -> bool {
|
||||||
|
if let PatKind::Binding(_, _, ident, _) = pat.kind {
|
||||||
|
match_var(expr, ident.name) && !(cx.tables().hir_owner == expr.hir_id.owner && is_adjusted(cx, expr))
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2044,7 +2044,7 @@ fn lint_clone_on_copy(cx: &LateContext<'_>, expr: &hir::Expr<'_>, arg: &hir::Exp
|
|||||||
}
|
}
|
||||||
span_lint_and_then(cx, CLONE_ON_COPY, expr.span, "using `clone` on a `Copy` type", |diag| {
|
span_lint_and_then(cx, CLONE_ON_COPY, expr.span, "using `clone` on a `Copy` type", |diag| {
|
||||||
if let Some((text, snip)) = snip {
|
if let Some((text, snip)) = snip {
|
||||||
diag.span_suggestion(expr.span, text, snip, Applicability::Unspecified);
|
diag.span_suggestion(expr.span, text, snip, Applicability::MachineApplicable);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,11 +3,11 @@ use rustc_ast::ast::LitKind;
|
|||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
use rustc_hir::intravisit::FnKind;
|
use rustc_hir::intravisit::FnKind;
|
||||||
use rustc_hir::{
|
use rustc_hir::{
|
||||||
def, BinOpKind, BindingAnnotation, Body, Expr, ExprKind, FnDecl, HirId, Mutability, PatKind, Stmt, StmtKind, Ty,
|
self as hir, def, BinOpKind, BindingAnnotation, Body, Expr, ExprKind, FnDecl, HirId, Mutability, PatKind, Stmt,
|
||||||
TyKind, UnOp,
|
StmtKind, TyKind, UnOp,
|
||||||
};
|
};
|
||||||
use rustc_lint::{LateContext, LateLintPass};
|
use rustc_lint::{LateContext, LateLintPass};
|
||||||
use rustc_middle::ty;
|
use rustc_middle::ty::{self, Ty};
|
||||||
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||||
use rustc_span::hygiene::DesugaringKind;
|
use rustc_span::hygiene::DesugaringKind;
|
||||||
use rustc_span::source_map::{ExpnKind, Span};
|
use rustc_span::source_map::{ExpnKind, Span};
|
||||||
@@ -371,8 +371,8 @@ impl<'tcx> LateLintPass<'tcx> for MiscLints {
|
|||||||
if op.is_comparison() {
|
if op.is_comparison() {
|
||||||
check_nan(cx, left, expr);
|
check_nan(cx, left, expr);
|
||||||
check_nan(cx, right, expr);
|
check_nan(cx, right, expr);
|
||||||
check_to_owned(cx, left, right);
|
check_to_owned(cx, left, right, true);
|
||||||
check_to_owned(cx, right, left);
|
check_to_owned(cx, right, left, false);
|
||||||
}
|
}
|
||||||
if (op == BinOpKind::Eq || op == BinOpKind::Ne) && (is_float(cx, left) || is_float(cx, right)) {
|
if (op == BinOpKind::Eq || op == BinOpKind::Ne) && (is_float(cx, left) || is_float(cx, right)) {
|
||||||
if is_allowed(cx, left) || is_allowed(cx, right) {
|
if is_allowed(cx, left) || is_allowed(cx, right) {
|
||||||
@@ -570,11 +570,30 @@ fn is_array(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
|
|||||||
matches!(&walk_ptrs_ty(cx.tables().expr_ty(expr)).kind, ty::Array(_, _))
|
matches!(&walk_ptrs_ty(cx.tables().expr_ty(expr)).kind, ty::Array(_, _))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_to_owned(cx: &LateContext<'_>, expr: &Expr<'_>, other: &Expr<'_>) {
|
fn check_to_owned(cx: &LateContext<'_>, expr: &Expr<'_>, other: &Expr<'_>, left: bool) {
|
||||||
|
#[derive(Default)]
|
||||||
|
struct EqImpl {
|
||||||
|
ty_eq_other: bool,
|
||||||
|
other_eq_ty: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl EqImpl {
|
||||||
|
fn is_implemented(&self) -> bool {
|
||||||
|
self.ty_eq_other || self.other_eq_ty
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn symmetric_partial_eq<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, other: Ty<'tcx>) -> Option<EqImpl> {
|
||||||
|
cx.tcx.lang_items().eq_trait().map(|def_id| EqImpl {
|
||||||
|
ty_eq_other: implements_trait(cx, ty, def_id, &[other.into()]),
|
||||||
|
other_eq_ty: implements_trait(cx, other, def_id, &[ty.into()]),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
let (arg_ty, snip) = match expr.kind {
|
let (arg_ty, snip) = match expr.kind {
|
||||||
ExprKind::MethodCall(.., ref args, _) if args.len() == 1 => {
|
ExprKind::MethodCall(.., ref args, _) if args.len() == 1 => {
|
||||||
if match_trait_method(cx, expr, &paths::TO_STRING) || match_trait_method(cx, expr, &paths::TO_OWNED) {
|
if match_trait_method(cx, expr, &paths::TO_STRING) || match_trait_method(cx, expr, &paths::TO_OWNED) {
|
||||||
(cx.tables().expr_ty_adjusted(&args[0]), snippet(cx, args[0].span, ".."))
|
(cx.tables().expr_ty(&args[0]), snippet(cx, args[0].span, ".."))
|
||||||
} else {
|
} else {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -582,7 +601,7 @@ fn check_to_owned(cx: &LateContext<'_>, expr: &Expr<'_>, other: &Expr<'_>) {
|
|||||||
ExprKind::Call(ref path, ref v) if v.len() == 1 => {
|
ExprKind::Call(ref path, ref v) if v.len() == 1 => {
|
||||||
if let ExprKind::Path(ref path) = path.kind {
|
if let ExprKind::Path(ref path) = path.kind {
|
||||||
if match_qpath(path, &["String", "from_str"]) || match_qpath(path, &["String", "from"]) {
|
if match_qpath(path, &["String", "from_str"]) || match_qpath(path, &["String", "from"]) {
|
||||||
(cx.tables().expr_ty_adjusted(&v[0]), snippet(cx, v[0].span, ".."))
|
(cx.tables().expr_ty(&v[0]), snippet(cx, v[0].span, ".."))
|
||||||
} else {
|
} else {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -593,28 +612,19 @@ fn check_to_owned(cx: &LateContext<'_>, expr: &Expr<'_>, other: &Expr<'_>) {
|
|||||||
_ => return,
|
_ => return,
|
||||||
};
|
};
|
||||||
|
|
||||||
let other_ty = cx.tables().expr_ty_adjusted(other);
|
let other_ty = cx.tables().expr_ty(other);
|
||||||
let partial_eq_trait_id = match cx.tcx.lang_items().eq_trait() {
|
|
||||||
Some(id) => id,
|
|
||||||
None => return,
|
|
||||||
};
|
|
||||||
|
|
||||||
let deref_arg_impl_partial_eq_other = arg_ty.builtin_deref(true).map_or(false, |tam| {
|
let without_deref = symmetric_partial_eq(cx, arg_ty, other_ty).unwrap_or_default();
|
||||||
implements_trait(cx, tam.ty, partial_eq_trait_id, &[other_ty.into()])
|
let with_deref = arg_ty
|
||||||
});
|
.builtin_deref(true)
|
||||||
let arg_impl_partial_eq_deref_other = other_ty.builtin_deref(true).map_or(false, |tam| {
|
.and_then(|tam| symmetric_partial_eq(cx, tam.ty, other_ty))
|
||||||
implements_trait(cx, arg_ty, partial_eq_trait_id, &[tam.ty.into()])
|
.unwrap_or_default();
|
||||||
});
|
|
||||||
let arg_impl_partial_eq_other = implements_trait(cx, arg_ty, partial_eq_trait_id, &[other_ty.into()]);
|
|
||||||
|
|
||||||
if !deref_arg_impl_partial_eq_other && !arg_impl_partial_eq_deref_other && !arg_impl_partial_eq_other {
|
if !with_deref.is_implemented() && !without_deref.is_implemented() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let other_gets_derefed = match other.kind {
|
let other_gets_derefed = matches!(other.kind, ExprKind::Unary(UnOp::UnDeref, _));
|
||||||
ExprKind::Unary(UnOp::UnDeref, _) => true,
|
|
||||||
_ => false,
|
|
||||||
};
|
|
||||||
|
|
||||||
let lint_span = if other_gets_derefed {
|
let lint_span = if other_gets_derefed {
|
||||||
expr.span.to(other.span)
|
expr.span.to(other.span)
|
||||||
@@ -634,18 +644,34 @@ fn check_to_owned(cx: &LateContext<'_>, expr: &Expr<'_>, other: &Expr<'_>) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let try_hint = if deref_arg_impl_partial_eq_other {
|
let expr_snip;
|
||||||
// suggest deref on the left
|
let eq_impl;
|
||||||
format!("*{}", snip)
|
if with_deref.is_implemented() {
|
||||||
|
expr_snip = format!("*{}", snip);
|
||||||
|
eq_impl = with_deref;
|
||||||
} else {
|
} else {
|
||||||
// suggest dropping the to_owned on the left
|
expr_snip = snip.to_string();
|
||||||
snip.to_string()
|
eq_impl = without_deref;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let span;
|
||||||
|
let hint;
|
||||||
|
if (eq_impl.ty_eq_other && left) || (eq_impl.other_eq_ty && !left) {
|
||||||
|
span = expr.span;
|
||||||
|
hint = expr_snip;
|
||||||
|
} else {
|
||||||
|
span = expr.span.to(other.span);
|
||||||
|
if eq_impl.ty_eq_other {
|
||||||
|
hint = format!("{} == {}", expr_snip, snippet(cx, other.span, ".."));
|
||||||
|
} else {
|
||||||
|
hint = format!("{} == {}", snippet(cx, other.span, ".."), expr_snip);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
diag.span_suggestion(
|
diag.span_suggestion(
|
||||||
lint_span,
|
span,
|
||||||
"try",
|
"try",
|
||||||
try_hint,
|
hint,
|
||||||
Applicability::MachineApplicable, // snippet
|
Applicability::MachineApplicable, // snippet
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
@@ -694,7 +720,7 @@ fn non_macro_local(cx: &LateContext<'_>, res: def::Res) -> bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_cast(cx: &LateContext<'_>, span: Span, e: &Expr<'_>, ty: &Ty<'_>) {
|
fn check_cast(cx: &LateContext<'_>, span: Span, e: &Expr<'_>, ty: &hir::Ty<'_>) {
|
||||||
if_chain! {
|
if_chain! {
|
||||||
if let TyKind::Ptr(ref mut_ty) = ty.kind;
|
if let TyKind::Ptr(ref mut_ty) = ty.kind;
|
||||||
if let ExprKind::Lit(ref lit) = e.kind;
|
if let ExprKind::Lit(ref lit) = e.kind;
|
||||||
|
|||||||
@@ -40,9 +40,8 @@ declare_clippy_lint! {
|
|||||||
/// assert_eq!(v.len(), 42);
|
/// assert_eq!(v.len(), 42);
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
///
|
/// should be
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// // should be
|
|
||||||
/// fn foo(v: &[i32]) {
|
/// fn foo(v: &[i32]) {
|
||||||
/// assert_eq!(v.len(), 42);
|
/// assert_eq!(v.len(), 42);
|
||||||
/// }
|
/// }
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
use crate::consts::{constant, Constant};
|
use crate::consts::{constant, Constant};
|
||||||
use crate::utils::{is_expn_of, match_def_path, match_type, paths, span_lint, span_lint_and_help};
|
use crate::utils::{match_def_path, paths, span_lint, span_lint_and_help};
|
||||||
use if_chain::if_chain;
|
use if_chain::if_chain;
|
||||||
use rustc_ast::ast::{LitKind, StrStyle};
|
use rustc_ast::ast::{LitKind, StrStyle};
|
||||||
use rustc_data_structures::fx::FxHashSet;
|
use rustc_data_structures::fx::FxHashSet;
|
||||||
use rustc_hir::{Block, BorrowKind, Crate, Expr, ExprKind, HirId};
|
use rustc_hir::{BorrowKind, Expr, ExprKind, HirId};
|
||||||
use rustc_lint::{LateContext, LateLintPass};
|
use rustc_lint::{LateContext, LateLintPass};
|
||||||
use rustc_session::{declare_tool_lint, impl_lint_pass};
|
use rustc_session::{declare_tool_lint, impl_lint_pass};
|
||||||
use rustc_span::source_map::{BytePos, Span};
|
use rustc_span::source_map::{BytePos, Span};
|
||||||
@@ -46,66 +46,15 @@ declare_clippy_lint! {
|
|||||||
"trivial regular expressions"
|
"trivial regular expressions"
|
||||||
}
|
}
|
||||||
|
|
||||||
declare_clippy_lint! {
|
|
||||||
/// **What it does:** Checks for usage of `regex!(_)` which (as of now) is
|
|
||||||
/// usually slower than `Regex::new(_)` unless called in a loop (which is a bad
|
|
||||||
/// idea anyway).
|
|
||||||
///
|
|
||||||
/// **Why is this bad?** Performance, at least for now. The macro version is
|
|
||||||
/// likely to catch up long-term, but for now the dynamic version is faster.
|
|
||||||
///
|
|
||||||
/// **Known problems:** None.
|
|
||||||
///
|
|
||||||
/// **Example:**
|
|
||||||
/// ```ignore
|
|
||||||
/// regex!("foo|bar")
|
|
||||||
/// ```
|
|
||||||
pub REGEX_MACRO,
|
|
||||||
style,
|
|
||||||
"use of `regex!(_)` instead of `Regex::new(_)`"
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Default)]
|
#[derive(Clone, Default)]
|
||||||
pub struct Regex {
|
pub struct Regex {
|
||||||
spans: FxHashSet<Span>,
|
spans: FxHashSet<Span>,
|
||||||
last: Option<HirId>,
|
last: Option<HirId>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_lint_pass!(Regex => [INVALID_REGEX, REGEX_MACRO, TRIVIAL_REGEX]);
|
impl_lint_pass!(Regex => [INVALID_REGEX, TRIVIAL_REGEX]);
|
||||||
|
|
||||||
impl<'tcx> LateLintPass<'tcx> for Regex {
|
impl<'tcx> LateLintPass<'tcx> for Regex {
|
||||||
fn check_crate(&mut self, _: &LateContext<'tcx>, _: &'tcx Crate<'_>) {
|
|
||||||
self.spans.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn check_block(&mut self, cx: &LateContext<'tcx>, block: &'tcx Block<'_>) {
|
|
||||||
if_chain! {
|
|
||||||
if self.last.is_none();
|
|
||||||
if let Some(ref expr) = block.expr;
|
|
||||||
if match_type(cx, cx.tables().expr_ty(expr), &paths::REGEX);
|
|
||||||
if let Some(span) = is_expn_of(expr.span, "regex");
|
|
||||||
then {
|
|
||||||
if !self.spans.contains(&span) {
|
|
||||||
span_lint(
|
|
||||||
cx,
|
|
||||||
REGEX_MACRO,
|
|
||||||
span,
|
|
||||||
"`regex!(_)` found. \
|
|
||||||
Please use `Regex::new(_)`, which is faster for now."
|
|
||||||
);
|
|
||||||
self.spans.insert(span);
|
|
||||||
}
|
|
||||||
self.last = Some(block.hir_id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn check_block_post(&mut self, _: &LateContext<'tcx>, block: &'tcx Block<'_>) {
|
|
||||||
if self.last.map_or(false, |id| block.hir_id == id) {
|
|
||||||
self.last = None;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
|
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
|
||||||
if_chain! {
|
if_chain! {
|
||||||
if let ExprKind::Call(ref fun, ref args) = expr.kind;
|
if let ExprKind::Call(ref fun, ref args) = expr.kind;
|
||||||
|
|||||||
@@ -72,8 +72,8 @@ impl EarlyLintPass for UnnestedOrPatterns {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn lint_unnested_or_patterns(cx: &EarlyContext<'_>, pat: &Pat) {
|
fn lint_unnested_or_patterns(cx: &EarlyContext<'_>, pat: &Pat) {
|
||||||
if !cx.sess.opts.unstable_features.is_nightly_build() {
|
if !cx.sess.features_untracked().or_patterns {
|
||||||
// User cannot do `#![feature(or_patterns)]`, so bail.
|
// Do not suggest nesting the patterns if the feature `or_patterns` is not enabled.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -98,7 +98,6 @@ pub const RANGE_TO_STD: [&str; 3] = ["std", "ops", "RangeTo"];
|
|||||||
pub const RC: [&str; 3] = ["alloc", "rc", "Rc"];
|
pub const RC: [&str; 3] = ["alloc", "rc", "Rc"];
|
||||||
pub const RC_PTR_EQ: [&str; 4] = ["alloc", "rc", "Rc", "ptr_eq"];
|
pub const RC_PTR_EQ: [&str; 4] = ["alloc", "rc", "Rc", "ptr_eq"];
|
||||||
pub const RECEIVER: [&str; 4] = ["std", "sync", "mpsc", "Receiver"];
|
pub const RECEIVER: [&str; 4] = ["std", "sync", "mpsc", "Receiver"];
|
||||||
pub const REGEX: [&str; 3] = ["regex", "re_unicode", "Regex"];
|
|
||||||
pub const REGEX_BUILDER_NEW: [&str; 5] = ["regex", "re_builder", "unicode", "RegexBuilder", "new"];
|
pub const REGEX_BUILDER_NEW: [&str; 5] = ["regex", "re_builder", "unicode", "RegexBuilder", "new"];
|
||||||
pub const REGEX_BYTES_BUILDER_NEW: [&str; 5] = ["regex", "re_builder", "bytes", "RegexBuilder", "new"];
|
pub const REGEX_BYTES_BUILDER_NEW: [&str; 5] = ["regex", "re_builder", "bytes", "RegexBuilder", "new"];
|
||||||
pub const REGEX_BYTES_NEW: [&str; 4] = ["regex", "re_bytes", "Regex", "new"];
|
pub const REGEX_BYTES_NEW: [&str; 4] = ["regex", "re_bytes", "Regex", "new"];
|
||||||
|
|||||||
@@ -325,22 +325,22 @@ pub fn make_unop(op: &str, expr: Sugg<'_>) -> Sugg<'static> {
|
|||||||
/// parenthesis will always be added for a mix of these.
|
/// parenthesis will always be added for a mix of these.
|
||||||
pub fn make_assoc(op: AssocOp, lhs: &Sugg<'_>, rhs: &Sugg<'_>) -> Sugg<'static> {
|
pub fn make_assoc(op: AssocOp, lhs: &Sugg<'_>, rhs: &Sugg<'_>) -> Sugg<'static> {
|
||||||
/// Returns `true` if the operator is a shift operator `<<` or `>>`.
|
/// Returns `true` if the operator is a shift operator `<<` or `>>`.
|
||||||
fn is_shift(op: &AssocOp) -> bool {
|
fn is_shift(op: AssocOp) -> bool {
|
||||||
matches!(*op, AssocOp::ShiftLeft | AssocOp::ShiftRight)
|
matches!(op, AssocOp::ShiftLeft | AssocOp::ShiftRight)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns `true` if the operator is a arithmetic operator
|
/// Returns `true` if the operator is a arithmetic operator
|
||||||
/// (i.e., `+`, `-`, `*`, `/`, `%`).
|
/// (i.e., `+`, `-`, `*`, `/`, `%`).
|
||||||
fn is_arith(op: &AssocOp) -> bool {
|
fn is_arith(op: AssocOp) -> bool {
|
||||||
matches!(
|
matches!(
|
||||||
*op,
|
op,
|
||||||
AssocOp::Add | AssocOp::Subtract | AssocOp::Multiply | AssocOp::Divide | AssocOp::Modulus
|
AssocOp::Add | AssocOp::Subtract | AssocOp::Multiply | AssocOp::Divide | AssocOp::Modulus
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns `true` if the operator `op` needs parenthesis with the operator
|
/// Returns `true` if the operator `op` needs parenthesis with the operator
|
||||||
/// `other` in the direction `dir`.
|
/// `other` in the direction `dir`.
|
||||||
fn needs_paren(op: &AssocOp, other: &AssocOp, dir: Associativity) -> bool {
|
fn needs_paren(op: AssocOp, other: AssocOp, dir: Associativity) -> bool {
|
||||||
other.precedence() < op.precedence()
|
other.precedence() < op.precedence()
|
||||||
|| (other.precedence() == op.precedence()
|
|| (other.precedence() == op.precedence()
|
||||||
&& ((op != other && associativity(op) != dir)
|
&& ((op != other && associativity(op) != dir)
|
||||||
@@ -349,14 +349,14 @@ pub fn make_assoc(op: AssocOp, lhs: &Sugg<'_>, rhs: &Sugg<'_>) -> Sugg<'static>
|
|||||||
|| is_shift(other) && is_arith(op)
|
|| is_shift(other) && is_arith(op)
|
||||||
}
|
}
|
||||||
|
|
||||||
let lhs_paren = if let Sugg::BinOp(ref lop, _) = *lhs {
|
let lhs_paren = if let Sugg::BinOp(lop, _) = *lhs {
|
||||||
needs_paren(&op, lop, Associativity::Left)
|
needs_paren(op, lop, Associativity::Left)
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
};
|
};
|
||||||
|
|
||||||
let rhs_paren = if let Sugg::BinOp(ref rop, _) = *rhs {
|
let rhs_paren = if let Sugg::BinOp(rop, _) = *rhs {
|
||||||
needs_paren(&op, rop, Associativity::Right)
|
needs_paren(op, rop, Associativity::Right)
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
};
|
};
|
||||||
@@ -424,13 +424,13 @@ enum Associativity {
|
|||||||
/// they are considered
|
/// they are considered
|
||||||
/// associative.
|
/// associative.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
fn associativity(op: &AssocOp) -> Associativity {
|
fn associativity(op: AssocOp) -> Associativity {
|
||||||
use rustc_ast::util::parser::AssocOp::{
|
use rustc_ast::util::parser::AssocOp::{
|
||||||
Add, As, Assign, AssignOp, BitAnd, BitOr, BitXor, Colon, Divide, DotDot, DotDotEq, Equal, Greater,
|
Add, As, Assign, AssignOp, BitAnd, BitOr, BitXor, Colon, Divide, DotDot, DotDotEq, Equal, Greater,
|
||||||
GreaterEqual, LAnd, LOr, Less, LessEqual, Modulus, Multiply, NotEqual, ShiftLeft, ShiftRight, Subtract,
|
GreaterEqual, LAnd, LOr, Less, LessEqual, Modulus, Multiply, NotEqual, ShiftLeft, ShiftRight, Subtract,
|
||||||
};
|
};
|
||||||
|
|
||||||
match *op {
|
match op {
|
||||||
Assign | AssignOp(_) => Associativity::Right,
|
Assign | AssignOp(_) => Associativity::Right,
|
||||||
Add | BitAnd | BitOr | BitXor | LAnd | LOr | Multiply | As | Colon => Associativity::Both,
|
Add | BitAnd | BitOr | BitXor | LAnd | LOr | Multiply | As | Colon => Associativity::Both,
|
||||||
Divide | Equal | Greater | GreaterEqual | Less | LessEqual | Modulus | NotEqual | ShiftLeft | ShiftRight
|
Divide | Equal | Greater | GreaterEqual | Less | LessEqual | Modulus | NotEqual | ShiftLeft | ShiftRight
|
||||||
|
|||||||
@@ -23,7 +23,11 @@ declare_clippy_lint! {
|
|||||||
///
|
///
|
||||||
/// **Example:**
|
/// **Example:**
|
||||||
/// ```rust
|
/// ```rust
|
||||||
|
/// // Bad
|
||||||
/// println!("");
|
/// println!("");
|
||||||
|
///
|
||||||
|
/// // Good
|
||||||
|
/// println!();
|
||||||
/// ```
|
/// ```
|
||||||
pub PRINTLN_EMPTY_STRING,
|
pub PRINTLN_EMPTY_STRING,
|
||||||
style,
|
style,
|
||||||
@@ -32,8 +36,7 @@ declare_clippy_lint! {
|
|||||||
|
|
||||||
declare_clippy_lint! {
|
declare_clippy_lint! {
|
||||||
/// **What it does:** This lint warns when you use `print!()` with a format
|
/// **What it does:** This lint warns when you use `print!()` with a format
|
||||||
/// string that
|
/// string that ends in a newline.
|
||||||
/// ends in a newline.
|
|
||||||
///
|
///
|
||||||
/// **Why is this bad?** You should use `println!()` instead, which appends the
|
/// **Why is this bad?** You should use `println!()` instead, which appends the
|
||||||
/// newline.
|
/// newline.
|
||||||
@@ -125,7 +128,12 @@ declare_clippy_lint! {
|
|||||||
/// ```rust
|
/// ```rust
|
||||||
/// # use std::fmt::Write;
|
/// # use std::fmt::Write;
|
||||||
/// # let mut buf = String::new();
|
/// # let mut buf = String::new();
|
||||||
|
///
|
||||||
|
/// // Bad
|
||||||
/// writeln!(buf, "");
|
/// writeln!(buf, "");
|
||||||
|
///
|
||||||
|
/// // Good
|
||||||
|
/// writeln!(buf);
|
||||||
/// ```
|
/// ```
|
||||||
pub WRITELN_EMPTY_STRING,
|
pub WRITELN_EMPTY_STRING,
|
||||||
style,
|
style,
|
||||||
@@ -147,7 +155,12 @@ declare_clippy_lint! {
|
|||||||
/// # use std::fmt::Write;
|
/// # use std::fmt::Write;
|
||||||
/// # let mut buf = String::new();
|
/// # let mut buf = String::new();
|
||||||
/// # let name = "World";
|
/// # let name = "World";
|
||||||
|
///
|
||||||
|
/// // Bad
|
||||||
/// write!(buf, "Hello {}!\n", name);
|
/// write!(buf, "Hello {}!\n", name);
|
||||||
|
///
|
||||||
|
/// // Good
|
||||||
|
/// writeln!(buf, "Hello {}!", name);
|
||||||
/// ```
|
/// ```
|
||||||
pub WRITE_WITH_NEWLINE,
|
pub WRITE_WITH_NEWLINE,
|
||||||
style,
|
style,
|
||||||
@@ -168,7 +181,12 @@ declare_clippy_lint! {
|
|||||||
/// ```rust
|
/// ```rust
|
||||||
/// # use std::fmt::Write;
|
/// # use std::fmt::Write;
|
||||||
/// # let mut buf = String::new();
|
/// # let mut buf = String::new();
|
||||||
|
///
|
||||||
|
/// // Bad
|
||||||
/// writeln!(buf, "{}", "foo");
|
/// writeln!(buf, "{}", "foo");
|
||||||
|
///
|
||||||
|
/// // Good
|
||||||
|
/// writeln!(buf, "foo");
|
||||||
/// ```
|
/// ```
|
||||||
pub WRITE_LITERAL,
|
pub WRITE_LITERAL,
|
||||||
style,
|
style,
|
||||||
@@ -279,12 +297,11 @@ impl EarlyLintPass for Write {
|
|||||||
if let (Some(fmt_str), expr) = self.check_tts(cx, &mac.args.inner_tokens(), true) {
|
if let (Some(fmt_str), expr) = self.check_tts(cx, &mac.args.inner_tokens(), true) {
|
||||||
if fmt_str.symbol == Symbol::intern("") {
|
if fmt_str.symbol == Symbol::intern("") {
|
||||||
let mut applicability = Applicability::MachineApplicable;
|
let mut applicability = Applicability::MachineApplicable;
|
||||||
let suggestion = match expr {
|
let suggestion = if let Some(e) = expr {
|
||||||
Some(expr) => snippet_with_applicability(cx, expr.span, "v", &mut applicability),
|
snippet_with_applicability(cx, e.span, "v", &mut applicability)
|
||||||
None => {
|
} else {
|
||||||
applicability = Applicability::HasPlaceholders;
|
applicability = Applicability::HasPlaceholders;
|
||||||
Cow::Borrowed("v")
|
Cow::Borrowed("v")
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
span_lint_and_sugg(
|
span_lint_and_sugg(
|
||||||
|
|||||||
@@ -80,6 +80,13 @@ pub static ref ALL_LINTS: Vec<Lint> = vec![
|
|||||||
deprecation: None,
|
deprecation: None,
|
||||||
module: "blacklisted_name",
|
module: "blacklisted_name",
|
||||||
},
|
},
|
||||||
|
Lint {
|
||||||
|
name: "blanket_clippy_restriction_lints",
|
||||||
|
group: "style",
|
||||||
|
desc: "enabling the complete restriction group",
|
||||||
|
deprecation: None,
|
||||||
|
module: "attrs",
|
||||||
|
},
|
||||||
Lint {
|
Lint {
|
||||||
name: "blocks_in_if_conditions",
|
name: "blocks_in_if_conditions",
|
||||||
group: "style",
|
group: "style",
|
||||||
@@ -1144,6 +1151,13 @@ pub static ref ALL_LINTS: Vec<Lint> = vec![
|
|||||||
deprecation: None,
|
deprecation: None,
|
||||||
module: "methods",
|
module: "methods",
|
||||||
},
|
},
|
||||||
|
Lint {
|
||||||
|
name: "map_identity",
|
||||||
|
group: "complexity",
|
||||||
|
desc: "using iterator.map(|x| x)",
|
||||||
|
deprecation: None,
|
||||||
|
module: "map_identity",
|
||||||
|
},
|
||||||
Lint {
|
Lint {
|
||||||
name: "map_unwrap_or",
|
name: "map_unwrap_or",
|
||||||
group: "pedantic",
|
group: "pedantic",
|
||||||
@@ -1851,13 +1865,6 @@ pub static ref ALL_LINTS: Vec<Lint> = vec![
|
|||||||
deprecation: None,
|
deprecation: None,
|
||||||
module: "reference",
|
module: "reference",
|
||||||
},
|
},
|
||||||
Lint {
|
|
||||||
name: "regex_macro",
|
|
||||||
group: "style",
|
|
||||||
desc: "use of `regex!(_)` instead of `Regex::new(_)`",
|
|
||||||
deprecation: None,
|
|
||||||
module: "regex",
|
|
||||||
},
|
|
||||||
Lint {
|
Lint {
|
||||||
name: "rest_pat_in_fully_bound_structs",
|
name: "rest_pat_in_fully_bound_structs",
|
||||||
group: "restriction",
|
group: "restriction",
|
||||||
|
|||||||
@@ -155,9 +155,6 @@ fn run_ui_toml(config: &mut compiletest::Config) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn run_ui_cargo(config: &mut compiletest::Config) {
|
fn run_ui_cargo(config: &mut compiletest::Config) {
|
||||||
if cargo::is_rustc_test_suite() {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
fn run_tests(
|
fn run_tests(
|
||||||
config: &compiletest::Config,
|
config: &compiletest::Config,
|
||||||
filter: &Option<String>,
|
filter: &Option<String>,
|
||||||
|
|||||||
109
tests/ui-cargo/multiple_crate_versions/fail/Cargo.lock
generated
Normal file
109
tests/ui-cargo/multiple_crate_versions/fail/Cargo.lock
generated
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
[[package]]
|
||||||
|
name = "ansi_term"
|
||||||
|
version = "0.11.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
|
||||||
|
dependencies = [
|
||||||
|
"winapi 0.3.9",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bitflags"
|
||||||
|
version = "0.9.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cfg-if"
|
||||||
|
version = "0.1.10"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ctrlc"
|
||||||
|
version = "3.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "653abc99aa905f693d89df4797fadc08085baee379db92be9f2496cefe8a6f2c"
|
||||||
|
dependencies = [
|
||||||
|
"kernel32-sys",
|
||||||
|
"nix",
|
||||||
|
"winapi 0.2.8",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "kernel32-sys"
|
||||||
|
version = "0.2.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
|
||||||
|
dependencies = [
|
||||||
|
"winapi 0.2.8",
|
||||||
|
"winapi-build",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libc"
|
||||||
|
version = "0.2.71"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9457b06509d27052635f90d6466700c65095fdf75409b3fbdd903e988b886f49"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "multiple_crate_versions"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"ansi_term",
|
||||||
|
"ctrlc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "nix"
|
||||||
|
version = "0.9.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a2c5afeb0198ec7be8569d666644b574345aad2e95a53baf3a532da3e0f3fb32"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
|
"cfg-if",
|
||||||
|
"libc",
|
||||||
|
"void",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "void"
|
||||||
|
version = "1.0.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi"
|
||||||
|
version = "0.2.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi"
|
||||||
|
version = "0.3.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
|
||||||
|
dependencies = [
|
||||||
|
"winapi-i686-pc-windows-gnu",
|
||||||
|
"winapi-x86_64-pc-windows-gnu",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi-build"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi-i686-pc-windows-gnu"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi-x86_64-pc-windows-gnu"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
error: multiple versions for dependency `winapi`: 0.2.8, 0.3.8
|
error: multiple versions for dependency `winapi`: 0.2.8, 0.3.9
|
||||||
|
|
|
|
||||||
= note: `-D clippy::multiple-crate-versions` implied by `-D warnings`
|
= note: `-D clippy::multiple-crate-versions` implied by `-D warnings`
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,11 @@
|
|||||||
#![warn(clippy::inline_always, clippy::deprecated_semver)]
|
#![warn(clippy::inline_always, clippy::deprecated_semver)]
|
||||||
#![allow(clippy::assertions_on_constants)]
|
#![allow(clippy::assertions_on_constants)]
|
||||||
|
// Test that the whole restriction group is not enabled
|
||||||
|
#![warn(clippy::restriction)]
|
||||||
|
#![deny(clippy::restriction)]
|
||||||
|
#![forbid(clippy::restriction)]
|
||||||
|
#![allow(clippy::missing_docs_in_private_items, clippy::panic, clippy::unreachable)]
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn test_attr_lint() {
|
fn test_attr_lint() {
|
||||||
assert!(true)
|
assert!(true)
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
error: you have declared `#[inline(always)]` on `test_attr_lint`. This is usually a bad idea
|
error: you have declared `#[inline(always)]` on `test_attr_lint`. This is usually a bad idea
|
||||||
--> $DIR/attrs.rs:3:1
|
--> $DIR/attrs.rs:9:1
|
||||||
|
|
|
|
||||||
LL | #[inline(always)]
|
LL | #[inline(always)]
|
||||||
| ^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^
|
||||||
@@ -7,7 +7,7 @@ LL | #[inline(always)]
|
|||||||
= note: `-D clippy::inline-always` implied by `-D warnings`
|
= note: `-D clippy::inline-always` implied by `-D warnings`
|
||||||
|
|
||||||
error: the since field must contain a semver-compliant version
|
error: the since field must contain a semver-compliant version
|
||||||
--> $DIR/attrs.rs:23:14
|
--> $DIR/attrs.rs:29:14
|
||||||
|
|
|
|
||||||
LL | #[deprecated(since = "forever")]
|
LL | #[deprecated(since = "forever")]
|
||||||
| ^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^
|
||||||
@@ -15,10 +15,35 @@ LL | #[deprecated(since = "forever")]
|
|||||||
= note: `-D clippy::deprecated-semver` implied by `-D warnings`
|
= note: `-D clippy::deprecated-semver` implied by `-D warnings`
|
||||||
|
|
||||||
error: the since field must contain a semver-compliant version
|
error: the since field must contain a semver-compliant version
|
||||||
--> $DIR/attrs.rs:26:14
|
--> $DIR/attrs.rs:32:14
|
||||||
|
|
|
|
||||||
LL | #[deprecated(since = "1")]
|
LL | #[deprecated(since = "1")]
|
||||||
| ^^^^^^^^^^^
|
| ^^^^^^^^^^^
|
||||||
|
|
||||||
error: aborting due to 3 previous errors
|
error: restriction lints are not meant to be all enabled
|
||||||
|
--> $DIR/attrs.rs:4:9
|
||||||
|
|
|
||||||
|
LL | #![warn(clippy::restriction)]
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: `-D clippy::blanket-clippy-restriction-lints` implied by `-D warnings`
|
||||||
|
= help: try enabling only the lints you really need
|
||||||
|
|
||||||
|
error: restriction lints are not meant to be all enabled
|
||||||
|
--> $DIR/attrs.rs:5:9
|
||||||
|
|
|
||||||
|
LL | #![deny(clippy::restriction)]
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= help: try enabling only the lints you really need
|
||||||
|
|
||||||
|
error: restriction lints are not meant to be all enabled
|
||||||
|
--> $DIR/attrs.rs:6:11
|
||||||
|
|
|
||||||
|
LL | #![forbid(clippy::restriction)]
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= help: try enabling only the lints you really need
|
||||||
|
|
||||||
|
error: aborting due to 6 previous errors
|
||||||
|
|
||||||
|
|||||||
40
tests/ui/clone_on_copy.fixed
Normal file
40
tests/ui/clone_on_copy.fixed
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
// run-rustfix
|
||||||
|
|
||||||
|
#![allow(
|
||||||
|
unused,
|
||||||
|
clippy::redundant_clone,
|
||||||
|
clippy::deref_addrof,
|
||||||
|
clippy::no_effect,
|
||||||
|
clippy::unnecessary_operation
|
||||||
|
)]
|
||||||
|
|
||||||
|
use std::cell::RefCell;
|
||||||
|
use std::rc::{self, Rc};
|
||||||
|
use std::sync::{self, Arc};
|
||||||
|
|
||||||
|
fn main() {}
|
||||||
|
|
||||||
|
fn is_ascii(ch: char) -> bool {
|
||||||
|
ch.is_ascii()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn clone_on_copy() {
|
||||||
|
42;
|
||||||
|
|
||||||
|
vec![1].clone(); // ok, not a Copy type
|
||||||
|
Some(vec![1]).clone(); // ok, not a Copy type
|
||||||
|
*(&42);
|
||||||
|
|
||||||
|
let rc = RefCell::new(0);
|
||||||
|
*rc.borrow();
|
||||||
|
|
||||||
|
// Issue #4348
|
||||||
|
let mut x = 43;
|
||||||
|
let _ = &x.clone(); // ok, getting a ref
|
||||||
|
'a'.clone().make_ascii_uppercase(); // ok, clone and then mutate
|
||||||
|
is_ascii('z');
|
||||||
|
|
||||||
|
// Issue #5436
|
||||||
|
let mut vec = Vec::new();
|
||||||
|
vec.push(42);
|
||||||
|
}
|
||||||
40
tests/ui/clone_on_copy.rs
Normal file
40
tests/ui/clone_on_copy.rs
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
// run-rustfix
|
||||||
|
|
||||||
|
#![allow(
|
||||||
|
unused,
|
||||||
|
clippy::redundant_clone,
|
||||||
|
clippy::deref_addrof,
|
||||||
|
clippy::no_effect,
|
||||||
|
clippy::unnecessary_operation
|
||||||
|
)]
|
||||||
|
|
||||||
|
use std::cell::RefCell;
|
||||||
|
use std::rc::{self, Rc};
|
||||||
|
use std::sync::{self, Arc};
|
||||||
|
|
||||||
|
fn main() {}
|
||||||
|
|
||||||
|
fn is_ascii(ch: char) -> bool {
|
||||||
|
ch.is_ascii()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn clone_on_copy() {
|
||||||
|
42.clone();
|
||||||
|
|
||||||
|
vec![1].clone(); // ok, not a Copy type
|
||||||
|
Some(vec![1]).clone(); // ok, not a Copy type
|
||||||
|
(&42).clone();
|
||||||
|
|
||||||
|
let rc = RefCell::new(0);
|
||||||
|
rc.borrow().clone();
|
||||||
|
|
||||||
|
// Issue #4348
|
||||||
|
let mut x = 43;
|
||||||
|
let _ = &x.clone(); // ok, getting a ref
|
||||||
|
'a'.clone().make_ascii_uppercase(); // ok, clone and then mutate
|
||||||
|
is_ascii('z'.clone());
|
||||||
|
|
||||||
|
// Issue #5436
|
||||||
|
let mut vec = Vec::new();
|
||||||
|
vec.push(42.clone());
|
||||||
|
}
|
||||||
34
tests/ui/clone_on_copy.stderr
Normal file
34
tests/ui/clone_on_copy.stderr
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
error: using `clone` on a `Copy` type
|
||||||
|
--> $DIR/clone_on_copy.rs:22:5
|
||||||
|
|
|
||||||
|
LL | 42.clone();
|
||||||
|
| ^^^^^^^^^^ help: try removing the `clone` call: `42`
|
||||||
|
|
|
||||||
|
= note: `-D clippy::clone-on-copy` implied by `-D warnings`
|
||||||
|
|
||||||
|
error: using `clone` on a `Copy` type
|
||||||
|
--> $DIR/clone_on_copy.rs:26:5
|
||||||
|
|
|
||||||
|
LL | (&42).clone();
|
||||||
|
| ^^^^^^^^^^^^^ help: try dereferencing it: `*(&42)`
|
||||||
|
|
||||||
|
error: using `clone` on a `Copy` type
|
||||||
|
--> $DIR/clone_on_copy.rs:29:5
|
||||||
|
|
|
||||||
|
LL | rc.borrow().clone();
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^ help: try dereferencing it: `*rc.borrow()`
|
||||||
|
|
||||||
|
error: using `clone` on a `Copy` type
|
||||||
|
--> $DIR/clone_on_copy.rs:35:14
|
||||||
|
|
|
||||||
|
LL | is_ascii('z'.clone());
|
||||||
|
| ^^^^^^^^^^^ help: try removing the `clone` call: `'z'`
|
||||||
|
|
||||||
|
error: using `clone` on a `Copy` type
|
||||||
|
--> $DIR/clone_on_copy.rs:39:14
|
||||||
|
|
|
||||||
|
LL | vec.push(42.clone());
|
||||||
|
| ^^^^^^^^^^ help: try removing the `clone` call: `42`
|
||||||
|
|
||||||
|
error: aborting due to 5 previous errors
|
||||||
|
|
||||||
93
tests/ui/cmp_owned/asymmetric_partial_eq.fixed
Normal file
93
tests/ui/cmp_owned/asymmetric_partial_eq.fixed
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
// run-rustfix
|
||||||
|
#![allow(unused, clippy::redundant_clone)] // See #5700
|
||||||
|
|
||||||
|
// Define the types in each module to avoid trait impls leaking between modules.
|
||||||
|
macro_rules! impl_types {
|
||||||
|
() => {
|
||||||
|
#[derive(PartialEq)]
|
||||||
|
pub struct Owned;
|
||||||
|
|
||||||
|
pub struct Borrowed;
|
||||||
|
|
||||||
|
impl ToOwned for Borrowed {
|
||||||
|
type Owned = Owned;
|
||||||
|
fn to_owned(&self) -> Owned {
|
||||||
|
Owned {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::borrow::Borrow<Borrowed> for Owned {
|
||||||
|
fn borrow(&self) -> &Borrowed {
|
||||||
|
static VALUE: Borrowed = Borrowed {};
|
||||||
|
&VALUE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only Borrowed == Owned is implemented
|
||||||
|
mod borrowed_eq_owned {
|
||||||
|
impl_types!();
|
||||||
|
|
||||||
|
impl PartialEq<Owned> for Borrowed {
|
||||||
|
fn eq(&self, _: &Owned) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn compare() {
|
||||||
|
let owned = Owned {};
|
||||||
|
let borrowed = Borrowed {};
|
||||||
|
|
||||||
|
if borrowed == owned {}
|
||||||
|
if borrowed == owned {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only Owned == Borrowed is implemented
|
||||||
|
mod owned_eq_borrowed {
|
||||||
|
impl_types!();
|
||||||
|
|
||||||
|
impl PartialEq<Borrowed> for Owned {
|
||||||
|
fn eq(&self, _: &Borrowed) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn compare() {
|
||||||
|
let owned = Owned {};
|
||||||
|
let borrowed = Borrowed {};
|
||||||
|
|
||||||
|
if owned == borrowed {}
|
||||||
|
if owned == borrowed {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mod issue_4874 {
|
||||||
|
impl_types!();
|
||||||
|
|
||||||
|
// NOTE: PartialEq<Borrowed> for T can't be implemented due to the orphan rules
|
||||||
|
impl<T> PartialEq<T> for Borrowed
|
||||||
|
where
|
||||||
|
T: AsRef<str> + ?Sized,
|
||||||
|
{
|
||||||
|
fn eq(&self, _: &T) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Display for Borrowed {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
write!(f, "borrowed")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn compare() {
|
||||||
|
let borrowed = Borrowed {};
|
||||||
|
|
||||||
|
if borrowed == "Hi" {}
|
||||||
|
if borrowed == "Hi" {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
||||||
93
tests/ui/cmp_owned/asymmetric_partial_eq.rs
Normal file
93
tests/ui/cmp_owned/asymmetric_partial_eq.rs
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
// run-rustfix
|
||||||
|
#![allow(unused, clippy::redundant_clone)] // See #5700
|
||||||
|
|
||||||
|
// Define the types in each module to avoid trait impls leaking between modules.
|
||||||
|
macro_rules! impl_types {
|
||||||
|
() => {
|
||||||
|
#[derive(PartialEq)]
|
||||||
|
pub struct Owned;
|
||||||
|
|
||||||
|
pub struct Borrowed;
|
||||||
|
|
||||||
|
impl ToOwned for Borrowed {
|
||||||
|
type Owned = Owned;
|
||||||
|
fn to_owned(&self) -> Owned {
|
||||||
|
Owned {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::borrow::Borrow<Borrowed> for Owned {
|
||||||
|
fn borrow(&self) -> &Borrowed {
|
||||||
|
static VALUE: Borrowed = Borrowed {};
|
||||||
|
&VALUE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only Borrowed == Owned is implemented
|
||||||
|
mod borrowed_eq_owned {
|
||||||
|
impl_types!();
|
||||||
|
|
||||||
|
impl PartialEq<Owned> for Borrowed {
|
||||||
|
fn eq(&self, _: &Owned) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn compare() {
|
||||||
|
let owned = Owned {};
|
||||||
|
let borrowed = Borrowed {};
|
||||||
|
|
||||||
|
if borrowed.to_owned() == owned {}
|
||||||
|
if owned == borrowed.to_owned() {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only Owned == Borrowed is implemented
|
||||||
|
mod owned_eq_borrowed {
|
||||||
|
impl_types!();
|
||||||
|
|
||||||
|
impl PartialEq<Borrowed> for Owned {
|
||||||
|
fn eq(&self, _: &Borrowed) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn compare() {
|
||||||
|
let owned = Owned {};
|
||||||
|
let borrowed = Borrowed {};
|
||||||
|
|
||||||
|
if owned == borrowed.to_owned() {}
|
||||||
|
if borrowed.to_owned() == owned {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mod issue_4874 {
|
||||||
|
impl_types!();
|
||||||
|
|
||||||
|
// NOTE: PartialEq<Borrowed> for T can't be implemented due to the orphan rules
|
||||||
|
impl<T> PartialEq<T> for Borrowed
|
||||||
|
where
|
||||||
|
T: AsRef<str> + ?Sized,
|
||||||
|
{
|
||||||
|
fn eq(&self, _: &T) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Display for Borrowed {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
write!(f, "borrowed")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn compare() {
|
||||||
|
let borrowed = Borrowed {};
|
||||||
|
|
||||||
|
if "Hi" == borrowed.to_string() {}
|
||||||
|
if borrowed.to_string() == "Hi" {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
||||||
46
tests/ui/cmp_owned/asymmetric_partial_eq.stderr
Normal file
46
tests/ui/cmp_owned/asymmetric_partial_eq.stderr
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
error: this creates an owned instance just for comparison
|
||||||
|
--> $DIR/asymmetric_partial_eq.rs:42:12
|
||||||
|
|
|
||||||
|
LL | if borrowed.to_owned() == owned {}
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^ help: try: `borrowed`
|
||||||
|
|
|
||||||
|
= note: `-D clippy::cmp-owned` implied by `-D warnings`
|
||||||
|
|
||||||
|
error: this creates an owned instance just for comparison
|
||||||
|
--> $DIR/asymmetric_partial_eq.rs:43:21
|
||||||
|
|
|
||||||
|
LL | if owned == borrowed.to_owned() {}
|
||||||
|
| ---------^^^^^^^^^^^^^^^^^^^
|
||||||
|
| |
|
||||||
|
| help: try: `borrowed == owned`
|
||||||
|
|
||||||
|
error: this creates an owned instance just for comparison
|
||||||
|
--> $DIR/asymmetric_partial_eq.rs:61:21
|
||||||
|
|
|
||||||
|
LL | if owned == borrowed.to_owned() {}
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^ help: try: `borrowed`
|
||||||
|
|
||||||
|
error: this creates an owned instance just for comparison
|
||||||
|
--> $DIR/asymmetric_partial_eq.rs:62:12
|
||||||
|
|
|
||||||
|
LL | if borrowed.to_owned() == owned {}
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^---------
|
||||||
|
| |
|
||||||
|
| help: try: `owned == borrowed`
|
||||||
|
|
||||||
|
error: this creates an owned instance just for comparison
|
||||||
|
--> $DIR/asymmetric_partial_eq.rs:88:20
|
||||||
|
|
|
||||||
|
LL | if "Hi" == borrowed.to_string() {}
|
||||||
|
| --------^^^^^^^^^^^^^^^^^^^^
|
||||||
|
| |
|
||||||
|
| help: try: `borrowed == "Hi"`
|
||||||
|
|
||||||
|
error: this creates an owned instance just for comparison
|
||||||
|
--> $DIR/asymmetric_partial_eq.rs:89:12
|
||||||
|
|
|
||||||
|
LL | if borrowed.to_string() == "Hi" {}
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^ help: try: `borrowed`
|
||||||
|
|
||||||
|
error: aborting due to 6 previous errors
|
||||||
|
|
||||||
@@ -7,5 +7,6 @@
|
|||||||
#[warn(clippy::invalid_ref)]
|
#[warn(clippy::invalid_ref)]
|
||||||
#[warn(clippy::into_iter_on_array)]
|
#[warn(clippy::into_iter_on_array)]
|
||||||
#[warn(clippy::unused_label)]
|
#[warn(clippy::unused_label)]
|
||||||
|
#[warn(clippy::regex_macro)]
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|||||||
@@ -54,11 +54,17 @@ error: lint `clippy::unused_label` has been removed: `this lint has been uplifte
|
|||||||
LL | #[warn(clippy::unused_label)]
|
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
|
||||||
|
|
|
||||||
|
LL | #[warn(clippy::regex_macro)]
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
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::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
|
--> $DIR/deprecated.rs:1:8
|
||||||
|
|
|
|
||||||
LL | #[warn(clippy::str_to_string)]
|
LL | #[warn(clippy::str_to_string)]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: aborting due to 10 previous errors
|
error: aborting due to 11 previous errors
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#![warn(clippy::all, clippy::pedantic)]
|
#![warn(clippy::all, clippy::pedantic)]
|
||||||
#![allow(clippy::missing_docs_in_private_items)]
|
#![allow(clippy::missing_docs_in_private_items)]
|
||||||
|
#![allow(clippy::map_identity)]
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let _: Vec<_> = vec![5_i8; 6].into_iter().flat_map(|x| 0..x).collect();
|
let _: Vec<_> = vec![5_i8; 6].into_iter().flat_map(|x| 0..x).collect();
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#![warn(clippy::all, clippy::pedantic)]
|
#![warn(clippy::all, clippy::pedantic)]
|
||||||
#![allow(clippy::missing_docs_in_private_items)]
|
#![allow(clippy::missing_docs_in_private_items)]
|
||||||
|
#![allow(clippy::map_identity)]
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let _: Vec<_> = vec![5_i8; 6].into_iter().map(|x| 0..x).flatten().collect();
|
let _: Vec<_> = vec![5_i8; 6].into_iter().map(|x| 0..x).flatten().collect();
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
error: called `map(..).flatten()` on an `Iterator`. This is more succinctly expressed by calling `.flat_map(..)`
|
error: called `map(..).flatten()` on an `Iterator`. This is more succinctly expressed by calling `.flat_map(..)`
|
||||||
--> $DIR/map_flatten.rs:7:21
|
--> $DIR/map_flatten.rs:8:21
|
||||||
|
|
|
|
||||||
LL | let _: Vec<_> = vec![5_i8; 6].into_iter().map(|x| 0..x).flatten().collect();
|
LL | let _: Vec<_> = vec![5_i8; 6].into_iter().map(|x| 0..x).flatten().collect();
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using `flat_map` instead: `vec![5_i8; 6].into_iter().flat_map(|x| 0..x)`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using `flat_map` instead: `vec![5_i8; 6].into_iter().flat_map(|x| 0..x)`
|
||||||
@@ -7,7 +7,7 @@ LL | let _: Vec<_> = vec![5_i8; 6].into_iter().map(|x| 0..x).flatten().colle
|
|||||||
= note: `-D clippy::map-flatten` implied by `-D warnings`
|
= note: `-D clippy::map-flatten` implied by `-D warnings`
|
||||||
|
|
||||||
error: called `map(..).flatten()` on an `Option`. This is more succinctly expressed by calling `.and_then(..)`
|
error: called `map(..).flatten()` on an `Option`. This is more succinctly expressed by calling `.and_then(..)`
|
||||||
--> $DIR/map_flatten.rs:8:24
|
--> $DIR/map_flatten.rs:9:24
|
||||||
|
|
|
|
||||||
LL | let _: Option<_> = (Some(Some(1))).map(|x| x).flatten();
|
LL | let _: Option<_> = (Some(Some(1))).map(|x| x).flatten();
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using `and_then` instead: `(Some(Some(1))).and_then(|x| x)`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using `and_then` instead: `(Some(Some(1))).and_then(|x| x)`
|
||||||
|
|||||||
23
tests/ui/map_identity.fixed
Normal file
23
tests/ui/map_identity.fixed
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
// run-rustfix
|
||||||
|
#![warn(clippy::map_identity)]
|
||||||
|
#![allow(clippy::needless_return)]
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let x: [u16; 3] = [1, 2, 3];
|
||||||
|
// should lint
|
||||||
|
let _: Vec<_> = x.iter().map(not_identity).collect();
|
||||||
|
let _: Vec<_> = x.iter().collect();
|
||||||
|
let _: Option<u8> = Some(3);
|
||||||
|
let _: Result<i8, f32> = Ok(-3);
|
||||||
|
// should not lint
|
||||||
|
let _: Vec<_> = x.iter().map(|x| 2 * x).collect();
|
||||||
|
let _: Vec<_> = x.iter().map(not_identity).map(|x| return x - 4).collect();
|
||||||
|
let _: Option<u8> = None.map(|x: u8| x - 1);
|
||||||
|
let _: Result<i8, f32> = Err(2.3).map(|x: i8| {
|
||||||
|
return x + 3;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn not_identity(x: &u16) -> u16 {
|
||||||
|
*x
|
||||||
|
}
|
||||||
25
tests/ui/map_identity.rs
Normal file
25
tests/ui/map_identity.rs
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
// run-rustfix
|
||||||
|
#![warn(clippy::map_identity)]
|
||||||
|
#![allow(clippy::needless_return)]
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let x: [u16; 3] = [1, 2, 3];
|
||||||
|
// should lint
|
||||||
|
let _: Vec<_> = x.iter().map(not_identity).map(|x| return x).collect();
|
||||||
|
let _: Vec<_> = x.iter().map(std::convert::identity).map(|y| y).collect();
|
||||||
|
let _: Option<u8> = Some(3).map(|x| x);
|
||||||
|
let _: Result<i8, f32> = Ok(-3).map(|x| {
|
||||||
|
return x;
|
||||||
|
});
|
||||||
|
// should not lint
|
||||||
|
let _: Vec<_> = x.iter().map(|x| 2 * x).collect();
|
||||||
|
let _: Vec<_> = x.iter().map(not_identity).map(|x| return x - 4).collect();
|
||||||
|
let _: Option<u8> = None.map(|x: u8| x - 1);
|
||||||
|
let _: Result<i8, f32> = Err(2.3).map(|x: i8| {
|
||||||
|
return x + 3;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn not_identity(x: &u16) -> u16 {
|
||||||
|
*x
|
||||||
|
}
|
||||||
37
tests/ui/map_identity.stderr
Normal file
37
tests/ui/map_identity.stderr
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
error: unnecessary map of the identity function
|
||||||
|
--> $DIR/map_identity.rs:8:47
|
||||||
|
|
|
||||||
|
LL | let _: Vec<_> = x.iter().map(not_identity).map(|x| return x).collect();
|
||||||
|
| ^^^^^^^^^^^^^^^^^^ help: remove the call to `map`
|
||||||
|
|
|
||||||
|
= note: `-D clippy::map-identity` implied by `-D warnings`
|
||||||
|
|
||||||
|
error: unnecessary map of the identity function
|
||||||
|
--> $DIR/map_identity.rs:9:57
|
||||||
|
|
|
||||||
|
LL | let _: Vec<_> = x.iter().map(std::convert::identity).map(|y| y).collect();
|
||||||
|
| ^^^^^^^^^^^ help: remove the call to `map`
|
||||||
|
|
||||||
|
error: unnecessary map of the identity function
|
||||||
|
--> $DIR/map_identity.rs:9:29
|
||||||
|
|
|
||||||
|
LL | let _: Vec<_> = x.iter().map(std::convert::identity).map(|y| y).collect();
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove the call to `map`
|
||||||
|
|
||||||
|
error: unnecessary map of the identity function
|
||||||
|
--> $DIR/map_identity.rs:10:32
|
||||||
|
|
|
||||||
|
LL | let _: Option<u8> = Some(3).map(|x| x);
|
||||||
|
| ^^^^^^^^^^^ help: remove the call to `map`
|
||||||
|
|
||||||
|
error: unnecessary map of the identity function
|
||||||
|
--> $DIR/map_identity.rs:11:36
|
||||||
|
|
|
||||||
|
LL | let _: Result<i8, f32> = Ok(-3).map(|x| {
|
||||||
|
| ____________________________________^
|
||||||
|
LL | | return x;
|
||||||
|
LL | | });
|
||||||
|
| |______^ help: remove the call to `map`
|
||||||
|
|
||||||
|
error: aborting due to 5 previous errors
|
||||||
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
#![allow(unused)]
|
#![allow(unused)]
|
||||||
#![warn(clippy::invalid_regex, clippy::trivial_regex, clippy::regex_macro)]
|
#![warn(clippy::invalid_regex, clippy::trivial_regex)]
|
||||||
|
|
||||||
extern crate regex;
|
extern crate regex;
|
||||||
|
|
||||||
|
|||||||
@@ -13,31 +13,6 @@ impl SomeTrait for SomeImpl {}
|
|||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
||||||
fn is_ascii(ch: char) -> bool {
|
|
||||||
ch.is_ascii()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn clone_on_copy() {
|
|
||||||
42.clone();
|
|
||||||
|
|
||||||
vec![1].clone(); // ok, not a Copy type
|
|
||||||
Some(vec![1]).clone(); // ok, not a Copy type
|
|
||||||
(&42).clone();
|
|
||||||
|
|
||||||
let rc = RefCell::new(0);
|
|
||||||
rc.borrow().clone();
|
|
||||||
|
|
||||||
// Issue #4348
|
|
||||||
let mut x = 43;
|
|
||||||
let _ = &x.clone(); // ok, getting a ref
|
|
||||||
'a'.clone().make_ascii_uppercase(); // ok, clone and then mutate
|
|
||||||
is_ascii('z'.clone());
|
|
||||||
|
|
||||||
// Issue #5436
|
|
||||||
let mut vec = Vec::new();
|
|
||||||
vec.push(42.clone());
|
|
||||||
}
|
|
||||||
|
|
||||||
fn clone_on_ref_ptr() {
|
fn clone_on_ref_ptr() {
|
||||||
let rc = Rc::new(true);
|
let rc = Rc::new(true);
|
||||||
let arc = Arc::new(true);
|
let arc = Arc::new(true);
|
||||||
|
|||||||
@@ -1,37 +1,5 @@
|
|||||||
error: using `clone` on a `Copy` type
|
|
||||||
--> $DIR/unnecessary_clone.rs:21:5
|
|
||||||
|
|
|
||||||
LL | 42.clone();
|
|
||||||
| ^^^^^^^^^^ help: try removing the `clone` call: `42`
|
|
||||||
|
|
|
||||||
= note: `-D clippy::clone-on-copy` implied by `-D warnings`
|
|
||||||
|
|
||||||
error: using `clone` on a `Copy` type
|
|
||||||
--> $DIR/unnecessary_clone.rs:25:5
|
|
||||||
|
|
|
||||||
LL | (&42).clone();
|
|
||||||
| ^^^^^^^^^^^^^ help: try dereferencing it: `*(&42)`
|
|
||||||
|
|
||||||
error: using `clone` on a `Copy` type
|
|
||||||
--> $DIR/unnecessary_clone.rs:28:5
|
|
||||||
|
|
|
||||||
LL | rc.borrow().clone();
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^ help: try dereferencing it: `*rc.borrow()`
|
|
||||||
|
|
||||||
error: using `clone` on a `Copy` type
|
|
||||||
--> $DIR/unnecessary_clone.rs:34:14
|
|
||||||
|
|
|
||||||
LL | is_ascii('z'.clone());
|
|
||||||
| ^^^^^^^^^^^ help: try removing the `clone` call: `'z'`
|
|
||||||
|
|
||||||
error: using `clone` on a `Copy` type
|
|
||||||
--> $DIR/unnecessary_clone.rs:38:14
|
|
||||||
|
|
|
||||||
LL | vec.push(42.clone());
|
|
||||||
| ^^^^^^^^^^ help: try removing the `clone` call: `42`
|
|
||||||
|
|
||||||
error: using `.clone()` on a ref-counted pointer
|
error: using `.clone()` on a ref-counted pointer
|
||||||
--> $DIR/unnecessary_clone.rs:48:5
|
--> $DIR/unnecessary_clone.rs:23:5
|
||||||
|
|
|
|
||||||
LL | rc.clone();
|
LL | rc.clone();
|
||||||
| ^^^^^^^^^^ help: try this: `Rc::<bool>::clone(&rc)`
|
| ^^^^^^^^^^ help: try this: `Rc::<bool>::clone(&rc)`
|
||||||
@@ -39,43 +7,45 @@ LL | rc.clone();
|
|||||||
= note: `-D clippy::clone-on-ref-ptr` implied by `-D warnings`
|
= note: `-D clippy::clone-on-ref-ptr` implied by `-D warnings`
|
||||||
|
|
||||||
error: using `.clone()` on a ref-counted pointer
|
error: using `.clone()` on a ref-counted pointer
|
||||||
--> $DIR/unnecessary_clone.rs:51:5
|
--> $DIR/unnecessary_clone.rs:26:5
|
||||||
|
|
|
|
||||||
LL | arc.clone();
|
LL | arc.clone();
|
||||||
| ^^^^^^^^^^^ help: try this: `Arc::<bool>::clone(&arc)`
|
| ^^^^^^^^^^^ help: try this: `Arc::<bool>::clone(&arc)`
|
||||||
|
|
||||||
error: using `.clone()` on a ref-counted pointer
|
error: using `.clone()` on a ref-counted pointer
|
||||||
--> $DIR/unnecessary_clone.rs:54:5
|
--> $DIR/unnecessary_clone.rs:29:5
|
||||||
|
|
|
|
||||||
LL | rcweak.clone();
|
LL | rcweak.clone();
|
||||||
| ^^^^^^^^^^^^^^ help: try this: `Weak::<bool>::clone(&rcweak)`
|
| ^^^^^^^^^^^^^^ help: try this: `Weak::<bool>::clone(&rcweak)`
|
||||||
|
|
||||||
error: using `.clone()` on a ref-counted pointer
|
error: using `.clone()` on a ref-counted pointer
|
||||||
--> $DIR/unnecessary_clone.rs:57:5
|
--> $DIR/unnecessary_clone.rs:32:5
|
||||||
|
|
|
|
||||||
LL | arc_weak.clone();
|
LL | arc_weak.clone();
|
||||||
| ^^^^^^^^^^^^^^^^ help: try this: `Weak::<bool>::clone(&arc_weak)`
|
| ^^^^^^^^^^^^^^^^ help: try this: `Weak::<bool>::clone(&arc_weak)`
|
||||||
|
|
||||||
error: using `.clone()` on a ref-counted pointer
|
error: using `.clone()` on a ref-counted pointer
|
||||||
--> $DIR/unnecessary_clone.rs:61:33
|
--> $DIR/unnecessary_clone.rs:36:33
|
||||||
|
|
|
|
||||||
LL | let _: Arc<dyn SomeTrait> = x.clone();
|
LL | let _: Arc<dyn SomeTrait> = x.clone();
|
||||||
| ^^^^^^^^^ help: try this: `Arc::<SomeImpl>::clone(&x)`
|
| ^^^^^^^^^ help: try this: `Arc::<SomeImpl>::clone(&x)`
|
||||||
|
|
||||||
error: using `clone` on a `Copy` type
|
error: using `clone` on a `Copy` type
|
||||||
--> $DIR/unnecessary_clone.rs:65:5
|
--> $DIR/unnecessary_clone.rs:40:5
|
||||||
|
|
|
|
||||||
LL | t.clone();
|
LL | t.clone();
|
||||||
| ^^^^^^^^^ help: try removing the `clone` call: `t`
|
| ^^^^^^^^^ help: try removing the `clone` call: `t`
|
||||||
|
|
|
||||||
|
= note: `-D clippy::clone-on-copy` implied by `-D warnings`
|
||||||
|
|
||||||
error: using `clone` on a `Copy` type
|
error: using `clone` on a `Copy` type
|
||||||
--> $DIR/unnecessary_clone.rs:67:5
|
--> $DIR/unnecessary_clone.rs:42:5
|
||||||
|
|
|
|
||||||
LL | Some(t).clone();
|
LL | Some(t).clone();
|
||||||
| ^^^^^^^^^^^^^^^ help: try removing the `clone` call: `Some(t)`
|
| ^^^^^^^^^^^^^^^ help: try removing the `clone` call: `Some(t)`
|
||||||
|
|
||||||
error: using `clone` on a double-reference; this will copy the reference instead of cloning the inner type
|
error: using `clone` on a double-reference; this will copy the reference instead of cloning the inner type
|
||||||
--> $DIR/unnecessary_clone.rs:73:22
|
--> $DIR/unnecessary_clone.rs:48:22
|
||||||
|
|
|
|
||||||
LL | let z: &Vec<_> = y.clone();
|
LL | let z: &Vec<_> = y.clone();
|
||||||
| ^^^^^^^^^
|
| ^^^^^^^^^
|
||||||
@@ -91,13 +61,13 @@ LL | let z: &Vec<_> = <&std::vec::Vec<i32>>::clone(y);
|
|||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: using `clone` on a `Copy` type
|
error: using `clone` on a `Copy` type
|
||||||
--> $DIR/unnecessary_clone.rs:109:20
|
--> $DIR/unnecessary_clone.rs:84:20
|
||||||
|
|
|
|
||||||
LL | let _: E = a.clone();
|
LL | let _: E = a.clone();
|
||||||
| ^^^^^^^^^ help: try dereferencing it: `*****a`
|
| ^^^^^^^^^ help: try dereferencing it: `*****a`
|
||||||
|
|
||||||
error: using `clone` on a double-reference; this will copy the reference instead of cloning the inner type
|
error: using `clone` on a double-reference; this will copy the reference instead of cloning the inner type
|
||||||
--> $DIR/unnecessary_clone.rs:114:22
|
--> $DIR/unnecessary_clone.rs:89:22
|
||||||
|
|
|
|
||||||
LL | let _ = &mut encoded.clone();
|
LL | let _ = &mut encoded.clone();
|
||||||
| ^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^
|
||||||
@@ -112,7 +82,7 @@ LL | let _ = &mut <&[u8]>::clone(encoded);
|
|||||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: using `clone` on a double-reference; this will copy the reference instead of cloning the inner type
|
error: using `clone` on a double-reference; this will copy the reference instead of cloning the inner type
|
||||||
--> $DIR/unnecessary_clone.rs:115:18
|
--> $DIR/unnecessary_clone.rs:90:18
|
||||||
|
|
|
|
||||||
LL | let _ = &encoded.clone();
|
LL | let _ = &encoded.clone();
|
||||||
| ^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^
|
||||||
@@ -126,5 +96,5 @@ help: or try being explicit if you are sure, that you want to clone a reference
|
|||||||
LL | let _ = &<&[u8]>::clone(encoded);
|
LL | let _ = &<&[u8]>::clone(encoded);
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: aborting due to 16 previous errors
|
error: aborting due to 11 previous errors
|
||||||
|
|
||||||
|
|||||||
6
tests/ui/unnested_or_patterns3.rs
Normal file
6
tests/ui/unnested_or_patterns3.rs
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
#![warn(clippy::unnested_or_patterns)]
|
||||||
|
|
||||||
|
// Test that `unnested_or_patterns` does not trigger without enabling `or_patterns`
|
||||||
|
fn main() {
|
||||||
|
if let (0, 1) | (0, 2) | (0, 3) = (0, 0) {}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user