Add config flag for reborrows in explicit_iter_loop
This commit adds a config flag for enforcing explicit into iter lint for reborrowed values. The config flag, enforce_iter_loop_reborrow, can be added to clippy.toml files to enable the linting behaviour. By default the lint is not enabled.
This commit is contained in:
parent
8c20739e4d
commit
be55a96d80
8 changed files with 68 additions and 56 deletions
|
|
@ -695,7 +695,8 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
|
|||
});
|
||||
store.register_late_pass(|_| Box::<shadow::Shadow>::default());
|
||||
store.register_late_pass(|_| Box::new(unit_types::UnitTypes));
|
||||
store.register_late_pass(move |_| Box::new(loops::Loops::new(msrv())));
|
||||
let enforce_iter_loop_reborrow = conf.enforce_iter_loop_reborrow;
|
||||
store.register_late_pass(move |_| Box::new(loops::Loops::new(msrv(), enforce_iter_loop_reborrow)));
|
||||
store.register_late_pass(|_| Box::<main_recursion::MainRecursion>::default());
|
||||
store.register_late_pass(|_| Box::new(lifetimes::Lifetimes));
|
||||
store.register_late_pass(|_| Box::new(entry::HashMapPass));
|
||||
|
|
|
|||
|
|
@ -13,8 +13,14 @@ use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMut
|
|||
use rustc_middle::ty::{self, EarlyBinder, Ty, TypeAndMut};
|
||||
use rustc_span::sym;
|
||||
|
||||
pub(super) fn check(cx: &LateContext<'_>, self_arg: &Expr<'_>, call_expr: &Expr<'_>, msrv: &Msrv) {
|
||||
let Some((adjust, ty)) = is_ref_iterable(cx, self_arg, call_expr) else {
|
||||
pub(super) fn check(
|
||||
cx: &LateContext<'_>,
|
||||
self_arg: &Expr<'_>,
|
||||
call_expr: &Expr<'_>,
|
||||
msrv: &Msrv,
|
||||
enforce_iter_loop_reborrow: bool,
|
||||
) {
|
||||
let Some((adjust, ty)) = is_ref_iterable(cx, self_arg, call_expr, enforce_iter_loop_reborrow) else {
|
||||
return;
|
||||
};
|
||||
if let ty::Array(_, count) = *ty.peel_refs().kind() {
|
||||
|
|
@ -102,6 +108,7 @@ fn is_ref_iterable<'tcx>(
|
|||
cx: &LateContext<'tcx>,
|
||||
self_arg: &Expr<'_>,
|
||||
call_expr: &Expr<'_>,
|
||||
enforce_iter_loop_reborrow: bool,
|
||||
) -> Option<(AdjustKind, Ty<'tcx>)> {
|
||||
let typeck = cx.typeck_results();
|
||||
if let Some(trait_id) = cx.tcx.get_diagnostic_item(sym::IntoIterator)
|
||||
|
|
@ -142,7 +149,8 @@ fn is_ref_iterable<'tcx>(
|
|||
{
|
||||
return Some((AdjustKind::None, self_ty));
|
||||
}
|
||||
} else if let ty::Ref(region, ty, Mutability::Mut) = *self_ty.kind()
|
||||
} else if enforce_iter_loop_reborrow
|
||||
&& let ty::Ref(region, ty, Mutability::Mut) = *self_ty.kind()
|
||||
&& let Some(mutbl) = mutbl
|
||||
{
|
||||
// Attempt to reborrow the mutable reference
|
||||
|
|
@ -186,7 +194,8 @@ fn is_ref_iterable<'tcx>(
|
|||
},
|
||||
..
|
||||
] => {
|
||||
if target != self_ty
|
||||
if enforce_iter_loop_reborrow
|
||||
&& target != self_ty
|
||||
&& implements_trait(cx, target, trait_id, &[])
|
||||
&& let Some(ty) =
|
||||
make_normalized_projection(cx.tcx, cx.param_env, trait_id, sym!(IntoIter), [target])
|
||||
|
|
|
|||
|
|
@ -609,10 +609,14 @@ declare_clippy_lint! {
|
|||
|
||||
pub struct Loops {
|
||||
msrv: Msrv,
|
||||
enforce_iter_loop_reborrow: bool,
|
||||
}
|
||||
impl Loops {
|
||||
pub fn new(msrv: Msrv) -> Self {
|
||||
Self { msrv }
|
||||
pub fn new(msrv: Msrv, enforce_iter_loop_reborrow: bool) -> Self {
|
||||
Self {
|
||||
msrv,
|
||||
enforce_iter_loop_reborrow,
|
||||
}
|
||||
}
|
||||
}
|
||||
impl_lint_pass!(Loops => [
|
||||
|
|
@ -719,7 +723,7 @@ impl Loops {
|
|||
if let ExprKind::MethodCall(method, self_arg, [], _) = arg.kind {
|
||||
match method.ident.as_str() {
|
||||
"iter" | "iter_mut" => {
|
||||
explicit_iter_loop::check(cx, self_arg, arg, &self.msrv);
|
||||
explicit_iter_loop::check(cx, self_arg, arg, &self.msrv, self.enforce_iter_loop_reborrow);
|
||||
},
|
||||
"into_iter" => {
|
||||
explicit_into_iter_loop::check(cx, self_arg, arg);
|
||||
|
|
|
|||
|
|
@ -561,6 +561,26 @@ define_Conf! {
|
|||
/// Which crates to allow absolute paths from
|
||||
(absolute_paths_allowed_crates: rustc_data_structures::fx::FxHashSet<String> =
|
||||
rustc_data_structures::fx::FxHashSet::default()),
|
||||
/// Lint: EXPLICIT_ITER_LOOP
|
||||
///
|
||||
/// Whether to recommend using implicit into iter for reborrowed values.
|
||||
///
|
||||
/// #### Example
|
||||
/// ```
|
||||
/// let mut vec = vec![1, 2, 3];
|
||||
/// let rmvec = &mut vec;
|
||||
/// for _ in rmvec.iter() {}
|
||||
/// for _ in rmvec.iter_mut() {}
|
||||
/// ```
|
||||
///
|
||||
/// Use instead:
|
||||
/// ```
|
||||
/// let mut vec = vec![1, 2, 3];
|
||||
/// let rmvec = &mut vec;
|
||||
/// for _ in &*rmvec {}
|
||||
/// for _ in &mut *rmvec {}
|
||||
/// ```
|
||||
(enforce_iter_loop_reborrow: bool = false),
|
||||
}
|
||||
|
||||
/// Search for the configuration file.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue