use crate::lints::{ShadowedIntoIterDiag, ShadowedIntoIterDiagSub};
use crate::{LateContext, LateLintPass, LintContext};
use rustc_hir as hir;
use rustc_middle::ty::{self, Ty};
use rustc_session::lint::FutureIncompatibilityReason;
use rustc_session::{declare_lint, impl_lint_pass};
use rustc_span::edition::Edition;

declare_lint! {
    /// The `array_into_iter` lint detects calling `into_iter` on arrays.
    ///
    /// ### Example
    ///
    /// ```rust,edition2018
    /// # #![allow(unused)]
    /// [1, 2, 3].into_iter().for_each(|n| { *n; });
    /// ```
    ///
    /// {{produces}}
    ///
    /// ### Explanation
    ///
    /// Since Rust 1.53, arrays implement `IntoIterator`. However, to avoid
    /// breakage, `array.into_iter()` in Rust 2015 and 2018 code will still
    /// behave as `(&array).into_iter()`, returning an iterator over
    /// references, just like in Rust 1.52 and earlier.
    /// This only applies to the method call syntax `array.into_iter()`, not to
    /// any other syntax such as `for _ in array` or `IntoIterator::into_iter(array)`.
    pub ARRAY_INTO_ITER,
    Warn,
    "detects calling `into_iter` on arrays in Rust 2015 and 2018",
    @future_incompatible = FutureIncompatibleInfo {
        reason: FutureIncompatibilityReason::EditionSemanticsChange(Edition::Edition2021),
        reference: "<https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html>",
    };
}

declare_lint! {
    /// The `boxed_slice_into_iter` lint detects calling `into_iter` on boxed slices.
    ///
    /// ### Example
    ///
    /// ```rust,edition2021
    /// # #![allow(unused)]
    /// vec![1, 2, 3].into_boxed_slice().into_iter().for_each(|n| { *n; });
    /// ```
    ///
    /// {{produces}}
    ///
    /// ### Explanation
    ///
    /// Since Rust CURRENT_RUSTC_VERSION, boxed slices implement `IntoIterator`. However, to avoid
    /// breakage, `boxed_slice.into_iter()` in Rust 2015, 2018, and 2021 code will still
    /// behave as `(&boxed_slice).into_iter()`, returning an iterator over
    /// references, just like in Rust CURRENT_RUSTC_VERSION and earlier.
    /// This only applies to the method call syntax `boxed_slice.into_iter()`, not to
    /// any other syntax such as `for _ in boxed_slice` or `IntoIterator::into_iter(boxed_slice)`.
    pub BOXED_SLICE_INTO_ITER,
    Warn,
    "detects calling `into_iter` on boxed slices in Rust 2015, 2018, and 2021",
    @future_incompatible = FutureIncompatibleInfo {
        reason: FutureIncompatibilityReason::EditionSemanticsChange(Edition::Edition2024),
    };
}

#[derive(Copy, Clone)]
pub struct ShadowedIntoIter;

impl_lint_pass!(ShadowedIntoIter => [ARRAY_INTO_ITER, BOXED_SLICE_INTO_ITER]);

impl<'tcx> LateLintPass<'tcx> for ShadowedIntoIter {
    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) {
        let hir::ExprKind::MethodCall(call, receiver_arg, ..) = &expr.kind else {
            return;
        };

        // Check if the method call actually calls the libcore
        // `IntoIterator::into_iter`.
        let Some(method_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id) else {
            return;
        };
        if Some(method_def_id) != cx.tcx.lang_items().into_iter_fn() {
            return;
        }

        // As this is a method call expression, we have at least one argument.
        let receiver_ty = cx.typeck_results().expr_ty(receiver_arg);
        let adjustments = cx.typeck_results().expr_adjustments(receiver_arg);

        let adjusted_receiver_tys: Vec<_> =
            [receiver_ty].into_iter().chain(adjustments.iter().map(|adj| adj.target)).collect();

        fn is_ref_to_array(ty: Ty<'_>) -> bool {
            if let ty::Ref(_, pointee_ty, _) = *ty.kind() { pointee_ty.is_array() } else { false }
        }
        fn is_boxed_slice(ty: Ty<'_>) -> bool {
            ty.is_box() && ty.boxed_ty().is_slice()
        }
        fn is_ref_to_boxed_slice(ty: Ty<'_>) -> bool {
            if let ty::Ref(_, pointee_ty, _) = *ty.kind() {
                is_boxed_slice(pointee_ty)
            } else {
                false
            }
        }

        let (lint, target, edition, can_suggest_ufcs) =
            if is_ref_to_array(*adjusted_receiver_tys.last().unwrap())
                && let Some(idx) = adjusted_receiver_tys
                    .iter()
                    .copied()
                    .take_while(|ty| !is_ref_to_array(*ty))
                    .position(|ty| ty.is_array())
            {
                (ARRAY_INTO_ITER, "[T; N]", "2021", idx == 0)
            } else if is_ref_to_boxed_slice(*adjusted_receiver_tys.last().unwrap())
                && let Some(idx) = adjusted_receiver_tys
                    .iter()
                    .copied()
                    .take_while(|ty| !is_ref_to_boxed_slice(*ty))
                    .position(|ty| is_boxed_slice(ty))
            {
                (BOXED_SLICE_INTO_ITER, "Box<[T]>", "2024", idx == 0)
            } else {
                return;
            };

        // If this expression comes from the `IntoIter::into_iter` inside of a for loop,
        // we should just suggest removing the `.into_iter()` or changing it to `.iter()`
        // to disambiguate if we want to iterate by-value or by-ref.
        let sub = if let Some((_, hir::Node::Expr(parent_expr))) =
            cx.tcx.hir().parent_iter(expr.hir_id).nth(1)
            && let hir::ExprKind::Match(arg, [_], hir::MatchSource::ForLoopDesugar) =
                &parent_expr.kind
            && let hir::ExprKind::Call(path, [_]) = &arg.kind
            && let hir::ExprKind::Path(hir::QPath::LangItem(hir::LangItem::IntoIterIntoIter, ..)) =
                &path.kind
        {
            Some(ShadowedIntoIterDiagSub::RemoveIntoIter {
                span: receiver_arg.span.shrink_to_hi().to(expr.span.shrink_to_hi()),
            })
        } else if can_suggest_ufcs {
            Some(ShadowedIntoIterDiagSub::UseExplicitIntoIter {
                start_span: expr.span.shrink_to_lo(),
                end_span: receiver_arg.span.shrink_to_hi().to(expr.span.shrink_to_hi()),
            })
        } else {
            None
        };

        cx.emit_span_lint(
            lint,
            call.ident.span,
            ShadowedIntoIterDiag { target, edition, suggestion: call.ident.span, sub },
        );
    }
}
