//! Basic types for managing and implementing lints.
//!
//! See <https://rustc-dev-guide.rust-lang.org/diagnostics.html> for an
//! overview of how lints are implemented.

use std::cell::Cell;
use std::slice;

use rustc_ast::BindingMode;
use rustc_ast::util::parser::ExprPrecedence;
use rustc_data_structures::fx::FxIndexMap;
use rustc_data_structures::sync;
use rustc_data_structures::unord::UnordMap;
use rustc_errors::{Diag, LintBuffer, LintDiagnostic, MultiSpan};
use rustc_feature::Features;
use rustc_hir::def::Res;
use rustc_hir::def_id::{CrateNum, DefId};
use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData};
use rustc_hir::{Pat, PatKind};
use rustc_middle::bug;
use rustc_middle::lint::LevelAndSource;
use rustc_middle::middle::privacy::EffectiveVisibilities;
use rustc_middle::ty::layout::{LayoutError, LayoutOfHelpers, TyAndLayout};
use rustc_middle::ty::print::{PrintError, PrintTraitRefExt as _, Printer, with_no_trimmed_paths};
use rustc_middle::ty::{self, GenericArg, RegisteredTools, Ty, TyCtxt, TypingEnv, TypingMode};
use rustc_session::lint::{FutureIncompatibleInfo, Lint, LintExpectationId, LintId};
use rustc_session::{DynLintStore, Session};
use rustc_span::edit_distance::find_best_match_for_names;
use rustc_span::{Ident, Span, Symbol, sym};
use tracing::debug;
use {rustc_abi as abi, rustc_hir as hir};

use self::TargetLint::*;
use crate::levels::LintLevelsBuilder;
use crate::passes::{EarlyLintPassObject, LateLintPassObject};

type EarlyLintPassFactory = dyn Fn() -> EarlyLintPassObject + sync::DynSend + sync::DynSync;
type LateLintPassFactory =
    dyn for<'tcx> Fn(TyCtxt<'tcx>) -> LateLintPassObject<'tcx> + sync::DynSend + sync::DynSync;

/// Information about the registered lints.
pub struct LintStore {
    /// Registered lints.
    lints: Vec<&'static Lint>,

    /// Constructor functions for each variety of lint pass.
    ///
    /// These should only be called once, but since we want to avoid locks or
    /// interior mutability, we don't enforce this (and lints should, in theory,
    /// be compatible with being constructed more than once, though not
    /// necessarily in a sane manner. This is safe though.)
    pub pre_expansion_passes: Vec<Box<EarlyLintPassFactory>>,
    pub early_passes: Vec<Box<EarlyLintPassFactory>>,
    pub late_passes: Vec<Box<LateLintPassFactory>>,
    /// This is unique in that we construct them per-module, so not once.
    pub late_module_passes: Vec<Box<LateLintPassFactory>>,

    /// Lints indexed by name.
    by_name: UnordMap<String, TargetLint>,

    /// Map of registered lint groups to what lints they expand to.
    lint_groups: FxIndexMap<&'static str, LintGroup>,
}

impl DynLintStore for LintStore {
    fn lint_groups_iter(&self) -> Box<dyn Iterator<Item = rustc_session::LintGroup> + '_> {
        Box::new(self.get_lint_groups().map(|(name, lints, is_externally_loaded)| {
            rustc_session::LintGroup { name, lints, is_externally_loaded }
        }))
    }
}

/// The target of the `by_name` map, which accounts for renaming/deprecation.
#[derive(Debug)]
enum TargetLint {
    /// A direct lint target
    Id(LintId),

    /// Temporary renaming, used for easing migration pain; see #16545
    Renamed(String, LintId),

    /// Lint with this name existed previously, but has been removed/deprecated.
    /// The string argument is the reason for removal.
    Removed(String),

    /// A lint name that should give no warnings and have no effect.
    ///
    /// This is used by rustc to avoid warning about old rustdoc lints before rustdoc registers
    /// them as tool lints.
    Ignored,
}

struct LintAlias {
    name: &'static str,
    /// Whether deprecation warnings should be suppressed for this alias.
    silent: bool,
}

struct LintGroup {
    lint_ids: Vec<LintId>,
    is_externally_loaded: bool,
    depr: Option<LintAlias>,
}

#[derive(Debug)]
pub enum CheckLintNameResult<'a> {
    Ok(&'a [LintId]),
    /// Lint doesn't exist. Potentially contains a suggestion for a correct lint name.
    NoLint(Option<(Symbol, bool)>),
    /// The lint refers to a tool that has not been registered.
    NoTool,
    /// The lint has been renamed to a new name.
    Renamed(String),
    /// The lint has been removed due to the given reason.
    Removed(String),

    /// The lint is from a tool. The `LintId` will be returned as if it were a
    /// rustc lint. The `Option<String>` indicates if the lint has been
    /// renamed.
    Tool(&'a [LintId], Option<String>),

    /// The lint is from a tool. Either the lint does not exist in the tool or
    /// the code was not compiled with the tool and therefore the lint was
    /// never added to the `LintStore`.
    MissingTool,
}

impl LintStore {
    pub fn new() -> LintStore {
        LintStore {
            lints: vec![],
            pre_expansion_passes: vec![],
            early_passes: vec![],
            late_passes: vec![],
            late_module_passes: vec![],
            by_name: Default::default(),
            lint_groups: Default::default(),
        }
    }

    pub fn get_lints<'t>(&'t self) -> &'t [&'static Lint] {
        &self.lints
    }

    pub fn get_lint_groups(&self) -> impl Iterator<Item = (&'static str, Vec<LintId>, bool)> {
        self.lint_groups
            .iter()
            .filter(|(_, LintGroup { depr, .. })| {
                // Don't display deprecated lint groups.
                depr.is_none()
            })
            .map(|(k, LintGroup { lint_ids, is_externally_loaded, .. })| {
                (*k, lint_ids.clone(), *is_externally_loaded)
            })
    }

    pub fn register_early_pass(
        &mut self,
        pass: impl Fn() -> EarlyLintPassObject + 'static + sync::DynSend + sync::DynSync,
    ) {
        self.early_passes.push(Box::new(pass));
    }

    /// This lint pass is softly deprecated. It misses expanded code and has caused a few
    /// errors in the past. Currently, it is only used in Clippy. New implementations
    /// should avoid using this interface, as it might be removed in the future.
    ///
    /// * See [rust#69838](https://github.com/rust-lang/rust/pull/69838)
    /// * See [rust-clippy#5518](https://github.com/rust-lang/rust-clippy/pull/5518)
    pub fn register_pre_expansion_pass(
        &mut self,
        pass: impl Fn() -> EarlyLintPassObject + 'static + sync::DynSend + sync::DynSync,
    ) {
        self.pre_expansion_passes.push(Box::new(pass));
    }

    pub fn register_late_pass(
        &mut self,
        pass: impl for<'tcx> Fn(TyCtxt<'tcx>) -> LateLintPassObject<'tcx>
        + 'static
        + sync::DynSend
        + sync::DynSync,
    ) {
        self.late_passes.push(Box::new(pass));
    }

    pub fn register_late_mod_pass(
        &mut self,
        pass: impl for<'tcx> Fn(TyCtxt<'tcx>) -> LateLintPassObject<'tcx>
        + 'static
        + sync::DynSend
        + sync::DynSync,
    ) {
        self.late_module_passes.push(Box::new(pass));
    }

    /// Helper method for register_early/late_pass
    pub fn register_lints(&mut self, lints: &[&'static Lint]) {
        for lint in lints {
            self.lints.push(lint);

            let id = LintId::of(lint);
            if self.by_name.insert(lint.name_lower(), Id(id)).is_some() {
                bug!("duplicate specification of lint {}", lint.name_lower())
            }

            if let Some(FutureIncompatibleInfo { reason, .. }) = lint.future_incompatible {
                if let Some(edition) = reason.edition() {
                    self.lint_groups
                        .entry(edition.lint_name())
                        .or_insert(LintGroup {
                            lint_ids: vec![],
                            is_externally_loaded: lint.is_externally_loaded,
                            depr: None,
                        })
                        .lint_ids
                        .push(id);
                } else {
                    // Lints belonging to the `future_incompatible` lint group are lints where a
                    // future version of rustc will cause existing code to stop compiling.
                    // Lints tied to an edition don't count because they are opt-in.
                    self.lint_groups
                        .entry("future_incompatible")
                        .or_insert(LintGroup {
                            lint_ids: vec![],
                            is_externally_loaded: lint.is_externally_loaded,
                            depr: None,
                        })
                        .lint_ids
                        .push(id);
                }
            }
        }
    }

    fn insert_group(&mut self, name: &'static str, group: LintGroup) {
        let previous = self.lint_groups.insert(name, group);
        if previous.is_some() {
            bug!("group {name:?} already exists");
        }
    }

    pub fn register_group_alias(&mut self, group_name: &'static str, alias: &'static str) {
        let Some(LintGroup { lint_ids, .. }) = self.lint_groups.get(group_name) else {
            bug!("group alias {alias:?} points to unregistered group {group_name:?}")
        };

        self.insert_group(
            alias,
            LintGroup {
                lint_ids: lint_ids.clone(),
                is_externally_loaded: false,
                depr: Some(LintAlias { name: group_name, silent: true }),
            },
        );
    }

    pub fn register_group(
        &mut self,
        is_externally_loaded: bool,
        name: &'static str,
        deprecated_name: Option<&'static str>,
        to: Vec<LintId>,
    ) {
        if let Some(deprecated) = deprecated_name {
            self.insert_group(
                deprecated,
                LintGroup {
                    lint_ids: to.clone(),
                    is_externally_loaded,
                    depr: Some(LintAlias { name, silent: false }),
                },
            );
        }
        self.insert_group(name, LintGroup { lint_ids: to, is_externally_loaded, depr: None });
    }

    /// This lint should give no warning and have no effect.
    ///
    /// This is used by rustc to avoid warning about old rustdoc lints before rustdoc registers them as tool lints.
    #[track_caller]
    pub fn register_ignored(&mut self, name: &str) {
        if self.by_name.insert(name.to_string(), Ignored).is_some() {
            bug!("duplicate specification of lint {}", name);
        }
    }

    /// This lint has been renamed; warn about using the new name and apply the lint.
    #[track_caller]
    pub fn register_renamed(&mut self, old_name: &str, new_name: &str) {
        let Some(&Id(target)) = self.by_name.get(new_name) else {
            bug!("invalid lint renaming of {} to {}", old_name, new_name);
        };
        self.by_name.insert(old_name.to_string(), Renamed(new_name.to_string(), target));
    }

    pub fn register_removed(&mut self, name: &str, reason: &str) {
        self.by_name.insert(name.into(), Removed(reason.into()));
    }

    pub fn find_lints(&self, lint_name: &str) -> Option<&[LintId]> {
        match self.by_name.get(lint_name) {
            Some(Id(lint_id)) => Some(slice::from_ref(lint_id)),
            Some(Renamed(_, lint_id)) => Some(slice::from_ref(lint_id)),
            Some(Removed(_)) => None,
            Some(Ignored) => Some(&[]),
            None => match self.lint_groups.get(lint_name) {
                Some(LintGroup { lint_ids, .. }) => Some(lint_ids),
                None => None,
            },
        }
    }

    /// True if this symbol represents a lint group name.
    pub fn is_lint_group(&self, lint_name: Symbol) -> bool {
        debug!(
            "is_lint_group(lint_name={:?}, lint_groups={:?})",
            lint_name,
            self.lint_groups.keys().collect::<Vec<_>>()
        );
        let lint_name_str = lint_name.as_str();
        self.lint_groups.contains_key(lint_name_str) || {
            let warnings_name_str = crate::WARNINGS.name_lower();
            lint_name_str == warnings_name_str
        }
    }

    /// Checks the name of a lint for its existence, and whether it was
    /// renamed or removed. Generates a `Diag` containing a
    /// warning for renamed and removed lints. This is over both lint
    /// names from attributes and those passed on the command line. Since
    /// it emits non-fatal warnings and there are *two* lint passes that
    /// inspect attributes, this is only run from the late pass to avoid
    /// printing duplicate warnings.
    pub fn check_lint_name(
        &self,
        lint_name: &str,
        tool_name: Option<Symbol>,
        registered_tools: &RegisteredTools,
    ) -> CheckLintNameResult<'_> {
        if let Some(tool_name) = tool_name {
            // FIXME: rustc and rustdoc are considered tools for lints, but not for attributes.
            if tool_name != sym::rustc
                && tool_name != sym::rustdoc
                && !registered_tools.contains(&Ident::with_dummy_span(tool_name))
            {
                return CheckLintNameResult::NoTool;
            }
        }

        let complete_name = if let Some(tool_name) = tool_name {
            format!("{tool_name}::{lint_name}")
        } else {
            lint_name.to_string()
        };
        // If the lint was scoped with `tool::` check if the tool lint exists
        if let Some(tool_name) = tool_name {
            match self.by_name.get(&complete_name) {
                None => match self.lint_groups.get(&*complete_name) {
                    // If the lint isn't registered, there are two possibilities:
                    None => {
                        // 1. The tool is currently running, so this lint really doesn't exist.
                        // FIXME: should this handle tools that never register a lint, like rustfmt?
                        debug!("lints={:?}", self.by_name);
                        let tool_prefix = format!("{tool_name}::");

                        return if self.by_name.keys().any(|lint| lint.starts_with(&tool_prefix)) {
                            self.no_lint_suggestion(&complete_name, tool_name.as_str())
                        } else {
                            // 2. The tool isn't currently running, so no lints will be registered.
                            // To avoid giving a false positive, ignore all unknown lints.
                            CheckLintNameResult::MissingTool
                        };
                    }
                    Some(LintGroup { lint_ids, depr, .. }) => {
                        return if let &Some(LintAlias { name, silent: false }) = depr {
                            CheckLintNameResult::Tool(lint_ids, Some(name.to_string()))
                        } else {
                            CheckLintNameResult::Tool(lint_ids, None)
                        };
                    }
                },
                Some(Id(id)) => return CheckLintNameResult::Tool(slice::from_ref(id), None),
                // If the lint was registered as removed or renamed by the lint tool, we don't need
                // to treat tool_lints and rustc lints different and can use the code below.
                _ => {}
            }
        }
        match self.by_name.get(&complete_name) {
            Some(Renamed(new_name, _)) => CheckLintNameResult::Renamed(new_name.to_string()),
            Some(Removed(reason)) => CheckLintNameResult::Removed(reason.to_string()),
            None => match self.lint_groups.get(&*complete_name) {
                // If neither the lint, nor the lint group exists check if there is a `clippy::`
                // variant of this lint
                None => self.check_tool_name_for_backwards_compat(&complete_name, "clippy"),
                Some(LintGroup { lint_ids, depr, .. }) => {
                    // Check if the lint group name is deprecated
                    if let &Some(LintAlias { name, silent: false }) = depr {
                        CheckLintNameResult::Tool(lint_ids, Some(name.to_string()))
                    } else {
                        CheckLintNameResult::Ok(lint_ids)
                    }
                }
            },
            Some(Id(id)) => CheckLintNameResult::Ok(slice::from_ref(id)),
            Some(&Ignored) => CheckLintNameResult::Ok(&[]),
        }
    }

    fn no_lint_suggestion(&self, lint_name: &str, tool_name: &str) -> CheckLintNameResult<'_> {
        let name_lower = lint_name.to_lowercase();

        if lint_name.chars().any(char::is_uppercase) && self.find_lints(&name_lower).is_some() {
            // First check if the lint name is (partly) in upper case instead of lower case...
            return CheckLintNameResult::NoLint(Some((Symbol::intern(&name_lower), false)));
        }

        // ...if not, search for lints with a similar name
        // Note: find_best_match_for_name depends on the sort order of its input vector.
        // To ensure deterministic output, sort elements of the lint_groups hash map.
        // Also, never suggest deprecated lint groups.
        // We will soon sort, so the initial order does not matter.
        #[allow(rustc::potential_query_instability)]
        let mut groups: Vec<_> = self
            .lint_groups
            .iter()
            .filter_map(|(k, LintGroup { depr, .. })| depr.is_none().then_some(k))
            .collect();
        groups.sort();
        let groups = groups.iter().map(|k| Symbol::intern(k));
        let lints = self.lints.iter().map(|l| Symbol::intern(&l.name_lower()));
        let names: Vec<Symbol> = groups.chain(lints).collect();
        let mut lookups = vec![Symbol::intern(&name_lower)];
        if let Some(stripped) = name_lower.split("::").last() {
            lookups.push(Symbol::intern(stripped));
        }
        let res = find_best_match_for_names(&names, &lookups, None);
        let is_rustc = res.map_or_else(
            || false,
            |s| name_lower.contains("::") && !s.as_str().starts_with(tool_name),
        );
        let suggestion = res.map(|s| (s, is_rustc));
        CheckLintNameResult::NoLint(suggestion)
    }

    fn check_tool_name_for_backwards_compat(
        &self,
        lint_name: &str,
        tool_name: &str,
    ) -> CheckLintNameResult<'_> {
        let complete_name = format!("{tool_name}::{lint_name}");
        match self.by_name.get(&complete_name) {
            None => match self.lint_groups.get(&*complete_name) {
                // Now we are sure, that this lint exists nowhere
                None => self.no_lint_suggestion(lint_name, tool_name),
                Some(LintGroup { lint_ids, .. }) => {
                    CheckLintNameResult::Tool(lint_ids, Some(complete_name))
                }
            },
            Some(Id(id)) => CheckLintNameResult::Tool(slice::from_ref(id), Some(complete_name)),
            Some(other) => {
                debug!("got renamed lint {:?}", other);
                CheckLintNameResult::NoLint(None)
            }
        }
    }
}

/// Context for lint checking outside of type inference.
pub struct LateContext<'tcx> {
    /// Type context we're checking in.
    pub tcx: TyCtxt<'tcx>,

    /// Current body, or `None` if outside a body.
    pub enclosing_body: Option<hir::BodyId>,

    /// Type-checking results for the current body. Access using the `typeck_results`
    /// and `maybe_typeck_results` methods, which handle querying the typeck results on demand.
    // FIXME(eddyb) move all the code accessing internal fields like this,
    // to this module, to avoid exposing it to lint logic.
    pub(super) cached_typeck_results: Cell<Option<&'tcx ty::TypeckResults<'tcx>>>,

    /// Parameter environment for the item we are in.
    pub param_env: ty::ParamEnv<'tcx>,

    /// Items accessible from the crate being checked.
    pub effective_visibilities: &'tcx EffectiveVisibilities,

    pub last_node_with_lint_attrs: hir::HirId,

    /// Generic type parameters in scope for the item we are in.
    pub generics: Option<&'tcx hir::Generics<'tcx>>,

    /// We are only looking at one module
    pub only_module: bool,
}

/// Context for lint checking of the AST, after expansion, before lowering to HIR.
pub struct EarlyContext<'a> {
    pub builder: LintLevelsBuilder<'a, crate::levels::TopDown>,
    pub buffered: LintBuffer,
}

pub trait LintContext {
    fn sess(&self) -> &Session;

    // FIXME: These methods should not take an Into<MultiSpan> -- instead, callers should need to
    // set the span in their `decorate` function (preferably using set_span).
    /// Emit a lint at the appropriate level, with an optional associated span.
    ///
    /// [`lint_level`]: rustc_middle::lint::lint_level#decorate-signature
    #[rustc_lint_diagnostics]
    #[track_caller]
    fn opt_span_lint<S: Into<MultiSpan>>(
        &self,
        lint: &'static Lint,
        span: Option<S>,
        decorate: impl for<'a, 'b> FnOnce(&'b mut Diag<'a, ()>),
    );

    /// Emit a lint at `span` from a lint struct (some type that implements `LintDiagnostic`,
    /// typically generated by `#[derive(LintDiagnostic)]`).
    fn emit_span_lint<S: Into<MultiSpan>>(
        &self,
        lint: &'static Lint,
        span: S,
        decorator: impl for<'a> LintDiagnostic<'a, ()>,
    ) {
        self.opt_span_lint(lint, Some(span), |lint| {
            decorator.decorate_lint(lint);
        });
    }

    /// Emit a lint at `span` from a lazily-constructed lint struct (some type that implements
    /// `LintDiagnostic`, typically generated by `#[derive(LintDiagnostic)]`).
    fn emit_span_lint_lazy<S: Into<MultiSpan>, L: for<'a> LintDiagnostic<'a, ()>>(
        &self,
        lint: &'static Lint,
        span: S,
        decorator: impl FnOnce() -> L,
    ) {
        self.opt_span_lint(lint, Some(span), |lint| {
            let decorator = decorator();
            decorator.decorate_lint(lint);
        });
    }

    /// Emit a lint at the appropriate level, with an associated span.
    ///
    /// [`lint_level`]: rustc_middle::lint::lint_level#decorate-signature
    #[rustc_lint_diagnostics]
    #[track_caller]
    fn span_lint<S: Into<MultiSpan>>(
        &self,
        lint: &'static Lint,
        span: S,
        decorate: impl for<'a, 'b> FnOnce(&'b mut Diag<'a, ()>),
    ) {
        self.opt_span_lint(lint, Some(span), decorate);
    }

    /// Emit a lint from a lint struct (some type that implements `LintDiagnostic`, typically
    /// generated by `#[derive(LintDiagnostic)]`).
    fn emit_lint(&self, lint: &'static Lint, decorator: impl for<'a> LintDiagnostic<'a, ()>) {
        self.opt_span_lint(lint, None as Option<Span>, |lint| {
            decorator.decorate_lint(lint);
        });
    }

    /// Emit a lint at the appropriate level, with no associated span.
    ///
    /// [`lint_level`]: rustc_middle::lint::lint_level#decorate-signature
    #[rustc_lint_diagnostics]
    fn lint(&self, lint: &'static Lint, decorate: impl for<'a, 'b> FnOnce(&'b mut Diag<'a, ()>)) {
        self.opt_span_lint(lint, None as Option<Span>, decorate);
    }

    /// This returns the lint level for the given lint at the current location.
    fn get_lint_level(&self, lint: &'static Lint) -> LevelAndSource;

    /// This function can be used to manually fulfill an expectation. This can
    /// be used for lints which contain several spans, and should be suppressed,
    /// if either location was marked with an expectation.
    ///
    /// Note that this function should only be called for [`LintExpectationId`]s
    /// retrieved from the current lint pass. Buffered or manually created ids can
    /// cause ICEs.
    fn fulfill_expectation(&self, expectation: LintExpectationId) {
        // We need to make sure that submitted expectation ids are correctly fulfilled suppressed
        // and stored between compilation sessions. To not manually do these steps, we simply create
        // a dummy diagnostic and emit it as usual, which will be suppressed and stored like a
        // normal expected lint diagnostic.
        #[allow(rustc::diagnostic_outside_of_impl)]
        #[allow(rustc::untranslatable_diagnostic)]
        self.sess()
            .dcx()
            .struct_expect(
                "this is a dummy diagnostic, to submit and store an expectation",
                expectation,
            )
            .emit();
    }
}

impl<'a> EarlyContext<'a> {
    pub(crate) fn new(
        sess: &'a Session,
        features: &'a Features,
        lint_added_lints: bool,
        lint_store: &'a LintStore,
        registered_tools: &'a RegisteredTools,
        buffered: LintBuffer,
    ) -> EarlyContext<'a> {
        EarlyContext {
            builder: LintLevelsBuilder::new(
                sess,
                features,
                lint_added_lints,
                lint_store,
                registered_tools,
            ),
            buffered,
        }
    }
}

impl<'tcx> LintContext for LateContext<'tcx> {
    /// Gets the overall compiler `Session` object.
    fn sess(&self) -> &Session {
        self.tcx.sess
    }

    #[rustc_lint_diagnostics]
    fn opt_span_lint<S: Into<MultiSpan>>(
        &self,
        lint: &'static Lint,
        span: Option<S>,
        decorate: impl for<'a, 'b> FnOnce(&'b mut Diag<'a, ()>),
    ) {
        let hir_id = self.last_node_with_lint_attrs;

        match span {
            Some(s) => self.tcx.node_span_lint(lint, hir_id, s, decorate),
            None => self.tcx.node_lint(lint, hir_id, decorate),
        }
    }

    fn get_lint_level(&self, lint: &'static Lint) -> LevelAndSource {
        self.tcx.lint_level_at_node(lint, self.last_node_with_lint_attrs)
    }
}

impl LintContext for EarlyContext<'_> {
    /// Gets the overall compiler `Session` object.
    fn sess(&self) -> &Session {
        self.builder.sess()
    }

    #[rustc_lint_diagnostics]
    fn opt_span_lint<S: Into<MultiSpan>>(
        &self,
        lint: &'static Lint,
        span: Option<S>,
        decorate: impl for<'a, 'b> FnOnce(&'b mut Diag<'a, ()>),
    ) {
        self.builder.opt_span_lint(lint, span.map(|s| s.into()), decorate)
    }

    fn get_lint_level(&self, lint: &'static Lint) -> LevelAndSource {
        self.builder.lint_level(lint)
    }
}

impl<'tcx> LateContext<'tcx> {
    /// The typing mode of the currently visited node. Use this when
    /// building a new `InferCtxt`.
    pub fn typing_mode(&self) -> TypingMode<'tcx> {
        // FIXME(#132279): In case we're in a body, we should use a typing
        // mode which reveals the opaque types defined by that body.
        TypingMode::non_body_analysis()
    }

    pub fn typing_env(&self) -> TypingEnv<'tcx> {
        TypingEnv { typing_mode: self.typing_mode(), param_env: self.param_env }
    }

    pub fn type_is_copy_modulo_regions(&self, ty: Ty<'tcx>) -> bool {
        self.tcx.type_is_copy_modulo_regions(self.typing_env(), ty)
    }

    pub fn type_is_use_cloned_modulo_regions(&self, ty: Ty<'tcx>) -> bool {
        self.tcx.type_is_use_cloned_modulo_regions(self.typing_env(), ty)
    }

    /// Gets the type-checking results for the current body,
    /// or `None` if outside a body.
    pub fn maybe_typeck_results(&self) -> Option<&'tcx ty::TypeckResults<'tcx>> {
        self.cached_typeck_results.get().or_else(|| {
            self.enclosing_body.map(|body| {
                let typeck_results = self.tcx.typeck_body(body);
                self.cached_typeck_results.set(Some(typeck_results));
                typeck_results
            })
        })
    }

    /// Gets the type-checking results for the current body.
    /// As this will ICE if called outside bodies, only call when working with
    /// `Expr` or `Pat` nodes (they are guaranteed to be found only in bodies).
    #[track_caller]
    pub fn typeck_results(&self) -> &'tcx ty::TypeckResults<'tcx> {
        self.maybe_typeck_results().expect("`LateContext::typeck_results` called outside of body")
    }

    /// Returns the final resolution of a `QPath`, or `Res::Err` if unavailable.
    /// Unlike `.typeck_results().qpath_res(qpath, id)`, this can be used even outside
    /// bodies (e.g. for paths in `hir::Ty`), without any risk of ICE-ing.
    pub fn qpath_res(&self, qpath: &hir::QPath<'_>, id: hir::HirId) -> Res {
        match *qpath {
            hir::QPath::Resolved(_, path) => path.res,
            hir::QPath::TypeRelative(..) | hir::QPath::LangItem(..) => self
                .maybe_typeck_results()
                .filter(|typeck_results| typeck_results.hir_owner == id.owner)
                .or_else(|| {
                    self.tcx
                        .has_typeck_results(id.owner.def_id)
                        .then(|| self.tcx.typeck(id.owner.def_id))
                })
                .and_then(|typeck_results| typeck_results.type_dependent_def(id))
                .map_or(Res::Err, |(kind, def_id)| Res::Def(kind, def_id)),
        }
    }

    /// Gets the absolute path of `def_id` as a vector of `Symbol`.
    ///
    /// Note that this is kinda expensive because it has to
    /// travel the tree and pretty-print. Use sparingly.
    ///
    /// If you're trying to match for an item given by its path, use a
    /// diagnostic item. If you're only interested in given sections, use more
    /// specific functions, such as [`TyCtxt::crate_name`]
    ///
    /// FIXME: It would be great if this could be optimized.
    ///
    /// # Examples
    ///
    /// ```rust,ignore (no context or def id available)
    /// let def_path = cx.get_def_path(def_id);
    /// if let &[sym::core, sym::option, sym::Option] = &def_path[..] {
    ///     // The given `def_id` is that of an `Option` type
    /// }
    /// ```
    pub fn get_def_path(&self, def_id: DefId) -> Vec<Symbol> {
        struct LintPathPrinter<'tcx> {
            tcx: TyCtxt<'tcx>,
            path: Vec<Symbol>,
        }

        impl<'tcx> Printer<'tcx> for LintPathPrinter<'tcx> {
            fn tcx(&self) -> TyCtxt<'tcx> {
                self.tcx
            }

            fn print_region(&mut self, _region: ty::Region<'_>) -> Result<(), PrintError> {
                unreachable!(); // because `print_path_with_generic_args` ignores the `GenericArgs`
            }

            fn print_type(&mut self, _ty: Ty<'tcx>) -> Result<(), PrintError> {
                unreachable!(); // because `print_path_with_generic_args` ignores the `GenericArgs`
            }

            fn print_dyn_existential(
                &mut self,
                _predicates: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
            ) -> Result<(), PrintError> {
                unreachable!(); // because `print_path_with_generic_args` ignores the `GenericArgs`
            }

            fn print_const(&mut self, _ct: ty::Const<'tcx>) -> Result<(), PrintError> {
                unreachable!(); // because `print_path_with_generic_args` ignores the `GenericArgs`
            }

            fn print_crate_name(&mut self, cnum: CrateNum) -> Result<(), PrintError> {
                self.path = vec![self.tcx.crate_name(cnum)];
                Ok(())
            }

            fn print_path_with_qualified(
                &mut self,
                self_ty: Ty<'tcx>,
                trait_ref: Option<ty::TraitRef<'tcx>>,
            ) -> Result<(), PrintError> {
                if trait_ref.is_none()
                    && let ty::Adt(def, args) = self_ty.kind()
                {
                    return self.print_def_path(def.did(), args);
                }

                // This shouldn't ever be needed, but just in case:
                with_no_trimmed_paths!({
                    self.path = vec![match trait_ref {
                        Some(trait_ref) => Symbol::intern(&format!("{trait_ref:?}")),
                        None => Symbol::intern(&format!("<{self_ty}>")),
                    }];
                    Ok(())
                })
            }

            fn print_path_with_impl(
                &mut self,
                print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>,
                self_ty: Ty<'tcx>,
                trait_ref: Option<ty::TraitRef<'tcx>>,
            ) -> Result<(), PrintError> {
                print_prefix(self)?;

                // This shouldn't ever be needed, but just in case:
                self.path.push(match trait_ref {
                    Some(trait_ref) => {
                        with_no_trimmed_paths!(Symbol::intern(&format!(
                            "<impl {} for {}>",
                            trait_ref.print_only_trait_path(),
                            self_ty
                        )))
                    }
                    None => {
                        with_no_trimmed_paths!(Symbol::intern(&format!("<impl {self_ty}>")))
                    }
                });

                Ok(())
            }

            fn print_path_with_simple(
                &mut self,
                print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>,
                disambiguated_data: &DisambiguatedDefPathData,
            ) -> Result<(), PrintError> {
                print_prefix(self)?;

                // Skip `::{{extern}}` blocks and `::{{constructor}}` on tuple/unit structs.
                if let DefPathData::ForeignMod | DefPathData::Ctor = disambiguated_data.data {
                    return Ok(());
                }

                self.path.push(match disambiguated_data.data.get_opt_name() {
                    Some(sym) => sym,
                    None => Symbol::intern(&disambiguated_data.data.to_string()),
                });
                Ok(())
            }

            fn print_path_with_generic_args(
                &mut self,
                print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>,
                _args: &[GenericArg<'tcx>],
            ) -> Result<(), PrintError> {
                print_prefix(self)
            }
        }

        let mut p = LintPathPrinter { tcx: self.tcx, path: vec![] };
        p.print_def_path(def_id, &[]).unwrap();
        p.path
    }

    /// Returns the associated type `name` for `self_ty` as an implementation of `trait_id`.
    /// Do not invoke without first verifying that the type implements the trait.
    pub fn get_associated_type(
        &self,
        self_ty: Ty<'tcx>,
        trait_id: DefId,
        name: Symbol,
    ) -> Option<Ty<'tcx>> {
        let tcx = self.tcx;
        tcx.associated_items(trait_id)
            .find_by_ident_and_kind(tcx, Ident::with_dummy_span(name), ty::AssocTag::Type, trait_id)
            .and_then(|assoc| {
                let proj = Ty::new_projection(tcx, assoc.def_id, [self_ty]);
                tcx.try_normalize_erasing_regions(self.typing_env(), proj).ok()
            })
    }

    /// Returns the effective precedence of an expression for the purpose of
    /// rendering diagnostic. This is not the same as the precedence that would
    /// be used for pretty-printing HIR by rustc_hir_pretty.
    pub fn precedence(&self, expr: &hir::Expr<'_>) -> ExprPrecedence {
        let has_attr = |id: hir::HirId| -> bool {
            for attr in self.tcx.hir_attrs(id) {
                if attr.span().desugaring_kind().is_none() {
                    return true;
                }
            }
            false
        };
        expr.precedence(&has_attr)
    }

    /// If the given expression is a local binding, find the initializer expression.
    /// If that initializer expression is another local binding, find its initializer again.
    ///
    /// This process repeats as long as possible (but usually no more than once).
    /// Type-check adjustments are not taken in account in this function.
    ///
    /// Examples:
    /// ```
    /// let abc = 1;
    /// let def = abc + 2;
    /// //        ^^^^^^^ output
    /// let def = def;
    /// dbg!(def);
    /// //   ^^^ input
    /// ```
    pub fn expr_or_init<'a>(&self, mut expr: &'a hir::Expr<'tcx>) -> &'a hir::Expr<'tcx> {
        expr = expr.peel_blocks();

        while let hir::ExprKind::Path(ref qpath) = expr.kind
            && let Some(parent_node) = match self.qpath_res(qpath, expr.hir_id) {
                Res::Local(hir_id) => Some(self.tcx.parent_hir_node(hir_id)),
                _ => None,
            }
            && let Some(init) = match parent_node {
                hir::Node::Expr(expr) => Some(expr),
                hir::Node::LetStmt(hir::LetStmt {
                    init,
                    // Binding is immutable, init cannot be re-assigned
                    pat: Pat { kind: PatKind::Binding(BindingMode::NONE, ..), .. },
                    ..
                }) => *init,
                _ => None,
            }
        {
            expr = init.peel_blocks();
        }
        expr
    }

    /// If the given expression is a local binding, find the initializer expression.
    /// If that initializer expression is another local or **outside** (`const`/`static`)
    /// binding, find its initializer again.
    ///
    /// This process repeats as long as possible (but usually no more than once).
    /// Type-check adjustments are not taken in account in this function.
    ///
    /// Examples:
    /// ```
    /// const ABC: i32 = 1;
    /// //               ^ output
    /// let def = ABC;
    /// dbg!(def);
    /// //   ^^^ input
    ///
    /// // or...
    /// let abc = 1;
    /// let def = abc + 2;
    /// //        ^^^^^^^ output
    /// dbg!(def);
    /// //   ^^^ input
    /// ```
    pub fn expr_or_init_with_outside_body<'a>(
        &self,
        mut expr: &'a hir::Expr<'tcx>,
    ) -> &'a hir::Expr<'tcx> {
        expr = expr.peel_blocks();

        while let hir::ExprKind::Path(ref qpath) = expr.kind
            && let Some(parent_node) = match self.qpath_res(qpath, expr.hir_id) {
                Res::Local(hir_id) => Some(self.tcx.parent_hir_node(hir_id)),
                Res::Def(_, def_id) => self.tcx.hir_get_if_local(def_id),
                _ => None,
            }
            && let Some(init) = match parent_node {
                hir::Node::Expr(expr) => Some(expr),
                hir::Node::LetStmt(hir::LetStmt {
                    init,
                    // Binding is immutable, init cannot be re-assigned
                    pat: Pat { kind: PatKind::Binding(BindingMode::NONE, ..), .. },
                    ..
                }) => *init,
                hir::Node::Item(item) => match item.kind {
                    hir::ItemKind::Const(.., body_id) | hir::ItemKind::Static(.., body_id) => {
                        Some(self.tcx.hir_body(body_id).value)
                    }
                    _ => None,
                },
                _ => None,
            }
        {
            expr = init.peel_blocks();
        }
        expr
    }
}

impl<'tcx> abi::HasDataLayout for LateContext<'tcx> {
    #[inline]
    fn data_layout(&self) -> &abi::TargetDataLayout {
        &self.tcx.data_layout
    }
}

impl<'tcx> ty::layout::HasTyCtxt<'tcx> for LateContext<'tcx> {
    #[inline]
    fn tcx(&self) -> TyCtxt<'tcx> {
        self.tcx
    }
}

impl<'tcx> ty::layout::HasTypingEnv<'tcx> for LateContext<'tcx> {
    #[inline]
    fn typing_env(&self) -> ty::TypingEnv<'tcx> {
        self.typing_env()
    }
}

impl<'tcx> LayoutOfHelpers<'tcx> for LateContext<'tcx> {
    type LayoutOfResult = Result<TyAndLayout<'tcx>, LayoutError<'tcx>>;

    #[inline]
    fn handle_layout_err(&self, err: LayoutError<'tcx>, _: Span, _: Ty<'tcx>) -> LayoutError<'tcx> {
        err
    }
}
