Add msrv config for map_clone

This commit is contained in:
xFrednet 2022-01-14 23:45:05 +01:00
parent 5cada57f30
commit 9e7858545a
No known key found for this signature in database
GPG key ID: FCDCBF29AF64D601
5 changed files with 56 additions and 29 deletions

View file

@ -581,6 +581,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
store.register_late_pass(move || Box::new(needless_question_mark::NeedlessQuestionMark));
store.register_late_pass(move || Box::new(casts::Casts::new(msrv)));
store.register_early_pass(move || Box::new(unnested_or_patterns::UnnestedOrPatterns::new(msrv)));
store.register_late_pass(move || Box::new(map_clone::MapClone::new(msrv)));
store.register_late_pass(|| Box::new(size_of_in_element_count::SizeOfInElementCount));
store.register_late_pass(|| Box::new(same_name_method::SameNameMethod));
@ -591,7 +592,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
msrv,
))
});
store.register_late_pass(|| Box::new(map_clone::MapClone));
store.register_late_pass(|| Box::new(map_err_ignore::MapErrIgnore));
store.register_late_pass(|| Box::new(shadow::Shadow::default()));
store.register_late_pass(|| Box::new(unit_types::UnitTypes));

View file

@ -1,15 +1,16 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::snippet_with_applicability;
use clippy_utils::ty::{is_copy, is_type_diagnostic_item};
use clippy_utils::{is_trait_method, peel_blocks};
use clippy_utils::{is_trait_method, meets_msrv, msrvs, peel_blocks};
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir as hir;
use rustc_lint::{LateContext, LateLintPass};
use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::mir::Mutability;
use rustc_middle::ty;
use rustc_middle::ty::adjustment::Adjust;
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_semver::RustcVersion;
use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::symbol::Ident;
use rustc_span::{sym, Span};
@ -42,7 +43,17 @@ declare_clippy_lint! {
"using `iterator.map(|x| x.clone())`, or dereferencing closures for `Copy` types"
}
declare_lint_pass!(MapClone => [MAP_CLONE]);
pub struct MapClone {
msrv: Option<RustcVersion>,
}
impl_lint_pass!(MapClone => [MAP_CLONE]);
impl MapClone {
pub fn new(msrv: Option<RustcVersion>) -> Self {
Self { msrv }
}
}
impl<'tcx> LateLintPass<'tcx> for MapClone {
fn check_expr(&mut self, cx: &LateContext<'_>, e: &hir::Expr<'_>) {
@ -65,7 +76,7 @@ impl<'tcx> LateLintPass<'tcx> for MapClone {
hir::BindingAnnotation::Unannotated, .., name, None
) = inner.kind {
if ident_eq(name, closure_expr) {
lint(cx, e.span, args[0].span, true);
self.lint_explicit_closure(cx, e.span, args[0].span, true);
}
},
hir::PatKind::Binding(hir::BindingAnnotation::Unannotated, .., name, None) => {
@ -73,7 +84,7 @@ impl<'tcx> LateLintPass<'tcx> for MapClone {
hir::ExprKind::Unary(hir::UnOp::Deref, inner) => {
if ident_eq(name, inner) {
if let ty::Ref(.., Mutability::Not) = cx.typeck_results().expr_ty(inner).kind() {
lint(cx, e.span, args[0].span, true);
self.lint_explicit_closure(cx, e.span, args[0].span, true);
}
}
},
@ -90,7 +101,7 @@ impl<'tcx> LateLintPass<'tcx> for MapClone {
if let ty::Ref(_, ty, mutability) = obj_ty.kind() {
if matches!(mutability, Mutability::Not) {
let copy = is_copy(cx, ty);
lint(cx, e.span, args[0].span, copy);
self.lint_explicit_closure(cx, e.span, args[0].span, copy);
}
} else {
lint_needless_cloning(cx, e.span, args[0].span);
@ -105,6 +116,8 @@ impl<'tcx> LateLintPass<'tcx> for MapClone {
}
}
}
extract_msrv_attr!(LateContext);
}
fn ident_eq(name: Ident, path: &hir::Expr<'_>) -> bool {
@ -127,31 +140,30 @@ fn lint_needless_cloning(cx: &LateContext<'_>, root: Span, receiver: Span) {
);
}
fn lint(cx: &LateContext<'_>, replace: Span, root: Span, copied: bool) {
let mut applicability = Applicability::MachineApplicable;
if copied {
impl MapClone {
fn lint_explicit_closure(&self, cx: &LateContext<'_>, replace: Span, root: Span, is_copy: bool) {
let mut applicability = Applicability::MachineApplicable;
let message = if is_copy {
"you are using an explicit closure for copying elements"
} else {
"you are using an explicit closure for cloning elements"
};
let sugg_method = if is_copy && meets_msrv(self.msrv.as_ref(), &msrvs::ITERATOR_COPIED) {
"copied"
} else {
"cloned"
};
span_lint_and_sugg(
cx,
MAP_CLONE,
replace,
"you are using an explicit closure for copying elements",
"consider calling the dedicated `copied` method",
message,
&format!("consider calling the dedicated `{}` method", sugg_method),
format!(
"{}.copied()",
snippet_with_applicability(cx, root, "..", &mut applicability)
),
applicability,
);
} else {
span_lint_and_sugg(
cx,
MAP_CLONE,
replace,
"you are using an explicit closure for cloning elements",
"consider calling the dedicated `cloned` method",
format!(
"{}.cloned()",
snippet_with_applicability(cx, root, "..", &mut applicability)
"{}.{}()",
snippet_with_applicability(cx, root, "..", &mut applicability),
sugg_method,
),
applicability,
);

View file

@ -156,7 +156,7 @@ define_Conf! {
///
/// Suppress lints whenever the suggested change would cause breakage for other crates.
(avoid_breaking_exported_api: bool = true),
/// Lint: MANUAL_SPLIT_ONCE, MANUAL_STR_REPEAT, CLONED_INSTEAD_OF_COPIED, REDUNDANT_FIELD_NAMES, REDUNDANT_STATIC_LIFETIMES, FILTER_MAP_NEXT, CHECKED_CONVERSIONS, MANUAL_RANGE_CONTAINS, USE_SELF, MEM_REPLACE_WITH_DEFAULT, MANUAL_NON_EXHAUSTIVE, OPTION_AS_REF_DEREF, MAP_UNWRAP_OR, MATCH_LIKE_MATCHES_MACRO, MANUAL_STRIP, MISSING_CONST_FOR_FN, UNNESTED_OR_PATTERNS, FROM_OVER_INTO, PTR_AS_PTR, IF_THEN_SOME_ELSE_NONE, APPROX_CONSTANT, DEPRECATED_CFG_ATTR, INDEX_REFUTABLE_SLICE.
/// Lint: MANUAL_SPLIT_ONCE, MANUAL_STR_REPEAT, CLONED_INSTEAD_OF_COPIED, REDUNDANT_FIELD_NAMES, REDUNDANT_STATIC_LIFETIMES, FILTER_MAP_NEXT, CHECKED_CONVERSIONS, MANUAL_RANGE_CONTAINS, USE_SELF, MEM_REPLACE_WITH_DEFAULT, MANUAL_NON_EXHAUSTIVE, OPTION_AS_REF_DEREF, MAP_UNWRAP_OR, MATCH_LIKE_MATCHES_MACRO, MANUAL_STRIP, MISSING_CONST_FOR_FN, UNNESTED_OR_PATTERNS, FROM_OVER_INTO, PTR_AS_PTR, IF_THEN_SOME_ELSE_NONE, APPROX_CONSTANT, DEPRECATED_CFG_ATTR, INDEX_REFUTABLE_SLICE, MAP_CLONE.
///
/// The minimum rust version that the project supports
(msrv: Option<String> = None),

View file

@ -68,6 +68,11 @@ fn check_index_refutable_slice() {
}
}
fn map_clone_suggest_copied() {
// This should still trigger the lint but suggest `cloned()` instead of `copied()`
let _: Option<u64> = Some(&16).map(|b| *b);
}
fn main() {
option_as_ref_deref();
match_like_matches();

View file

@ -0,0 +1,10 @@
error: you are using an explicit closure for copying elements
--> $DIR/min_rust_version.rs:73:26
|
LL | let _: Option<u64> = Some(&16).map(|b| *b);
| ^^^^^^^^^^^^^^^^^^^^^ help: consider calling the dedicated `cloned` method: `Some(&16).cloned()`
|
= note: `-D clippy::map-clone` implied by `-D warnings`
error: aborting due to previous error