mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-01 06:51:58 +00:00
Merge commit '7f27e2e74ef957baa382dc05cf08df6368165c74' into clippyup
This commit is contained in:
commit
01c75848eb
7
src/tools/clippy/.github/driver.sh
vendored
7
src/tools/clippy/.github/driver.sh
vendored
@ -17,6 +17,13 @@ test "$sysroot" = $desired_sysroot
|
||||
sysroot=$(SYSROOT=$desired_sysroot ./target/debug/clippy-driver --print sysroot)
|
||||
test "$sysroot" = $desired_sysroot
|
||||
|
||||
# Check that the --sysroot argument is only passed once (SYSROOT is ignored)
|
||||
(
|
||||
cd rustc_tools_util
|
||||
touch src/lib.rs
|
||||
SYSROOT=/tmp RUSTFLAGS="--sysroot=$(rustc --print sysroot)" ../target/debug/cargo-clippy clippy --verbose
|
||||
)
|
||||
|
||||
# Make sure this isn't set - clippy-driver should cope without it
|
||||
unset CARGO_MANIFEST_DIR
|
||||
|
||||
|
@ -4137,6 +4137,7 @@ Released 2018-09-13
|
||||
[`derive_hash_xor_eq`]: https://rust-lang.github.io/rust-clippy/master/index.html#derive_hash_xor_eq
|
||||
[`derive_ord_xor_partial_ord`]: https://rust-lang.github.io/rust-clippy/master/index.html#derive_ord_xor_partial_ord
|
||||
[`derive_partial_eq_without_eq`]: https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq
|
||||
[`derived_hash_with_manual_eq`]: https://rust-lang.github.io/rust-clippy/master/index.html#derived_hash_with_manual_eq
|
||||
[`disallowed_macros`]: https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_macros
|
||||
[`disallowed_method`]: https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_method
|
||||
[`disallowed_methods`]: https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_methods
|
||||
|
@ -1,6 +1,6 @@
|
||||
# Installation
|
||||
|
||||
If you're using `rustup` to install and manage you're Rust toolchains, Clippy is
|
||||
If you're using `rustup` to install and manage your Rust toolchains, Clippy is
|
||||
usually **already installed**. In that case you can skip this chapter and go to
|
||||
the [Usage] chapter.
|
||||
|
||||
|
@ -5,6 +5,9 @@
|
||||
// warn on lints, that are included in `rust-lang/rust`s bootstrap
|
||||
#![warn(rust_2018_idioms, unused_lifetimes)]
|
||||
|
||||
// The `rustc_driver` crate seems to be required in order to use the `rust_lexer` crate.
|
||||
#[allow(unused_extern_crates)]
|
||||
extern crate rustc_driver;
|
||||
extern crate rustc_lexer;
|
||||
|
||||
use std::path::PathBuf;
|
||||
|
@ -8,7 +8,7 @@ use rustc_hir::{
|
||||
Block, Expr, ExprKind, Local, Node, QPath, TyKind,
|
||||
};
|
||||
use rustc_lint::{LateContext, LateLintPass, LintContext};
|
||||
use rustc_middle::lint::in_external_macro;
|
||||
use rustc_middle::{lint::in_external_macro, ty::print::with_forced_trimmed_paths};
|
||||
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||
use rustc_span::sym;
|
||||
|
||||
@ -59,7 +59,7 @@ impl LateLintPass<'_> for BoxDefault {
|
||||
if is_plain_default(arg_path) || given_type(cx, expr) {
|
||||
"Box::default()".into()
|
||||
} else {
|
||||
format!("Box::<{arg_ty}>::default()")
|
||||
with_forced_trimmed_paths!(format!("Box::<{arg_ty}>::default()"))
|
||||
},
|
||||
Applicability::MachineApplicable
|
||||
);
|
||||
|
@ -525,7 +525,11 @@ fn check_for_warn_of_moved_symbol(cx: &LateContext<'_>, symbols: &[(HirId, Symbo
|
||||
.iter()
|
||||
.filter(|&&(_, name)| !name.as_str().starts_with('_'))
|
||||
.any(|&(_, name)| {
|
||||
let mut walker = ContainsName { name, result: false };
|
||||
let mut walker = ContainsName {
|
||||
name,
|
||||
result: false,
|
||||
cx,
|
||||
};
|
||||
|
||||
// Scan block
|
||||
block
|
||||
|
@ -10,11 +10,11 @@ use rustc_span::sym;
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// ### What it does
|
||||
/// Checks for usage of dbg!() macro.
|
||||
/// Checks for usage of the [`dbg!`](https://doc.rust-lang.org/std/macro.dbg.html) macro.
|
||||
///
|
||||
/// ### Why is this bad?
|
||||
/// `dbg!` macro is intended as a debugging tool. It
|
||||
/// should not be in version control.
|
||||
/// The `dbg!` macro is intended as a debugging tool. It should not be present in released
|
||||
/// software or committed to a version control system.
|
||||
///
|
||||
/// ### Example
|
||||
/// ```rust,ignore
|
||||
@ -91,8 +91,8 @@ impl LateLintPass<'_> for DbgMacro {
|
||||
cx,
|
||||
DBG_MACRO,
|
||||
macro_call.span,
|
||||
"`dbg!` macro is intended as a debugging tool",
|
||||
"ensure to avoid having uses of it in version control",
|
||||
"the `dbg!` macro is intended as a debugging tool",
|
||||
"remove the invocation before committing it to a version control system",
|
||||
suggestion,
|
||||
applicability,
|
||||
);
|
||||
|
@ -111,7 +111,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
|
||||
crate::dereference::NEEDLESS_BORROW_INFO,
|
||||
crate::dereference::REF_BINDING_TO_REFERENCE_INFO,
|
||||
crate::derivable_impls::DERIVABLE_IMPLS_INFO,
|
||||
crate::derive::DERIVE_HASH_XOR_EQ_INFO,
|
||||
crate::derive::DERIVED_HASH_WITH_MANUAL_EQ_INFO,
|
||||
crate::derive::DERIVE_ORD_XOR_PARTIAL_ORD_INFO,
|
||||
crate::derive::DERIVE_PARTIAL_EQ_WITHOUT_EQ_INFO,
|
||||
crate::derive::EXPL_IMPL_CLONE_ON_COPY_INFO,
|
||||
|
@ -11,6 +11,7 @@ use rustc_hir::def::Res;
|
||||
use rustc_hir::{Block, Expr, ExprKind, PatKind, QPath, Stmt, StmtKind};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_middle::ty;
|
||||
use rustc_middle::ty::print::with_forced_trimmed_paths;
|
||||
use rustc_session::{declare_tool_lint, impl_lint_pass};
|
||||
use rustc_span::symbol::{Ident, Symbol};
|
||||
use rustc_span::Span;
|
||||
@ -98,9 +99,7 @@ impl<'tcx> LateLintPass<'tcx> for Default {
|
||||
if let ty::Adt(def, ..) = expr_ty.kind();
|
||||
if !is_from_proc_macro(cx, expr);
|
||||
then {
|
||||
// TODO: Work out a way to put "whatever the imported way of referencing
|
||||
// this type in this file" rather than a fully-qualified type.
|
||||
let replacement = format!("{}::default()", cx.tcx.def_path_str(def.did()));
|
||||
let replacement = with_forced_trimmed_paths!(format!("{}::default()", cx.tcx.def_path_str(def.did())));
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
DEFAULT_TRAIT_ACCESS,
|
||||
@ -170,7 +169,7 @@ impl<'tcx> LateLintPass<'tcx> for Default {
|
||||
// find out if and which field was set by this `consecutive_statement`
|
||||
if let Some((field_ident, assign_rhs)) = field_reassigned_by_stmt(consecutive_statement, binding_name) {
|
||||
// interrupt and cancel lint if assign_rhs references the original binding
|
||||
if contains_name(binding_name, assign_rhs) {
|
||||
if contains_name(binding_name, assign_rhs, cx) {
|
||||
cancel_lint = true;
|
||||
break;
|
||||
}
|
||||
|
@ -1282,10 +1282,10 @@ fn referent_used_exactly_once<'tcx>(
|
||||
possible_borrowers.push((body_owner_local_def_id, PossibleBorrowerMap::new(cx, mir)));
|
||||
}
|
||||
let possible_borrower = &mut possible_borrowers.last_mut().unwrap().1;
|
||||
// If `place.local` were not included here, the `copyable_iterator::warn` test would fail. The
|
||||
// reason is that `PossibleBorrowerVisitor::visit_terminator` considers `place.local` a possible
|
||||
// borrower of itself. See the comment in that method for an explanation as to why.
|
||||
possible_borrower.at_most_borrowers(cx, &[local, place.local], place.local, location)
|
||||
// If `only_borrowers` were used here, the `copyable_iterator::warn` test would fail. The reason is
|
||||
// that `PossibleBorrowerVisitor::visit_terminator` considers `place.local` a possible borrower of
|
||||
// itself. See the comment in that method for an explanation as to why.
|
||||
possible_borrower.bounded_borrowers(&[local], &[local, place.local], place.local, location)
|
||||
&& used_exactly_once(mir, place.local).unwrap_or(false)
|
||||
} else {
|
||||
false
|
||||
|
@ -1,12 +1,15 @@
|
||||
use clippy_utils::diagnostics::span_lint_and_then;
|
||||
use clippy_utils::msrvs::{self, Msrv};
|
||||
use clippy_utils::source::indent_of;
|
||||
use clippy_utils::{is_default_equivalent, peel_blocks};
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::{
|
||||
def::{DefKind, Res},
|
||||
Body, Expr, ExprKind, GenericArg, Impl, ImplItemKind, Item, ItemKind, Node, PathSegment, QPath, TyKind,
|
||||
def::{CtorKind, CtorOf, DefKind, Res},
|
||||
Body, Expr, ExprKind, GenericArg, Impl, ImplItemKind, Item, ItemKind, Node, PathSegment, QPath, Ty, TyKind,
|
||||
};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||
use rustc_middle::ty::{AdtDef, DefIdTree};
|
||||
use rustc_session::{declare_tool_lint, impl_lint_pass};
|
||||
use rustc_span::sym;
|
||||
|
||||
declare_clippy_lint! {
|
||||
@ -51,7 +54,18 @@ declare_clippy_lint! {
|
||||
"manual implementation of the `Default` trait which is equal to a derive"
|
||||
}
|
||||
|
||||
declare_lint_pass!(DerivableImpls => [DERIVABLE_IMPLS]);
|
||||
pub struct DerivableImpls {
|
||||
msrv: Msrv,
|
||||
}
|
||||
|
||||
impl DerivableImpls {
|
||||
#[must_use]
|
||||
pub fn new(msrv: Msrv) -> Self {
|
||||
DerivableImpls { msrv }
|
||||
}
|
||||
}
|
||||
|
||||
impl_lint_pass!(DerivableImpls => [DERIVABLE_IMPLS]);
|
||||
|
||||
fn is_path_self(e: &Expr<'_>) -> bool {
|
||||
if let ExprKind::Path(QPath::Resolved(_, p)) = e.kind {
|
||||
@ -61,6 +75,98 @@ fn is_path_self(e: &Expr<'_>) -> bool {
|
||||
}
|
||||
}
|
||||
|
||||
fn check_struct<'tcx>(
|
||||
cx: &LateContext<'tcx>,
|
||||
item: &'tcx Item<'_>,
|
||||
self_ty: &Ty<'_>,
|
||||
func_expr: &Expr<'_>,
|
||||
adt_def: AdtDef<'_>,
|
||||
) {
|
||||
if let TyKind::Path(QPath::Resolved(_, p)) = self_ty.kind {
|
||||
if let Some(PathSegment { args: Some(a), .. }) = p.segments.last() {
|
||||
for arg in a.args {
|
||||
if !matches!(arg, GenericArg::Lifetime(_)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
let should_emit = match peel_blocks(func_expr).kind {
|
||||
ExprKind::Tup(fields) => fields.iter().all(|e| is_default_equivalent(cx, e)),
|
||||
ExprKind::Call(callee, args) if is_path_self(callee) => args.iter().all(|e| is_default_equivalent(cx, e)),
|
||||
ExprKind::Struct(_, fields, _) => fields.iter().all(|ef| is_default_equivalent(cx, ef.expr)),
|
||||
_ => false,
|
||||
};
|
||||
|
||||
if should_emit {
|
||||
let struct_span = cx.tcx.def_span(adt_def.did());
|
||||
span_lint_and_then(cx, DERIVABLE_IMPLS, item.span, "this `impl` can be derived", |diag| {
|
||||
diag.span_suggestion_hidden(
|
||||
item.span,
|
||||
"remove the manual implementation...",
|
||||
String::new(),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
diag.span_suggestion(
|
||||
struct_span.shrink_to_lo(),
|
||||
"...and instead derive it",
|
||||
"#[derive(Default)]\n".to_string(),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
fn check_enum<'tcx>(cx: &LateContext<'tcx>, item: &'tcx Item<'_>, func_expr: &Expr<'_>, adt_def: AdtDef<'_>) {
|
||||
if_chain! {
|
||||
if let ExprKind::Path(QPath::Resolved(None, p)) = &peel_blocks(func_expr).kind;
|
||||
if let Res::Def(DefKind::Ctor(CtorOf::Variant, CtorKind::Const), id) = p.res;
|
||||
if let variant_id = cx.tcx.parent(id);
|
||||
if let Some(variant_def) = adt_def.variants().iter().find(|v| v.def_id == variant_id);
|
||||
if variant_def.fields.is_empty();
|
||||
if !variant_def.is_field_list_non_exhaustive();
|
||||
|
||||
then {
|
||||
let enum_span = cx.tcx.def_span(adt_def.did());
|
||||
let indent_enum = indent_of(cx, enum_span).unwrap_or(0);
|
||||
let variant_span = cx.tcx.def_span(variant_def.def_id);
|
||||
let indent_variant = indent_of(cx, variant_span).unwrap_or(0);
|
||||
span_lint_and_then(
|
||||
cx,
|
||||
DERIVABLE_IMPLS,
|
||||
item.span,
|
||||
"this `impl` can be derived",
|
||||
|diag| {
|
||||
diag.span_suggestion_hidden(
|
||||
item.span,
|
||||
"remove the manual implementation...",
|
||||
String::new(),
|
||||
Applicability::MachineApplicable
|
||||
);
|
||||
diag.span_suggestion(
|
||||
enum_span.shrink_to_lo(),
|
||||
"...and instead derive it...",
|
||||
format!(
|
||||
"#[derive(Default)]\n{indent}",
|
||||
indent = " ".repeat(indent_enum),
|
||||
),
|
||||
Applicability::MachineApplicable
|
||||
);
|
||||
diag.span_suggestion(
|
||||
variant_span.shrink_to_lo(),
|
||||
"...and mark the default variant",
|
||||
format!(
|
||||
"#[default]\n{indent}",
|
||||
indent = " ".repeat(indent_variant),
|
||||
),
|
||||
Applicability::MachineApplicable
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> LateLintPass<'tcx> for DerivableImpls {
|
||||
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
|
||||
if_chain! {
|
||||
@ -83,49 +189,16 @@ impl<'tcx> LateLintPass<'tcx> for DerivableImpls {
|
||||
if !attrs.iter().any(|attr| attr.doc_str().is_some());
|
||||
if let child_attrs = cx.tcx.hir().attrs(impl_item_hir);
|
||||
if !child_attrs.iter().any(|attr| attr.doc_str().is_some());
|
||||
if adt_def.is_struct();
|
||||
then {
|
||||
if let TyKind::Path(QPath::Resolved(_, p)) = self_ty.kind {
|
||||
if let Some(PathSegment { args: Some(a), .. }) = p.segments.last() {
|
||||
for arg in a.args {
|
||||
if !matches!(arg, GenericArg::Lifetime(_)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
let should_emit = match peel_blocks(func_expr).kind {
|
||||
ExprKind::Tup(fields) => fields.iter().all(|e| is_default_equivalent(cx, e)),
|
||||
ExprKind::Call(callee, args)
|
||||
if is_path_self(callee) => args.iter().all(|e| is_default_equivalent(cx, e)),
|
||||
ExprKind::Struct(_, fields, _) => fields.iter().all(|ef| is_default_equivalent(cx, ef.expr)),
|
||||
_ => false,
|
||||
};
|
||||
|
||||
if should_emit {
|
||||
let struct_span = cx.tcx.def_span(adt_def.did());
|
||||
span_lint_and_then(
|
||||
cx,
|
||||
DERIVABLE_IMPLS,
|
||||
item.span,
|
||||
"this `impl` can be derived",
|
||||
|diag| {
|
||||
diag.span_suggestion_hidden(
|
||||
item.span,
|
||||
"remove the manual implementation...",
|
||||
String::new(),
|
||||
Applicability::MachineApplicable
|
||||
);
|
||||
diag.span_suggestion(
|
||||
struct_span.shrink_to_lo(),
|
||||
"...and instead derive it",
|
||||
"#[derive(Default)]\n".to_string(),
|
||||
Applicability::MachineApplicable
|
||||
);
|
||||
}
|
||||
);
|
||||
then {
|
||||
if adt_def.is_struct() {
|
||||
check_struct(cx, item, self_ty, func_expr, adt_def);
|
||||
} else if adt_def.is_enum() && self.msrv.meets(msrvs::DEFAULT_ENUM_ATTRIBUTE) {
|
||||
check_enum(cx, item, func_expr, adt_def);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extract_msrv_attr!(LateContext);
|
||||
}
|
||||
|
@ -14,8 +14,8 @@ use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_middle::hir::nested_filter;
|
||||
use rustc_middle::traits::Reveal;
|
||||
use rustc_middle::ty::{
|
||||
self, Binder, BoundConstness, Clause, GenericParamDefKind, ImplPolarity, ParamEnv, PredicateKind, TraitPredicate,
|
||||
Ty, TyCtxt,
|
||||
self, Binder, BoundConstness, Clause, GenericArgKind, GenericParamDefKind, ImplPolarity, ParamEnv, PredicateKind,
|
||||
TraitPredicate, Ty, TyCtxt,
|
||||
};
|
||||
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||
use rustc_span::source_map::Span;
|
||||
@ -46,7 +46,7 @@ declare_clippy_lint! {
|
||||
/// }
|
||||
/// ```
|
||||
#[clippy::version = "pre 1.29.0"]
|
||||
pub DERIVE_HASH_XOR_EQ,
|
||||
pub DERIVED_HASH_WITH_MANUAL_EQ,
|
||||
correctness,
|
||||
"deriving `Hash` but implementing `PartialEq` explicitly"
|
||||
}
|
||||
@ -197,7 +197,7 @@ declare_clippy_lint! {
|
||||
|
||||
declare_lint_pass!(Derive => [
|
||||
EXPL_IMPL_CLONE_ON_COPY,
|
||||
DERIVE_HASH_XOR_EQ,
|
||||
DERIVED_HASH_WITH_MANUAL_EQ,
|
||||
DERIVE_ORD_XOR_PARTIAL_ORD,
|
||||
UNSAFE_DERIVE_DESERIALIZE,
|
||||
DERIVE_PARTIAL_EQ_WITHOUT_EQ
|
||||
@ -226,7 +226,7 @@ impl<'tcx> LateLintPass<'tcx> for Derive {
|
||||
}
|
||||
}
|
||||
|
||||
/// Implementation of the `DERIVE_HASH_XOR_EQ` lint.
|
||||
/// Implementation of the `DERIVED_HASH_WITH_MANUAL_EQ` lint.
|
||||
fn check_hash_peq<'tcx>(
|
||||
cx: &LateContext<'tcx>,
|
||||
span: Span,
|
||||
@ -243,7 +243,7 @@ fn check_hash_peq<'tcx>(
|
||||
cx.tcx.for_each_relevant_impl(peq_trait_def_id, ty, |impl_id| {
|
||||
let peq_is_automatically_derived = cx.tcx.has_attr(impl_id, sym::automatically_derived);
|
||||
|
||||
if peq_is_automatically_derived == hash_is_automatically_derived {
|
||||
if !hash_is_automatically_derived || peq_is_automatically_derived {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -252,17 +252,11 @@ fn check_hash_peq<'tcx>(
|
||||
// Only care about `impl PartialEq<Foo> for Foo`
|
||||
// For `impl PartialEq<B> for A, input_types is [A, B]
|
||||
if trait_ref.substs.type_at(1) == ty {
|
||||
let mess = if peq_is_automatically_derived {
|
||||
"you are implementing `Hash` explicitly but have derived `PartialEq`"
|
||||
} else {
|
||||
"you are deriving `Hash` but have implemented `PartialEq` explicitly"
|
||||
};
|
||||
|
||||
span_lint_and_then(
|
||||
cx,
|
||||
DERIVE_HASH_XOR_EQ,
|
||||
DERIVED_HASH_WITH_MANUAL_EQ,
|
||||
span,
|
||||
mess,
|
||||
"you are deriving `Hash` but have implemented `PartialEq` explicitly",
|
||||
|diag| {
|
||||
if let Some(local_def_id) = impl_id.as_local() {
|
||||
let hir_id = cx.tcx.hir().local_def_id_to_hir_id(local_def_id);
|
||||
@ -366,6 +360,15 @@ fn check_copy_clone<'tcx>(cx: &LateContext<'tcx>, item: &Item<'_>, trait_ref: &h
|
||||
if ty_subs.types().any(|ty| !implements_trait(cx, ty, clone_id, &[])) {
|
||||
return;
|
||||
}
|
||||
// `#[repr(packed)]` structs with type/const parameters can't derive `Clone`.
|
||||
// https://github.com/rust-lang/rust-clippy/issues/10188
|
||||
if ty_adt.repr().packed()
|
||||
&& ty_subs
|
||||
.iter()
|
||||
.any(|arg| matches!(arg.unpack(), GenericArgKind::Type(_) | GenericArgKind::Const(_)))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
span_lint_and_note(
|
||||
cx,
|
||||
|
@ -206,7 +206,7 @@ impl<'tcx> LateLintPass<'tcx> for DropForgetRef {
|
||||
let is_copy = is_copy(cx, arg_ty);
|
||||
let drop_is_single_call_in_arm = is_single_call_in_arm(cx, arg, expr);
|
||||
let (lint, msg) = match fn_name {
|
||||
sym::mem_drop if arg_ty.is_ref() => (DROP_REF, DROP_REF_SUMMARY),
|
||||
sym::mem_drop if arg_ty.is_ref() && !drop_is_single_call_in_arm => (DROP_REF, DROP_REF_SUMMARY),
|
||||
sym::mem_forget if arg_ty.is_ref() => (FORGET_REF, FORGET_REF_SUMMARY),
|
||||
sym::mem_drop if is_copy && !drop_is_single_call_in_arm => (DROP_COPY, DROP_COPY_SUMMARY),
|
||||
sym::mem_forget if is_copy => (FORGET_COPY, FORGET_COPY_SUMMARY),
|
||||
|
@ -45,7 +45,7 @@ impl EarlyLintPass for EmptyStructsWithBrackets {
|
||||
span_after_ident,
|
||||
"remove the brackets",
|
||||
";",
|
||||
Applicability::MachineApplicable);
|
||||
Applicability::Unspecified);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
@ -639,7 +639,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
|
||||
store.register_late_pass(|_| Box::new(panic_unimplemented::PanicUnimplemented));
|
||||
store.register_late_pass(|_| Box::new(strings::StringLitAsBytes));
|
||||
store.register_late_pass(|_| Box::new(derive::Derive));
|
||||
store.register_late_pass(|_| Box::new(derivable_impls::DerivableImpls));
|
||||
store.register_late_pass(move |_| Box::new(derivable_impls::DerivableImpls::new(msrv())));
|
||||
store.register_late_pass(|_| Box::new(drop_forget_ref::DropForgetRef));
|
||||
store.register_late_pass(|_| Box::new(empty_enum::EmptyEnum));
|
||||
store.register_late_pass(|_| Box::new(invalid_upcast_comparisons::InvalidUpcastComparisons));
|
||||
|
@ -81,7 +81,7 @@ pub(super) fn check<'tcx>(
|
||||
|
||||
let skip = if starts_at_zero {
|
||||
String::new()
|
||||
} else if visitor.indexed_mut.contains(&indexed) && contains_name(indexed, start) {
|
||||
} else if visitor.indexed_mut.contains(&indexed) && contains_name(indexed, start, cx) {
|
||||
return;
|
||||
} else {
|
||||
format!(".skip({})", snippet(cx, start.span, ".."))
|
||||
@ -109,7 +109,7 @@ pub(super) fn check<'tcx>(
|
||||
|
||||
if is_len_call(end, indexed) || is_end_eq_array_len(cx, end, limits, indexed_ty) {
|
||||
String::new()
|
||||
} else if visitor.indexed_mut.contains(&indexed) && contains_name(indexed, take_expr) {
|
||||
} else if visitor.indexed_mut.contains(&indexed) && contains_name(indexed, take_expr, cx) {
|
||||
return;
|
||||
} else {
|
||||
match limits {
|
||||
|
@ -1,6 +1,7 @@
|
||||
use super::SINGLE_ELEMENT_LOOP;
|
||||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||
use clippy_utils::source::{indent_of, snippet_with_applicability};
|
||||
use clippy_utils::visitors::contains_break_or_continue;
|
||||
use if_chain::if_chain;
|
||||
use rustc_ast::util::parser::PREC_PREFIX;
|
||||
use rustc_ast::Mutability;
|
||||
@ -67,6 +68,7 @@ pub(super) fn check<'tcx>(
|
||||
if_chain! {
|
||||
if let ExprKind::Block(block, _) = body.kind;
|
||||
if !block.stmts.is_empty();
|
||||
if !contains_break_or_continue(body);
|
||||
then {
|
||||
let mut applicability = Applicability::MachineApplicable;
|
||||
let pat_snip = snippet_with_applicability(cx, pat.span, "..", &mut applicability);
|
||||
|
@ -1,7 +1,10 @@
|
||||
use clippy_utils::diagnostics::span_lint_and_help;
|
||||
use clippy_utils::diagnostics::span_lint_and_then;
|
||||
use clippy_utils::source::snippet_opt;
|
||||
use clippy_utils::source::{indent_of, reindent_multiline};
|
||||
use clippy_utils::ty::is_type_lang_item;
|
||||
use if_chain::if_chain;
|
||||
use rustc_ast::ast::LitKind;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::{Expr, ExprKind, LangItem};
|
||||
use rustc_lint::LateContext;
|
||||
use rustc_span::{source_map::Spanned, Span};
|
||||
@ -15,6 +18,15 @@ pub(super) fn check<'tcx>(
|
||||
recv: &'tcx Expr<'_>,
|
||||
arg: &'tcx Expr<'_>,
|
||||
) {
|
||||
if let ExprKind::MethodCall(path_segment, ..) = recv.kind {
|
||||
if matches!(
|
||||
path_segment.ident.name.as_str(),
|
||||
"to_lowercase" | "to_uppercase" | "to_ascii_lowercase" | "to_ascii_uppercase"
|
||||
) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if_chain! {
|
||||
if let Some(method_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id);
|
||||
if let Some(impl_id) = cx.tcx.impl_of_method(method_id);
|
||||
@ -28,13 +40,37 @@ pub(super) fn check<'tcx>(
|
||||
let recv_ty = cx.typeck_results().expr_ty(recv).peel_refs();
|
||||
if recv_ty.is_str() || is_type_lang_item(cx, recv_ty, LangItem::String);
|
||||
then {
|
||||
span_lint_and_help(
|
||||
span_lint_and_then(
|
||||
cx,
|
||||
CASE_SENSITIVE_FILE_EXTENSION_COMPARISONS,
|
||||
call_span,
|
||||
recv.span.to(call_span),
|
||||
"case-sensitive file extension comparison",
|
||||
None,
|
||||
"consider using a case-insensitive comparison instead",
|
||||
|diag| {
|
||||
diag.help("consider using a case-insensitive comparison instead");
|
||||
if let Some(mut recv_source) = snippet_opt(cx, recv.span) {
|
||||
|
||||
if !cx.typeck_results().expr_ty(recv).is_ref() {
|
||||
recv_source = format!("&{recv_source}");
|
||||
}
|
||||
|
||||
let suggestion_source = reindent_multiline(
|
||||
format!(
|
||||
"std::path::Path::new({})
|
||||
.extension()
|
||||
.map_or(false, |ext| ext.eq_ignore_ascii_case(\"{}\"))",
|
||||
recv_source, ext_str.strip_prefix('.').unwrap()).into(),
|
||||
true,
|
||||
Some(indent_of(cx, call_span).unwrap_or(0) + 4)
|
||||
);
|
||||
|
||||
diag.span_suggestion(
|
||||
recv.span.to(call_span),
|
||||
"use std::path::Path",
|
||||
suggestion_source,
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ use clippy_utils::ty::is_copy;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::{BindingAnnotation, ByRef, Expr, ExprKind, MatchSource, Node, PatKind, QPath};
|
||||
use rustc_lint::LateContext;
|
||||
use rustc_middle::ty::{self, adjustment::Adjust};
|
||||
use rustc_middle::ty::{self, adjustment::Adjust, print::with_forced_trimmed_paths};
|
||||
use rustc_span::symbol::{sym, Symbol};
|
||||
|
||||
use super::CLONE_DOUBLE_REF;
|
||||
@ -47,10 +47,10 @@ pub(super) fn check(
|
||||
cx,
|
||||
CLONE_DOUBLE_REF,
|
||||
expr.span,
|
||||
&format!(
|
||||
&with_forced_trimmed_paths!(format!(
|
||||
"using `clone` on a double-reference; \
|
||||
this will copy the reference of type `{ty}` instead of cloning the inner type"
|
||||
),
|
||||
)),
|
||||
|diag| {
|
||||
if let Some(snip) = sugg::Sugg::hir_opt(cx, arg) {
|
||||
let mut ty = innermost;
|
||||
@ -61,11 +61,11 @@ pub(super) fn check(
|
||||
}
|
||||
let refs = "&".repeat(n + 1);
|
||||
let derefs = "*".repeat(n);
|
||||
let explicit = format!("<{refs}{ty}>::clone({snip})");
|
||||
let explicit = with_forced_trimmed_paths!(format!("<{refs}{ty}>::clone({snip})"));
|
||||
diag.span_suggestion(
|
||||
expr.span,
|
||||
"try dereferencing it",
|
||||
format!("{refs}({derefs}{}).clone()", snip.deref()),
|
||||
with_forced_trimmed_paths!(format!("{refs}({derefs}{}).clone()", snip.deref())),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
diag.span_suggestion(
|
||||
@ -129,7 +129,9 @@ pub(super) fn check(
|
||||
cx,
|
||||
CLONE_ON_COPY,
|
||||
expr.span,
|
||||
&format!("using `clone` on type `{ty}` which implements the `Copy` trait"),
|
||||
&with_forced_trimmed_paths!(format!(
|
||||
"using `clone` on type `{ty}` which implements the `Copy` trait"
|
||||
)),
|
||||
help,
|
||||
sugg,
|
||||
app,
|
||||
|
@ -30,12 +30,12 @@ fn is_method(cx: &LateContext<'_>, expr: &hir::Expr<'_>, method_name: Symbol) ->
|
||||
match closure_expr.kind {
|
||||
hir::ExprKind::MethodCall(hir::PathSegment { ident, .. }, receiver, ..) => {
|
||||
if_chain! {
|
||||
if ident.name == method_name;
|
||||
if let hir::ExprKind::Path(path) = &receiver.kind;
|
||||
if let Res::Local(ref local) = cx.qpath_res(path, receiver.hir_id);
|
||||
then {
|
||||
return arg_id == *local
|
||||
}
|
||||
if ident.name == method_name;
|
||||
if let hir::ExprKind::Path(path) = &receiver.kind;
|
||||
if let Res::Local(ref local) = cx.qpath_res(path, receiver.hir_id);
|
||||
then {
|
||||
return arg_id == *local
|
||||
}
|
||||
}
|
||||
false
|
||||
},
|
||||
@ -92,92 +92,92 @@ pub(super) fn check(
|
||||
}
|
||||
|
||||
if_chain! {
|
||||
if is_trait_method(cx, map_recv, sym::Iterator);
|
||||
if is_trait_method(cx, map_recv, sym::Iterator);
|
||||
|
||||
// filter(|x| ...is_some())...
|
||||
if let ExprKind::Closure(&Closure { body: filter_body_id, .. }) = filter_arg.kind;
|
||||
let filter_body = cx.tcx.hir().body(filter_body_id);
|
||||
if let [filter_param] = filter_body.params;
|
||||
// optional ref pattern: `filter(|&x| ..)`
|
||||
let (filter_pat, is_filter_param_ref) = if let PatKind::Ref(ref_pat, _) = filter_param.pat.kind {
|
||||
(ref_pat, true)
|
||||
// filter(|x| ...is_some())...
|
||||
if let ExprKind::Closure(&Closure { body: filter_body_id, .. }) = filter_arg.kind;
|
||||
let filter_body = cx.tcx.hir().body(filter_body_id);
|
||||
if let [filter_param] = filter_body.params;
|
||||
// optional ref pattern: `filter(|&x| ..)`
|
||||
let (filter_pat, is_filter_param_ref) = if let PatKind::Ref(ref_pat, _) = filter_param.pat.kind {
|
||||
(ref_pat, true)
|
||||
} else {
|
||||
(filter_param.pat, false)
|
||||
};
|
||||
// closure ends with is_some() or is_ok()
|
||||
if let PatKind::Binding(_, filter_param_id, _, None) = filter_pat.kind;
|
||||
if let ExprKind::MethodCall(path, filter_arg, [], _) = filter_body.value.kind;
|
||||
if let Some(opt_ty) = cx.typeck_results().expr_ty(filter_arg).peel_refs().ty_adt_def();
|
||||
if let Some(is_result) = if cx.tcx.is_diagnostic_item(sym::Option, opt_ty.did()) {
|
||||
Some(false)
|
||||
} else if cx.tcx.is_diagnostic_item(sym::Result, opt_ty.did()) {
|
||||
Some(true)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
if path.ident.name.as_str() == if is_result { "is_ok" } else { "is_some" };
|
||||
|
||||
// ...map(|x| ...unwrap())
|
||||
if let ExprKind::Closure(&Closure { body: map_body_id, .. }) = map_arg.kind;
|
||||
let map_body = cx.tcx.hir().body(map_body_id);
|
||||
if let [map_param] = map_body.params;
|
||||
if let PatKind::Binding(_, map_param_id, map_param_ident, None) = map_param.pat.kind;
|
||||
// closure ends with expect() or unwrap()
|
||||
if let ExprKind::MethodCall(seg, map_arg, ..) = map_body.value.kind;
|
||||
if matches!(seg.ident.name, sym::expect | sym::unwrap | sym::unwrap_or);
|
||||
|
||||
// .filter(..).map(|y| f(y).copied().unwrap())
|
||||
// ~~~~
|
||||
let map_arg_peeled = match map_arg.kind {
|
||||
ExprKind::MethodCall(method, original_arg, [], _) if acceptable_methods(method) => {
|
||||
original_arg
|
||||
},
|
||||
_ => map_arg,
|
||||
};
|
||||
|
||||
// .filter(|x| x.is_some()).map(|y| y[.acceptable_method()].unwrap())
|
||||
let simple_equal = path_to_local_id(filter_arg, filter_param_id)
|
||||
&& path_to_local_id(map_arg_peeled, map_param_id);
|
||||
|
||||
let eq_fallback = |a: &Expr<'_>, b: &Expr<'_>| {
|
||||
// in `filter(|x| ..)`, replace `*x` with `x`
|
||||
let a_path = if_chain! {
|
||||
if !is_filter_param_ref;
|
||||
if let ExprKind::Unary(UnOp::Deref, expr_path) = a.kind;
|
||||
then { expr_path } else { a }
|
||||
};
|
||||
// let the filter closure arg and the map closure arg be equal
|
||||
path_to_local_id(a_path, filter_param_id)
|
||||
&& path_to_local_id(b, map_param_id)
|
||||
&& cx.typeck_results().expr_ty_adjusted(a) == cx.typeck_results().expr_ty_adjusted(b)
|
||||
};
|
||||
|
||||
if simple_equal || SpanlessEq::new(cx).expr_fallback(eq_fallback).eq_expr(filter_arg, map_arg_peeled);
|
||||
then {
|
||||
let span = filter_span.with_hi(expr.span.hi());
|
||||
let (filter_name, lint) = if is_find {
|
||||
("find", MANUAL_FIND_MAP)
|
||||
} else {
|
||||
(filter_param.pat, false)
|
||||
("filter", MANUAL_FILTER_MAP)
|
||||
};
|
||||
// closure ends with is_some() or is_ok()
|
||||
if let PatKind::Binding(_, filter_param_id, _, None) = filter_pat.kind;
|
||||
if let ExprKind::MethodCall(path, filter_arg, [], _) = filter_body.value.kind;
|
||||
if let Some(opt_ty) = cx.typeck_results().expr_ty(filter_arg).peel_refs().ty_adt_def();
|
||||
if let Some(is_result) = if cx.tcx.is_diagnostic_item(sym::Option, opt_ty.did()) {
|
||||
Some(false)
|
||||
} else if cx.tcx.is_diagnostic_item(sym::Result, opt_ty.did()) {
|
||||
Some(true)
|
||||
let msg = format!("`{filter_name}(..).map(..)` can be simplified as `{filter_name}_map(..)`");
|
||||
let (to_opt, deref) = if is_result {
|
||||
(".ok()", String::new())
|
||||
} else {
|
||||
None
|
||||
let derefs = cx.typeck_results()
|
||||
.expr_adjustments(map_arg)
|
||||
.iter()
|
||||
.filter(|adj| matches!(adj.kind, Adjust::Deref(_)))
|
||||
.count();
|
||||
|
||||
("", "*".repeat(derefs))
|
||||
};
|
||||
if path.ident.name.as_str() == if is_result { "is_ok" } else { "is_some" };
|
||||
|
||||
// ...map(|x| ...unwrap())
|
||||
if let ExprKind::Closure(&Closure { body: map_body_id, .. }) = map_arg.kind;
|
||||
let map_body = cx.tcx.hir().body(map_body_id);
|
||||
if let [map_param] = map_body.params;
|
||||
if let PatKind::Binding(_, map_param_id, map_param_ident, None) = map_param.pat.kind;
|
||||
// closure ends with expect() or unwrap()
|
||||
if let ExprKind::MethodCall(seg, map_arg, ..) = map_body.value.kind;
|
||||
if matches!(seg.ident.name, sym::expect | sym::unwrap | sym::unwrap_or);
|
||||
|
||||
// .filter(..).map(|y| f(y).copied().unwrap())
|
||||
// ~~~~
|
||||
let map_arg_peeled = match map_arg.kind {
|
||||
ExprKind::MethodCall(method, original_arg, [], _) if acceptable_methods(method) => {
|
||||
original_arg
|
||||
},
|
||||
_ => map_arg,
|
||||
};
|
||||
|
||||
// .filter(|x| x.is_some()).map(|y| y[.acceptable_method()].unwrap())
|
||||
let simple_equal = path_to_local_id(filter_arg, filter_param_id)
|
||||
&& path_to_local_id(map_arg_peeled, map_param_id);
|
||||
|
||||
let eq_fallback = |a: &Expr<'_>, b: &Expr<'_>| {
|
||||
// in `filter(|x| ..)`, replace `*x` with `x`
|
||||
let a_path = if_chain! {
|
||||
if !is_filter_param_ref;
|
||||
if let ExprKind::Unary(UnOp::Deref, expr_path) = a.kind;
|
||||
then { expr_path } else { a }
|
||||
};
|
||||
// let the filter closure arg and the map closure arg be equal
|
||||
path_to_local_id(a_path, filter_param_id)
|
||||
&& path_to_local_id(b, map_param_id)
|
||||
&& cx.typeck_results().expr_ty_adjusted(a) == cx.typeck_results().expr_ty_adjusted(b)
|
||||
};
|
||||
|
||||
if simple_equal || SpanlessEq::new(cx).expr_fallback(eq_fallback).eq_expr(filter_arg, map_arg_peeled);
|
||||
then {
|
||||
let span = filter_span.with_hi(expr.span.hi());
|
||||
let (filter_name, lint) = if is_find {
|
||||
("find", MANUAL_FIND_MAP)
|
||||
} else {
|
||||
("filter", MANUAL_FILTER_MAP)
|
||||
};
|
||||
let msg = format!("`{filter_name}(..).map(..)` can be simplified as `{filter_name}_map(..)`");
|
||||
let (to_opt, deref) = if is_result {
|
||||
(".ok()", String::new())
|
||||
} else {
|
||||
let derefs = cx.typeck_results()
|
||||
.expr_adjustments(map_arg)
|
||||
.iter()
|
||||
.filter(|adj| matches!(adj.kind, Adjust::Deref(_)))
|
||||
.count();
|
||||
|
||||
("", "*".repeat(derefs))
|
||||
};
|
||||
let sugg = format!(
|
||||
"{filter_name}_map(|{map_param_ident}| {deref}{}{to_opt})",
|
||||
snippet(cx, map_arg.span, ".."),
|
||||
);
|
||||
span_lint_and_sugg(cx, lint, span, &msg, "try", sugg, Applicability::MachineApplicable);
|
||||
}
|
||||
let sugg = format!(
|
||||
"{filter_name}_map(|{map_param_ident}| {deref}{}{to_opt})",
|
||||
snippet(cx, map_arg.span, ".."),
|
||||
);
|
||||
span_lint_and_sugg(cx, lint, span, &msg, "try", sugg, Applicability::MachineApplicable);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6,7 +6,7 @@ use clippy_utils::source::{snippet, snippet_with_applicability};
|
||||
use clippy_utils::sugg;
|
||||
use clippy_utils::ty::is_type_diagnostic_item;
|
||||
use clippy_utils::visitors::is_local_used;
|
||||
use rustc_hir::{BindingAnnotation, Body, BorrowKind, Expr, ExprKind, Mutability, Pat, PatKind};
|
||||
use rustc_hir::{BindingAnnotation, Body, BorrowKind, ByRef, Expr, ExprKind, Mutability, Pat, PatKind};
|
||||
use rustc_lint::{LateContext, LintContext};
|
||||
use rustc_middle::ty;
|
||||
use rustc_span::sym;
|
||||
@ -30,9 +30,9 @@ pub(super) fn check<'tcx>(
|
||||
if let Body {params: [p], value: body_expr, generator_kind: _ } = cx.tcx.hir().body(c.body);
|
||||
if let PatKind::Tuple([key_pat, val_pat], _) = p.pat.kind;
|
||||
|
||||
let (replacement_kind, binded_ident) = match (&key_pat.kind, &val_pat.kind) {
|
||||
(key, PatKind::Binding(_, _, value, _)) if pat_is_wild(cx, key, m_arg) => ("value", value),
|
||||
(PatKind::Binding(_, _, key, _), value) if pat_is_wild(cx, value, m_arg) => ("key", key),
|
||||
let (replacement_kind, annotation, bound_ident) = match (&key_pat.kind, &val_pat.kind) {
|
||||
(key, PatKind::Binding(ann, _, value, _)) if pat_is_wild(cx, key, m_arg) => ("value", ann, value),
|
||||
(PatKind::Binding(ann, _, key, _), value) if pat_is_wild(cx, value, m_arg) => ("key", ann, key),
|
||||
_ => return,
|
||||
};
|
||||
|
||||
@ -47,7 +47,7 @@ pub(super) fn check<'tcx>(
|
||||
if_chain! {
|
||||
if let ExprKind::Path(rustc_hir::QPath::Resolved(_, path)) = body_expr.kind;
|
||||
if let [local_ident] = path.segments;
|
||||
if local_ident.ident.as_str() == binded_ident.as_str();
|
||||
if local_ident.ident.as_str() == bound_ident.as_str();
|
||||
|
||||
then {
|
||||
span_lint_and_sugg(
|
||||
@ -60,13 +60,23 @@ pub(super) fn check<'tcx>(
|
||||
applicability,
|
||||
);
|
||||
} else {
|
||||
let ref_annotation = if annotation.0 == ByRef::Yes {
|
||||
"ref "
|
||||
} else {
|
||||
""
|
||||
};
|
||||
let mut_annotation = if annotation.1 == Mutability::Mut {
|
||||
"mut "
|
||||
} else {
|
||||
""
|
||||
};
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
ITER_KV_MAP,
|
||||
expr.span,
|
||||
&format!("iterating on a map's {replacement_kind}s"),
|
||||
"try",
|
||||
format!("{recv_snippet}.{into_prefix}{replacement_kind}s().map(|{binded_ident}| {})",
|
||||
format!("{recv_snippet}.{into_prefix}{replacement_kind}s().map(|{ref_annotation}{mut_annotation}{bound_ident}| {})",
|
||||
snippet_with_applicability(cx, body_expr.span, "/* body */", &mut applicability)),
|
||||
applicability,
|
||||
);
|
||||
|
@ -5,7 +5,7 @@ use if_chain::if_chain;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir as hir;
|
||||
use rustc_lint::LateContext;
|
||||
use rustc_middle::ty;
|
||||
use rustc_middle::ty::{self, print::with_forced_trimmed_paths};
|
||||
use rustc_span::sym;
|
||||
|
||||
use super::SUSPICIOUS_TO_OWNED;
|
||||
@ -24,7 +24,9 @@ pub fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr<'_>) -
|
||||
cx,
|
||||
SUSPICIOUS_TO_OWNED,
|
||||
expr.span,
|
||||
&format!("this `to_owned` call clones the {input_type} itself and does not cause the {input_type} contents to become owned"),
|
||||
&with_forced_trimmed_paths!(format!(
|
||||
"this `to_owned` call clones the {input_type} itself and does not cause the {input_type} contents to become owned"
|
||||
)),
|
||||
"consider using, depending on intent",
|
||||
format!("{recv_snip}.clone()` or `{recv_snip}.into_owned()"),
|
||||
app,
|
||||
|
@ -1,6 +1,6 @@
|
||||
//! Checks for uses of mutex where an atomic value could be used
|
||||
//!
|
||||
//! This lint is **warn** by default
|
||||
//! This lint is **allow** by default
|
||||
|
||||
use clippy_utils::diagnostics::span_lint;
|
||||
use clippy_utils::ty::is_type_diagnostic_item;
|
||||
@ -20,6 +20,10 @@ declare_clippy_lint! {
|
||||
/// `std::sync::atomic::AtomicBool` and `std::sync::atomic::AtomicPtr` are leaner and
|
||||
/// faster.
|
||||
///
|
||||
/// On the other hand, `Mutex`es are, in general, easier to
|
||||
/// verify correctness. An atomic does not behave the same as
|
||||
/// an equivalent mutex. See [this issue](https://github.com/rust-lang/rust-clippy/issues/4295)'s commentary for more details.
|
||||
///
|
||||
/// ### Known problems
|
||||
/// This lint cannot detect if the mutex is actually used
|
||||
/// for waiting before a critical section.
|
||||
@ -39,8 +43,8 @@ declare_clippy_lint! {
|
||||
/// ```
|
||||
#[clippy::version = "pre 1.29.0"]
|
||||
pub MUTEX_ATOMIC,
|
||||
nursery,
|
||||
"using a mutex where an atomic value could be used instead"
|
||||
restriction,
|
||||
"using a mutex where an atomic value could be used instead."
|
||||
}
|
||||
|
||||
declare_clippy_lint! {
|
||||
|
@ -2,7 +2,7 @@ use super::ARITHMETIC_SIDE_EFFECTS;
|
||||
use clippy_utils::{
|
||||
consts::{constant, constant_simple},
|
||||
diagnostics::span_lint,
|
||||
peel_hir_expr_refs,
|
||||
peel_hir_expr_refs, peel_hir_expr_unary,
|
||||
};
|
||||
use rustc_ast as ast;
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||
@ -98,8 +98,11 @@ impl ArithmeticSideEffects {
|
||||
}
|
||||
|
||||
/// If `expr` is not a literal integer like `1`, returns `None`.
|
||||
///
|
||||
/// Returns the absolute value of the expression, if this is an integer literal.
|
||||
fn literal_integer(expr: &hir::Expr<'_>) -> Option<u128> {
|
||||
if let hir::ExprKind::Lit(ref lit) = expr.kind && let ast::LitKind::Int(n, _) = lit.node {
|
||||
let actual = peel_hir_expr_unary(expr).0;
|
||||
if let hir::ExprKind::Lit(ref lit) = actual.kind && let ast::LitKind::Int(n, _) = lit.node {
|
||||
Some(n)
|
||||
}
|
||||
else {
|
||||
@ -123,12 +126,12 @@ impl ArithmeticSideEffects {
|
||||
if !matches!(
|
||||
op.node,
|
||||
hir::BinOpKind::Add
|
||||
| hir::BinOpKind::Sub
|
||||
| hir::BinOpKind::Mul
|
||||
| hir::BinOpKind::Div
|
||||
| hir::BinOpKind::Mul
|
||||
| hir::BinOpKind::Rem
|
||||
| hir::BinOpKind::Shl
|
||||
| hir::BinOpKind::Shr
|
||||
| hir::BinOpKind::Sub
|
||||
) {
|
||||
return;
|
||||
};
|
||||
|
@ -103,7 +103,7 @@ declare_clippy_lint! {
|
||||
declare_clippy_lint! {
|
||||
/// ### What it does
|
||||
/// Checks for range expressions `x..y` where both `x` and `y`
|
||||
/// are constant and `x` is greater or equal to `y`.
|
||||
/// are constant and `x` is greater to `y`. Also triggers if `x` is equal to `y` when they are conditions to a `for` loop.
|
||||
///
|
||||
/// ### Why is this bad?
|
||||
/// Empty ranges yield no values so iterating them is a no-op.
|
||||
|
@ -131,7 +131,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClone {
|
||||
// `res = clone(arg)` can be turned into `res = move arg;`
|
||||
// if `arg` is the only borrow of `cloned` at this point.
|
||||
|
||||
if cannot_move_out || !possible_borrower.at_most_borrowers(cx, &[arg], cloned, loc) {
|
||||
if cannot_move_out || !possible_borrower.only_borrowers(&[arg], cloned, loc) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -178,7 +178,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClone {
|
||||
// StorageDead(pred_arg);
|
||||
// res = to_path_buf(cloned);
|
||||
// ```
|
||||
if cannot_move_out || !possible_borrower.at_most_borrowers(cx, &[arg, cloned], local, loc) {
|
||||
if cannot_move_out || !possible_borrower.only_borrowers(&[arg, cloned], local, loc) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -9,6 +9,7 @@ pub static RENAMED_LINTS: &[(&str, &str)] = &[
|
||||
("clippy::box_vec", "clippy::box_collection"),
|
||||
("clippy::const_static_lifetime", "clippy::redundant_static_lifetimes"),
|
||||
("clippy::cyclomatic_complexity", "clippy::cognitive_complexity"),
|
||||
("clippy::derive_hash_xor_eq", "clippy::derived_hash_with_manual_eq"),
|
||||
("clippy::disallowed_method", "clippy::disallowed_methods"),
|
||||
("clippy::disallowed_type", "clippy::disallowed_types"),
|
||||
("clippy::eval_order_dependence", "clippy::mixed_read_write_in_expression"),
|
||||
|
@ -210,22 +210,25 @@ fn check_final_expr<'tcx>(
|
||||
// if desugar of `do yeet`, don't lint
|
||||
if let Some(inner_expr) = inner
|
||||
&& let ExprKind::Call(path_expr, _) = inner_expr.kind
|
||||
&& let ExprKind::Path(QPath::LangItem(LangItem::TryTraitFromYeet, _, _)) = path_expr.kind {
|
||||
return;
|
||||
&& let ExprKind::Path(QPath::LangItem(LangItem::TryTraitFromYeet, _, _)) = path_expr.kind
|
||||
{
|
||||
return;
|
||||
}
|
||||
if cx.tcx.hir().attrs(expr.hir_id).is_empty() {
|
||||
let borrows = inner.map_or(false, |inner| last_statement_borrows(cx, inner));
|
||||
if !borrows {
|
||||
// check if expr return nothing
|
||||
let ret_span = if inner.is_none() && replacement == RetReplacement::Empty {
|
||||
extend_span_to_previous_non_ws(cx, peeled_drop_expr.span)
|
||||
} else {
|
||||
peeled_drop_expr.span
|
||||
};
|
||||
if !cx.tcx.hir().attrs(expr.hir_id).is_empty() {
|
||||
return;
|
||||
}
|
||||
let borrows = inner.map_or(false, |inner| last_statement_borrows(cx, inner));
|
||||
if borrows {
|
||||
return;
|
||||
}
|
||||
// check if expr return nothing
|
||||
let ret_span = if inner.is_none() && replacement == RetReplacement::Empty {
|
||||
extend_span_to_previous_non_ws(cx, peeled_drop_expr.span)
|
||||
} else {
|
||||
peeled_drop_expr.span
|
||||
};
|
||||
|
||||
emit_return_lint(cx, ret_span, semi_spans, inner.as_ref().map(|i| i.span), replacement);
|
||||
}
|
||||
}
|
||||
emit_return_lint(cx, ret_span, semi_spans, inner.as_ref().map(|i| i.span), replacement);
|
||||
},
|
||||
ExprKind::If(_, then, else_clause_opt) => {
|
||||
check_block_return(cx, &then.kind, semi_spans.clone());
|
||||
@ -292,7 +295,7 @@ fn last_statement_borrows<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>)
|
||||
{
|
||||
ControlFlow::Break(())
|
||||
} else {
|
||||
ControlFlow::Continue(Descend::from(!expr.span.from_expansion()))
|
||||
ControlFlow::Continue(Descend::from(!e.span.from_expansion()))
|
||||
}
|
||||
})
|
||||
.is_some()
|
||||
|
@ -127,7 +127,7 @@ declare_clippy_lint! {
|
||||
/// `Vec` or a `VecDeque` (formerly called `RingBuf`).
|
||||
///
|
||||
/// ### Why is this bad?
|
||||
/// Gankro says:
|
||||
/// Gankra says:
|
||||
///
|
||||
/// > The TL;DR of `LinkedList` is that it's built on a massive amount of
|
||||
/// pointers and indirection.
|
||||
|
@ -1,9 +1,11 @@
|
||||
use clippy_utils::diagnostics::span_lint_and_help;
|
||||
use clippy_utils::macros::root_macro_call_first_node;
|
||||
use clippy_utils::visitors::is_local_used;
|
||||
use if_chain::if_chain;
|
||||
use rustc_hir::{Impl, ImplItem, ImplItemKind, ItemKind};
|
||||
use rustc_hir::{Body, Impl, ImplItem, ImplItemKind, ItemKind};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_session::{declare_tool_lint, impl_lint_pass};
|
||||
use std::ops::ControlFlow;
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// ### What it does
|
||||
@ -57,6 +59,20 @@ impl<'tcx> LateLintPass<'tcx> for UnusedSelf {
|
||||
let parent = cx.tcx.hir().get_parent_item(impl_item.hir_id()).def_id;
|
||||
let parent_item = cx.tcx.hir().expect_item(parent);
|
||||
let assoc_item = cx.tcx.associated_item(impl_item.owner_id);
|
||||
let contains_todo = |cx, body: &'_ Body<'_>| -> bool {
|
||||
clippy_utils::visitors::for_each_expr(body.value, |e| {
|
||||
if let Some(macro_call) = root_macro_call_first_node(cx, e) {
|
||||
if cx.tcx.item_name(macro_call.def_id).as_str() == "todo" {
|
||||
ControlFlow::Break(())
|
||||
} else {
|
||||
ControlFlow::Continue(())
|
||||
}
|
||||
} else {
|
||||
ControlFlow::Continue(())
|
||||
}
|
||||
})
|
||||
.is_some()
|
||||
};
|
||||
if_chain! {
|
||||
if let ItemKind::Impl(Impl { of_trait: None, .. }) = parent_item.kind;
|
||||
if assoc_item.fn_has_self_parameter;
|
||||
@ -65,6 +81,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedSelf {
|
||||
let body = cx.tcx.hir().body(*body_id);
|
||||
if let [self_param, ..] = body.params;
|
||||
if !is_local_used(cx, body, self_param.pat.hir_id);
|
||||
if !contains_todo(cx, body);
|
||||
then {
|
||||
span_lint_and_help(
|
||||
cx,
|
||||
@ -72,7 +89,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedSelf {
|
||||
self_param.span,
|
||||
"unused `self` argument",
|
||||
None,
|
||||
"consider refactoring to a associated function",
|
||||
"consider refactoring to an associated function",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1058,7 +1058,7 @@ fn get_parent_local<'hir>(cx: &LateContext<'hir>, expr: &'hir hir::Expr<'hir>) -
|
||||
fn get_parent_local_hir_id<'hir>(cx: &LateContext<'hir>, hir_id: hir::HirId) -> Option<&'hir hir::Local<'hir>> {
|
||||
let map = cx.tcx.hir();
|
||||
|
||||
match map.find_parent((hir_id)) {
|
||||
match map.find_parent(hir_id) {
|
||||
Some(hir::Node::Local(local)) => Some(local),
|
||||
Some(hir::Node::Pat(pattern)) => get_parent_local_hir_id(cx, pattern.hir_id),
|
||||
_ => None,
|
||||
|
@ -22,6 +22,9 @@ extern crate rustc_ast;
|
||||
extern crate rustc_ast_pretty;
|
||||
extern crate rustc_attr;
|
||||
extern crate rustc_data_structures;
|
||||
// The `rustc_driver` crate seems to be required in order to use the `rust_ast` crate.
|
||||
#[allow(unused_extern_crates)]
|
||||
extern crate rustc_driver;
|
||||
extern crate rustc_errors;
|
||||
extern crate rustc_hir;
|
||||
extern crate rustc_hir_typeck;
|
||||
@ -116,6 +119,8 @@ use crate::consts::{constant, Constant};
|
||||
use crate::ty::{can_partially_move_ty, expr_sig, is_copy, is_recursively_primitive_type, ty_is_fn_once_param};
|
||||
use crate::visitors::for_each_expr;
|
||||
|
||||
use rustc_middle::hir::nested_filter;
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! extract_msrv_attr {
|
||||
($context:ident) => {
|
||||
@ -1253,22 +1258,33 @@ pub fn get_item_name(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<Symbol> {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ContainsName {
|
||||
pub struct ContainsName<'a, 'tcx> {
|
||||
pub cx: &'a LateContext<'tcx>,
|
||||
pub name: Symbol,
|
||||
pub result: bool,
|
||||
}
|
||||
|
||||
impl<'tcx> Visitor<'tcx> for ContainsName {
|
||||
impl<'a, 'tcx> Visitor<'tcx> for ContainsName<'a, 'tcx> {
|
||||
type NestedFilter = nested_filter::OnlyBodies;
|
||||
|
||||
fn visit_name(&mut self, name: Symbol) {
|
||||
if self.name == name {
|
||||
self.result = true;
|
||||
}
|
||||
}
|
||||
|
||||
fn nested_visit_map(&mut self) -> Self::Map {
|
||||
self.cx.tcx.hir()
|
||||
}
|
||||
}
|
||||
|
||||
/// Checks if an `Expr` contains a certain name.
|
||||
pub fn contains_name(name: Symbol, expr: &Expr<'_>) -> bool {
|
||||
let mut cn = ContainsName { name, result: false };
|
||||
pub fn contains_name<'tcx>(name: Symbol, expr: &'tcx Expr<'_>, cx: &LateContext<'tcx>) -> bool {
|
||||
let mut cn = ContainsName {
|
||||
name,
|
||||
result: false,
|
||||
cx,
|
||||
};
|
||||
cn.visit_expr(expr);
|
||||
cn.result
|
||||
}
|
||||
@ -1304,6 +1320,7 @@ pub fn get_parent_expr_for_hir<'tcx>(cx: &LateContext<'tcx>, hir_id: hir::HirId)
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets the enclosing block, if any.
|
||||
pub fn get_enclosing_block<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId) -> Option<&'tcx Block<'tcx>> {
|
||||
let map = &cx.tcx.hir();
|
||||
let enclosing_node = map
|
||||
@ -2244,6 +2261,18 @@ pub fn peel_n_hir_expr_refs<'a>(expr: &'a Expr<'a>, count: usize) -> (&'a Expr<'
|
||||
(e, count - remaining)
|
||||
}
|
||||
|
||||
/// Peels off all unary operators of an expression. Returns the underlying expression and the number
|
||||
/// of operators removed.
|
||||
pub fn peel_hir_expr_unary<'a>(expr: &'a Expr<'a>) -> (&'a Expr<'a>, usize) {
|
||||
let mut count: usize = 0;
|
||||
let mut curr_expr = expr;
|
||||
while let ExprKind::Unary(_, local_expr) = curr_expr.kind {
|
||||
count = count.wrapping_add(1);
|
||||
curr_expr = local_expr;
|
||||
}
|
||||
(curr_expr, count)
|
||||
}
|
||||
|
||||
/// Peels off all references on the expression. Returns the underlying expression and the number of
|
||||
/// references removed.
|
||||
pub fn peel_hir_expr_refs<'a>(expr: &'a Expr<'a>) -> (&'a Expr<'a>, usize) {
|
||||
|
@ -1,16 +1,11 @@
|
||||
use super::possible_origin::PossibleOriginVisitor;
|
||||
use super::{possible_origin::PossibleOriginVisitor, transitive_relation::TransitiveRelation};
|
||||
use crate::ty::is_copy;
|
||||
use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_index::bit_set::{BitSet, HybridBitSet};
|
||||
use rustc_lint::LateContext;
|
||||
use rustc_middle::mir::{
|
||||
self, visit::Visitor as _, BasicBlock, Local, Location, Mutability, Statement, StatementKind, Terminator,
|
||||
};
|
||||
use rustc_middle::ty::{self, visit::TypeVisitor, TyCtxt};
|
||||
use rustc_mir_dataflow::{
|
||||
fmt::DebugWithContext, impls::MaybeStorageLive, lattice::JoinSemiLattice, Analysis, AnalysisDomain,
|
||||
CallReturnPlaces, ResultsCursor,
|
||||
};
|
||||
use rustc_middle::mir::{self, visit::Visitor as _, Mutability};
|
||||
use rustc_middle::ty::{self, visit::TypeVisitor};
|
||||
use rustc_mir_dataflow::{impls::MaybeStorageLive, Analysis, ResultsCursor};
|
||||
use std::borrow::Cow;
|
||||
use std::ops::ControlFlow;
|
||||
|
||||
@ -18,120 +13,78 @@ use std::ops::ControlFlow;
|
||||
/// For example, `b = &a; c = &a;` will make `b` and (transitively) `c`
|
||||
/// possible borrowers of `a`.
|
||||
#[allow(clippy::module_name_repetitions)]
|
||||
struct PossibleBorrowerAnalysis<'b, 'tcx> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
struct PossibleBorrowerVisitor<'a, 'b, 'tcx> {
|
||||
possible_borrower: TransitiveRelation,
|
||||
body: &'b mir::Body<'tcx>,
|
||||
cx: &'a LateContext<'tcx>,
|
||||
possible_origin: FxHashMap<mir::Local, HybridBitSet<mir::Local>>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
struct PossibleBorrowerState {
|
||||
map: FxIndexMap<Local, BitSet<Local>>,
|
||||
domain_size: usize,
|
||||
}
|
||||
|
||||
impl PossibleBorrowerState {
|
||||
fn new(domain_size: usize) -> Self {
|
||||
Self {
|
||||
map: FxIndexMap::default(),
|
||||
domain_size,
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::similar_names)]
|
||||
fn add(&mut self, borrowed: Local, borrower: Local) {
|
||||
self.map
|
||||
.entry(borrowed)
|
||||
.or_insert(BitSet::new_empty(self.domain_size))
|
||||
.insert(borrower);
|
||||
}
|
||||
}
|
||||
|
||||
impl<C> DebugWithContext<C> for PossibleBorrowerState {
|
||||
fn fmt_with(&self, _ctxt: &C, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
<_ as std::fmt::Debug>::fmt(self, f)
|
||||
}
|
||||
fn fmt_diff_with(&self, _old: &Self, _ctxt: &C, _f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
impl JoinSemiLattice for PossibleBorrowerState {
|
||||
fn join(&mut self, other: &Self) -> bool {
|
||||
let mut changed = false;
|
||||
for (&borrowed, borrowers) in other.map.iter() {
|
||||
if !borrowers.is_empty() {
|
||||
changed |= self
|
||||
.map
|
||||
.entry(borrowed)
|
||||
.or_insert(BitSet::new_empty(self.domain_size))
|
||||
.union(borrowers);
|
||||
}
|
||||
}
|
||||
changed
|
||||
}
|
||||
}
|
||||
|
||||
impl<'b, 'tcx> AnalysisDomain<'tcx> for PossibleBorrowerAnalysis<'b, 'tcx> {
|
||||
type Domain = PossibleBorrowerState;
|
||||
|
||||
const NAME: &'static str = "possible_borrower";
|
||||
|
||||
fn bottom_value(&self, body: &mir::Body<'tcx>) -> Self::Domain {
|
||||
PossibleBorrowerState::new(body.local_decls.len())
|
||||
}
|
||||
|
||||
fn initialize_start_block(&self, _body: &mir::Body<'tcx>, _entry_set: &mut Self::Domain) {}
|
||||
}
|
||||
|
||||
impl<'b, 'tcx> PossibleBorrowerAnalysis<'b, 'tcx> {
|
||||
impl<'a, 'b, 'tcx> PossibleBorrowerVisitor<'a, 'b, 'tcx> {
|
||||
fn new(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
cx: &'a LateContext<'tcx>,
|
||||
body: &'b mir::Body<'tcx>,
|
||||
possible_origin: FxHashMap<mir::Local, HybridBitSet<mir::Local>>,
|
||||
) -> Self {
|
||||
Self {
|
||||
tcx,
|
||||
possible_borrower: TransitiveRelation::default(),
|
||||
cx,
|
||||
body,
|
||||
possible_origin,
|
||||
}
|
||||
}
|
||||
|
||||
fn into_map(
|
||||
self,
|
||||
cx: &'a LateContext<'tcx>,
|
||||
maybe_live: ResultsCursor<'b, 'tcx, MaybeStorageLive<'tcx>>,
|
||||
) -> PossibleBorrowerMap<'b, 'tcx> {
|
||||
let mut map = FxHashMap::default();
|
||||
for row in (1..self.body.local_decls.len()).map(mir::Local::from_usize) {
|
||||
if is_copy(cx, self.body.local_decls[row].ty) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let mut borrowers = self.possible_borrower.reachable_from(row, self.body.local_decls.len());
|
||||
borrowers.remove(mir::Local::from_usize(0));
|
||||
if !borrowers.is_empty() {
|
||||
map.insert(row, borrowers);
|
||||
}
|
||||
}
|
||||
|
||||
let bs = BitSet::new_empty(self.body.local_decls.len());
|
||||
PossibleBorrowerMap {
|
||||
map,
|
||||
maybe_live,
|
||||
bitset: (bs.clone(), bs),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'b, 'tcx> Analysis<'tcx> for PossibleBorrowerAnalysis<'b, 'tcx> {
|
||||
fn apply_call_return_effect(
|
||||
&self,
|
||||
_state: &mut Self::Domain,
|
||||
_block: BasicBlock,
|
||||
_return_places: CallReturnPlaces<'_, 'tcx>,
|
||||
) {
|
||||
}
|
||||
|
||||
fn apply_statement_effect(&self, state: &mut Self::Domain, statement: &Statement<'tcx>, _location: Location) {
|
||||
if let StatementKind::Assign(box (place, rvalue)) = &statement.kind {
|
||||
let lhs = place.local;
|
||||
match rvalue {
|
||||
mir::Rvalue::Ref(_, _, borrowed) => {
|
||||
state.add(borrowed.local, lhs);
|
||||
},
|
||||
other => {
|
||||
if ContainsRegion
|
||||
.visit_ty(place.ty(&self.body.local_decls, self.tcx).ty)
|
||||
.is_continue()
|
||||
{
|
||||
return;
|
||||
impl<'a, 'b, 'tcx> mir::visit::Visitor<'tcx> for PossibleBorrowerVisitor<'a, 'b, 'tcx> {
|
||||
fn visit_assign(&mut self, place: &mir::Place<'tcx>, rvalue: &mir::Rvalue<'_>, _location: mir::Location) {
|
||||
let lhs = place.local;
|
||||
match rvalue {
|
||||
mir::Rvalue::Ref(_, _, borrowed) => {
|
||||
self.possible_borrower.add(borrowed.local, lhs);
|
||||
},
|
||||
other => {
|
||||
if ContainsRegion
|
||||
.visit_ty(place.ty(&self.body.local_decls, self.cx.tcx).ty)
|
||||
.is_continue()
|
||||
{
|
||||
return;
|
||||
}
|
||||
rvalue_locals(other, |rhs| {
|
||||
if lhs != rhs {
|
||||
self.possible_borrower.add(rhs, lhs);
|
||||
}
|
||||
rvalue_locals(other, |rhs| {
|
||||
if lhs != rhs {
|
||||
state.add(rhs, lhs);
|
||||
}
|
||||
});
|
||||
},
|
||||
}
|
||||
});
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn apply_terminator_effect(&self, state: &mut Self::Domain, terminator: &Terminator<'tcx>, _location: Location) {
|
||||
fn visit_terminator(&mut self, terminator: &mir::Terminator<'_>, _loc: mir::Location) {
|
||||
if let mir::TerminatorKind::Call {
|
||||
args,
|
||||
destination: mir::Place { local: dest, .. },
|
||||
@ -171,10 +124,10 @@ impl<'b, 'tcx> Analysis<'tcx> for PossibleBorrowerAnalysis<'b, 'tcx> {
|
||||
|
||||
for y in mutable_variables {
|
||||
for x in &immutable_borrowers {
|
||||
state.add(*x, y);
|
||||
self.possible_borrower.add(*x, y);
|
||||
}
|
||||
for x in &mutable_borrowers {
|
||||
state.add(*x, y);
|
||||
self.possible_borrower.add(*x, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -210,98 +163,73 @@ fn rvalue_locals(rvalue: &mir::Rvalue<'_>, mut visit: impl FnMut(mir::Local)) {
|
||||
}
|
||||
}
|
||||
|
||||
/// Result of `PossibleBorrowerAnalysis`.
|
||||
/// Result of `PossibleBorrowerVisitor`.
|
||||
#[allow(clippy::module_name_repetitions)]
|
||||
pub struct PossibleBorrowerMap<'b, 'tcx> {
|
||||
body: &'b mir::Body<'tcx>,
|
||||
possible_borrower: ResultsCursor<'b, 'tcx, PossibleBorrowerAnalysis<'b, 'tcx>>,
|
||||
maybe_live: ResultsCursor<'b, 'tcx, MaybeStorageLive<'b>>,
|
||||
pushed: BitSet<Local>,
|
||||
stack: Vec<Local>,
|
||||
/// Mapping `Local -> its possible borrowers`
|
||||
pub map: FxHashMap<mir::Local, HybridBitSet<mir::Local>>,
|
||||
maybe_live: ResultsCursor<'b, 'tcx, MaybeStorageLive<'tcx>>,
|
||||
// Caches to avoid allocation of `BitSet` on every query
|
||||
pub bitset: (BitSet<mir::Local>, BitSet<mir::Local>),
|
||||
}
|
||||
|
||||
impl<'b, 'tcx> PossibleBorrowerMap<'b, 'tcx> {
|
||||
pub fn new(cx: &LateContext<'tcx>, mir: &'b mir::Body<'tcx>) -> Self {
|
||||
impl<'a, 'b, 'tcx> PossibleBorrowerMap<'b, 'tcx> {
|
||||
pub fn new(cx: &'a LateContext<'tcx>, mir: &'b mir::Body<'tcx>) -> Self {
|
||||
let possible_origin = {
|
||||
let mut vis = PossibleOriginVisitor::new(mir);
|
||||
vis.visit_body(mir);
|
||||
vis.into_map(cx)
|
||||
};
|
||||
let possible_borrower = PossibleBorrowerAnalysis::new(cx.tcx, mir, possible_origin)
|
||||
let maybe_storage_live_result = MaybeStorageLive::new(Cow::Owned(BitSet::new_empty(mir.local_decls.len())))
|
||||
.into_engine(cx.tcx, mir)
|
||||
.pass_name("possible_borrower")
|
||||
.pass_name("redundant_clone")
|
||||
.iterate_to_fixpoint()
|
||||
.into_results_cursor(mir);
|
||||
let maybe_live = MaybeStorageLive::new(Cow::Owned(BitSet::new_empty(mir.local_decls.len())))
|
||||
.into_engine(cx.tcx, mir)
|
||||
.pass_name("possible_borrower")
|
||||
.iterate_to_fixpoint()
|
||||
.into_results_cursor(mir);
|
||||
PossibleBorrowerMap {
|
||||
body: mir,
|
||||
possible_borrower,
|
||||
maybe_live,
|
||||
pushed: BitSet::new_empty(mir.local_decls.len()),
|
||||
stack: Vec::with_capacity(mir.local_decls.len()),
|
||||
}
|
||||
let mut vis = PossibleBorrowerVisitor::new(cx, mir, possible_origin);
|
||||
vis.visit_body(mir);
|
||||
vis.into_map(cx, maybe_storage_live_result)
|
||||
}
|
||||
|
||||
/// Returns true if the set of borrowers of `borrowed` living at `at` includes no more than
|
||||
/// `borrowers`.
|
||||
/// Notes:
|
||||
/// 1. It would be nice if `PossibleBorrowerMap` could store `cx` so that `at_most_borrowers`
|
||||
/// would not require it to be passed in. But a `PossibleBorrowerMap` is stored in `LintPass`
|
||||
/// `Dereferencing`, which outlives any `LateContext`.
|
||||
/// 2. In all current uses of `at_most_borrowers`, `borrowers` is a slice of at most two
|
||||
/// elements. Thus, `borrowers.contains(...)` is effectively a constant-time operation. If
|
||||
/// `at_most_borrowers`'s uses were to expand beyond this, its implementation might have to be
|
||||
/// adjusted.
|
||||
pub fn at_most_borrowers(
|
||||
/// Returns true if the set of borrowers of `borrowed` living at `at` matches with `borrowers`.
|
||||
pub fn only_borrowers(&mut self, borrowers: &[mir::Local], borrowed: mir::Local, at: mir::Location) -> bool {
|
||||
self.bounded_borrowers(borrowers, borrowers, borrowed, at)
|
||||
}
|
||||
|
||||
/// Returns true if the set of borrowers of `borrowed` living at `at` includes at least `below`
|
||||
/// but no more than `above`.
|
||||
pub fn bounded_borrowers(
|
||||
&mut self,
|
||||
cx: &LateContext<'tcx>,
|
||||
borrowers: &[mir::Local],
|
||||
below: &[mir::Local],
|
||||
above: &[mir::Local],
|
||||
borrowed: mir::Local,
|
||||
at: mir::Location,
|
||||
) -> bool {
|
||||
if is_copy(cx, self.body.local_decls[borrowed].ty) {
|
||||
return true;
|
||||
}
|
||||
self.maybe_live.seek_after_primary_effect(at);
|
||||
|
||||
self.possible_borrower.seek_before_primary_effect(at);
|
||||
self.maybe_live.seek_before_primary_effect(at);
|
||||
|
||||
let possible_borrower = &self.possible_borrower.get().map;
|
||||
let maybe_live = &self.maybe_live;
|
||||
|
||||
self.pushed.clear();
|
||||
self.stack.clear();
|
||||
|
||||
if let Some(borrowers) = possible_borrower.get(&borrowed) {
|
||||
for b in borrowers.iter() {
|
||||
if self.pushed.insert(b) {
|
||||
self.stack.push(b);
|
||||
}
|
||||
self.bitset.0.clear();
|
||||
let maybe_live = &mut self.maybe_live;
|
||||
if let Some(bitset) = self.map.get(&borrowed) {
|
||||
for b in bitset.iter().filter(move |b| maybe_live.contains(*b)) {
|
||||
self.bitset.0.insert(b);
|
||||
}
|
||||
} else {
|
||||
// Nothing borrows `borrowed` at `at`.
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
while let Some(borrower) = self.stack.pop() {
|
||||
if maybe_live.contains(borrower) && !borrowers.contains(&borrower) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if let Some(borrowers) = possible_borrower.get(&borrower) {
|
||||
for b in borrowers.iter() {
|
||||
if self.pushed.insert(b) {
|
||||
self.stack.push(b);
|
||||
}
|
||||
}
|
||||
}
|
||||
self.bitset.1.clear();
|
||||
for b in below {
|
||||
self.bitset.1.insert(*b);
|
||||
}
|
||||
|
||||
true
|
||||
if !self.bitset.0.superset(&self.bitset.1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for b in above {
|
||||
self.bitset.0.remove(*b);
|
||||
}
|
||||
|
||||
self.bitset.0.is_empty()
|
||||
}
|
||||
|
||||
pub fn local_is_alive_at(&mut self, local: mir::Local, at: mir::Location) -> bool {
|
||||
|
@ -20,8 +20,9 @@ macro_rules! msrv_aliases {
|
||||
// names may refer to stabilized feature flags or library items
|
||||
msrv_aliases! {
|
||||
1,65,0 { LET_ELSE }
|
||||
1,62,0 { BOOL_THEN_SOME }
|
||||
1,62,0 { BOOL_THEN_SOME, DEFAULT_ENUM_ATTRIBUTE }
|
||||
1,58,0 { FORMAT_ARGS_CAPTURE, PATTERN_TRAIT_CHAR_ARRAY }
|
||||
1,55,0 { SEEK_REWIND }
|
||||
1,53,0 { OR_PATTERNS, MANUAL_BITS, BTREE_MAP_RETAIN, BTREE_SET_RETAIN, ARRAY_INTO_ITERATOR }
|
||||
1,52,0 { STR_SPLIT_ONCE, REM_EUCLID_CONST }
|
||||
1,51,0 { BORROW_AS_PTR, SEEK_FROM_CURRENT, UNSIGNED_ABS }
|
||||
@ -45,7 +46,6 @@ msrv_aliases! {
|
||||
1,18,0 { HASH_MAP_RETAIN, HASH_SET_RETAIN }
|
||||
1,17,0 { FIELD_INIT_SHORTHAND, STATIC_IN_CONST, EXPECT_ERR }
|
||||
1,16,0 { STR_REPEAT }
|
||||
1,55,0 { SEEK_REWIND }
|
||||
}
|
||||
|
||||
fn parse_msrv(msrv: &str, sess: Option<&Session>, span: Option<Span>) -> Option<RustcVersion> {
|
||||
|
@ -47,7 +47,6 @@ pub const IDENT: [&str; 3] = ["rustc_span", "symbol", "Ident"];
|
||||
#[cfg(feature = "internal")]
|
||||
pub const IDENT_AS_STR: [&str; 4] = ["rustc_span", "symbol", "Ident", "as_str"];
|
||||
pub const INSERT_STR: [&str; 4] = ["alloc", "string", "String", "insert_str"];
|
||||
pub const ITER_COUNT: [&str; 6] = ["core", "iter", "traits", "iterator", "Iterator", "count"];
|
||||
pub const ITER_EMPTY: [&str; 5] = ["core", "iter", "sources", "empty", "Empty"];
|
||||
pub const ITERTOOLS_NEXT_TUPLE: [&str; 3] = ["itertools", "Itertools", "next_tuple"];
|
||||
#[cfg(feature = "internal")]
|
||||
|
@ -724,3 +724,14 @@ pub fn for_each_local_assignment<'tcx, B>(
|
||||
ControlFlow::Continue(())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn contains_break_or_continue(expr: &Expr<'_>) -> bool {
|
||||
for_each_expr(expr, |e| {
|
||||
if matches!(e.kind, ExprKind::Break(..) | ExprKind::Continue(..)) {
|
||||
ControlFlow::Break(())
|
||||
} else {
|
||||
ControlFlow::Continue(())
|
||||
}
|
||||
})
|
||||
.is_some()
|
||||
}
|
||||
|
@ -1,3 +1,3 @@
|
||||
[toolchain]
|
||||
channel = "nightly-2022-12-29"
|
||||
channel = "nightly-2023-01-12"
|
||||
components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"]
|
||||
|
@ -256,11 +256,14 @@ pub fn main() {
|
||||
LazyLock::force(&ICE_HOOK);
|
||||
exit(rustc_driver::catch_with_exit_code(move || {
|
||||
let mut orig_args: Vec<String> = env::args().collect();
|
||||
let has_sysroot_arg = arg_value(&orig_args, "--sysroot", |_| true).is_some();
|
||||
|
||||
let sys_root_env = std::env::var("SYSROOT").ok();
|
||||
let pass_sysroot_env_if_given = |args: &mut Vec<String>, sys_root_env| {
|
||||
if let Some(sys_root) = sys_root_env {
|
||||
args.extend(vec!["--sysroot".into(), sys_root]);
|
||||
if !has_sysroot_arg {
|
||||
args.extend(vec!["--sysroot".into(), sys_root]);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -1,3 +1,12 @@
|
||||
//! This test is meant to only be run in CI. To run it locally use:
|
||||
//!
|
||||
//! `env INTEGRATION=rust-lang/log cargo test --test integration --features=integration`
|
||||
//!
|
||||
//! You can use a different `INTEGRATION` value to test different repositories.
|
||||
//!
|
||||
//! This test will clone the specified repository and run Clippy on it. The test succeeds, if
|
||||
//! Clippy doesn't produce an ICE. Lint warnings are ignored by this test.
|
||||
|
||||
#![cfg(feature = "integration")]
|
||||
#![cfg_attr(feature = "deny-warnings", deny(warnings))]
|
||||
#![warn(rust_2018_idioms, unused_lifetimes)]
|
||||
|
@ -107,7 +107,7 @@ fn rhs_is_different() {
|
||||
fn unary() {
|
||||
// is explicitly on the list
|
||||
let _ = -OutOfNames;
|
||||
// is specifically on the list
|
||||
// is explicitly on the list
|
||||
let _ = -Foo;
|
||||
// not on the list
|
||||
let _ = -Bar;
|
||||
|
@ -1,99 +1,99 @@
|
||||
error: `dbg!` macro is intended as a debugging tool
|
||||
error: the `dbg!` macro is intended as a debugging tool
|
||||
--> $DIR/dbg_macro.rs:5:22
|
||||
|
|
||||
LL | if let Some(n) = dbg!(n.checked_sub(4)) { n } else { n }
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: `-D clippy::dbg-macro` implied by `-D warnings`
|
||||
help: ensure to avoid having uses of it in version control
|
||||
help: remove the invocation before committing it to a version control system
|
||||
|
|
||||
LL | if let Some(n) = n.checked_sub(4) { n } else { n }
|
||||
| ~~~~~~~~~~~~~~~~
|
||||
|
||||
error: `dbg!` macro is intended as a debugging tool
|
||||
error: the `dbg!` macro is intended as a debugging tool
|
||||
--> $DIR/dbg_macro.rs:9:8
|
||||
|
|
||||
LL | if dbg!(n <= 1) {
|
||||
| ^^^^^^^^^^^^
|
||||
|
|
||||
help: ensure to avoid having uses of it in version control
|
||||
help: remove the invocation before committing it to a version control system
|
||||
|
|
||||
LL | if n <= 1 {
|
||||
| ~~~~~~
|
||||
|
||||
error: `dbg!` macro is intended as a debugging tool
|
||||
error: the `dbg!` macro is intended as a debugging tool
|
||||
--> $DIR/dbg_macro.rs:10:9
|
||||
|
|
||||
LL | dbg!(1)
|
||||
| ^^^^^^^
|
||||
|
|
||||
help: ensure to avoid having uses of it in version control
|
||||
help: remove the invocation before committing it to a version control system
|
||||
|
|
||||
LL | 1
|
||||
|
|
||||
|
||||
error: `dbg!` macro is intended as a debugging tool
|
||||
error: the `dbg!` macro is intended as a debugging tool
|
||||
--> $DIR/dbg_macro.rs:12:9
|
||||
|
|
||||
LL | dbg!(n * factorial(n - 1))
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: ensure to avoid having uses of it in version control
|
||||
help: remove the invocation before committing it to a version control system
|
||||
|
|
||||
LL | n * factorial(n - 1)
|
||||
|
|
||||
|
||||
error: `dbg!` macro is intended as a debugging tool
|
||||
error: the `dbg!` macro is intended as a debugging tool
|
||||
--> $DIR/dbg_macro.rs:17:5
|
||||
|
|
||||
LL | dbg!(42);
|
||||
| ^^^^^^^^
|
||||
|
|
||||
help: ensure to avoid having uses of it in version control
|
||||
help: remove the invocation before committing it to a version control system
|
||||
|
|
||||
LL | 42;
|
||||
| ~~
|
||||
|
||||
error: `dbg!` macro is intended as a debugging tool
|
||||
error: the `dbg!` macro is intended as a debugging tool
|
||||
--> $DIR/dbg_macro.rs:18:5
|
||||
|
|
||||
LL | dbg!(dbg!(dbg!(42)));
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: ensure to avoid having uses of it in version control
|
||||
help: remove the invocation before committing it to a version control system
|
||||
|
|
||||
LL | dbg!(dbg!(42));
|
||||
| ~~~~~~~~~~~~~~
|
||||
|
||||
error: `dbg!` macro is intended as a debugging tool
|
||||
error: the `dbg!` macro is intended as a debugging tool
|
||||
--> $DIR/dbg_macro.rs:19:14
|
||||
|
|
||||
LL | foo(3) + dbg!(factorial(4));
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: ensure to avoid having uses of it in version control
|
||||
help: remove the invocation before committing it to a version control system
|
||||
|
|
||||
LL | foo(3) + factorial(4);
|
||||
| ~~~~~~~~~~~~
|
||||
|
||||
error: `dbg!` macro is intended as a debugging tool
|
||||
error: the `dbg!` macro is intended as a debugging tool
|
||||
--> $DIR/dbg_macro.rs:20:5
|
||||
|
|
||||
LL | dbg!(1, 2, dbg!(3, 4));
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: ensure to avoid having uses of it in version control
|
||||
help: remove the invocation before committing it to a version control system
|
||||
|
|
||||
LL | (1, 2, dbg!(3, 4));
|
||||
| ~~~~~~~~~~~~~~~~~~
|
||||
|
||||
error: `dbg!` macro is intended as a debugging tool
|
||||
error: the `dbg!` macro is intended as a debugging tool
|
||||
--> $DIR/dbg_macro.rs:21:5
|
||||
|
|
||||
LL | dbg!(1, 2, 3, 4, 5);
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: ensure to avoid having uses of it in version control
|
||||
help: remove the invocation before committing it to a version control system
|
||||
|
|
||||
LL | (1, 2, 3, 4, 5);
|
||||
| ~~~~~~~~~~~~~~~
|
||||
|
@ -2,6 +2,7 @@
|
||||
clippy::assign_op_pattern,
|
||||
clippy::erasing_op,
|
||||
clippy::identity_op,
|
||||
clippy::no_effect,
|
||||
clippy::op_ref,
|
||||
clippy::unnecessary_owned_empty_strings,
|
||||
arithmetic_overflow,
|
||||
@ -12,31 +13,95 @@
|
||||
|
||||
use core::num::{Saturating, Wrapping};
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct Custom;
|
||||
|
||||
macro_rules! impl_arith {
|
||||
( $( $_trait:ident, $ty:ty, $method:ident; )* ) => {
|
||||
( $( $_trait:ident, $lhs:ty, $rhs:ty, $method:ident; )* ) => {
|
||||
$(
|
||||
impl core::ops::$_trait<$ty> for Custom {
|
||||
type Output = Self;
|
||||
fn $method(self, _: $ty) -> Self::Output { Self }
|
||||
impl core::ops::$_trait<$lhs> for $rhs {
|
||||
type Output = Custom;
|
||||
fn $method(self, _: $lhs) -> Self::Output { todo!() }
|
||||
}
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! impl_assign_arith {
|
||||
( $( $_trait:ident, $lhs:ty, $rhs:ty, $method:ident; )* ) => {
|
||||
$(
|
||||
impl core::ops::$_trait<$lhs> for $rhs {
|
||||
fn $method(&mut self, _: $lhs) {}
|
||||
}
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
impl_arith!(
|
||||
Add, i32, add;
|
||||
Div, i32, div;
|
||||
Mul, i32, mul;
|
||||
Sub, i32, sub;
|
||||
Add, Custom, Custom, add;
|
||||
Div, Custom, Custom, div;
|
||||
Mul, Custom, Custom, mul;
|
||||
Rem, Custom, Custom, rem;
|
||||
Sub, Custom, Custom, sub;
|
||||
|
||||
Add, f64, add;
|
||||
Div, f64, div;
|
||||
Mul, f64, mul;
|
||||
Sub, f64, sub;
|
||||
Add, Custom, &Custom, add;
|
||||
Div, Custom, &Custom, div;
|
||||
Mul, Custom, &Custom, mul;
|
||||
Rem, Custom, &Custom, rem;
|
||||
Sub, Custom, &Custom, sub;
|
||||
|
||||
Add, &Custom, Custom, add;
|
||||
Div, &Custom, Custom, div;
|
||||
Mul, &Custom, Custom, mul;
|
||||
Rem, &Custom, Custom, rem;
|
||||
Sub, &Custom, Custom, sub;
|
||||
|
||||
Add, &Custom, &Custom, add;
|
||||
Div, &Custom, &Custom, div;
|
||||
Mul, &Custom, &Custom, mul;
|
||||
Rem, &Custom, &Custom, rem;
|
||||
Sub, &Custom, &Custom, sub;
|
||||
);
|
||||
|
||||
impl_assign_arith!(
|
||||
AddAssign, Custom, Custom, add_assign;
|
||||
DivAssign, Custom, Custom, div_assign;
|
||||
MulAssign, Custom, Custom, mul_assign;
|
||||
RemAssign, Custom, Custom, rem_assign;
|
||||
SubAssign, Custom, Custom, sub_assign;
|
||||
|
||||
AddAssign, Custom, &Custom, add_assign;
|
||||
DivAssign, Custom, &Custom, div_assign;
|
||||
MulAssign, Custom, &Custom, mul_assign;
|
||||
RemAssign, Custom, &Custom, rem_assign;
|
||||
SubAssign, Custom, &Custom, sub_assign;
|
||||
|
||||
AddAssign, &Custom, Custom, add_assign;
|
||||
DivAssign, &Custom, Custom, div_assign;
|
||||
MulAssign, &Custom, Custom, mul_assign;
|
||||
RemAssign, &Custom, Custom, rem_assign;
|
||||
SubAssign, &Custom, Custom, sub_assign;
|
||||
|
||||
AddAssign, &Custom, &Custom, add_assign;
|
||||
DivAssign, &Custom, &Custom, div_assign;
|
||||
MulAssign, &Custom, &Custom, mul_assign;
|
||||
RemAssign, &Custom, &Custom, rem_assign;
|
||||
SubAssign, &Custom, &Custom, sub_assign;
|
||||
);
|
||||
|
||||
impl core::ops::Neg for Custom {
|
||||
type Output = Custom;
|
||||
fn neg(self) -> Self::Output {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
impl core::ops::Neg for &Custom {
|
||||
type Output = Custom;
|
||||
fn neg(self) -> Self::Output {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn association_with_structures_should_not_trigger_the_lint() {
|
||||
enum Foo {
|
||||
Bar = -2,
|
||||
@ -125,6 +190,18 @@ pub fn non_overflowing_ops_or_ops_already_handled_by_the_compiler_should_not_tri
|
||||
_n *= &0;
|
||||
_n *= 1;
|
||||
_n *= &1;
|
||||
_n += -0;
|
||||
_n += &-0;
|
||||
_n -= -0;
|
||||
_n -= &-0;
|
||||
_n /= -99;
|
||||
_n /= &-99;
|
||||
_n %= -99;
|
||||
_n %= &-99;
|
||||
_n *= -0;
|
||||
_n *= &-0;
|
||||
_n *= -1;
|
||||
_n *= &-1;
|
||||
|
||||
// Binary
|
||||
_n = _n + 0;
|
||||
@ -158,8 +235,9 @@ pub fn non_overflowing_ops_or_ops_already_handled_by_the_compiler_should_not_tri
|
||||
_n = -&i32::MIN;
|
||||
}
|
||||
|
||||
pub fn runtime_ops() {
|
||||
pub fn unknown_ops_or_runtime_ops_that_can_overflow() {
|
||||
let mut _n = i32::MAX;
|
||||
let mut _custom = Custom;
|
||||
|
||||
// Assign
|
||||
_n += 1;
|
||||
@ -172,6 +250,36 @@ pub fn runtime_ops() {
|
||||
_n %= &0;
|
||||
_n *= 2;
|
||||
_n *= &2;
|
||||
_n += -1;
|
||||
_n += &-1;
|
||||
_n -= -1;
|
||||
_n -= &-1;
|
||||
_n /= -0;
|
||||
_n /= &-0;
|
||||
_n %= -0;
|
||||
_n %= &-0;
|
||||
_n *= -2;
|
||||
_n *= &-2;
|
||||
_custom += Custom;
|
||||
_custom += &Custom;
|
||||
_custom -= Custom;
|
||||
_custom -= &Custom;
|
||||
_custom /= Custom;
|
||||
_custom /= &Custom;
|
||||
_custom %= Custom;
|
||||
_custom %= &Custom;
|
||||
_custom *= Custom;
|
||||
_custom *= &Custom;
|
||||
_custom += -Custom;
|
||||
_custom += &-Custom;
|
||||
_custom -= -Custom;
|
||||
_custom -= &-Custom;
|
||||
_custom /= -Custom;
|
||||
_custom /= &-Custom;
|
||||
_custom %= -Custom;
|
||||
_custom %= &-Custom;
|
||||
_custom *= -Custom;
|
||||
_custom *= &-Custom;
|
||||
|
||||
// Binary
|
||||
_n = _n + 1;
|
||||
@ -193,36 +301,73 @@ pub fn runtime_ops() {
|
||||
_n = 23 + &85;
|
||||
_n = &23 + 85;
|
||||
_n = &23 + &85;
|
||||
|
||||
// Custom
|
||||
let _ = Custom + 0;
|
||||
let _ = Custom + 1;
|
||||
let _ = Custom + 2;
|
||||
let _ = Custom + 0.0;
|
||||
let _ = Custom + 1.0;
|
||||
let _ = Custom + 2.0;
|
||||
let _ = Custom - 0;
|
||||
let _ = Custom - 1;
|
||||
let _ = Custom - 2;
|
||||
let _ = Custom - 0.0;
|
||||
let _ = Custom - 1.0;
|
||||
let _ = Custom - 2.0;
|
||||
let _ = Custom / 0;
|
||||
let _ = Custom / 1;
|
||||
let _ = Custom / 2;
|
||||
let _ = Custom / 0.0;
|
||||
let _ = Custom / 1.0;
|
||||
let _ = Custom / 2.0;
|
||||
let _ = Custom * 0;
|
||||
let _ = Custom * 1;
|
||||
let _ = Custom * 2;
|
||||
let _ = Custom * 0.0;
|
||||
let _ = Custom * 1.0;
|
||||
let _ = Custom * 2.0;
|
||||
_custom = _custom + _custom;
|
||||
_custom = _custom + &_custom;
|
||||
_custom = Custom + _custom;
|
||||
_custom = &Custom + _custom;
|
||||
_custom = _custom - Custom;
|
||||
_custom = _custom - &Custom;
|
||||
_custom = Custom - _custom;
|
||||
_custom = &Custom - _custom;
|
||||
_custom = _custom / Custom;
|
||||
_custom = _custom / &Custom;
|
||||
_custom = _custom % Custom;
|
||||
_custom = _custom % &Custom;
|
||||
_custom = _custom * Custom;
|
||||
_custom = _custom * &Custom;
|
||||
_custom = Custom * _custom;
|
||||
_custom = &Custom * _custom;
|
||||
_custom = Custom + &Custom;
|
||||
_custom = &Custom + Custom;
|
||||
_custom = &Custom + &Custom;
|
||||
|
||||
// Unary
|
||||
_n = -_n;
|
||||
_n = -&_n;
|
||||
_custom = -_custom;
|
||||
_custom = -&_custom;
|
||||
}
|
||||
|
||||
// Copied and pasted from the `integer_arithmetic` lint for comparison.
|
||||
pub fn integer_arithmetic() {
|
||||
let mut i = 1i32;
|
||||
let mut var1 = 0i32;
|
||||
let mut var2 = -1i32;
|
||||
|
||||
1 + i;
|
||||
i * 2;
|
||||
1 % i / 2;
|
||||
i - 2 + 2 - i;
|
||||
-i;
|
||||
i >> 1;
|
||||
i << 1;
|
||||
|
||||
-1;
|
||||
-(-1);
|
||||
|
||||
i & 1;
|
||||
i | 1;
|
||||
i ^ 1;
|
||||
|
||||
i += 1;
|
||||
i -= 1;
|
||||
i *= 2;
|
||||
i /= 2;
|
||||
i /= 0;
|
||||
i /= -1;
|
||||
i /= var1;
|
||||
i /= var2;
|
||||
i %= 2;
|
||||
i %= 0;
|
||||
i %= -1;
|
||||
i %= var1;
|
||||
i %= var2;
|
||||
i <<= 3;
|
||||
i >>= 2;
|
||||
|
||||
i |= 1;
|
||||
i &= 1;
|
||||
i ^= i;
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
@ -1,5 +1,5 @@
|
||||
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||
--> $DIR/arithmetic_side_effects.rs:165:5
|
||||
--> $DIR/arithmetic_side_effects.rs:243:5
|
||||
|
|
||||
LL | _n += 1;
|
||||
| ^^^^^^^
|
||||
@ -7,328 +7,592 @@ LL | _n += 1;
|
||||
= note: `-D clippy::arithmetic-side-effects` implied by `-D warnings`
|
||||
|
||||
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||
--> $DIR/arithmetic_side_effects.rs:166:5
|
||||
--> $DIR/arithmetic_side_effects.rs:244:5
|
||||
|
|
||||
LL | _n += &1;
|
||||
| ^^^^^^^^
|
||||
|
||||
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||
--> $DIR/arithmetic_side_effects.rs:167:5
|
||||
--> $DIR/arithmetic_side_effects.rs:245:5
|
||||
|
|
||||
LL | _n -= 1;
|
||||
| ^^^^^^^
|
||||
|
||||
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||
--> $DIR/arithmetic_side_effects.rs:168:5
|
||||
--> $DIR/arithmetic_side_effects.rs:246:5
|
||||
|
|
||||
LL | _n -= &1;
|
||||
| ^^^^^^^^
|
||||
|
||||
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||
--> $DIR/arithmetic_side_effects.rs:169:5
|
||||
--> $DIR/arithmetic_side_effects.rs:247:5
|
||||
|
|
||||
LL | _n /= 0;
|
||||
| ^^^^^^^
|
||||
|
||||
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||
--> $DIR/arithmetic_side_effects.rs:170:5
|
||||
--> $DIR/arithmetic_side_effects.rs:248:5
|
||||
|
|
||||
LL | _n /= &0;
|
||||
| ^^^^^^^^
|
||||
|
||||
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||
--> $DIR/arithmetic_side_effects.rs:171:5
|
||||
--> $DIR/arithmetic_side_effects.rs:249:5
|
||||
|
|
||||
LL | _n %= 0;
|
||||
| ^^^^^^^
|
||||
|
||||
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||
--> $DIR/arithmetic_side_effects.rs:172:5
|
||||
--> $DIR/arithmetic_side_effects.rs:250:5
|
||||
|
|
||||
LL | _n %= &0;
|
||||
| ^^^^^^^^
|
||||
|
||||
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||
--> $DIR/arithmetic_side_effects.rs:173:5
|
||||
--> $DIR/arithmetic_side_effects.rs:251:5
|
||||
|
|
||||
LL | _n *= 2;
|
||||
| ^^^^^^^
|
||||
|
||||
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||
--> $DIR/arithmetic_side_effects.rs:174:5
|
||||
--> $DIR/arithmetic_side_effects.rs:252:5
|
||||
|
|
||||
LL | _n *= &2;
|
||||
| ^^^^^^^^
|
||||
|
||||
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||
--> $DIR/arithmetic_side_effects.rs:177:10
|
||||
--> $DIR/arithmetic_side_effects.rs:253:5
|
||||
|
|
||||
LL | _n += -1;
|
||||
| ^^^^^^^^
|
||||
|
||||
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||
--> $DIR/arithmetic_side_effects.rs:254:5
|
||||
|
|
||||
LL | _n += &-1;
|
||||
| ^^^^^^^^^
|
||||
|
||||
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||
--> $DIR/arithmetic_side_effects.rs:255:5
|
||||
|
|
||||
LL | _n -= -1;
|
||||
| ^^^^^^^^
|
||||
|
||||
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||
--> $DIR/arithmetic_side_effects.rs:256:5
|
||||
|
|
||||
LL | _n -= &-1;
|
||||
| ^^^^^^^^^
|
||||
|
||||
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||
--> $DIR/arithmetic_side_effects.rs:257:5
|
||||
|
|
||||
LL | _n /= -0;
|
||||
| ^^^^^^^^
|
||||
|
||||
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||
--> $DIR/arithmetic_side_effects.rs:258:5
|
||||
|
|
||||
LL | _n /= &-0;
|
||||
| ^^^^^^^^^
|
||||
|
||||
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||
--> $DIR/arithmetic_side_effects.rs:259:5
|
||||
|
|
||||
LL | _n %= -0;
|
||||
| ^^^^^^^^
|
||||
|
||||
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||
--> $DIR/arithmetic_side_effects.rs:260:5
|
||||
|
|
||||
LL | _n %= &-0;
|
||||
| ^^^^^^^^^
|
||||
|
||||
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||
--> $DIR/arithmetic_side_effects.rs:261:5
|
||||
|
|
||||
LL | _n *= -2;
|
||||
| ^^^^^^^^
|
||||
|
||||
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||
--> $DIR/arithmetic_side_effects.rs:262:5
|
||||
|
|
||||
LL | _n *= &-2;
|
||||
| ^^^^^^^^^
|
||||
|
||||
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||
--> $DIR/arithmetic_side_effects.rs:263:5
|
||||
|
|
||||
LL | _custom += Custom;
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||
--> $DIR/arithmetic_side_effects.rs:264:5
|
||||
|
|
||||
LL | _custom += &Custom;
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||
--> $DIR/arithmetic_side_effects.rs:265:5
|
||||
|
|
||||
LL | _custom -= Custom;
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||
--> $DIR/arithmetic_side_effects.rs:266:5
|
||||
|
|
||||
LL | _custom -= &Custom;
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||
--> $DIR/arithmetic_side_effects.rs:267:5
|
||||
|
|
||||
LL | _custom /= Custom;
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||
--> $DIR/arithmetic_side_effects.rs:268:5
|
||||
|
|
||||
LL | _custom /= &Custom;
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||
--> $DIR/arithmetic_side_effects.rs:269:5
|
||||
|
|
||||
LL | _custom %= Custom;
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||
--> $DIR/arithmetic_side_effects.rs:270:5
|
||||
|
|
||||
LL | _custom %= &Custom;
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||
--> $DIR/arithmetic_side_effects.rs:271:5
|
||||
|
|
||||
LL | _custom *= Custom;
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||
--> $DIR/arithmetic_side_effects.rs:272:5
|
||||
|
|
||||
LL | _custom *= &Custom;
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||
--> $DIR/arithmetic_side_effects.rs:273:5
|
||||
|
|
||||
LL | _custom += -Custom;
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||
--> $DIR/arithmetic_side_effects.rs:274:5
|
||||
|
|
||||
LL | _custom += &-Custom;
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||
--> $DIR/arithmetic_side_effects.rs:275:5
|
||||
|
|
||||
LL | _custom -= -Custom;
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||
--> $DIR/arithmetic_side_effects.rs:276:5
|
||||
|
|
||||
LL | _custom -= &-Custom;
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||
--> $DIR/arithmetic_side_effects.rs:277:5
|
||||
|
|
||||
LL | _custom /= -Custom;
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||
--> $DIR/arithmetic_side_effects.rs:278:5
|
||||
|
|
||||
LL | _custom /= &-Custom;
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||
--> $DIR/arithmetic_side_effects.rs:279:5
|
||||
|
|
||||
LL | _custom %= -Custom;
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||
--> $DIR/arithmetic_side_effects.rs:280:5
|
||||
|
|
||||
LL | _custom %= &-Custom;
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||
--> $DIR/arithmetic_side_effects.rs:281:5
|
||||
|
|
||||
LL | _custom *= -Custom;
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||
--> $DIR/arithmetic_side_effects.rs:282:5
|
||||
|
|
||||
LL | _custom *= &-Custom;
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||
--> $DIR/arithmetic_side_effects.rs:285:10
|
||||
|
|
||||
LL | _n = _n + 1;
|
||||
| ^^^^^^
|
||||
|
||||
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||
--> $DIR/arithmetic_side_effects.rs:178:10
|
||||
--> $DIR/arithmetic_side_effects.rs:286:10
|
||||
|
|
||||
LL | _n = _n + &1;
|
||||
| ^^^^^^^
|
||||
|
||||
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||
--> $DIR/arithmetic_side_effects.rs:179:10
|
||||
--> $DIR/arithmetic_side_effects.rs:287:10
|
||||
|
|
||||
LL | _n = 1 + _n;
|
||||
| ^^^^^^
|
||||
|
||||
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||
--> $DIR/arithmetic_side_effects.rs:180:10
|
||||
--> $DIR/arithmetic_side_effects.rs:288:10
|
||||
|
|
||||
LL | _n = &1 + _n;
|
||||
| ^^^^^^^
|
||||
|
||||
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||
--> $DIR/arithmetic_side_effects.rs:181:10
|
||||
--> $DIR/arithmetic_side_effects.rs:289:10
|
||||
|
|
||||
LL | _n = _n - 1;
|
||||
| ^^^^^^
|
||||
|
||||
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||
--> $DIR/arithmetic_side_effects.rs:182:10
|
||||
--> $DIR/arithmetic_side_effects.rs:290:10
|
||||
|
|
||||
LL | _n = _n - &1;
|
||||
| ^^^^^^^
|
||||
|
||||
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||
--> $DIR/arithmetic_side_effects.rs:183:10
|
||||
--> $DIR/arithmetic_side_effects.rs:291:10
|
||||
|
|
||||
LL | _n = 1 - _n;
|
||||
| ^^^^^^
|
||||
|
||||
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||
--> $DIR/arithmetic_side_effects.rs:184:10
|
||||
--> $DIR/arithmetic_side_effects.rs:292:10
|
||||
|
|
||||
LL | _n = &1 - _n;
|
||||
| ^^^^^^^
|
||||
|
||||
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||
--> $DIR/arithmetic_side_effects.rs:185:10
|
||||
--> $DIR/arithmetic_side_effects.rs:293:10
|
||||
|
|
||||
LL | _n = _n / 0;
|
||||
| ^^^^^^
|
||||
|
||||
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||
--> $DIR/arithmetic_side_effects.rs:186:10
|
||||
--> $DIR/arithmetic_side_effects.rs:294:10
|
||||
|
|
||||
LL | _n = _n / &0;
|
||||
| ^^^^^^^
|
||||
|
||||
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||
--> $DIR/arithmetic_side_effects.rs:187:10
|
||||
--> $DIR/arithmetic_side_effects.rs:295:10
|
||||
|
|
||||
LL | _n = _n % 0;
|
||||
| ^^^^^^
|
||||
|
||||
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||
--> $DIR/arithmetic_side_effects.rs:188:10
|
||||
--> $DIR/arithmetic_side_effects.rs:296:10
|
||||
|
|
||||
LL | _n = _n % &0;
|
||||
| ^^^^^^^
|
||||
|
||||
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||
--> $DIR/arithmetic_side_effects.rs:189:10
|
||||
--> $DIR/arithmetic_side_effects.rs:297:10
|
||||
|
|
||||
LL | _n = _n * 2;
|
||||
| ^^^^^^
|
||||
|
||||
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||
--> $DIR/arithmetic_side_effects.rs:190:10
|
||||
--> $DIR/arithmetic_side_effects.rs:298:10
|
||||
|
|
||||
LL | _n = _n * &2;
|
||||
| ^^^^^^^
|
||||
|
||||
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||
--> $DIR/arithmetic_side_effects.rs:191:10
|
||||
--> $DIR/arithmetic_side_effects.rs:299:10
|
||||
|
|
||||
LL | _n = 2 * _n;
|
||||
| ^^^^^^
|
||||
|
||||
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||
--> $DIR/arithmetic_side_effects.rs:192:10
|
||||
--> $DIR/arithmetic_side_effects.rs:300:10
|
||||
|
|
||||
LL | _n = &2 * _n;
|
||||
| ^^^^^^^
|
||||
|
||||
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||
--> $DIR/arithmetic_side_effects.rs:193:10
|
||||
--> $DIR/arithmetic_side_effects.rs:301:10
|
||||
|
|
||||
LL | _n = 23 + &85;
|
||||
| ^^^^^^^^
|
||||
|
||||
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||
--> $DIR/arithmetic_side_effects.rs:194:10
|
||||
--> $DIR/arithmetic_side_effects.rs:302:10
|
||||
|
|
||||
LL | _n = &23 + 85;
|
||||
| ^^^^^^^^
|
||||
|
||||
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||
--> $DIR/arithmetic_side_effects.rs:195:10
|
||||
--> $DIR/arithmetic_side_effects.rs:303:10
|
||||
|
|
||||
LL | _n = &23 + &85;
|
||||
| ^^^^^^^^^
|
||||
|
||||
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||
--> $DIR/arithmetic_side_effects.rs:198:13
|
||||
--> $DIR/arithmetic_side_effects.rs:304:15
|
||||
|
|
||||
LL | let _ = Custom + 0;
|
||||
| ^^^^^^^^^^
|
||||
LL | _custom = _custom + _custom;
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||
--> $DIR/arithmetic_side_effects.rs:199:13
|
||||
--> $DIR/arithmetic_side_effects.rs:305:15
|
||||
|
|
||||
LL | let _ = Custom + 1;
|
||||
| ^^^^^^^^^^
|
||||
LL | _custom = _custom + &_custom;
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||
--> $DIR/arithmetic_side_effects.rs:200:13
|
||||
--> $DIR/arithmetic_side_effects.rs:306:15
|
||||
|
|
||||
LL | let _ = Custom + 2;
|
||||
| ^^^^^^^^^^
|
||||
LL | _custom = Custom + _custom;
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
||||
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||
--> $DIR/arithmetic_side_effects.rs:201:13
|
||||
--> $DIR/arithmetic_side_effects.rs:307:15
|
||||
|
|
||||
LL | let _ = Custom + 0.0;
|
||||
| ^^^^^^^^^^^^
|
||||
LL | _custom = &Custom + _custom;
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||
--> $DIR/arithmetic_side_effects.rs:202:13
|
||||
--> $DIR/arithmetic_side_effects.rs:308:15
|
||||
|
|
||||
LL | let _ = Custom + 1.0;
|
||||
| ^^^^^^^^^^^^
|
||||
LL | _custom = _custom - Custom;
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
||||
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||
--> $DIR/arithmetic_side_effects.rs:203:13
|
||||
--> $DIR/arithmetic_side_effects.rs:309:15
|
||||
|
|
||||
LL | let _ = Custom + 2.0;
|
||||
| ^^^^^^^^^^^^
|
||||
LL | _custom = _custom - &Custom;
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||
--> $DIR/arithmetic_side_effects.rs:204:13
|
||||
--> $DIR/arithmetic_side_effects.rs:310:15
|
||||
|
|
||||
LL | let _ = Custom - 0;
|
||||
| ^^^^^^^^^^
|
||||
LL | _custom = Custom - _custom;
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
||||
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||
--> $DIR/arithmetic_side_effects.rs:205:13
|
||||
--> $DIR/arithmetic_side_effects.rs:311:15
|
||||
|
|
||||
LL | let _ = Custom - 1;
|
||||
| ^^^^^^^^^^
|
||||
LL | _custom = &Custom - _custom;
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||
--> $DIR/arithmetic_side_effects.rs:206:13
|
||||
--> $DIR/arithmetic_side_effects.rs:312:15
|
||||
|
|
||||
LL | let _ = Custom - 2;
|
||||
| ^^^^^^^^^^
|
||||
LL | _custom = _custom / Custom;
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
||||
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||
--> $DIR/arithmetic_side_effects.rs:207:13
|
||||
--> $DIR/arithmetic_side_effects.rs:313:15
|
||||
|
|
||||
LL | let _ = Custom - 0.0;
|
||||
| ^^^^^^^^^^^^
|
||||
LL | _custom = _custom / &Custom;
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||
--> $DIR/arithmetic_side_effects.rs:208:13
|
||||
--> $DIR/arithmetic_side_effects.rs:314:15
|
||||
|
|
||||
LL | let _ = Custom - 1.0;
|
||||
| ^^^^^^^^^^^^
|
||||
LL | _custom = _custom % Custom;
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
||||
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||
--> $DIR/arithmetic_side_effects.rs:209:13
|
||||
--> $DIR/arithmetic_side_effects.rs:315:15
|
||||
|
|
||||
LL | let _ = Custom - 2.0;
|
||||
| ^^^^^^^^^^^^
|
||||
LL | _custom = _custom % &Custom;
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||
--> $DIR/arithmetic_side_effects.rs:210:13
|
||||
--> $DIR/arithmetic_side_effects.rs:316:15
|
||||
|
|
||||
LL | let _ = Custom / 0;
|
||||
| ^^^^^^^^^^
|
||||
LL | _custom = _custom * Custom;
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
||||
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||
--> $DIR/arithmetic_side_effects.rs:211:13
|
||||
--> $DIR/arithmetic_side_effects.rs:317:15
|
||||
|
|
||||
LL | let _ = Custom / 1;
|
||||
| ^^^^^^^^^^
|
||||
LL | _custom = _custom * &Custom;
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||
--> $DIR/arithmetic_side_effects.rs:212:13
|
||||
--> $DIR/arithmetic_side_effects.rs:318:15
|
||||
|
|
||||
LL | let _ = Custom / 2;
|
||||
| ^^^^^^^^^^
|
||||
LL | _custom = Custom * _custom;
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
||||
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||
--> $DIR/arithmetic_side_effects.rs:213:13
|
||||
--> $DIR/arithmetic_side_effects.rs:319:15
|
||||
|
|
||||
LL | let _ = Custom / 0.0;
|
||||
| ^^^^^^^^^^^^
|
||||
LL | _custom = &Custom * _custom;
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||
--> $DIR/arithmetic_side_effects.rs:214:13
|
||||
--> $DIR/arithmetic_side_effects.rs:320:15
|
||||
|
|
||||
LL | let _ = Custom / 1.0;
|
||||
| ^^^^^^^^^^^^
|
||||
LL | _custom = Custom + &Custom;
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
||||
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||
--> $DIR/arithmetic_side_effects.rs:215:13
|
||||
--> $DIR/arithmetic_side_effects.rs:321:15
|
||||
|
|
||||
LL | let _ = Custom / 2.0;
|
||||
| ^^^^^^^^^^^^
|
||||
LL | _custom = &Custom + Custom;
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
||||
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||
--> $DIR/arithmetic_side_effects.rs:216:13
|
||||
--> $DIR/arithmetic_side_effects.rs:322:15
|
||||
|
|
||||
LL | let _ = Custom * 0;
|
||||
| ^^^^^^^^^^
|
||||
LL | _custom = &Custom + &Custom;
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||
--> $DIR/arithmetic_side_effects.rs:217:13
|
||||
|
|
||||
LL | let _ = Custom * 1;
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||
--> $DIR/arithmetic_side_effects.rs:218:13
|
||||
|
|
||||
LL | let _ = Custom * 2;
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||
--> $DIR/arithmetic_side_effects.rs:219:13
|
||||
|
|
||||
LL | let _ = Custom * 0.0;
|
||||
| ^^^^^^^^^^^^
|
||||
|
||||
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||
--> $DIR/arithmetic_side_effects.rs:220:13
|
||||
|
|
||||
LL | let _ = Custom * 1.0;
|
||||
| ^^^^^^^^^^^^
|
||||
|
||||
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||
--> $DIR/arithmetic_side_effects.rs:221:13
|
||||
|
|
||||
LL | let _ = Custom * 2.0;
|
||||
| ^^^^^^^^^^^^
|
||||
|
||||
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||
--> $DIR/arithmetic_side_effects.rs:224:10
|
||||
--> $DIR/arithmetic_side_effects.rs:325:10
|
||||
|
|
||||
LL | _n = -_n;
|
||||
| ^^^
|
||||
|
||||
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||
--> $DIR/arithmetic_side_effects.rs:225:10
|
||||
--> $DIR/arithmetic_side_effects.rs:326:10
|
||||
|
|
||||
LL | _n = -&_n;
|
||||
| ^^^^
|
||||
|
||||
error: aborting due to 55 previous errors
|
||||
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||
--> $DIR/arithmetic_side_effects.rs:327:15
|
||||
|
|
||||
LL | _custom = -_custom;
|
||||
| ^^^^^^^^
|
||||
|
||||
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||
--> $DIR/arithmetic_side_effects.rs:328:15
|
||||
|
|
||||
LL | _custom = -&_custom;
|
||||
| ^^^^^^^^^
|
||||
|
||||
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||
--> $DIR/arithmetic_side_effects.rs:337:5
|
||||
|
|
||||
LL | 1 + i;
|
||||
| ^^^^^
|
||||
|
||||
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||
--> $DIR/arithmetic_side_effects.rs:338:5
|
||||
|
|
||||
LL | i * 2;
|
||||
| ^^^^^
|
||||
|
||||
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||
--> $DIR/arithmetic_side_effects.rs:340:5
|
||||
|
|
||||
LL | i - 2 + 2 - i;
|
||||
| ^^^^^^^^^^^^^
|
||||
|
||||
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||
--> $DIR/arithmetic_side_effects.rs:341:5
|
||||
|
|
||||
LL | -i;
|
||||
| ^^
|
||||
|
||||
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||
--> $DIR/arithmetic_side_effects.rs:342:5
|
||||
|
|
||||
LL | i >> 1;
|
||||
| ^^^^^^
|
||||
|
||||
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||
--> $DIR/arithmetic_side_effects.rs:343:5
|
||||
|
|
||||
LL | i << 1;
|
||||
| ^^^^^^
|
||||
|
||||
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||
--> $DIR/arithmetic_side_effects.rs:352:5
|
||||
|
|
||||
LL | i += 1;
|
||||
| ^^^^^^
|
||||
|
||||
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||
--> $DIR/arithmetic_side_effects.rs:353:5
|
||||
|
|
||||
LL | i -= 1;
|
||||
| ^^^^^^
|
||||
|
||||
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||
--> $DIR/arithmetic_side_effects.rs:354:5
|
||||
|
|
||||
LL | i *= 2;
|
||||
| ^^^^^^
|
||||
|
||||
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||
--> $DIR/arithmetic_side_effects.rs:356:5
|
||||
|
|
||||
LL | i /= 0;
|
||||
| ^^^^^^
|
||||
|
||||
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||
--> $DIR/arithmetic_side_effects.rs:358:5
|
||||
|
|
||||
LL | i /= var1;
|
||||
| ^^^^^^^^^
|
||||
|
||||
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||
--> $DIR/arithmetic_side_effects.rs:359:5
|
||||
|
|
||||
LL | i /= var2;
|
||||
| ^^^^^^^^^
|
||||
|
||||
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||
--> $DIR/arithmetic_side_effects.rs:361:5
|
||||
|
|
||||
LL | i %= 0;
|
||||
| ^^^^^^
|
||||
|
||||
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||
--> $DIR/arithmetic_side_effects.rs:363:5
|
||||
|
|
||||
LL | i %= var1;
|
||||
| ^^^^^^^^^
|
||||
|
||||
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||
--> $DIR/arithmetic_side_effects.rs:364:5
|
||||
|
|
||||
LL | i %= var2;
|
||||
| ^^^^^^^^^
|
||||
|
||||
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||
--> $DIR/arithmetic_side_effects.rs:365:5
|
||||
|
|
||||
LL | i <<= 3;
|
||||
| ^^^^^^^
|
||||
|
||||
error: arithmetic operation that can potentially result in unexpected side-effects
|
||||
--> $DIR/arithmetic_side_effects.rs:366:5
|
||||
|
|
||||
LL | i >>= 2;
|
||||
| ^^^^^^^
|
||||
|
||||
error: aborting due to 99 previous errors
|
||||
|
||||
|
@ -21,16 +21,16 @@ macro_rules! outer {
|
||||
fn main() {
|
||||
let _string: Box<String> = Box::default();
|
||||
let _byte = Box::<u8>::default();
|
||||
let _vec = Box::<std::vec::Vec<u8>>::default();
|
||||
let _vec = Box::<Vec<u8>>::default();
|
||||
let _impl = Box::<ImplementsDefault>::default();
|
||||
let _impl2 = Box::<ImplementsDefault>::default();
|
||||
let _impl3: Box<ImplementsDefault> = Box::default();
|
||||
let _own = Box::new(OwnDefault::default()); // should not lint
|
||||
let _in_macro = outer!(Box::<std::string::String>::default());
|
||||
let _string_default = outer!(Box::<std::string::String>::default());
|
||||
let _in_macro = outer!(Box::<String>::default());
|
||||
let _string_default = outer!(Box::<String>::default());
|
||||
let _vec2: Box<Vec<ImplementsDefault>> = Box::default();
|
||||
let _vec3: Box<Vec<bool>> = Box::default();
|
||||
let _vec4: Box<_> = Box::<std::vec::Vec<bool>>::default();
|
||||
let _vec4: Box<_> = Box::<Vec<bool>>::default();
|
||||
let _more = ret_ty_fn();
|
||||
call_ty_fn(Box::default());
|
||||
}
|
||||
@ -54,4 +54,14 @@ impl Read for ImplementsDefault {
|
||||
|
||||
fn issue_9621_dyn_trait() {
|
||||
let _: Box<dyn Read> = Box::<ImplementsDefault>::default();
|
||||
issue_10089();
|
||||
}
|
||||
|
||||
fn issue_10089() {
|
||||
let _closure = || {
|
||||
#[derive(Default)]
|
||||
struct WeirdPathed;
|
||||
|
||||
let _ = Box::<WeirdPathed>::default();
|
||||
};
|
||||
}
|
||||
|
@ -54,4 +54,14 @@ impl Read for ImplementsDefault {
|
||||
|
||||
fn issue_9621_dyn_trait() {
|
||||
let _: Box<dyn Read> = Box::new(ImplementsDefault::default());
|
||||
issue_10089();
|
||||
}
|
||||
|
||||
fn issue_10089() {
|
||||
let _closure = || {
|
||||
#[derive(Default)]
|
||||
struct WeirdPathed;
|
||||
|
||||
let _ = Box::new(WeirdPathed::default());
|
||||
};
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ error: `Box::new(_)` of default value
|
||||
--> $DIR/box_default.rs:24:16
|
||||
|
|
||||
LL | let _vec = Box::new(Vec::<u8>::new());
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::<std::vec::Vec<u8>>::default()`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::<Vec<u8>>::default()`
|
||||
|
||||
error: `Box::new(_)` of default value
|
||||
--> $DIR/box_default.rs:25:17
|
||||
@ -40,13 +40,13 @@ error: `Box::new(_)` of default value
|
||||
--> $DIR/box_default.rs:29:28
|
||||
|
|
||||
LL | let _in_macro = outer!(Box::new(String::new()));
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::<std::string::String>::default()`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::<String>::default()`
|
||||
|
||||
error: `Box::new(_)` of default value
|
||||
--> $DIR/box_default.rs:30:34
|
||||
|
|
||||
LL | let _string_default = outer!(Box::new(String::from("")));
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::<std::string::String>::default()`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::<String>::default()`
|
||||
|
||||
error: `Box::new(_)` of default value
|
||||
--> $DIR/box_default.rs:31:46
|
||||
@ -64,7 +64,7 @@ error: `Box::new(_)` of default value
|
||||
--> $DIR/box_default.rs:33:25
|
||||
|
|
||||
LL | let _vec4: Box<_> = Box::new(Vec::from([false; 0]));
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::<std::vec::Vec<bool>>::default()`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::<Vec<bool>>::default()`
|
||||
|
||||
error: `Box::new(_)` of default value
|
||||
--> $DIR/box_default.rs:35:16
|
||||
@ -84,5 +84,11 @@ error: `Box::new(_)` of default value
|
||||
LL | let _: Box<dyn Read> = Box::new(ImplementsDefault::default());
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::<ImplementsDefault>::default()`
|
||||
|
||||
error: aborting due to 14 previous errors
|
||||
error: `Box::new(_)` of default value
|
||||
--> $DIR/box_default.rs:65:17
|
||||
|
|
||||
LL | let _ = Box::new(WeirdPathed::default());
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::<WeirdPathed>::default()`
|
||||
|
||||
error: aborting due to 15 previous errors
|
||||
|
||||
|
@ -0,0 +1,67 @@
|
||||
// run-rustfix
|
||||
#![warn(clippy::case_sensitive_file_extension_comparisons)]
|
||||
|
||||
use std::string::String;
|
||||
|
||||
struct TestStruct;
|
||||
|
||||
impl TestStruct {
|
||||
fn ends_with(self, _arg: &str) {}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn is_rust_file(filename: &str) -> bool {
|
||||
std::path::Path::new(filename)
|
||||
.extension()
|
||||
.map_or(false, |ext| ext.eq_ignore_ascii_case("rs"))
|
||||
}
|
||||
|
||||
fn main() {
|
||||
// std::string::String and &str should trigger the lint failure with .ext12
|
||||
let _ = std::path::Path::new(&String::new())
|
||||
.extension()
|
||||
.map_or(false, |ext| ext.eq_ignore_ascii_case("ext12"));
|
||||
let _ = std::path::Path::new("str")
|
||||
.extension()
|
||||
.map_or(false, |ext| ext.eq_ignore_ascii_case("ext12"));
|
||||
|
||||
// The fixup should preserve the indentation level
|
||||
{
|
||||
let _ = std::path::Path::new("str")
|
||||
.extension()
|
||||
.map_or(false, |ext| ext.eq_ignore_ascii_case("ext12"));
|
||||
}
|
||||
|
||||
// The test struct should not trigger the lint failure with .ext12
|
||||
TestStruct {}.ends_with(".ext12");
|
||||
|
||||
// std::string::String and &str should trigger the lint failure with .EXT12
|
||||
let _ = std::path::Path::new(&String::new())
|
||||
.extension()
|
||||
.map_or(false, |ext| ext.eq_ignore_ascii_case("EXT12"));
|
||||
let _ = std::path::Path::new("str")
|
||||
.extension()
|
||||
.map_or(false, |ext| ext.eq_ignore_ascii_case("EXT12"));
|
||||
|
||||
// Should not trigger the lint failure because of the calls to to_lowercase and to_uppercase
|
||||
let _ = String::new().to_lowercase().ends_with(".EXT12");
|
||||
let _ = String::new().to_uppercase().ends_with(".EXT12");
|
||||
|
||||
// The test struct should not trigger the lint failure with .EXT12
|
||||
TestStruct {}.ends_with(".EXT12");
|
||||
|
||||
// Should not trigger the lint failure with .eXT12
|
||||
let _ = String::new().ends_with(".eXT12");
|
||||
let _ = "str".ends_with(".eXT12");
|
||||
TestStruct {}.ends_with(".eXT12");
|
||||
|
||||
// Should not trigger the lint failure with .EXT123 (too long)
|
||||
let _ = String::new().ends_with(".EXT123");
|
||||
let _ = "str".ends_with(".EXT123");
|
||||
TestStruct {}.ends_with(".EXT123");
|
||||
|
||||
// Shouldn't fail if it doesn't start with a dot
|
||||
let _ = String::new().ends_with("a.ext");
|
||||
let _ = "str".ends_with("a.extA");
|
||||
TestStruct {}.ends_with("a.ext");
|
||||
}
|
@ -1,3 +1,4 @@
|
||||
// run-rustfix
|
||||
#![warn(clippy::case_sensitive_file_extension_comparisons)]
|
||||
|
||||
use std::string::String;
|
||||
@ -5,9 +6,10 @@ use std::string::String;
|
||||
struct TestStruct;
|
||||
|
||||
impl TestStruct {
|
||||
fn ends_with(self, arg: &str) {}
|
||||
fn ends_with(self, _arg: &str) {}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn is_rust_file(filename: &str) -> bool {
|
||||
filename.ends_with(".rs")
|
||||
}
|
||||
@ -17,6 +19,11 @@ fn main() {
|
||||
let _ = String::new().ends_with(".ext12");
|
||||
let _ = "str".ends_with(".ext12");
|
||||
|
||||
// The fixup should preserve the indentation level
|
||||
{
|
||||
let _ = "str".ends_with(".ext12");
|
||||
}
|
||||
|
||||
// The test struct should not trigger the lint failure with .ext12
|
||||
TestStruct {}.ends_with(".ext12");
|
||||
|
||||
@ -24,6 +31,10 @@ fn main() {
|
||||
let _ = String::new().ends_with(".EXT12");
|
||||
let _ = "str".ends_with(".EXT12");
|
||||
|
||||
// Should not trigger the lint failure because of the calls to to_lowercase and to_uppercase
|
||||
let _ = String::new().to_lowercase().ends_with(".EXT12");
|
||||
let _ = String::new().to_uppercase().ends_with(".EXT12");
|
||||
|
||||
// The test struct should not trigger the lint failure with .EXT12
|
||||
TestStruct {}.ends_with(".EXT12");
|
||||
|
||||
|
@ -1,43 +1,87 @@
|
||||
error: case-sensitive file extension comparison
|
||||
--> $DIR/case_sensitive_file_extension_comparisons.rs:12:14
|
||||
--> $DIR/case_sensitive_file_extension_comparisons.rs:14:5
|
||||
|
|
||||
LL | filename.ends_with(".rs")
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: consider using a case-insensitive comparison instead
|
||||
= note: `-D clippy::case-sensitive-file-extension-comparisons` implied by `-D warnings`
|
||||
help: use std::path::Path
|
||||
|
|
||||
LL ~ std::path::Path::new(filename)
|
||||
LL + .extension()
|
||||
LL + .map_or(false, |ext| ext.eq_ignore_ascii_case("rs"))
|
||||
|
|
||||
|
||||
error: case-sensitive file extension comparison
|
||||
--> $DIR/case_sensitive_file_extension_comparisons.rs:17:27
|
||||
--> $DIR/case_sensitive_file_extension_comparisons.rs:19:13
|
||||
|
|
||||
LL | let _ = String::new().ends_with(".ext12");
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: consider using a case-insensitive comparison instead
|
||||
help: use std::path::Path
|
||||
|
|
||||
LL ~ let _ = std::path::Path::new(&String::new())
|
||||
LL + .extension()
|
||||
LL ~ .map_or(false, |ext| ext.eq_ignore_ascii_case("ext12"));
|
||||
|
|
||||
|
||||
error: case-sensitive file extension comparison
|
||||
--> $DIR/case_sensitive_file_extension_comparisons.rs:18:19
|
||||
--> $DIR/case_sensitive_file_extension_comparisons.rs:20:13
|
||||
|
|
||||
LL | let _ = "str".ends_with(".ext12");
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: consider using a case-insensitive comparison instead
|
||||
help: use std::path::Path
|
||||
|
|
||||
LL ~ let _ = std::path::Path::new("str")
|
||||
LL + .extension()
|
||||
LL ~ .map_or(false, |ext| ext.eq_ignore_ascii_case("ext12"));
|
||||
|
|
||||
|
||||
error: case-sensitive file extension comparison
|
||||
--> $DIR/case_sensitive_file_extension_comparisons.rs:24:27
|
||||
--> $DIR/case_sensitive_file_extension_comparisons.rs:24:17
|
||||
|
|
||||
LL | let _ = "str".ends_with(".ext12");
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: consider using a case-insensitive comparison instead
|
||||
help: use std::path::Path
|
||||
|
|
||||
LL ~ let _ = std::path::Path::new("str")
|
||||
LL + .extension()
|
||||
LL ~ .map_or(false, |ext| ext.eq_ignore_ascii_case("ext12"));
|
||||
|
|
||||
|
||||
error: case-sensitive file extension comparison
|
||||
--> $DIR/case_sensitive_file_extension_comparisons.rs:31:13
|
||||
|
|
||||
LL | let _ = String::new().ends_with(".EXT12");
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: consider using a case-insensitive comparison instead
|
||||
help: use std::path::Path
|
||||
|
|
||||
LL ~ let _ = std::path::Path::new(&String::new())
|
||||
LL + .extension()
|
||||
LL ~ .map_or(false, |ext| ext.eq_ignore_ascii_case("EXT12"));
|
||||
|
|
||||
|
||||
error: case-sensitive file extension comparison
|
||||
--> $DIR/case_sensitive_file_extension_comparisons.rs:25:19
|
||||
--> $DIR/case_sensitive_file_extension_comparisons.rs:32:13
|
||||
|
|
||||
LL | let _ = "str".ends_with(".EXT12");
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: consider using a case-insensitive comparison instead
|
||||
help: use std::path::Path
|
||||
|
|
||||
LL ~ let _ = std::path::Path::new("str")
|
||||
LL + .extension()
|
||||
LL ~ .map_or(false, |ext| ext.eq_ignore_ascii_case("EXT12"));
|
||||
|
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
error: aborting due to 6 previous errors
|
||||
|
||||
|
@ -48,7 +48,7 @@ error: using `clone` on type `i32` which implements the `Copy` trait
|
||||
LL | vec.push(42.clone());
|
||||
| ^^^^^^^^^^ help: try removing the `clone` call: `42`
|
||||
|
||||
error: using `clone` on type `std::option::Option<i32>` which implements the `Copy` trait
|
||||
error: using `clone` on type `Option<i32>` which implements the `Copy` trait
|
||||
--> $DIR/clone_on_copy.rs:77:17
|
||||
|
|
||||
LL | let value = opt.clone()?; // operator precedence needed (*opt)?
|
||||
|
@ -1,143 +1,143 @@
|
||||
error: `dbg!` macro is intended as a debugging tool
|
||||
error: the `dbg!` macro is intended as a debugging tool
|
||||
--> $DIR/dbg_macro.rs:5:22
|
||||
|
|
||||
LL | if let Some(n) = dbg!(n.checked_sub(4)) { n } else { n }
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: `-D clippy::dbg-macro` implied by `-D warnings`
|
||||
help: ensure to avoid having uses of it in version control
|
||||
help: remove the invocation before committing it to a version control system
|
||||
|
|
||||
LL | if let Some(n) = n.checked_sub(4) { n } else { n }
|
||||
| ~~~~~~~~~~~~~~~~
|
||||
|
||||
error: `dbg!` macro is intended as a debugging tool
|
||||
error: the `dbg!` macro is intended as a debugging tool
|
||||
--> $DIR/dbg_macro.rs:9:8
|
||||
|
|
||||
LL | if dbg!(n <= 1) {
|
||||
| ^^^^^^^^^^^^
|
||||
|
|
||||
help: ensure to avoid having uses of it in version control
|
||||
help: remove the invocation before committing it to a version control system
|
||||
|
|
||||
LL | if n <= 1 {
|
||||
| ~~~~~~
|
||||
|
||||
error: `dbg!` macro is intended as a debugging tool
|
||||
error: the `dbg!` macro is intended as a debugging tool
|
||||
--> $DIR/dbg_macro.rs:10:9
|
||||
|
|
||||
LL | dbg!(1)
|
||||
| ^^^^^^^
|
||||
|
|
||||
help: ensure to avoid having uses of it in version control
|
||||
help: remove the invocation before committing it to a version control system
|
||||
|
|
||||
LL | 1
|
||||
|
|
||||
|
||||
error: `dbg!` macro is intended as a debugging tool
|
||||
error: the `dbg!` macro is intended as a debugging tool
|
||||
--> $DIR/dbg_macro.rs:12:9
|
||||
|
|
||||
LL | dbg!(n * factorial(n - 1))
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: ensure to avoid having uses of it in version control
|
||||
help: remove the invocation before committing it to a version control system
|
||||
|
|
||||
LL | n * factorial(n - 1)
|
||||
|
|
||||
|
||||
error: `dbg!` macro is intended as a debugging tool
|
||||
error: the `dbg!` macro is intended as a debugging tool
|
||||
--> $DIR/dbg_macro.rs:17:5
|
||||
|
|
||||
LL | dbg!(42);
|
||||
| ^^^^^^^^
|
||||
|
|
||||
help: ensure to avoid having uses of it in version control
|
||||
help: remove the invocation before committing it to a version control system
|
||||
|
|
||||
LL | 42;
|
||||
| ~~
|
||||
|
||||
error: `dbg!` macro is intended as a debugging tool
|
||||
error: the `dbg!` macro is intended as a debugging tool
|
||||
--> $DIR/dbg_macro.rs:18:5
|
||||
|
|
||||
LL | dbg!(dbg!(dbg!(42)));
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: ensure to avoid having uses of it in version control
|
||||
help: remove the invocation before committing it to a version control system
|
||||
|
|
||||
LL | dbg!(dbg!(42));
|
||||
| ~~~~~~~~~~~~~~
|
||||
|
||||
error: `dbg!` macro is intended as a debugging tool
|
||||
error: the `dbg!` macro is intended as a debugging tool
|
||||
--> $DIR/dbg_macro.rs:19:14
|
||||
|
|
||||
LL | foo(3) + dbg!(factorial(4));
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: ensure to avoid having uses of it in version control
|
||||
help: remove the invocation before committing it to a version control system
|
||||
|
|
||||
LL | foo(3) + factorial(4);
|
||||
| ~~~~~~~~~~~~
|
||||
|
||||
error: `dbg!` macro is intended as a debugging tool
|
||||
error: the `dbg!` macro is intended as a debugging tool
|
||||
--> $DIR/dbg_macro.rs:20:5
|
||||
|
|
||||
LL | dbg!(1, 2, dbg!(3, 4));
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: ensure to avoid having uses of it in version control
|
||||
help: remove the invocation before committing it to a version control system
|
||||
|
|
||||
LL | (1, 2, dbg!(3, 4));
|
||||
| ~~~~~~~~~~~~~~~~~~
|
||||
|
||||
error: `dbg!` macro is intended as a debugging tool
|
||||
error: the `dbg!` macro is intended as a debugging tool
|
||||
--> $DIR/dbg_macro.rs:21:5
|
||||
|
|
||||
LL | dbg!(1, 2, 3, 4, 5);
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: ensure to avoid having uses of it in version control
|
||||
help: remove the invocation before committing it to a version control system
|
||||
|
|
||||
LL | (1, 2, 3, 4, 5);
|
||||
| ~~~~~~~~~~~~~~~
|
||||
|
||||
error: `dbg!` macro is intended as a debugging tool
|
||||
error: the `dbg!` macro is intended as a debugging tool
|
||||
--> $DIR/dbg_macro.rs:41:9
|
||||
|
|
||||
LL | dbg!(2);
|
||||
| ^^^^^^^
|
||||
|
|
||||
help: ensure to avoid having uses of it in version control
|
||||
help: remove the invocation before committing it to a version control system
|
||||
|
|
||||
LL | 2;
|
||||
| ~
|
||||
|
||||
error: `dbg!` macro is intended as a debugging tool
|
||||
error: the `dbg!` macro is intended as a debugging tool
|
||||
--> $DIR/dbg_macro.rs:47:5
|
||||
|
|
||||
LL | dbg!(1);
|
||||
| ^^^^^^^
|
||||
|
|
||||
help: ensure to avoid having uses of it in version control
|
||||
help: remove the invocation before committing it to a version control system
|
||||
|
|
||||
LL | 1;
|
||||
| ~
|
||||
|
||||
error: `dbg!` macro is intended as a debugging tool
|
||||
error: the `dbg!` macro is intended as a debugging tool
|
||||
--> $DIR/dbg_macro.rs:52:5
|
||||
|
|
||||
LL | dbg!(1);
|
||||
| ^^^^^^^
|
||||
|
|
||||
help: ensure to avoid having uses of it in version control
|
||||
help: remove the invocation before committing it to a version control system
|
||||
|
|
||||
LL | 1;
|
||||
| ~
|
||||
|
||||
error: `dbg!` macro is intended as a debugging tool
|
||||
error: the `dbg!` macro is intended as a debugging tool
|
||||
--> $DIR/dbg_macro.rs:58:9
|
||||
|
|
||||
LL | dbg!(1);
|
||||
| ^^^^^^^
|
||||
|
|
||||
help: ensure to avoid having uses of it in version control
|
||||
help: remove the invocation before committing it to a version control system
|
||||
|
|
||||
LL | 1;
|
||||
| ~
|
||||
|
@ -12,17 +12,17 @@ use std::default::Default as D2;
|
||||
use std::string;
|
||||
|
||||
fn main() {
|
||||
let s1: String = std::string::String::default();
|
||||
let s1: String = String::default();
|
||||
|
||||
let s2 = String::default();
|
||||
|
||||
let s3: String = std::string::String::default();
|
||||
let s3: String = String::default();
|
||||
|
||||
let s4: String = std::string::String::default();
|
||||
let s4: String = String::default();
|
||||
|
||||
let s5 = string::String::default();
|
||||
|
||||
let s6: String = std::string::String::default();
|
||||
let s6: String = String::default();
|
||||
|
||||
let s7 = std::string::String::default();
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
error: calling `std::string::String::default()` is more clear than this expression
|
||||
error: calling `String::default()` is more clear than this expression
|
||||
--> $DIR/default_trait_access.rs:15:22
|
||||
|
|
||||
LL | let s1: String = Default::default();
|
||||
| ^^^^^^^^^^^^^^^^^^ help: try: `std::string::String::default()`
|
||||
| ^^^^^^^^^^^^^^^^^^ help: try: `String::default()`
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/default_trait_access.rs:3:9
|
||||
@ -10,23 +10,23 @@ note: the lint level is defined here
|
||||
LL | #![deny(clippy::default_trait_access)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: calling `std::string::String::default()` is more clear than this expression
|
||||
error: calling `String::default()` is more clear than this expression
|
||||
--> $DIR/default_trait_access.rs:19:22
|
||||
|
|
||||
LL | let s3: String = D2::default();
|
||||
| ^^^^^^^^^^^^^ help: try: `std::string::String::default()`
|
||||
| ^^^^^^^^^^^^^ help: try: `String::default()`
|
||||
|
||||
error: calling `std::string::String::default()` is more clear than this expression
|
||||
error: calling `String::default()` is more clear than this expression
|
||||
--> $DIR/default_trait_access.rs:21:22
|
||||
|
|
||||
LL | let s4: String = std::default::Default::default();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::string::String::default()`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `String::default()`
|
||||
|
||||
error: calling `std::string::String::default()` is more clear than this expression
|
||||
error: calling `String::default()` is more clear than this expression
|
||||
--> $DIR/default_trait_access.rs:25:22
|
||||
|
|
||||
LL | let s6: String = default::Default::default();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::string::String::default()`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `String::default()`
|
||||
|
||||
error: calling `GenericDerivedDefault::default()` is more clear than this expression
|
||||
--> $DIR/default_trait_access.rs:35:46
|
||||
|
@ -210,4 +210,25 @@ impl Default for IntOrString {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub enum SimpleEnum {
|
||||
Foo,
|
||||
#[default]
|
||||
Bar,
|
||||
}
|
||||
|
||||
|
||||
|
||||
pub enum NonExhaustiveEnum {
|
||||
Foo,
|
||||
#[non_exhaustive]
|
||||
Bar,
|
||||
}
|
||||
|
||||
impl Default for NonExhaustiveEnum {
|
||||
fn default() -> Self {
|
||||
NonExhaustiveEnum::Bar
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
@ -244,4 +244,27 @@ impl Default for IntOrString {
|
||||
}
|
||||
}
|
||||
|
||||
pub enum SimpleEnum {
|
||||
Foo,
|
||||
Bar,
|
||||
}
|
||||
|
||||
impl Default for SimpleEnum {
|
||||
fn default() -> Self {
|
||||
SimpleEnum::Bar
|
||||
}
|
||||
}
|
||||
|
||||
pub enum NonExhaustiveEnum {
|
||||
Foo,
|
||||
#[non_exhaustive]
|
||||
Bar,
|
||||
}
|
||||
|
||||
impl Default for NonExhaustiveEnum {
|
||||
fn default() -> Self {
|
||||
NonExhaustiveEnum::Bar
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
@ -113,5 +113,26 @@ help: ...and instead derive it
|
||||
LL | #[derive(Default)]
|
||||
|
|
||||
|
||||
error: aborting due to 7 previous errors
|
||||
error: this `impl` can be derived
|
||||
--> $DIR/derivable_impls.rs:252:1
|
||||
|
|
||||
LL | / impl Default for SimpleEnum {
|
||||
LL | | fn default() -> Self {
|
||||
LL | | SimpleEnum::Bar
|
||||
LL | | }
|
||||
LL | | }
|
||||
| |_^
|
||||
|
|
||||
= help: remove the manual implementation...
|
||||
help: ...and instead derive it...
|
||||
|
|
||||
LL | #[derive(Default)]
|
||||
|
|
||||
help: ...and mark the default variant
|
||||
|
|
||||
LL ~ #[default]
|
||||
LL ~ Bar,
|
||||
|
|
||||
|
||||
error: aborting due to 8 previous errors
|
||||
|
||||
|
@ -86,4 +86,15 @@ impl<T: Clone, U> Clone for GenericRef<'_, T, U> {
|
||||
}
|
||||
}
|
||||
|
||||
// https://github.com/rust-lang/rust-clippy/issues/10188
|
||||
#[repr(packed)]
|
||||
#[derive(Copy)]
|
||||
struct Packed<T>(T);
|
||||
|
||||
impl<T: Copy> Clone for Packed<T> {
|
||||
fn clone(&self) -> Self {
|
||||
*self
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
@ -1,59 +0,0 @@
|
||||
error: you are deriving `Hash` but have implemented `PartialEq` explicitly
|
||||
--> $DIR/derive_hash_xor_eq.rs:12:10
|
||||
|
|
||||
LL | #[derive(Hash)]
|
||||
| ^^^^
|
||||
|
|
||||
note: `PartialEq` implemented here
|
||||
--> $DIR/derive_hash_xor_eq.rs:15:1
|
||||
|
|
||||
LL | impl PartialEq for Bar {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
= note: `#[deny(clippy::derive_hash_xor_eq)]` on by default
|
||||
= note: this error originates in the derive macro `Hash` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: you are deriving `Hash` but have implemented `PartialEq` explicitly
|
||||
--> $DIR/derive_hash_xor_eq.rs:21:10
|
||||
|
|
||||
LL | #[derive(Hash)]
|
||||
| ^^^^
|
||||
|
|
||||
note: `PartialEq` implemented here
|
||||
--> $DIR/derive_hash_xor_eq.rs:24:1
|
||||
|
|
||||
LL | impl PartialEq<Baz> for Baz {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= note: this error originates in the derive macro `Hash` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: you are implementing `Hash` explicitly but have derived `PartialEq`
|
||||
--> $DIR/derive_hash_xor_eq.rs:33:1
|
||||
|
|
||||
LL | / impl std::hash::Hash for Bah {
|
||||
LL | | fn hash<H: std::hash::Hasher>(&self, _: &mut H) {}
|
||||
LL | | }
|
||||
| |_^
|
||||
|
|
||||
note: `PartialEq` implemented here
|
||||
--> $DIR/derive_hash_xor_eq.rs:30:10
|
||||
|
|
||||
LL | #[derive(PartialEq)]
|
||||
| ^^^^^^^^^
|
||||
= note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: you are implementing `Hash` explicitly but have derived `PartialEq`
|
||||
--> $DIR/derive_hash_xor_eq.rs:51:5
|
||||
|
|
||||
LL | / impl Hash for Foo3 {
|
||||
LL | | fn hash<H: std::hash::Hasher>(&self, _: &mut H) {}
|
||||
LL | | }
|
||||
| |_____^
|
||||
|
|
||||
note: `PartialEq` implemented here
|
||||
--> $DIR/derive_hash_xor_eq.rs:48:14
|
||||
|
|
||||
LL | #[derive(PartialEq)]
|
||||
| ^^^^^^^^^
|
||||
= note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
@ -27,6 +27,8 @@ impl PartialEq<Baz> for Baz {
|
||||
}
|
||||
}
|
||||
|
||||
// Implementing `Hash` with a derived `PartialEq` is fine. See #2627
|
||||
|
||||
#[derive(PartialEq)]
|
||||
struct Bah;
|
||||
|
||||
@ -34,23 +36,4 @@ impl std::hash::Hash for Bah {
|
||||
fn hash<H: std::hash::Hasher>(&self, _: &mut H) {}
|
||||
}
|
||||
|
||||
#[derive(PartialEq)]
|
||||
struct Foo2;
|
||||
|
||||
trait Hash {}
|
||||
|
||||
// We don't want to lint on user-defined traits called `Hash`
|
||||
impl Hash for Foo2 {}
|
||||
|
||||
mod use_hash {
|
||||
use std::hash::{Hash, Hasher};
|
||||
|
||||
#[derive(PartialEq)]
|
||||
struct Foo3;
|
||||
|
||||
impl Hash for Foo3 {
|
||||
fn hash<H: std::hash::Hasher>(&self, _: &mut H) {}
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
29
src/tools/clippy/tests/ui/derived_hash_with_manual_eq.stderr
Normal file
29
src/tools/clippy/tests/ui/derived_hash_with_manual_eq.stderr
Normal file
@ -0,0 +1,29 @@
|
||||
error: you are deriving `Hash` but have implemented `PartialEq` explicitly
|
||||
--> $DIR/derived_hash_with_manual_eq.rs:12:10
|
||||
|
|
||||
LL | #[derive(Hash)]
|
||||
| ^^^^
|
||||
|
|
||||
note: `PartialEq` implemented here
|
||||
--> $DIR/derived_hash_with_manual_eq.rs:15:1
|
||||
|
|
||||
LL | impl PartialEq for Bar {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
= note: `#[deny(clippy::derived_hash_with_manual_eq)]` on by default
|
||||
= note: this error originates in the derive macro `Hash` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: you are deriving `Hash` but have implemented `PartialEq` explicitly
|
||||
--> $DIR/derived_hash_with_manual_eq.rs:21:10
|
||||
|
|
||||
LL | #[derive(Hash)]
|
||||
| ^^^^
|
||||
|
|
||||
note: `PartialEq` implemented here
|
||||
--> $DIR/derived_hash_with_manual_eq.rs:24:1
|
||||
|
|
||||
LL | impl PartialEq<Baz> for Baz {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= note: this error originates in the derive macro `Hash` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
@ -72,3 +72,26 @@ fn test_owl_result_2() -> Result<u8, ()> {
|
||||
produce_half_owl_ok().map(drop)?;
|
||||
Ok(1)
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
#[allow(clippy::unit_cmp)]
|
||||
fn issue10122(x: u8) {
|
||||
// This is a function which returns a reference and has a side-effect, which means
|
||||
// that calling drop() on the function is considered an idiomatic way of achieving the side-effect
|
||||
// in a match arm.
|
||||
fn println_and<T>(t: &T) -> &T {
|
||||
println!("foo");
|
||||
t
|
||||
}
|
||||
|
||||
match x {
|
||||
0 => drop(println_and(&12)), // Don't lint (copy type), we only care about side-effects
|
||||
1 => drop(println_and(&String::new())), // Don't lint (no copy type), we only care about side-effects
|
||||
2 => {
|
||||
drop(println_and(&13)); // Lint, even if we only care about the side-effect, it's already in a block
|
||||
},
|
||||
3 if drop(println_and(&14)) == () => (), // Lint, idiomatic use is only in body of `Arm`
|
||||
4 => drop(&2), // Lint, not a fn/method call
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
@ -107,5 +107,41 @@ note: argument has type `&SomeStruct`
|
||||
LL | std::mem::drop(&SomeStruct);
|
||||
| ^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 9 previous errors
|
||||
error: calls to `std::mem::drop` with a reference instead of an owned value. Dropping a reference does nothing
|
||||
--> $DIR/drop_ref.rs:91:13
|
||||
|
|
||||
LL | drop(println_and(&13)); // Lint, even if we only care about the side-effect, it's already in a block
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: argument has type `&i32`
|
||||
--> $DIR/drop_ref.rs:91:18
|
||||
|
|
||||
LL | drop(println_and(&13)); // Lint, even if we only care about the side-effect, it's already in a block
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
||||
error: calls to `std::mem::drop` with a reference instead of an owned value. Dropping a reference does nothing
|
||||
--> $DIR/drop_ref.rs:93:14
|
||||
|
|
||||
LL | 3 if drop(println_and(&14)) == () => (), // Lint, idiomatic use is only in body of `Arm`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: argument has type `&i32`
|
||||
--> $DIR/drop_ref.rs:93:19
|
||||
|
|
||||
LL | 3 if drop(println_and(&14)) == () => (), // Lint, idiomatic use is only in body of `Arm`
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
||||
error: calls to `std::mem::drop` with a reference instead of an owned value. Dropping a reference does nothing
|
||||
--> $DIR/drop_ref.rs:94:14
|
||||
|
|
||||
LL | 4 => drop(&2), // Lint, not a fn/method call
|
||||
| ^^^^^^^^
|
||||
|
|
||||
note: argument has type `&i32`
|
||||
--> $DIR/drop_ref.rs:94:19
|
||||
|
|
||||
LL | 4 => drop(&2), // Lint, not a fn/method call
|
||||
| ^^
|
||||
|
||||
error: aborting due to 12 previous errors
|
||||
|
||||
|
@ -247,3 +247,24 @@ mod issue6312 {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct Collection {
|
||||
items: Vec<i32>,
|
||||
len: usize,
|
||||
}
|
||||
|
||||
impl Default for Collection {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
items: vec![1, 2, 3],
|
||||
len: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::redundant_closure_call)]
|
||||
fn issue10136() {
|
||||
let mut c = Collection::default();
|
||||
// don't lint, since c.items was used to calculate this value
|
||||
c.len = (|| c.items.len())();
|
||||
}
|
||||
|
@ -1,14 +1,15 @@
|
||||
// run-rustfix
|
||||
|
||||
#![warn(clippy::iter_kv_map)]
|
||||
#![allow(clippy::redundant_clone)]
|
||||
#![allow(clippy::suspicious_map)]
|
||||
#![allow(clippy::map_identity)]
|
||||
#![allow(unused_mut, clippy::redundant_clone, clippy::suspicious_map, clippy::map_identity)]
|
||||
|
||||
use std::collections::{BTreeMap, HashMap};
|
||||
|
||||
fn main() {
|
||||
let get_key = |(key, _val)| key;
|
||||
fn ref_acceptor(v: &u32) -> u32 {
|
||||
*v
|
||||
}
|
||||
|
||||
let map: HashMap<u32, u32> = HashMap::new();
|
||||
|
||||
@ -36,6 +37,20 @@ fn main() {
|
||||
let _ = map.keys().map(|key| key * 9).count();
|
||||
let _ = map.values().map(|value| value * 17).count();
|
||||
|
||||
// Preserve the ref in the fix.
|
||||
let _ = map.clone().into_values().map(|ref val| ref_acceptor(val)).count();
|
||||
|
||||
// Preserve the mut in the fix.
|
||||
let _ = map
|
||||
.clone().into_values().map(|mut val| {
|
||||
val += 2;
|
||||
val
|
||||
})
|
||||
.count();
|
||||
|
||||
// Don't let a mut interfere.
|
||||
let _ = map.clone().into_values().count();
|
||||
|
||||
let map: BTreeMap<u32, u32> = BTreeMap::new();
|
||||
|
||||
let _ = map.keys().collect::<Vec<_>>();
|
||||
@ -61,4 +76,18 @@ fn main() {
|
||||
// Lint
|
||||
let _ = map.keys().map(|key| key * 9).count();
|
||||
let _ = map.values().map(|value| value * 17).count();
|
||||
|
||||
// Preserve the ref in the fix.
|
||||
let _ = map.clone().into_values().map(|ref val| ref_acceptor(val)).count();
|
||||
|
||||
// Preserve the mut in the fix.
|
||||
let _ = map
|
||||
.clone().into_values().map(|mut val| {
|
||||
val += 2;
|
||||
val
|
||||
})
|
||||
.count();
|
||||
|
||||
// Don't let a mut interfere.
|
||||
let _ = map.clone().into_values().count();
|
||||
}
|
||||
|
@ -1,14 +1,15 @@
|
||||
// run-rustfix
|
||||
|
||||
#![warn(clippy::iter_kv_map)]
|
||||
#![allow(clippy::redundant_clone)]
|
||||
#![allow(clippy::suspicious_map)]
|
||||
#![allow(clippy::map_identity)]
|
||||
#![allow(unused_mut, clippy::redundant_clone, clippy::suspicious_map, clippy::map_identity)]
|
||||
|
||||
use std::collections::{BTreeMap, HashMap};
|
||||
|
||||
fn main() {
|
||||
let get_key = |(key, _val)| key;
|
||||
fn ref_acceptor(v: &u32) -> u32 {
|
||||
*v
|
||||
}
|
||||
|
||||
let map: HashMap<u32, u32> = HashMap::new();
|
||||
|
||||
@ -36,6 +37,22 @@ fn main() {
|
||||
let _ = map.iter().map(|(key, _value)| key * 9).count();
|
||||
let _ = map.iter().map(|(_key, value)| value * 17).count();
|
||||
|
||||
// Preserve the ref in the fix.
|
||||
let _ = map.clone().into_iter().map(|(_, ref val)| ref_acceptor(val)).count();
|
||||
|
||||
// Preserve the mut in the fix.
|
||||
let _ = map
|
||||
.clone()
|
||||
.into_iter()
|
||||
.map(|(_, mut val)| {
|
||||
val += 2;
|
||||
val
|
||||
})
|
||||
.count();
|
||||
|
||||
// Don't let a mut interfere.
|
||||
let _ = map.clone().into_iter().map(|(_, mut val)| val).count();
|
||||
|
||||
let map: BTreeMap<u32, u32> = BTreeMap::new();
|
||||
|
||||
let _ = map.iter().map(|(key, _)| key).collect::<Vec<_>>();
|
||||
@ -61,4 +78,20 @@ fn main() {
|
||||
// Lint
|
||||
let _ = map.iter().map(|(key, _value)| key * 9).count();
|
||||
let _ = map.iter().map(|(_key, value)| value * 17).count();
|
||||
|
||||
// Preserve the ref in the fix.
|
||||
let _ = map.clone().into_iter().map(|(_, ref val)| ref_acceptor(val)).count();
|
||||
|
||||
// Preserve the mut in the fix.
|
||||
let _ = map
|
||||
.clone()
|
||||
.into_iter()
|
||||
.map(|(_, mut val)| {
|
||||
val += 2;
|
||||
val
|
||||
})
|
||||
.count();
|
||||
|
||||
// Don't let a mut interfere.
|
||||
let _ = map.clone().into_iter().map(|(_, mut val)| val).count();
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
error: iterating on a map's keys
|
||||
--> $DIR/iter_kv_map.rs:15:13
|
||||
--> $DIR/iter_kv_map.rs:16:13
|
||||
|
|
||||
LL | let _ = map.iter().map(|(key, _)| key).collect::<Vec<_>>();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.keys()`
|
||||
@ -7,130 +7,198 @@ LL | let _ = map.iter().map(|(key, _)| key).collect::<Vec<_>>();
|
||||
= note: `-D clippy::iter-kv-map` implied by `-D warnings`
|
||||
|
||||
error: iterating on a map's values
|
||||
--> $DIR/iter_kv_map.rs:16:13
|
||||
--> $DIR/iter_kv_map.rs:17:13
|
||||
|
|
||||
LL | let _ = map.iter().map(|(_, value)| value).collect::<Vec<_>>();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.values()`
|
||||
|
||||
error: iterating on a map's values
|
||||
--> $DIR/iter_kv_map.rs:17:13
|
||||
--> $DIR/iter_kv_map.rs:18:13
|
||||
|
|
||||
LL | let _ = map.iter().map(|(_, v)| v + 2).collect::<Vec<_>>();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.values().map(|v| v + 2)`
|
||||
|
||||
error: iterating on a map's keys
|
||||
--> $DIR/iter_kv_map.rs:19:13
|
||||
--> $DIR/iter_kv_map.rs:20:13
|
||||
|
|
||||
LL | let _ = map.clone().into_iter().map(|(key, _)| key).collect::<Vec<_>>();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_keys()`
|
||||
|
||||
error: iterating on a map's keys
|
||||
--> $DIR/iter_kv_map.rs:20:13
|
||||
--> $DIR/iter_kv_map.rs:21:13
|
||||
|
|
||||
LL | let _ = map.clone().into_iter().map(|(key, _)| key + 2).collect::<Vec<_>>();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_keys().map(|key| key + 2)`
|
||||
|
||||
error: iterating on a map's values
|
||||
--> $DIR/iter_kv_map.rs:22:13
|
||||
--> $DIR/iter_kv_map.rs:23:13
|
||||
|
|
||||
LL | let _ = map.clone().into_iter().map(|(_, val)| val).collect::<Vec<_>>();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_values()`
|
||||
|
||||
error: iterating on a map's values
|
||||
--> $DIR/iter_kv_map.rs:23:13
|
||||
--> $DIR/iter_kv_map.rs:24:13
|
||||
|
|
||||
LL | let _ = map.clone().into_iter().map(|(_, val)| val + 2).collect::<Vec<_>>();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_values().map(|val| val + 2)`
|
||||
|
||||
error: iterating on a map's values
|
||||
--> $DIR/iter_kv_map.rs:25:13
|
||||
--> $DIR/iter_kv_map.rs:26:13
|
||||
|
|
||||
LL | let _ = map.clone().iter().map(|(_, val)| val).collect::<Vec<_>>();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().values()`
|
||||
|
||||
error: iterating on a map's keys
|
||||
--> $DIR/iter_kv_map.rs:26:13
|
||||
--> $DIR/iter_kv_map.rs:27:13
|
||||
|
|
||||
LL | let _ = map.iter().map(|(key, _)| key).filter(|x| *x % 2 == 0).count();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.keys()`
|
||||
|
||||
error: iterating on a map's keys
|
||||
--> $DIR/iter_kv_map.rs:36:13
|
||||
--> $DIR/iter_kv_map.rs:37:13
|
||||
|
|
||||
LL | let _ = map.iter().map(|(key, _value)| key * 9).count();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.keys().map(|key| key * 9)`
|
||||
|
||||
error: iterating on a map's values
|
||||
--> $DIR/iter_kv_map.rs:37:13
|
||||
--> $DIR/iter_kv_map.rs:38:13
|
||||
|
|
||||
LL | let _ = map.iter().map(|(_key, value)| value * 17).count();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.values().map(|value| value * 17)`
|
||||
|
||||
error: iterating on a map's keys
|
||||
error: iterating on a map's values
|
||||
--> $DIR/iter_kv_map.rs:41:13
|
||||
|
|
||||
LL | let _ = map.clone().into_iter().map(|(_, ref val)| ref_acceptor(val)).count();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_values().map(|ref val| ref_acceptor(val))`
|
||||
|
||||
error: iterating on a map's values
|
||||
--> $DIR/iter_kv_map.rs:44:13
|
||||
|
|
||||
LL | let _ = map
|
||||
| _____________^
|
||||
LL | | .clone()
|
||||
LL | | .into_iter()
|
||||
LL | | .map(|(_, mut val)| {
|
||||
LL | | val += 2;
|
||||
LL | | val
|
||||
LL | | })
|
||||
| |__________^
|
||||
|
|
||||
help: try
|
||||
|
|
||||
LL ~ let _ = map
|
||||
LL + .clone().into_values().map(|mut val| {
|
||||
LL + val += 2;
|
||||
LL + val
|
||||
LL + })
|
||||
|
|
||||
|
||||
error: iterating on a map's values
|
||||
--> $DIR/iter_kv_map.rs:54:13
|
||||
|
|
||||
LL | let _ = map.clone().into_iter().map(|(_, mut val)| val).count();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_values()`
|
||||
|
||||
error: iterating on a map's keys
|
||||
--> $DIR/iter_kv_map.rs:58:13
|
||||
|
|
||||
LL | let _ = map.iter().map(|(key, _)| key).collect::<Vec<_>>();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.keys()`
|
||||
|
||||
error: iterating on a map's values
|
||||
--> $DIR/iter_kv_map.rs:42:13
|
||||
--> $DIR/iter_kv_map.rs:59:13
|
||||
|
|
||||
LL | let _ = map.iter().map(|(_, value)| value).collect::<Vec<_>>();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.values()`
|
||||
|
||||
error: iterating on a map's values
|
||||
--> $DIR/iter_kv_map.rs:43:13
|
||||
--> $DIR/iter_kv_map.rs:60:13
|
||||
|
|
||||
LL | let _ = map.iter().map(|(_, v)| v + 2).collect::<Vec<_>>();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.values().map(|v| v + 2)`
|
||||
|
||||
error: iterating on a map's keys
|
||||
--> $DIR/iter_kv_map.rs:45:13
|
||||
--> $DIR/iter_kv_map.rs:62:13
|
||||
|
|
||||
LL | let _ = map.clone().into_iter().map(|(key, _)| key).collect::<Vec<_>>();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_keys()`
|
||||
|
||||
error: iterating on a map's keys
|
||||
--> $DIR/iter_kv_map.rs:46:13
|
||||
--> $DIR/iter_kv_map.rs:63:13
|
||||
|
|
||||
LL | let _ = map.clone().into_iter().map(|(key, _)| key + 2).collect::<Vec<_>>();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_keys().map(|key| key + 2)`
|
||||
|
||||
error: iterating on a map's values
|
||||
--> $DIR/iter_kv_map.rs:48:13
|
||||
--> $DIR/iter_kv_map.rs:65:13
|
||||
|
|
||||
LL | let _ = map.clone().into_iter().map(|(_, val)| val).collect::<Vec<_>>();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_values()`
|
||||
|
||||
error: iterating on a map's values
|
||||
--> $DIR/iter_kv_map.rs:49:13
|
||||
--> $DIR/iter_kv_map.rs:66:13
|
||||
|
|
||||
LL | let _ = map.clone().into_iter().map(|(_, val)| val + 2).collect::<Vec<_>>();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_values().map(|val| val + 2)`
|
||||
|
||||
error: iterating on a map's values
|
||||
--> $DIR/iter_kv_map.rs:51:13
|
||||
--> $DIR/iter_kv_map.rs:68:13
|
||||
|
|
||||
LL | let _ = map.clone().iter().map(|(_, val)| val).collect::<Vec<_>>();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().values()`
|
||||
|
||||
error: iterating on a map's keys
|
||||
--> $DIR/iter_kv_map.rs:52:13
|
||||
--> $DIR/iter_kv_map.rs:69:13
|
||||
|
|
||||
LL | let _ = map.iter().map(|(key, _)| key).filter(|x| *x % 2 == 0).count();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.keys()`
|
||||
|
||||
error: iterating on a map's keys
|
||||
--> $DIR/iter_kv_map.rs:62:13
|
||||
--> $DIR/iter_kv_map.rs:79:13
|
||||
|
|
||||
LL | let _ = map.iter().map(|(key, _value)| key * 9).count();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.keys().map(|key| key * 9)`
|
||||
|
||||
error: iterating on a map's values
|
||||
--> $DIR/iter_kv_map.rs:63:13
|
||||
--> $DIR/iter_kv_map.rs:80:13
|
||||
|
|
||||
LL | let _ = map.iter().map(|(_key, value)| value * 17).count();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.values().map(|value| value * 17)`
|
||||
|
||||
error: aborting due to 22 previous errors
|
||||
error: iterating on a map's values
|
||||
--> $DIR/iter_kv_map.rs:83:13
|
||||
|
|
||||
LL | let _ = map.clone().into_iter().map(|(_, ref val)| ref_acceptor(val)).count();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_values().map(|ref val| ref_acceptor(val))`
|
||||
|
||||
error: iterating on a map's values
|
||||
--> $DIR/iter_kv_map.rs:86:13
|
||||
|
|
||||
LL | let _ = map
|
||||
| _____________^
|
||||
LL | | .clone()
|
||||
LL | | .into_iter()
|
||||
LL | | .map(|(_, mut val)| {
|
||||
LL | | val += 2;
|
||||
LL | | val
|
||||
LL | | })
|
||||
| |__________^
|
||||
|
|
||||
help: try
|
||||
|
|
||||
LL ~ let _ = map
|
||||
LL + .clone().into_values().map(|mut val| {
|
||||
LL + val += 2;
|
||||
LL + val
|
||||
LL + })
|
||||
|
|
||||
|
||||
error: iterating on a map's values
|
||||
--> $DIR/iter_kv_map.rs:96:13
|
||||
|
|
||||
LL | let _ = map.clone().into_iter().map(|(_, mut val)| val).count();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_values()`
|
||||
|
||||
error: aborting due to 28 previous errors
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
// run-rustfix
|
||||
#![feature(custom_inner_attributes, lint_reasons, rustc_private)]
|
||||
#![feature(lint_reasons)]
|
||||
#![allow(
|
||||
unused,
|
||||
clippy::uninlined_format_args,
|
||||
@ -491,14 +491,3 @@ mod issue_9782_method_variant {
|
||||
S.foo::<&[u8; 100]>(&a);
|
||||
}
|
||||
}
|
||||
|
||||
extern crate rustc_lint;
|
||||
extern crate rustc_span;
|
||||
|
||||
#[allow(dead_code)]
|
||||
mod span_lint {
|
||||
use rustc_lint::{LateContext, Lint, LintContext};
|
||||
fn foo(cx: &LateContext<'_>, lint: &'static Lint) {
|
||||
cx.struct_span_lint(lint, rustc_span::Span::default(), "", |diag| diag.note(String::new()));
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
// run-rustfix
|
||||
#![feature(custom_inner_attributes, lint_reasons, rustc_private)]
|
||||
#![feature(lint_reasons)]
|
||||
#![allow(
|
||||
unused,
|
||||
clippy::uninlined_format_args,
|
||||
@ -491,14 +491,3 @@ mod issue_9782_method_variant {
|
||||
S.foo::<&[u8; 100]>(&a);
|
||||
}
|
||||
}
|
||||
|
||||
extern crate rustc_lint;
|
||||
extern crate rustc_span;
|
||||
|
||||
#[allow(dead_code)]
|
||||
mod span_lint {
|
||||
use rustc_lint::{LateContext, Lint, LintContext};
|
||||
fn foo(cx: &LateContext<'_>, lint: &'static Lint) {
|
||||
cx.struct_span_lint(lint, rustc_span::Span::default(), "", |diag| diag.note(&String::new()));
|
||||
}
|
||||
}
|
||||
|
@ -216,11 +216,5 @@ error: the borrowed expression implements the required traits
|
||||
LL | foo(&a);
|
||||
| ^^ help: change this to: `a`
|
||||
|
||||
error: the borrowed expression implements the required traits
|
||||
--> $DIR/needless_borrow.rs:502:85
|
||||
|
|
||||
LL | cx.struct_span_lint(lint, rustc_span::Span::default(), "", |diag| diag.note(&String::new()));
|
||||
| ^^^^^^^^^^^^^^ help: change this to: `String::new()`
|
||||
|
||||
error: aborting due to 37 previous errors
|
||||
error: aborting due to 36 previous errors
|
||||
|
||||
|
@ -277,4 +277,14 @@ fn issue9947() -> Result<(), String> {
|
||||
do yeet "hello";
|
||||
}
|
||||
|
||||
// without anyhow, but triggers the same bug I believe
|
||||
#[expect(clippy::useless_format)]
|
||||
fn issue10051() -> Result<String, String> {
|
||||
if true {
|
||||
Ok(format!("ok!"))
|
||||
} else {
|
||||
Err(format!("err!"))
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
@ -287,4 +287,14 @@ fn issue9947() -> Result<(), String> {
|
||||
do yeet "hello";
|
||||
}
|
||||
|
||||
// without anyhow, but triggers the same bug I believe
|
||||
#[expect(clippy::useless_format)]
|
||||
fn issue10051() -> Result<String, String> {
|
||||
if true {
|
||||
return Ok(format!("ok!"));
|
||||
} else {
|
||||
return Err(format!("err!"));
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
@ -386,5 +386,21 @@ LL | let _ = 42; return;
|
||||
|
|
||||
= help: remove `return`
|
||||
|
||||
error: aborting due to 46 previous errors
|
||||
error: unneeded `return` statement
|
||||
--> $DIR/needless_return.rs:294:9
|
||||
|
|
||||
LL | return Ok(format!("ok!"));
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: remove `return`
|
||||
|
||||
error: unneeded `return` statement
|
||||
--> $DIR/needless_return.rs:296:9
|
||||
|
|
||||
LL | return Err(format!("err!"));
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: remove `return`
|
||||
|
||||
error: aborting due to 48 previous errors
|
||||
|
||||
|
@ -239,9 +239,3 @@ fn false_negative_5707() {
|
||||
let _z = x.clone(); // pr 7346 can't lint on `x`
|
||||
drop(y);
|
||||
}
|
||||
|
||||
#[allow(unused, clippy::manual_retain)]
|
||||
fn possible_borrower_improvements() {
|
||||
let mut s = String::from("foobar");
|
||||
s = s.chars().filter(|&c| c != 'o').collect();
|
||||
}
|
||||
|
@ -239,9 +239,3 @@ fn false_negative_5707() {
|
||||
let _z = x.clone(); // pr 7346 can't lint on `x`
|
||||
drop(y);
|
||||
}
|
||||
|
||||
#[allow(unused, clippy::manual_retain)]
|
||||
fn possible_borrower_improvements() {
|
||||
let mut s = String::from("foobar");
|
||||
s = s.chars().filter(|&c| c != 'o').to_owned().collect();
|
||||
}
|
||||
|
@ -179,17 +179,5 @@ note: this value is dropped without further use
|
||||
LL | foo(&x.clone(), move || {
|
||||
| ^
|
||||
|
||||
error: redundant clone
|
||||
--> $DIR/redundant_clone.rs:246:40
|
||||
|
|
||||
LL | s = s.chars().filter(|&c| c != 'o').to_owned().collect();
|
||||
| ^^^^^^^^^^^ help: remove this
|
||||
|
|
||||
note: this value is dropped without further use
|
||||
--> $DIR/redundant_clone.rs:246:9
|
||||
|
|
||||
LL | s = s.chars().filter(|&c| c != 'o').to_owned().collect();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 16 previous errors
|
||||
error: aborting due to 15 previous errors
|
||||
|
||||
|
@ -10,6 +10,7 @@
|
||||
#![allow(clippy::box_collection)]
|
||||
#![allow(clippy::redundant_static_lifetimes)]
|
||||
#![allow(clippy::cognitive_complexity)]
|
||||
#![allow(clippy::derived_hash_with_manual_eq)]
|
||||
#![allow(clippy::disallowed_methods)]
|
||||
#![allow(clippy::disallowed_types)]
|
||||
#![allow(clippy::mixed_read_write_in_expression)]
|
||||
@ -45,6 +46,7 @@
|
||||
#![warn(clippy::box_collection)]
|
||||
#![warn(clippy::redundant_static_lifetimes)]
|
||||
#![warn(clippy::cognitive_complexity)]
|
||||
#![warn(clippy::derived_hash_with_manual_eq)]
|
||||
#![warn(clippy::disallowed_methods)]
|
||||
#![warn(clippy::disallowed_types)]
|
||||
#![warn(clippy::mixed_read_write_in_expression)]
|
||||
|
@ -10,6 +10,7 @@
|
||||
#![allow(clippy::box_collection)]
|
||||
#![allow(clippy::redundant_static_lifetimes)]
|
||||
#![allow(clippy::cognitive_complexity)]
|
||||
#![allow(clippy::derived_hash_with_manual_eq)]
|
||||
#![allow(clippy::disallowed_methods)]
|
||||
#![allow(clippy::disallowed_types)]
|
||||
#![allow(clippy::mixed_read_write_in_expression)]
|
||||
@ -45,6 +46,7 @@
|
||||
#![warn(clippy::box_vec)]
|
||||
#![warn(clippy::const_static_lifetime)]
|
||||
#![warn(clippy::cyclomatic_complexity)]
|
||||
#![warn(clippy::derive_hash_xor_eq)]
|
||||
#![warn(clippy::disallowed_method)]
|
||||
#![warn(clippy::disallowed_type)]
|
||||
#![warn(clippy::eval_order_dependence)]
|
||||
|
@ -1,5 +1,5 @@
|
||||
error: lint `clippy::almost_complete_letter_range` has been renamed to `clippy::almost_complete_range`
|
||||
--> $DIR/rename.rs:41:9
|
||||
--> $DIR/rename.rs:42:9
|
||||
|
|
||||
LL | #![warn(clippy::almost_complete_letter_range)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::almost_complete_range`
|
||||
@ -7,244 +7,250 @@ LL | #![warn(clippy::almost_complete_letter_range)]
|
||||
= note: `-D renamed-and-removed-lints` implied by `-D warnings`
|
||||
|
||||
error: lint `clippy::blacklisted_name` has been renamed to `clippy::disallowed_names`
|
||||
--> $DIR/rename.rs:42:9
|
||||
--> $DIR/rename.rs:43:9
|
||||
|
|
||||
LL | #![warn(clippy::blacklisted_name)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_names`
|
||||
|
||||
error: lint `clippy::block_in_if_condition_expr` has been renamed to `clippy::blocks_in_if_conditions`
|
||||
--> $DIR/rename.rs:43:9
|
||||
--> $DIR/rename.rs:44:9
|
||||
|
|
||||
LL | #![warn(clippy::block_in_if_condition_expr)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_if_conditions`
|
||||
|
||||
error: lint `clippy::block_in_if_condition_stmt` has been renamed to `clippy::blocks_in_if_conditions`
|
||||
--> $DIR/rename.rs:44:9
|
||||
--> $DIR/rename.rs:45:9
|
||||
|
|
||||
LL | #![warn(clippy::block_in_if_condition_stmt)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_if_conditions`
|
||||
|
||||
error: lint `clippy::box_vec` has been renamed to `clippy::box_collection`
|
||||
--> $DIR/rename.rs:45:9
|
||||
--> $DIR/rename.rs:46:9
|
||||
|
|
||||
LL | #![warn(clippy::box_vec)]
|
||||
| ^^^^^^^^^^^^^^^ help: use the new name: `clippy::box_collection`
|
||||
|
||||
error: lint `clippy::const_static_lifetime` has been renamed to `clippy::redundant_static_lifetimes`
|
||||
--> $DIR/rename.rs:46:9
|
||||
--> $DIR/rename.rs:47:9
|
||||
|
|
||||
LL | #![warn(clippy::const_static_lifetime)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::redundant_static_lifetimes`
|
||||
|
||||
error: lint `clippy::cyclomatic_complexity` has been renamed to `clippy::cognitive_complexity`
|
||||
--> $DIR/rename.rs:47:9
|
||||
--> $DIR/rename.rs:48:9
|
||||
|
|
||||
LL | #![warn(clippy::cyclomatic_complexity)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::cognitive_complexity`
|
||||
|
||||
error: lint `clippy::derive_hash_xor_eq` has been renamed to `clippy::derived_hash_with_manual_eq`
|
||||
--> $DIR/rename.rs:49:9
|
||||
|
|
||||
LL | #![warn(clippy::derive_hash_xor_eq)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::derived_hash_with_manual_eq`
|
||||
|
||||
error: lint `clippy::disallowed_method` has been renamed to `clippy::disallowed_methods`
|
||||
--> $DIR/rename.rs:48:9
|
||||
--> $DIR/rename.rs:50:9
|
||||
|
|
||||
LL | #![warn(clippy::disallowed_method)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_methods`
|
||||
|
||||
error: lint `clippy::disallowed_type` has been renamed to `clippy::disallowed_types`
|
||||
--> $DIR/rename.rs:49:9
|
||||
--> $DIR/rename.rs:51:9
|
||||
|
|
||||
LL | #![warn(clippy::disallowed_type)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_types`
|
||||
|
||||
error: lint `clippy::eval_order_dependence` has been renamed to `clippy::mixed_read_write_in_expression`
|
||||
--> $DIR/rename.rs:50:9
|
||||
--> $DIR/rename.rs:52:9
|
||||
|
|
||||
LL | #![warn(clippy::eval_order_dependence)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::mixed_read_write_in_expression`
|
||||
|
||||
error: lint `clippy::identity_conversion` has been renamed to `clippy::useless_conversion`
|
||||
--> $DIR/rename.rs:51:9
|
||||
--> $DIR/rename.rs:53:9
|
||||
|
|
||||
LL | #![warn(clippy::identity_conversion)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::useless_conversion`
|
||||
|
||||
error: lint `clippy::if_let_some_result` has been renamed to `clippy::match_result_ok`
|
||||
--> $DIR/rename.rs:52:9
|
||||
--> $DIR/rename.rs:54:9
|
||||
|
|
||||
LL | #![warn(clippy::if_let_some_result)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::match_result_ok`
|
||||
|
||||
error: lint `clippy::logic_bug` has been renamed to `clippy::overly_complex_bool_expr`
|
||||
--> $DIR/rename.rs:53:9
|
||||
--> $DIR/rename.rs:55:9
|
||||
|
|
||||
LL | #![warn(clippy::logic_bug)]
|
||||
| ^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::overly_complex_bool_expr`
|
||||
|
||||
error: lint `clippy::new_without_default_derive` has been renamed to `clippy::new_without_default`
|
||||
--> $DIR/rename.rs:54:9
|
||||
--> $DIR/rename.rs:56:9
|
||||
|
|
||||
LL | #![warn(clippy::new_without_default_derive)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::new_without_default`
|
||||
|
||||
error: lint `clippy::option_and_then_some` has been renamed to `clippy::bind_instead_of_map`
|
||||
--> $DIR/rename.rs:55:9
|
||||
--> $DIR/rename.rs:57:9
|
||||
|
|
||||
LL | #![warn(clippy::option_and_then_some)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::bind_instead_of_map`
|
||||
|
||||
error: lint `clippy::option_expect_used` has been renamed to `clippy::expect_used`
|
||||
--> $DIR/rename.rs:56:9
|
||||
--> $DIR/rename.rs:58:9
|
||||
|
|
||||
LL | #![warn(clippy::option_expect_used)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::expect_used`
|
||||
|
||||
error: lint `clippy::option_map_unwrap_or` has been renamed to `clippy::map_unwrap_or`
|
||||
--> $DIR/rename.rs:57:9
|
||||
--> $DIR/rename.rs:59:9
|
||||
|
|
||||
LL | #![warn(clippy::option_map_unwrap_or)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or`
|
||||
|
||||
error: lint `clippy::option_map_unwrap_or_else` has been renamed to `clippy::map_unwrap_or`
|
||||
--> $DIR/rename.rs:58:9
|
||||
--> $DIR/rename.rs:60:9
|
||||
|
|
||||
LL | #![warn(clippy::option_map_unwrap_or_else)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or`
|
||||
|
||||
error: lint `clippy::option_unwrap_used` has been renamed to `clippy::unwrap_used`
|
||||
--> $DIR/rename.rs:59:9
|
||||
--> $DIR/rename.rs:61:9
|
||||
|
|
||||
LL | #![warn(clippy::option_unwrap_used)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_used`
|
||||
|
||||
error: lint `clippy::ref_in_deref` has been renamed to `clippy::needless_borrow`
|
||||
--> $DIR/rename.rs:60:9
|
||||
--> $DIR/rename.rs:62:9
|
||||
|
|
||||
LL | #![warn(clippy::ref_in_deref)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::needless_borrow`
|
||||
|
||||
error: lint `clippy::result_expect_used` has been renamed to `clippy::expect_used`
|
||||
--> $DIR/rename.rs:61:9
|
||||
--> $DIR/rename.rs:63:9
|
||||
|
|
||||
LL | #![warn(clippy::result_expect_used)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::expect_used`
|
||||
|
||||
error: lint `clippy::result_map_unwrap_or_else` has been renamed to `clippy::map_unwrap_or`
|
||||
--> $DIR/rename.rs:62:9
|
||||
--> $DIR/rename.rs:64:9
|
||||
|
|
||||
LL | #![warn(clippy::result_map_unwrap_or_else)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or`
|
||||
|
||||
error: lint `clippy::result_unwrap_used` has been renamed to `clippy::unwrap_used`
|
||||
--> $DIR/rename.rs:63:9
|
||||
--> $DIR/rename.rs:65:9
|
||||
|
|
||||
LL | #![warn(clippy::result_unwrap_used)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_used`
|
||||
|
||||
error: lint `clippy::single_char_push_str` has been renamed to `clippy::single_char_add_str`
|
||||
--> $DIR/rename.rs:64:9
|
||||
--> $DIR/rename.rs:66:9
|
||||
|
|
||||
LL | #![warn(clippy::single_char_push_str)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::single_char_add_str`
|
||||
|
||||
error: lint `clippy::stutter` has been renamed to `clippy::module_name_repetitions`
|
||||
--> $DIR/rename.rs:65:9
|
||||
--> $DIR/rename.rs:67:9
|
||||
|
|
||||
LL | #![warn(clippy::stutter)]
|
||||
| ^^^^^^^^^^^^^^^ help: use the new name: `clippy::module_name_repetitions`
|
||||
|
||||
error: lint `clippy::to_string_in_display` has been renamed to `clippy::recursive_format_impl`
|
||||
--> $DIR/rename.rs:66:9
|
||||
--> $DIR/rename.rs:68:9
|
||||
|
|
||||
LL | #![warn(clippy::to_string_in_display)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::recursive_format_impl`
|
||||
|
||||
error: lint `clippy::zero_width_space` has been renamed to `clippy::invisible_characters`
|
||||
--> $DIR/rename.rs:67:9
|
||||
--> $DIR/rename.rs:69:9
|
||||
|
|
||||
LL | #![warn(clippy::zero_width_space)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::invisible_characters`
|
||||
|
||||
error: lint `clippy::drop_bounds` has been renamed to `drop_bounds`
|
||||
--> $DIR/rename.rs:68:9
|
||||
--> $DIR/rename.rs:70:9
|
||||
|
|
||||
LL | #![warn(clippy::drop_bounds)]
|
||||
| ^^^^^^^^^^^^^^^^^^^ help: use the new name: `drop_bounds`
|
||||
|
||||
error: lint `clippy::for_loop_over_option` has been renamed to `for_loops_over_fallibles`
|
||||
--> $DIR/rename.rs:69:9
|
||||
--> $DIR/rename.rs:71:9
|
||||
|
|
||||
LL | #![warn(clippy::for_loop_over_option)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles`
|
||||
|
||||
error: lint `clippy::for_loop_over_result` has been renamed to `for_loops_over_fallibles`
|
||||
--> $DIR/rename.rs:70:9
|
||||
--> $DIR/rename.rs:72:9
|
||||
|
|
||||
LL | #![warn(clippy::for_loop_over_result)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles`
|
||||
|
||||
error: lint `clippy::for_loops_over_fallibles` has been renamed to `for_loops_over_fallibles`
|
||||
--> $DIR/rename.rs:71:9
|
||||
--> $DIR/rename.rs:73:9
|
||||
|
|
||||
LL | #![warn(clippy::for_loops_over_fallibles)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles`
|
||||
|
||||
error: lint `clippy::into_iter_on_array` has been renamed to `array_into_iter`
|
||||
--> $DIR/rename.rs:72:9
|
||||
--> $DIR/rename.rs:74:9
|
||||
|
|
||||
LL | #![warn(clippy::into_iter_on_array)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `array_into_iter`
|
||||
|
||||
error: lint `clippy::invalid_atomic_ordering` has been renamed to `invalid_atomic_ordering`
|
||||
--> $DIR/rename.rs:73:9
|
||||
--> $DIR/rename.rs:75:9
|
||||
|
|
||||
LL | #![warn(clippy::invalid_atomic_ordering)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_atomic_ordering`
|
||||
|
||||
error: lint `clippy::invalid_ref` has been renamed to `invalid_value`
|
||||
--> $DIR/rename.rs:74:9
|
||||
--> $DIR/rename.rs:76:9
|
||||
|
|
||||
LL | #![warn(clippy::invalid_ref)]
|
||||
| ^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_value`
|
||||
|
||||
error: lint `clippy::let_underscore_drop` has been renamed to `let_underscore_drop`
|
||||
--> $DIR/rename.rs:75:9
|
||||
--> $DIR/rename.rs:77:9
|
||||
|
|
||||
LL | #![warn(clippy::let_underscore_drop)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `let_underscore_drop`
|
||||
|
||||
error: lint `clippy::mem_discriminant_non_enum` has been renamed to `enum_intrinsics_non_enums`
|
||||
--> $DIR/rename.rs:76:9
|
||||
--> $DIR/rename.rs:78:9
|
||||
|
|
||||
LL | #![warn(clippy::mem_discriminant_non_enum)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `enum_intrinsics_non_enums`
|
||||
|
||||
error: lint `clippy::panic_params` has been renamed to `non_fmt_panics`
|
||||
--> $DIR/rename.rs:77:9
|
||||
--> $DIR/rename.rs:79:9
|
||||
|
|
||||
LL | #![warn(clippy::panic_params)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `non_fmt_panics`
|
||||
|
||||
error: lint `clippy::positional_named_format_parameters` has been renamed to `named_arguments_used_positionally`
|
||||
--> $DIR/rename.rs:78:9
|
||||
--> $DIR/rename.rs:80:9
|
||||
|
|
||||
LL | #![warn(clippy::positional_named_format_parameters)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `named_arguments_used_positionally`
|
||||
|
||||
error: lint `clippy::temporary_cstring_as_ptr` has been renamed to `temporary_cstring_as_ptr`
|
||||
--> $DIR/rename.rs:79:9
|
||||
--> $DIR/rename.rs:81:9
|
||||
|
|
||||
LL | #![warn(clippy::temporary_cstring_as_ptr)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `temporary_cstring_as_ptr`
|
||||
|
||||
error: lint `clippy::unknown_clippy_lints` has been renamed to `unknown_lints`
|
||||
--> $DIR/rename.rs:80:9
|
||||
--> $DIR/rename.rs:82:9
|
||||
|
|
||||
LL | #![warn(clippy::unknown_clippy_lints)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unknown_lints`
|
||||
|
||||
error: lint `clippy::unused_label` has been renamed to `unused_labels`
|
||||
--> $DIR/rename.rs:81:9
|
||||
--> $DIR/rename.rs:83:9
|
||||
|
|
||||
LL | #![warn(clippy::unused_label)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unused_labels`
|
||||
|
||||
error: aborting due to 41 previous errors
|
||||
error: aborting due to 42 previous errors
|
||||
|
||||
|
@ -33,4 +33,31 @@ fn main() {
|
||||
let item = 0..5;
|
||||
dbg!(item);
|
||||
}
|
||||
|
||||
// should not lint (issue #10018)
|
||||
for e in [42] {
|
||||
if e > 0 {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// should not lint (issue #10018)
|
||||
for e in [42] {
|
||||
if e > 0 {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// should lint (issue #10018)
|
||||
{
|
||||
let _ = 42;
|
||||
let _f = |n: u32| {
|
||||
for i in 0..n {
|
||||
if i > 10 {
|
||||
dbg!(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -27,4 +27,30 @@ fn main() {
|
||||
for item in [0..5].into_iter() {
|
||||
dbg!(item);
|
||||
}
|
||||
|
||||
// should not lint (issue #10018)
|
||||
for e in [42] {
|
||||
if e > 0 {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// should not lint (issue #10018)
|
||||
for e in [42] {
|
||||
if e > 0 {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// should lint (issue #10018)
|
||||
for _ in [42] {
|
||||
let _f = |n: u32| {
|
||||
for i in 0..n {
|
||||
if i > 10 {
|
||||
dbg!(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -95,5 +95,32 @@ LL + dbg!(item);
|
||||
LL + }
|
||||
|
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
error: for loop over a single element
|
||||
--> $DIR/single_element_loop.rs:46:5
|
||||
|
|
||||
LL | / for _ in [42] {
|
||||
LL | | let _f = |n: u32| {
|
||||
LL | | for i in 0..n {
|
||||
LL | | if i > 10 {
|
||||
... |
|
||||
LL | | };
|
||||
LL | | }
|
||||
| |_____^
|
||||
|
|
||||
help: try
|
||||
|
|
||||
LL ~ {
|
||||
LL + let _ = 42;
|
||||
LL + let _f = |n: u32| {
|
||||
LL + for i in 0..n {
|
||||
LL + if i > 10 {
|
||||
LL + dbg!(i);
|
||||
LL + break;
|
||||
LL + }
|
||||
LL + }
|
||||
LL + };
|
||||
LL + }
|
||||
|
|
||||
|
||||
error: aborting due to 7 previous errors
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
error: this `to_owned` call clones the std::borrow::Cow<'_, str> itself and does not cause the std::borrow::Cow<'_, str> contents to become owned
|
||||
error: this `to_owned` call clones the Cow<'_, str> itself and does not cause the Cow<'_, str> contents to become owned
|
||||
--> $DIR/suspicious_to_owned.rs:16:13
|
||||
|
|
||||
LL | let _ = cow.to_owned();
|
||||
@ -6,19 +6,19 @@ LL | let _ = cow.to_owned();
|
||||
|
|
||||
= note: `-D clippy::suspicious-to-owned` implied by `-D warnings`
|
||||
|
||||
error: this `to_owned` call clones the std::borrow::Cow<'_, [char; 3]> itself and does not cause the std::borrow::Cow<'_, [char; 3]> contents to become owned
|
||||
error: this `to_owned` call clones the Cow<'_, [char; 3]> itself and does not cause the Cow<'_, [char; 3]> contents to become owned
|
||||
--> $DIR/suspicious_to_owned.rs:26:13
|
||||
|
|
||||
LL | let _ = cow.to_owned();
|
||||
| ^^^^^^^^^^^^^^ help: consider using, depending on intent: `cow.clone()` or `cow.into_owned()`
|
||||
|
||||
error: this `to_owned` call clones the std::borrow::Cow<'_, std::vec::Vec<char>> itself and does not cause the std::borrow::Cow<'_, std::vec::Vec<char>> contents to become owned
|
||||
error: this `to_owned` call clones the Cow<'_, Vec<char>> itself and does not cause the Cow<'_, Vec<char>> contents to become owned
|
||||
--> $DIR/suspicious_to_owned.rs:36:13
|
||||
|
|
||||
LL | let _ = cow.to_owned();
|
||||
| ^^^^^^^^^^^^^^ help: consider using, depending on intent: `cow.clone()` or `cow.into_owned()`
|
||||
|
||||
error: this `to_owned` call clones the std::borrow::Cow<'_, str> itself and does not cause the std::borrow::Cow<'_, str> contents to become owned
|
||||
error: this `to_owned` call clones the Cow<'_, str> itself and does not cause the Cow<'_, str> contents to become owned
|
||||
--> $DIR/suspicious_to_owned.rs:46:13
|
||||
|
|
||||
LL | let _ = cow.to_owned();
|
||||
|
@ -38,13 +38,13 @@ LL | t.clone();
|
||||
|
|
||||
= note: `-D clippy::clone-on-copy` implied by `-D warnings`
|
||||
|
||||
error: using `clone` on type `std::option::Option<T>` which implements the `Copy` trait
|
||||
error: using `clone` on type `Option<T>` which implements the `Copy` trait
|
||||
--> $DIR/unnecessary_clone.rs:42:5
|
||||
|
|
||||
LL | Some(t).clone();
|
||||
| ^^^^^^^^^^^^^^^ help: try removing the `clone` call: `Some(t)`
|
||||
|
||||
error: using `clone` on a double-reference; this will copy the reference of type `&std::vec::Vec<i32>` instead of cloning the inner type
|
||||
error: using `clone` on a double-reference; this will copy the reference of type `&Vec<i32>` instead of cloning the inner type
|
||||
--> $DIR/unnecessary_clone.rs:48:22
|
||||
|
|
||||
LL | let z: &Vec<_> = y.clone();
|
||||
@ -57,10 +57,10 @@ LL | let z: &Vec<_> = &(*y).clone();
|
||||
| ~~~~~~~~~~~~~
|
||||
help: or try being explicit if you are sure, that you want to clone a reference
|
||||
|
|
||||
LL | let z: &Vec<_> = <&std::vec::Vec<i32>>::clone(y);
|
||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
LL | let z: &Vec<_> = <&Vec<i32>>::clone(y);
|
||||
| ~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
error: using `clone` on type `many_derefs::E` which implements the `Copy` trait
|
||||
error: using `clone` on type `E` which implements the `Copy` trait
|
||||
--> $DIR/unnecessary_clone.rs:84:20
|
||||
|
|
||||
LL | let _: E = a.clone();
|
||||
|
@ -60,6 +60,16 @@ mod unused_self_allow {
|
||||
// shouldn't trigger for public methods
|
||||
pub fn unused_self_move(self) {}
|
||||
}
|
||||
|
||||
pub struct E;
|
||||
|
||||
impl E {
|
||||
// shouldn't trigger if body contains todo!()
|
||||
pub fn unused_self_todo(self) {
|
||||
let x = 42;
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub use unused_self_allow::D;
|
||||
|
@ -4,7 +4,7 @@ error: unused `self` argument
|
||||
LL | fn unused_self_move(self) {}
|
||||
| ^^^^
|
||||
|
|
||||
= help: consider refactoring to a associated function
|
||||
= help: consider refactoring to an associated function
|
||||
= note: `-D clippy::unused-self` implied by `-D warnings`
|
||||
|
||||
error: unused `self` argument
|
||||
@ -13,7 +13,7 @@ error: unused `self` argument
|
||||
LL | fn unused_self_ref(&self) {}
|
||||
| ^^^^^
|
||||
|
|
||||
= help: consider refactoring to a associated function
|
||||
= help: consider refactoring to an associated function
|
||||
|
||||
error: unused `self` argument
|
||||
--> $DIR/unused_self.rs:13:32
|
||||
@ -21,7 +21,7 @@ error: unused `self` argument
|
||||
LL | fn unused_self_mut_ref(&mut self) {}
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= help: consider refactoring to a associated function
|
||||
= help: consider refactoring to an associated function
|
||||
|
||||
error: unused `self` argument
|
||||
--> $DIR/unused_self.rs:14:32
|
||||
@ -29,7 +29,7 @@ error: unused `self` argument
|
||||
LL | fn unused_self_pin_ref(self: Pin<&Self>) {}
|
||||
| ^^^^
|
||||
|
|
||||
= help: consider refactoring to a associated function
|
||||
= help: consider refactoring to an associated function
|
||||
|
||||
error: unused `self` argument
|
||||
--> $DIR/unused_self.rs:15:36
|
||||
@ -37,7 +37,7 @@ error: unused `self` argument
|
||||
LL | fn unused_self_pin_mut_ref(self: Pin<&mut Self>) {}
|
||||
| ^^^^
|
||||
|
|
||||
= help: consider refactoring to a associated function
|
||||
= help: consider refactoring to an associated function
|
||||
|
||||
error: unused `self` argument
|
||||
--> $DIR/unused_self.rs:16:35
|
||||
@ -45,7 +45,7 @@ error: unused `self` argument
|
||||
LL | fn unused_self_pin_nested(self: Pin<Arc<Self>>) {}
|
||||
| ^^^^
|
||||
|
|
||||
= help: consider refactoring to a associated function
|
||||
= help: consider refactoring to an associated function
|
||||
|
||||
error: unused `self` argument
|
||||
--> $DIR/unused_self.rs:17:28
|
||||
@ -53,7 +53,7 @@ error: unused `self` argument
|
||||
LL | fn unused_self_box(self: Box<Self>) {}
|
||||
| ^^^^
|
||||
|
|
||||
= help: consider refactoring to a associated function
|
||||
= help: consider refactoring to an associated function
|
||||
|
||||
error: unused `self` argument
|
||||
--> $DIR/unused_self.rs:18:40
|
||||
@ -61,7 +61,7 @@ error: unused `self` argument
|
||||
LL | fn unused_with_other_used_args(&self, x: u8, y: u8) -> u8 {
|
||||
| ^^^^^
|
||||
|
|
||||
= help: consider refactoring to a associated function
|
||||
= help: consider refactoring to an associated function
|
||||
|
||||
error: unused `self` argument
|
||||
--> $DIR/unused_self.rs:21:37
|
||||
@ -69,7 +69,7 @@ error: unused `self` argument
|
||||
LL | fn unused_self_class_method(&self) {
|
||||
| ^^^^^
|
||||
|
|
||||
= help: consider refactoring to a associated function
|
||||
= help: consider refactoring to an associated function
|
||||
|
||||
error: aborting due to 9 previous errors
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user