| use super::EXPLICIT_INTO_ITER_LOOP; |
| use clippy_utils::diagnostics::span_lint_and_sugg; |
| use clippy_utils::res::{MaybeDef, MaybeTypeckRes}; |
| use clippy_utils::source::snippet_with_context; |
| use rustc_errors::Applicability; |
| use rustc_hir::Expr; |
| use rustc_lint::LateContext; |
| use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMutability}; |
| use rustc_span::symbol::sym; |
| |
| #[derive(Clone, Copy)] |
| enum AdjustKind { |
| None, |
| Borrow, |
| BorrowMut, |
| Reborrow, |
| ReborrowMut, |
| } |
| impl AdjustKind { |
| fn borrow(mutbl: AutoBorrowMutability) -> Self { |
| match mutbl { |
| AutoBorrowMutability::Not => Self::Borrow, |
| AutoBorrowMutability::Mut { .. } => Self::BorrowMut, |
| } |
| } |
| |
| fn reborrow(mutbl: AutoBorrowMutability) -> Self { |
| match mutbl { |
| AutoBorrowMutability::Not => Self::Reborrow, |
| AutoBorrowMutability::Mut { .. } => Self::ReborrowMut, |
| } |
| } |
| |
| fn display(self) -> &'static str { |
| match self { |
| Self::None => "", |
| Self::Borrow => "&", |
| Self::BorrowMut => "&mut ", |
| Self::Reborrow => "&*", |
| Self::ReborrowMut => "&mut *", |
| } |
| } |
| } |
| |
| pub(super) fn check(cx: &LateContext<'_>, self_arg: &Expr<'_>, call_expr: &Expr<'_>) { |
| if !cx |
| .ty_based_def(call_expr) |
| .opt_parent(cx) |
| .is_diag_item(cx, sym::IntoIterator) |
| { |
| return; |
| } |
| |
| let typeck = cx.typeck_results(); |
| let self_ty = typeck.expr_ty(self_arg); |
| let adjust = match typeck.expr_adjustments(self_arg) { |
| [] => AdjustKind::None, |
| &[ |
| Adjustment { |
| kind: Adjust::Borrow(AutoBorrow::Ref(mutbl)), |
| .. |
| }, |
| ] => AdjustKind::borrow(mutbl), |
| &[ |
| Adjustment { |
| kind: Adjust::Deref(_), .. |
| }, |
| Adjustment { |
| kind: Adjust::Borrow(AutoBorrow::Ref(mutbl)), |
| target, |
| }, |
| ] => { |
| if self_ty == target && matches!(mutbl, AutoBorrowMutability::Not) { |
| AdjustKind::None |
| } else { |
| AdjustKind::reborrow(mutbl) |
| } |
| }, |
| _ => return, |
| }; |
| |
| let mut applicability = Applicability::MachineApplicable; |
| let object = snippet_with_context(cx, self_arg.span, call_expr.span.ctxt(), "_", &mut applicability).0; |
| span_lint_and_sugg( |
| cx, |
| EXPLICIT_INTO_ITER_LOOP, |
| call_expr.span, |
| "it is more concise to loop over containers instead of using explicit \ |
| iteration methods", |
| "to write this more concisely, try", |
| format!("{}{object}", adjust.display()), |
| applicability, |
| ); |
| } |