use std::assert_matches::debug_assert_matches;
use std::cell::LazyCell;

use rustc_data_structures::fx::{FxHashMap, FxIndexMap, FxIndexSet};
use rustc_data_structures::unord::UnordSet;
use rustc_errors::{LintDiagnostic, Subdiagnostic};
use rustc_hir as hir;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_infer::infer::TyCtxtInferExt;
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
use rustc_macros::LintDiagnostic;
use rustc_middle::middle::resolve_bound_vars::ResolvedArg;
use rustc_middle::ty::relate::{
    Relate, RelateResult, TypeRelation, structurally_relate_consts, structurally_relate_tys,
};
use rustc_middle::ty::{
    self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor,
};
use rustc_middle::{bug, span_bug};
use rustc_session::lint::FutureIncompatibilityReason;
use rustc_session::{declare_lint, declare_lint_pass};
use rustc_span::edition::Edition;
use rustc_span::{Span, Symbol};
use rustc_trait_selection::errors::{
    AddPreciseCapturingForOvercapture, impl_trait_overcapture_suggestion,
};
use rustc_trait_selection::regions::OutlivesEnvironmentBuildExt;
use rustc_trait_selection::traits::ObligationCtxt;

use crate::{LateContext, LateLintPass, fluent_generated as fluent};

declare_lint! {
    /// The `impl_trait_overcaptures` lint warns against cases where lifetime
    /// capture behavior will differ in edition 2024.
    ///
    /// In the 2024 edition, `impl Trait`s will capture all lifetimes in scope,
    /// rather than just the lifetimes that are mentioned in the bounds of the type.
    /// Often these sets are equal, but if not, it means that the `impl Trait` may
    /// cause erroneous borrow-checker errors.
    ///
    /// ### Example
    ///
    /// ```rust,compile_fail,edition2021
    /// # #![deny(impl_trait_overcaptures)]
    /// # use std::fmt::Display;
    /// let mut x = vec![];
    /// x.push(1);
    ///
    /// fn test(x: &Vec<i32>) -> impl Display {
    ///     x[0]
    /// }
    ///
    /// let element = test(&x);
    /// x.push(2);
    /// println!("{element}");
    /// ```
    ///
    /// {{produces}}
    ///
    /// ### Explanation
    ///
    /// In edition < 2024, the returned `impl Display` doesn't capture the
    /// lifetime from the `&Vec<i32>`, so the vector can be mutably borrowed
    /// while the `impl Display` is live.
    ///
    /// To fix this, we can explicitly state that the `impl Display` doesn't
    /// capture any lifetimes, using `impl Display + use<>`.
    pub IMPL_TRAIT_OVERCAPTURES,
    Allow,
    "`impl Trait` will capture more lifetimes than possibly intended in edition 2024",
    @future_incompatible = FutureIncompatibleInfo {
        reason: FutureIncompatibilityReason::EditionSemanticsChange(Edition::Edition2024),
        reference: "<https://doc.rust-lang.org/edition-guide/rust-2024/rpit-lifetime-capture.html>",
    };
}

declare_lint! {
    /// The `impl_trait_redundant_captures` lint warns against cases where use of the
    /// precise capturing `use<...>` syntax is not needed.
    ///
    /// In the 2024 edition, `impl Trait`s will capture all lifetimes in scope.
    /// If precise-capturing `use<...>` syntax is used, and the set of parameters
    /// that are captures are *equal* to the set of parameters in scope, then
    /// the syntax is redundant, and can be removed.
    ///
    /// ### Example
    ///
    /// ```rust,edition2024,compile_fail
    /// # #![deny(impl_trait_redundant_captures)]
    /// fn test<'a>(x: &'a i32) -> impl Sized + use<'a> { x }
    /// ```
    ///
    /// {{produces}}
    ///
    /// ### Explanation
    ///
    /// To fix this, remove the `use<'a>`, since the lifetime is already captured
    /// since it is in scope.
    pub IMPL_TRAIT_REDUNDANT_CAPTURES,
    Allow,
    "redundant precise-capturing `use<...>` syntax on an `impl Trait`",
}

declare_lint_pass!(
    /// Lint for opaque types that will begin capturing in-scope but unmentioned lifetimes
    /// in edition 2024.
    ImplTraitOvercaptures => [IMPL_TRAIT_OVERCAPTURES, IMPL_TRAIT_REDUNDANT_CAPTURES]
);

impl<'tcx> LateLintPass<'tcx> for ImplTraitOvercaptures {
    fn check_item(&mut self, cx: &LateContext<'tcx>, it: &'tcx hir::Item<'tcx>) {
        match &it.kind {
            hir::ItemKind::Fn { .. } => check_fn(cx.tcx, it.owner_id.def_id),
            _ => {}
        }
    }

    fn check_impl_item(&mut self, cx: &LateContext<'tcx>, it: &'tcx hir::ImplItem<'tcx>) {
        match &it.kind {
            hir::ImplItemKind::Fn(_, _) => check_fn(cx.tcx, it.owner_id.def_id),
            _ => {}
        }
    }

    fn check_trait_item(&mut self, cx: &LateContext<'tcx>, it: &'tcx hir::TraitItem<'tcx>) {
        match &it.kind {
            hir::TraitItemKind::Fn(_, _) => check_fn(cx.tcx, it.owner_id.def_id),
            _ => {}
        }
    }
}

#[derive(PartialEq, Eq, Hash, Debug, Copy, Clone)]
enum ParamKind {
    // Early-bound var.
    Early(Symbol, u32),
    // Late-bound var on function, not within a binder. We can capture these.
    Free(DefId),
    // Late-bound var in a binder. We can't capture these yet.
    Late,
}

fn check_fn(tcx: TyCtxt<'_>, parent_def_id: LocalDefId) {
    let sig = tcx.fn_sig(parent_def_id).instantiate_identity();

    let mut in_scope_parameters = FxIndexMap::default();
    // Populate the in_scope_parameters list first with all of the generics in scope
    let mut current_def_id = Some(parent_def_id.to_def_id());
    while let Some(def_id) = current_def_id {
        let generics = tcx.generics_of(def_id);
        for param in &generics.own_params {
            in_scope_parameters.insert(param.def_id, ParamKind::Early(param.name, param.index));
        }
        current_def_id = generics.parent;
    }

    for bound_var in sig.bound_vars() {
        let ty::BoundVariableKind::Region(ty::BoundRegionKind::Named(def_id)) = bound_var else {
            span_bug!(tcx.def_span(parent_def_id), "unexpected non-lifetime binder on fn sig");
        };

        in_scope_parameters.insert(def_id, ParamKind::Free(def_id));
    }

    let sig = tcx.liberate_late_bound_regions(parent_def_id.to_def_id(), sig);

    // Then visit the signature to walk through all the binders (incl. the late-bound
    // vars on the function itself, which we need to count too).
    sig.visit_with(&mut VisitOpaqueTypes {
        tcx,
        parent_def_id,
        in_scope_parameters,
        seen: Default::default(),
        // Lazily compute these two, since they're likely a bit expensive.
        variances: LazyCell::new(|| {
            let mut functional_variances = FunctionalVariances {
                tcx,
                variances: FxHashMap::default(),
                ambient_variance: ty::Covariant,
                generics: tcx.generics_of(parent_def_id),
            };
            functional_variances.relate(sig, sig).unwrap();
            functional_variances.variances
        }),
        outlives_env: LazyCell::new(|| {
            let typing_env = ty::TypingEnv::non_body_analysis(tcx, parent_def_id);
            let (infcx, param_env) = tcx.infer_ctxt().build_with_typing_env(typing_env);
            let ocx = ObligationCtxt::new(&infcx);
            let assumed_wf_tys = ocx.assumed_wf_types(param_env, parent_def_id).unwrap_or_default();
            OutlivesEnvironment::new(&infcx, parent_def_id, param_env, assumed_wf_tys)
        }),
    });
}

struct VisitOpaqueTypes<'tcx, VarFn, OutlivesFn> {
    tcx: TyCtxt<'tcx>,
    parent_def_id: LocalDefId,
    in_scope_parameters: FxIndexMap<DefId, ParamKind>,
    variances: LazyCell<FxHashMap<DefId, ty::Variance>, VarFn>,
    outlives_env: LazyCell<OutlivesEnvironment<'tcx>, OutlivesFn>,
    seen: FxIndexSet<LocalDefId>,
}

impl<'tcx, VarFn, OutlivesFn> TypeVisitor<TyCtxt<'tcx>>
    for VisitOpaqueTypes<'tcx, VarFn, OutlivesFn>
where
    VarFn: FnOnce() -> FxHashMap<DefId, ty::Variance>,
    OutlivesFn: FnOnce() -> OutlivesEnvironment<'tcx>,
{
    fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>(&mut self, t: &ty::Binder<'tcx, T>) {
        // When we get into a binder, we need to add its own bound vars to the scope.
        let mut added = vec![];
        for arg in t.bound_vars() {
            let arg: ty::BoundVariableKind = arg;
            match arg {
                ty::BoundVariableKind::Region(ty::BoundRegionKind::Named(def_id))
                | ty::BoundVariableKind::Ty(ty::BoundTyKind::Param(def_id)) => {
                    added.push(def_id);
                    let unique = self.in_scope_parameters.insert(def_id, ParamKind::Late);
                    assert_eq!(unique, None);
                }
                _ => {
                    self.tcx.dcx().span_delayed_bug(
                        self.tcx.def_span(self.parent_def_id),
                        format!("unsupported bound variable kind: {arg:?}"),
                    );
                }
            }
        }

        t.super_visit_with(self);

        // And remove them. The `shift_remove` should be `O(1)` since we're popping
        // them off from the end.
        for arg in added.into_iter().rev() {
            self.in_scope_parameters.shift_remove(&arg);
        }
    }

    fn visit_ty(&mut self, t: Ty<'tcx>) {
        if !t.has_aliases() {
            return;
        }

        if let ty::Alias(ty::Projection, opaque_ty) = *t.kind()
            && self.tcx.is_impl_trait_in_trait(opaque_ty.def_id)
        {
            // visit the opaque of the RPITIT
            self.tcx
                .type_of(opaque_ty.def_id)
                .instantiate(self.tcx, opaque_ty.args)
                .visit_with(self)
        } else if let ty::Alias(ty::Opaque, opaque_ty) = *t.kind()
            && let Some(opaque_def_id) = opaque_ty.def_id.as_local()
            // Don't recurse infinitely on an opaque
            && self.seen.insert(opaque_def_id)
            // If it's owned by this function
            && let opaque =
                self.tcx.hir_node_by_def_id(opaque_def_id).expect_opaque_ty()
            // We want to recurse into RPITs and async fns, even though the latter
            // doesn't overcapture on its own, it may mention additional RPITs
            // in its bounds.
            && let hir::OpaqueTyOrigin::FnReturn { parent, .. }
                | hir::OpaqueTyOrigin::AsyncFn { parent, .. } = opaque.origin
            && parent == self.parent_def_id
        {
            let opaque_span = self.tcx.def_span(opaque_def_id);
            let new_capture_rules = opaque_span.at_least_rust_2024();
            if !new_capture_rules
                && !opaque.bounds.iter().any(|bound| matches!(bound, hir::GenericBound::Use(..)))
            {
                // Compute the set of args that are captured by the opaque...
                let mut captured = FxIndexSet::default();
                let mut captured_regions = FxIndexSet::default();
                let variances = self.tcx.variances_of(opaque_def_id);
                let mut current_def_id = Some(opaque_def_id.to_def_id());
                while let Some(def_id) = current_def_id {
                    let generics = self.tcx.generics_of(def_id);
                    for param in &generics.own_params {
                        // A param is captured if it's invariant.
                        if variances[param.index as usize] != ty::Invariant {
                            continue;
                        }

                        let arg = opaque_ty.args[param.index as usize];
                        // We need to turn all `ty::Param`/`ConstKind::Param` and
                        // `ReEarlyParam`/`ReBound` into def ids.
                        captured.insert(extract_def_id_from_arg(self.tcx, generics, arg));

                        captured_regions.extend(arg.as_region());
                    }
                    current_def_id = generics.parent;
                }

                // Compute the set of in scope params that are not captured.
                let mut uncaptured_args: FxIndexSet<_> = self
                    .in_scope_parameters
                    .iter()
                    .filter(|&(def_id, _)| !captured.contains(def_id))
                    .collect();
                // Remove the set of lifetimes that are in-scope that outlive some other captured
                // lifetime and are contravariant (i.e. covariant in argument position).
                uncaptured_args.retain(|&(def_id, kind)| {
                    let Some(ty::Bivariant | ty::Contravariant) = self.variances.get(def_id) else {
                        // Keep all covariant/invariant args. Also if variance is `None`,
                        // then that means it's either not a lifetime, or it didn't show up
                        // anywhere in the signature.
                        return true;
                    };
                    // We only computed variance of lifetimes...
                    debug_assert_matches!(self.tcx.def_kind(def_id), DefKind::LifetimeParam);
                    let uncaptured = match *kind {
                        ParamKind::Early(name, index) => ty::Region::new_early_param(
                            self.tcx,
                            ty::EarlyParamRegion { name, index },
                        ),
                        ParamKind::Free(def_id) => ty::Region::new_late_param(
                            self.tcx,
                            self.parent_def_id.to_def_id(),
                            ty::LateParamRegionKind::Named(def_id),
                        ),
                        // Totally ignore late bound args from binders.
                        ParamKind::Late => return true,
                    };
                    // Does this region outlive any captured region?
                    !captured_regions.iter().any(|r| {
                        self.outlives_env
                            .free_region_map()
                            .sub_free_regions(self.tcx, *r, uncaptured)
                    })
                });

                // If we have uncaptured args, and if the opaque doesn't already have
                // `use<>` syntax on it, and we're < edition 2024, then warn the user.
                if !uncaptured_args.is_empty() {
                    let suggestion = impl_trait_overcapture_suggestion(
                        self.tcx,
                        opaque_def_id,
                        self.parent_def_id,
                        captured,
                    );

                    let uncaptured_spans: Vec<_> = uncaptured_args
                        .into_iter()
                        .map(|(def_id, _)| self.tcx.def_span(def_id))
                        .collect();

                    self.tcx.emit_node_span_lint(
                        IMPL_TRAIT_OVERCAPTURES,
                        self.tcx.local_def_id_to_hir_id(opaque_def_id),
                        opaque_span,
                        ImplTraitOvercapturesLint {
                            self_ty: t,
                            num_captured: uncaptured_spans.len(),
                            uncaptured_spans,
                            suggestion,
                        },
                    );
                }
            }

            // Otherwise, if we are edition 2024, have `use<>` syntax, and
            // have no uncaptured args, then we should warn to the user that
            // it's redundant to capture all args explicitly.
            if new_capture_rules
                && let Some((captured_args, capturing_span)) =
                    opaque.bounds.iter().find_map(|bound| match *bound {
                        hir::GenericBound::Use(a, s) => Some((a, s)),
                        _ => None,
                    })
            {
                let mut explicitly_captured = UnordSet::default();
                for arg in captured_args {
                    match self.tcx.named_bound_var(arg.hir_id()) {
                        Some(
                            ResolvedArg::EarlyBound(def_id) | ResolvedArg::LateBound(_, _, def_id),
                        ) => {
                            if self.tcx.def_kind(self.tcx.local_parent(def_id)) == DefKind::OpaqueTy
                            {
                                let def_id = self
                                    .tcx
                                    .map_opaque_lifetime_to_parent_lifetime(def_id)
                                    .opt_param_def_id(self.tcx, self.parent_def_id.to_def_id())
                                    .expect("variable should have been duplicated from parent");

                                explicitly_captured.insert(def_id);
                            } else {
                                explicitly_captured.insert(def_id.to_def_id());
                            }
                        }
                        _ => {
                            self.tcx.dcx().span_delayed_bug(
                                self.tcx.hir_span(arg.hir_id()),
                                "no valid for captured arg",
                            );
                        }
                    }
                }

                if self
                    .in_scope_parameters
                    .iter()
                    .all(|(def_id, _)| explicitly_captured.contains(def_id))
                {
                    self.tcx.emit_node_span_lint(
                        IMPL_TRAIT_REDUNDANT_CAPTURES,
                        self.tcx.local_def_id_to_hir_id(opaque_def_id),
                        opaque_span,
                        ImplTraitRedundantCapturesLint { capturing_span },
                    );
                }
            }

            // Walk into the bounds of the opaque, too, since we want to get nested opaques
            // in this lint as well. Interestingly, one place that I expect this lint to fire
            // is for `impl for<'a> Bound<Out = impl Other>`, since `impl Other` will begin
            // to capture `'a` in e2024 (even though late-bound vars in opaques are not allowed).
            for clause in
                self.tcx.item_bounds(opaque_ty.def_id).iter_instantiated(self.tcx, opaque_ty.args)
            {
                clause.visit_with(self)
            }
        }

        t.super_visit_with(self);
    }
}

struct ImplTraitOvercapturesLint<'tcx> {
    uncaptured_spans: Vec<Span>,
    self_ty: Ty<'tcx>,
    num_captured: usize,
    suggestion: Option<AddPreciseCapturingForOvercapture>,
}

impl<'a> LintDiagnostic<'a, ()> for ImplTraitOvercapturesLint<'_> {
    fn decorate_lint<'b>(self, diag: &'b mut rustc_errors::Diag<'a, ()>) {
        diag.primary_message(fluent::lint_impl_trait_overcaptures);
        diag.arg("self_ty", self.self_ty.to_string())
            .arg("num_captured", self.num_captured)
            .span_note(self.uncaptured_spans, fluent::lint_note)
            .note(fluent::lint_note2);
        if let Some(suggestion) = self.suggestion {
            suggestion.add_to_diag(diag);
        }
    }
}

#[derive(LintDiagnostic)]
#[diag(lint_impl_trait_redundant_captures)]
struct ImplTraitRedundantCapturesLint {
    #[suggestion(lint_suggestion, code = "", applicability = "machine-applicable")]
    capturing_span: Span,
}

fn extract_def_id_from_arg<'tcx>(
    tcx: TyCtxt<'tcx>,
    generics: &'tcx ty::Generics,
    arg: ty::GenericArg<'tcx>,
) -> DefId {
    match arg.kind() {
        ty::GenericArgKind::Lifetime(re) => match re.kind() {
            ty::ReEarlyParam(ebr) => generics.region_param(ebr, tcx).def_id,
            ty::ReBound(_, ty::BoundRegion { kind: ty::BoundRegionKind::Named(def_id), .. })
            | ty::ReLateParam(ty::LateParamRegion {
                scope: _,
                kind: ty::LateParamRegionKind::Named(def_id),
            }) => def_id,
            _ => unreachable!(),
        },
        ty::GenericArgKind::Type(ty) => {
            let ty::Param(param_ty) = *ty.kind() else {
                bug!();
            };
            generics.type_param(param_ty, tcx).def_id
        }
        ty::GenericArgKind::Const(ct) => {
            let ty::ConstKind::Param(param_ct) = ct.kind() else {
                bug!();
            };
            generics.const_param(param_ct, tcx).def_id
        }
    }
}

/// Computes the variances of regions that appear in the type, but considering
/// late-bound regions too, which don't have their variance computed usually.
///
/// Like generalization, this is a unary operation implemented on top of the binary
/// relation infrastructure, mostly because it's much easier to have the relation
/// track the variance for you, rather than having to do it yourself.
struct FunctionalVariances<'tcx> {
    tcx: TyCtxt<'tcx>,
    variances: FxHashMap<DefId, ty::Variance>,
    ambient_variance: ty::Variance,
    generics: &'tcx ty::Generics,
}

impl<'tcx> TypeRelation<TyCtxt<'tcx>> for FunctionalVariances<'tcx> {
    fn cx(&self) -> TyCtxt<'tcx> {
        self.tcx
    }

    fn relate_with_variance<T: Relate<TyCtxt<'tcx>>>(
        &mut self,
        variance: ty::Variance,
        _: ty::VarianceDiagInfo<TyCtxt<'tcx>>,
        a: T,
        b: T,
    ) -> RelateResult<'tcx, T> {
        let old_variance = self.ambient_variance;
        self.ambient_variance = self.ambient_variance.xform(variance);
        self.relate(a, b).unwrap();
        self.ambient_variance = old_variance;
        Ok(a)
    }

    fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
        structurally_relate_tys(self, a, b).unwrap();
        Ok(a)
    }

    fn regions(
        &mut self,
        a: ty::Region<'tcx>,
        _: ty::Region<'tcx>,
    ) -> RelateResult<'tcx, ty::Region<'tcx>> {
        let def_id = match a.kind() {
            ty::ReEarlyParam(ebr) => self.generics.region_param(ebr, self.tcx).def_id,
            ty::ReBound(_, ty::BoundRegion { kind: ty::BoundRegionKind::Named(def_id), .. })
            | ty::ReLateParam(ty::LateParamRegion {
                scope: _,
                kind: ty::LateParamRegionKind::Named(def_id),
            }) => def_id,
            _ => {
                return Ok(a);
            }
        };

        if let Some(variance) = self.variances.get_mut(&def_id) {
            *variance = unify(*variance, self.ambient_variance);
        } else {
            self.variances.insert(def_id, self.ambient_variance);
        }

        Ok(a)
    }

    fn consts(
        &mut self,
        a: ty::Const<'tcx>,
        b: ty::Const<'tcx>,
    ) -> RelateResult<'tcx, ty::Const<'tcx>> {
        structurally_relate_consts(self, a, b).unwrap();
        Ok(a)
    }

    fn binders<T>(
        &mut self,
        a: ty::Binder<'tcx, T>,
        b: ty::Binder<'tcx, T>,
    ) -> RelateResult<'tcx, ty::Binder<'tcx, T>>
    where
        T: Relate<TyCtxt<'tcx>>,
    {
        self.relate(a.skip_binder(), b.skip_binder()).unwrap();
        Ok(a)
    }
}

/// What is the variance that satisfies the two variances?
fn unify(a: ty::Variance, b: ty::Variance) -> ty::Variance {
    match (a, b) {
        // Bivariance is lattice bottom.
        (ty::Bivariant, other) | (other, ty::Bivariant) => other,
        // Invariant is lattice top.
        (ty::Invariant, _) | (_, ty::Invariant) => ty::Invariant,
        // If type is required to be covariant and contravariant, then it's invariant.
        (ty::Contravariant, ty::Covariant) | (ty::Covariant, ty::Contravariant) => ty::Invariant,
        // Otherwise, co + co = co, contra + contra = contra.
        (ty::Contravariant, ty::Contravariant) => ty::Contravariant,
        (ty::Covariant, ty::Covariant) => ty::Covariant,
    }
}
