//! Lints in the Rust compiler.
//!
//! This contains lints which can feasibly be implemented as their own
//! AST visitor. Also see `rustc_session::lint::builtin`, which contains the
//! definitions of lints that are emitted directly inside the main compiler.
//!
//! To add a new lint to rustc, declare it here using [`declare_lint!`].
//! Then add code to emit the new lint in the appropriate circumstances.
//!
//! If you define a new [`EarlyLintPass`], you will also need to add it to the
//! [`crate::early_lint_methods!`] invocation in `lib.rs`.
//!
//! If you define a new [`LateLintPass`], you will also need to add it to the
//! [`crate::late_lint_methods!`] invocation in `lib.rs`.

use std::fmt::Write;

use ast::token::TokenKind;
use rustc_abi::BackendRepr;
use rustc_ast::tokenstream::{TokenStream, TokenTree};
use rustc_ast::visit::{FnCtxt, FnKind};
use rustc_ast::{self as ast, *};
use rustc_ast_pretty::pprust::expr_to_string;
use rustc_attr_parsing::AttributeParser;
use rustc_errors::{Applicability, LintDiagnostic};
use rustc_feature::GateIssue;
use rustc_hir as hir;
use rustc_hir::attrs::AttributeKind;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::{CRATE_DEF_ID, DefId, LocalDefId};
use rustc_hir::intravisit::FnKind as HirFnKind;
use rustc_hir::{Body, FnDecl, ImplItemImplKind, PatKind, PredicateOrigin, find_attr};
use rustc_middle::bug;
use rustc_middle::lint::LevelAndSource;
use rustc_middle::ty::layout::LayoutOf;
use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_middle::ty::{self, AssocContainer, Ty, TyCtxt, TypeVisitableExt, Upcast, VariantDef};
use rustc_session::lint::FutureIncompatibilityReason;
// hardwired lints from rustc_lint_defs
pub use rustc_session::lint::builtin::*;
use rustc_session::{declare_lint, declare_lint_pass, impl_lint_pass};
use rustc_span::edition::Edition;
use rustc_span::source_map::Spanned;
use rustc_span::{BytePos, DUMMY_SP, Ident, InnerSpan, Span, Symbol, kw, sym};
use rustc_target::asm::InlineAsmArch;
use rustc_trait_selection::infer::{InferCtxtExt, TyCtxtInferExt};
use rustc_trait_selection::traits::misc::type_allowed_to_implement_copy;
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
use rustc_trait_selection::traits::{self};

use crate::errors::BuiltinEllipsisInclusiveRangePatterns;
use crate::lints::{
    BuiltinAnonymousParams, BuiltinConstNoMangle, BuiltinDerefNullptr, BuiltinDoubleNegations,
    BuiltinDoubleNegationsAddParens, BuiltinEllipsisInclusiveRangePatternsLint,
    BuiltinExplicitOutlives, BuiltinExplicitOutlivesSuggestion, BuiltinFeatureIssueNote,
    BuiltinIncompleteFeatures, BuiltinIncompleteFeaturesHelp, BuiltinInternalFeatures,
    BuiltinKeywordIdents, BuiltinMissingCopyImpl, BuiltinMissingDebugImpl, BuiltinMissingDoc,
    BuiltinMutablesTransmutes, BuiltinNoMangleGeneric, BuiltinNonShorthandFieldPatterns,
    BuiltinSpecialModuleNameUsed, BuiltinTrivialBounds, BuiltinTypeAliasBounds,
    BuiltinUngatedAsyncFnTrackCaller, BuiltinUnpermittedTypeInit, BuiltinUnpermittedTypeInitSub,
    BuiltinUnreachablePub, BuiltinUnsafe, BuiltinUnstableFeatures, BuiltinUnusedDocComment,
    BuiltinUnusedDocCommentSub, BuiltinWhileTrue, InvalidAsmLabel,
};
use crate::{
    EarlyContext, EarlyLintPass, LateContext, LateLintPass, Level, LintContext,
    fluent_generated as fluent,
};
declare_lint! {
    /// The `while_true` lint detects `while true { }`.
    ///
    /// ### Example
    ///
    /// ```rust,no_run
    /// while true {
    ///
    /// }
    /// ```
    ///
    /// {{produces}}
    ///
    /// ### Explanation
    ///
    /// `while true` should be replaced with `loop`. A `loop` expression is
    /// the preferred way to write an infinite loop because it more directly
    /// expresses the intent of the loop.
    WHILE_TRUE,
    Warn,
    "suggest using `loop { }` instead of `while true { }`"
}

declare_lint_pass!(WhileTrue => [WHILE_TRUE]);

impl EarlyLintPass for WhileTrue {
    #[inline]
    fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &ast::Expr) {
        if let ast::ExprKind::While(cond, _, label) = &e.kind
            && let ast::ExprKind::Lit(token_lit) = cond.peel_parens().kind
            && let token::Lit { kind: token::Bool, symbol: kw::True, .. } = token_lit
            && !cond.span.from_expansion()
        {
            let condition_span = e.span.with_hi(cond.span.hi());
            let replace = format!(
                "{}loop",
                label.map_or_else(String::new, |label| format!("{}: ", label.ident,))
            );
            cx.emit_span_lint(
                WHILE_TRUE,
                condition_span,
                BuiltinWhileTrue { suggestion: condition_span, replace },
            );
        }
    }
}

declare_lint! {
    /// The `non_shorthand_field_patterns` lint detects using `Struct { x: x }`
    /// instead of `Struct { x }` in a pattern.
    ///
    /// ### Example
    ///
    /// ```rust
    /// struct Point {
    ///     x: i32,
    ///     y: i32,
    /// }
    ///
    ///
    /// fn main() {
    ///     let p = Point {
    ///         x: 5,
    ///         y: 5,
    ///     };
    ///
    ///     match p {
    ///         Point { x: x, y: y } => (),
    ///     }
    /// }
    /// ```
    ///
    /// {{produces}}
    ///
    /// ### Explanation
    ///
    /// The preferred style is to avoid the repetition of specifying both the
    /// field name and the binding name if both identifiers are the same.
    NON_SHORTHAND_FIELD_PATTERNS,
    Warn,
    "using `Struct { x: x }` instead of `Struct { x }` in a pattern"
}

declare_lint_pass!(NonShorthandFieldPatterns => [NON_SHORTHAND_FIELD_PATTERNS]);

impl<'tcx> LateLintPass<'tcx> for NonShorthandFieldPatterns {
    fn check_pat(&mut self, cx: &LateContext<'_>, pat: &hir::Pat<'_>) {
        if let PatKind::Struct(ref qpath, field_pats, _) = pat.kind {
            let variant = cx
                .typeck_results()
                .pat_ty(pat)
                .ty_adt_def()
                .expect("struct pattern type is not an ADT")
                .variant_of_res(cx.qpath_res(qpath, pat.hir_id));
            for fieldpat in field_pats {
                if fieldpat.is_shorthand {
                    continue;
                }
                if fieldpat.span.from_expansion() {
                    // Don't lint if this is a macro expansion: macro authors
                    // shouldn't have to worry about this kind of style issue
                    // (Issue #49588)
                    continue;
                }
                if let PatKind::Binding(binding_annot, _, ident, None) = fieldpat.pat.kind {
                    if cx.tcx.find_field_index(ident, variant)
                        == Some(cx.typeck_results().field_index(fieldpat.hir_id))
                    {
                        cx.emit_span_lint(
                            NON_SHORTHAND_FIELD_PATTERNS,
                            fieldpat.span,
                            BuiltinNonShorthandFieldPatterns {
                                ident,
                                suggestion: fieldpat.span,
                                prefix: binding_annot.prefix_str(),
                            },
                        );
                    }
                }
            }
        }
    }
}

declare_lint! {
    /// The `unsafe_code` lint catches usage of `unsafe` code and other
    /// potentially unsound constructs like `no_mangle`, `export_name`,
    /// and `link_section`.
    ///
    /// ### Example
    ///
    /// ```rust,compile_fail
    /// #![deny(unsafe_code)]
    /// fn main() {
    ///     unsafe {
    ///
    ///     }
    /// }
    ///
    /// #[no_mangle]
    /// fn func_0() { }
    ///
    /// #[export_name = "exported_symbol_name"]
    /// pub fn name_in_rust() { }
    ///
    /// #[no_mangle]
    /// #[link_section = ".example_section"]
    /// pub static VAR1: u32 = 1;
    /// ```
    ///
    /// {{produces}}
    ///
    /// ### Explanation
    ///
    /// This lint is intended to restrict the usage of `unsafe` blocks and other
    /// constructs (including, but not limited to `no_mangle`, `link_section`
    /// and `export_name` attributes) wrong usage of which causes undefined
    /// behavior.
    UNSAFE_CODE,
    Allow,
    "usage of `unsafe` code and other potentially unsound constructs",
    @eval_always = true
}

declare_lint_pass!(UnsafeCode => [UNSAFE_CODE]);

impl UnsafeCode {
    fn report_unsafe(
        &self,
        cx: &EarlyContext<'_>,
        span: Span,
        decorate: impl for<'a> LintDiagnostic<'a, ()>,
    ) {
        // This comes from a macro that has `#[allow_internal_unsafe]`.
        if span.allows_unsafe() {
            return;
        }

        cx.emit_span_lint(UNSAFE_CODE, span, decorate);
    }
}

impl EarlyLintPass for UnsafeCode {
    #[inline]
    fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &ast::Expr) {
        if let ast::ExprKind::Block(ref blk, _) = e.kind {
            // Don't warn about generated blocks; that'll just pollute the output.
            if blk.rules == ast::BlockCheckMode::Unsafe(ast::UserProvided) {
                self.report_unsafe(cx, blk.span, BuiltinUnsafe::UnsafeBlock);
            }
        }
    }

    fn check_item(&mut self, cx: &EarlyContext<'_>, it: &ast::Item) {
        match it.kind {
            ast::ItemKind::Trait(box ast::Trait { safety: ast::Safety::Unsafe(_), .. }) => {
                self.report_unsafe(cx, it.span, BuiltinUnsafe::UnsafeTrait);
            }

            ast::ItemKind::Impl(ast::Impl {
                of_trait: Some(box ast::TraitImplHeader { safety: ast::Safety::Unsafe(_), .. }),
                ..
            }) => {
                self.report_unsafe(cx, it.span, BuiltinUnsafe::UnsafeImpl);
            }

            ast::ItemKind::Fn(..) => {
                if let Some(attr) = attr::find_by_name(&it.attrs, sym::no_mangle) {
                    self.report_unsafe(cx, attr.span, BuiltinUnsafe::NoMangleFn);
                }

                if let Some(attr) = attr::find_by_name(&it.attrs, sym::export_name) {
                    self.report_unsafe(cx, attr.span, BuiltinUnsafe::ExportNameFn);
                }

                if let Some(attr) = attr::find_by_name(&it.attrs, sym::link_section) {
                    self.report_unsafe(cx, attr.span, BuiltinUnsafe::LinkSectionFn);
                }
            }

            ast::ItemKind::Static(..) => {
                if let Some(attr) = attr::find_by_name(&it.attrs, sym::no_mangle) {
                    self.report_unsafe(cx, attr.span, BuiltinUnsafe::NoMangleStatic);
                }

                if let Some(attr) = attr::find_by_name(&it.attrs, sym::export_name) {
                    self.report_unsafe(cx, attr.span, BuiltinUnsafe::ExportNameStatic);
                }

                if let Some(attr) = attr::find_by_name(&it.attrs, sym::link_section) {
                    self.report_unsafe(cx, attr.span, BuiltinUnsafe::LinkSectionStatic);
                }
            }

            ast::ItemKind::GlobalAsm(..) => {
                self.report_unsafe(cx, it.span, BuiltinUnsafe::GlobalAsm);
            }

            ast::ItemKind::ForeignMod(ForeignMod { safety, .. }) => {
                if let Safety::Unsafe(_) = safety {
                    self.report_unsafe(cx, it.span, BuiltinUnsafe::UnsafeExternBlock);
                }
            }

            ast::ItemKind::MacroDef(..) => {
                if let Some(attr) = AttributeParser::parse_limited(
                    cx.builder.sess(),
                    &it.attrs,
                    sym::allow_internal_unsafe,
                    it.span,
                    DUMMY_NODE_ID,
                    Some(cx.builder.features()),
                ) {
                    self.report_unsafe(cx, attr.span(), BuiltinUnsafe::AllowInternalUnsafe);
                }
            }

            _ => {}
        }
    }

    fn check_impl_item(&mut self, cx: &EarlyContext<'_>, it: &ast::AssocItem) {
        if let ast::AssocItemKind::Fn(..) = it.kind {
            if let Some(attr) = attr::find_by_name(&it.attrs, sym::no_mangle) {
                self.report_unsafe(cx, attr.span, BuiltinUnsafe::NoMangleMethod);
            }
            if let Some(attr) = attr::find_by_name(&it.attrs, sym::export_name) {
                self.report_unsafe(cx, attr.span, BuiltinUnsafe::ExportNameMethod);
            }
        }
    }

    fn check_fn(&mut self, cx: &EarlyContext<'_>, fk: FnKind<'_>, span: Span, _: ast::NodeId) {
        if let FnKind::Fn(
            ctxt,
            _,
            ast::Fn {
                sig: ast::FnSig { header: ast::FnHeader { safety: ast::Safety::Unsafe(_), .. }, .. },
                body,
                ..
            },
        ) = fk
        {
            let decorator = match ctxt {
                FnCtxt::Foreign => return,
                FnCtxt::Free => BuiltinUnsafe::DeclUnsafeFn,
                FnCtxt::Assoc(_) if body.is_none() => BuiltinUnsafe::DeclUnsafeMethod,
                FnCtxt::Assoc(_) => BuiltinUnsafe::ImplUnsafeMethod,
            };
            self.report_unsafe(cx, span, decorator);
        }
    }
}

declare_lint! {
    /// The `missing_docs` lint detects missing documentation for public items.
    ///
    /// ### Example
    ///
    /// ```rust,compile_fail
    /// #![deny(missing_docs)]
    /// pub fn foo() {}
    /// ```
    ///
    /// {{produces}}
    ///
    /// ### Explanation
    ///
    /// This lint is intended to ensure that a library is well-documented.
    /// Items without documentation can be difficult for users to understand
    /// how to use properly.
    ///
    /// This lint is "allow" by default because it can be noisy, and not all
    /// projects may want to enforce everything to be documented.
    pub MISSING_DOCS,
    Allow,
    "detects missing documentation for public members",
    report_in_external_macro
}

#[derive(Default)]
pub struct MissingDoc;

impl_lint_pass!(MissingDoc => [MISSING_DOCS]);

fn has_doc(attr: &hir::Attribute) -> bool {
    if attr.is_doc_comment() {
        return true;
    }

    if !attr.has_name(sym::doc) {
        return false;
    }

    if attr.value_str().is_some() {
        return true;
    }

    if let Some(list) = attr.meta_item_list() {
        for meta in list {
            if meta.has_name(sym::hidden) {
                return true;
            }
        }
    }

    false
}

impl MissingDoc {
    fn check_missing_docs_attrs(
        &self,
        cx: &LateContext<'_>,
        def_id: LocalDefId,
        article: &'static str,
        desc: &'static str,
    ) {
        // Only check publicly-visible items, using the result from the privacy pass.
        // It's an option so the crate root can also use this function (it doesn't
        // have a `NodeId`).
        if def_id != CRATE_DEF_ID && !cx.effective_visibilities.is_exported(def_id) {
            return;
        }

        let attrs = cx.tcx.hir_attrs(cx.tcx.local_def_id_to_hir_id(def_id));
        let has_doc = attrs.iter().any(has_doc);
        if !has_doc {
            cx.emit_span_lint(
                MISSING_DOCS,
                cx.tcx.def_span(def_id),
                BuiltinMissingDoc { article, desc },
            );
        }
    }
}

impl<'tcx> LateLintPass<'tcx> for MissingDoc {
    fn check_crate(&mut self, cx: &LateContext<'_>) {
        self.check_missing_docs_attrs(cx, CRATE_DEF_ID, "the", "crate");
    }

    fn check_item(&mut self, cx: &LateContext<'_>, it: &hir::Item<'_>) {
        // Previously the Impl and Use types have been excluded from missing docs,
        // so we will continue to exclude them for compatibility.
        //
        // The documentation on `ExternCrate` is not used at the moment so no need to warn for it.
        if let hir::ItemKind::Impl(..) | hir::ItemKind::Use(..) | hir::ItemKind::ExternCrate(..) =
            it.kind
        {
            return;
        }

        let (article, desc) = cx.tcx.article_and_description(it.owner_id.to_def_id());
        self.check_missing_docs_attrs(cx, it.owner_id.def_id, article, desc);
    }

    fn check_trait_item(&mut self, cx: &LateContext<'_>, trait_item: &hir::TraitItem<'_>) {
        let (article, desc) = cx.tcx.article_and_description(trait_item.owner_id.to_def_id());

        self.check_missing_docs_attrs(cx, trait_item.owner_id.def_id, article, desc);
    }

    fn check_impl_item(&mut self, cx: &LateContext<'_>, impl_item: &hir::ImplItem<'_>) {
        let container = cx.tcx.associated_item(impl_item.owner_id.def_id).container;

        match container {
            // If the method is an impl for a trait, don't doc.
            AssocContainer::TraitImpl(_) => return,
            AssocContainer::Trait => {}
            // If the method is an impl for an item with docs_hidden, don't doc.
            AssocContainer::InherentImpl => {
                let parent = cx.tcx.hir_get_parent_item(impl_item.hir_id());
                let impl_ty = cx.tcx.type_of(parent).instantiate_identity();
                let outerdef = match impl_ty.kind() {
                    ty::Adt(def, _) => Some(def.did()),
                    ty::Foreign(def_id) => Some(*def_id),
                    _ => None,
                };
                let is_hidden = match outerdef {
                    Some(id) => cx.tcx.is_doc_hidden(id),
                    None => false,
                };
                if is_hidden {
                    return;
                }
            }
        }

        let (article, desc) = cx.tcx.article_and_description(impl_item.owner_id.to_def_id());
        self.check_missing_docs_attrs(cx, impl_item.owner_id.def_id, article, desc);
    }

    fn check_foreign_item(&mut self, cx: &LateContext<'_>, foreign_item: &hir::ForeignItem<'_>) {
        let (article, desc) = cx.tcx.article_and_description(foreign_item.owner_id.to_def_id());
        self.check_missing_docs_attrs(cx, foreign_item.owner_id.def_id, article, desc);
    }

    fn check_field_def(&mut self, cx: &LateContext<'_>, sf: &hir::FieldDef<'_>) {
        if !sf.is_positional() {
            self.check_missing_docs_attrs(cx, sf.def_id, "a", "struct field")
        }
    }

    fn check_variant(&mut self, cx: &LateContext<'_>, v: &hir::Variant<'_>) {
        self.check_missing_docs_attrs(cx, v.def_id, "a", "variant");
    }
}

declare_lint! {
    /// The `missing_copy_implementations` lint detects potentially-forgotten
    /// implementations of [`Copy`] for public types.
    ///
    /// [`Copy`]: https://doc.rust-lang.org/std/marker/trait.Copy.html
    ///
    /// ### Example
    ///
    /// ```rust,compile_fail
    /// #![deny(missing_copy_implementations)]
    /// pub struct Foo {
    ///     pub field: i32
    /// }
    /// # fn main() {}
    /// ```
    ///
    /// {{produces}}
    ///
    /// ### Explanation
    ///
    /// Historically (before 1.0), types were automatically marked as `Copy`
    /// if possible. This was changed so that it required an explicit opt-in
    /// by implementing the `Copy` trait. As part of this change, a lint was
    /// added to alert if a copyable type was not marked `Copy`.
    ///
    /// This lint is "allow" by default because this code isn't bad; it is
    /// common to write newtypes like this specifically so that a `Copy` type
    /// is no longer `Copy`. `Copy` types can result in unintended copies of
    /// large data which can impact performance.
    pub MISSING_COPY_IMPLEMENTATIONS,
    Allow,
    "detects potentially-forgotten implementations of `Copy`"
}

declare_lint_pass!(MissingCopyImplementations => [MISSING_COPY_IMPLEMENTATIONS]);

impl<'tcx> LateLintPass<'tcx> for MissingCopyImplementations {
    fn check_item(&mut self, cx: &LateContext<'_>, item: &hir::Item<'_>) {
        if !cx.effective_visibilities.is_reachable(item.owner_id.def_id) {
            return;
        }
        let (def, ty) = match item.kind {
            hir::ItemKind::Struct(_, generics, _) => {
                if !generics.params.is_empty() {
                    return;
                }
                let def = cx.tcx.adt_def(item.owner_id);
                (def, Ty::new_adt(cx.tcx, def, ty::List::empty()))
            }
            hir::ItemKind::Union(_, generics, _) => {
                if !generics.params.is_empty() {
                    return;
                }
                let def = cx.tcx.adt_def(item.owner_id);
                (def, Ty::new_adt(cx.tcx, def, ty::List::empty()))
            }
            hir::ItemKind::Enum(_, generics, _) => {
                if !generics.params.is_empty() {
                    return;
                }
                let def = cx.tcx.adt_def(item.owner_id);
                (def, Ty::new_adt(cx.tcx, def, ty::List::empty()))
            }
            _ => return,
        };
        if def.has_dtor(cx.tcx) {
            return;
        }

        // If the type contains a raw pointer, it may represent something like a handle,
        // and recommending Copy might be a bad idea.
        for field in def.all_fields() {
            let did = field.did;
            if cx.tcx.type_of(did).instantiate_identity().is_raw_ptr() {
                return;
            }
        }
        if cx.type_is_copy_modulo_regions(ty) {
            return;
        }
        if type_implements_negative_copy_modulo_regions(cx.tcx, ty, cx.typing_env()) {
            return;
        }
        if def.is_variant_list_non_exhaustive()
            || def.variants().iter().any(|variant| variant.is_field_list_non_exhaustive())
        {
            return;
        }

        // We shouldn't recommend implementing `Copy` on stateful things,
        // such as iterators.
        if let Some(iter_trait) = cx.tcx.get_diagnostic_item(sym::Iterator)
            && cx
                .tcx
                .infer_ctxt()
                .build(cx.typing_mode())
                .type_implements_trait(iter_trait, [ty], cx.param_env)
                .must_apply_modulo_regions()
        {
            return;
        }

        // Default value of clippy::trivially_copy_pass_by_ref
        const MAX_SIZE: u64 = 256;

        if let Some(size) = cx.layout_of(ty).ok().map(|l| l.size.bytes()) {
            if size > MAX_SIZE {
                return;
            }
        }

        if type_allowed_to_implement_copy(
            cx.tcx,
            cx.param_env,
            ty,
            traits::ObligationCause::misc(item.span, item.owner_id.def_id),
            hir::Safety::Safe,
        )
        .is_ok()
        {
            cx.emit_span_lint(MISSING_COPY_IMPLEMENTATIONS, item.span, BuiltinMissingCopyImpl);
        }
    }
}

/// Check whether a `ty` has a negative `Copy` implementation, ignoring outlives constraints.
fn type_implements_negative_copy_modulo_regions<'tcx>(
    tcx: TyCtxt<'tcx>,
    ty: Ty<'tcx>,
    typing_env: ty::TypingEnv<'tcx>,
) -> bool {
    let (infcx, param_env) = tcx.infer_ctxt().build_with_typing_env(typing_env);
    let trait_ref =
        ty::TraitRef::new(tcx, tcx.require_lang_item(hir::LangItem::Copy, DUMMY_SP), [ty]);
    let pred = ty::TraitPredicate { trait_ref, polarity: ty::PredicatePolarity::Negative };
    let obligation = traits::Obligation {
        cause: traits::ObligationCause::dummy(),
        param_env,
        recursion_depth: 0,
        predicate: pred.upcast(tcx),
    };
    infcx.predicate_must_hold_modulo_regions(&obligation)
}

declare_lint! {
    /// The `missing_debug_implementations` lint detects missing
    /// implementations of [`fmt::Debug`] for public types.
    ///
    /// [`fmt::Debug`]: https://doc.rust-lang.org/std/fmt/trait.Debug.html
    ///
    /// ### Example
    ///
    /// ```rust,compile_fail
    /// #![deny(missing_debug_implementations)]
    /// pub struct Foo;
    /// # fn main() {}
    /// ```
    ///
    /// {{produces}}
    ///
    /// ### Explanation
    ///
    /// Having a `Debug` implementation on all types can assist with
    /// debugging, as it provides a convenient way to format and display a
    /// value. Using the `#[derive(Debug)]` attribute will automatically
    /// generate a typical implementation, or a custom implementation can be
    /// added by manually implementing the `Debug` trait.
    ///
    /// This lint is "allow" by default because adding `Debug` to all types can
    /// have a negative impact on compile time and code size. It also requires
    /// boilerplate to be added to every type, which can be an impediment.
    MISSING_DEBUG_IMPLEMENTATIONS,
    Allow,
    "detects missing implementations of Debug"
}

#[derive(Default)]
pub(crate) struct MissingDebugImplementations;

impl_lint_pass!(MissingDebugImplementations => [MISSING_DEBUG_IMPLEMENTATIONS]);

impl<'tcx> LateLintPass<'tcx> for MissingDebugImplementations {
    fn check_item(&mut self, cx: &LateContext<'_>, item: &hir::Item<'_>) {
        if !cx.effective_visibilities.is_reachable(item.owner_id.def_id) {
            return;
        }

        match item.kind {
            hir::ItemKind::Struct(..) | hir::ItemKind::Union(..) | hir::ItemKind::Enum(..) => {}
            _ => return,
        }

        // Avoid listing trait impls if the trait is allowed.
        let LevelAndSource { level, .. } =
            cx.tcx.lint_level_at_node(MISSING_DEBUG_IMPLEMENTATIONS, item.hir_id());
        if level == Level::Allow {
            return;
        }

        let Some(debug) = cx.tcx.get_diagnostic_item(sym::Debug) else { return };

        let has_impl = cx
            .tcx
            .non_blanket_impls_for_ty(debug, cx.tcx.type_of(item.owner_id).instantiate_identity())
            .next()
            .is_some();
        if !has_impl {
            cx.emit_span_lint(
                MISSING_DEBUG_IMPLEMENTATIONS,
                item.span,
                BuiltinMissingDebugImpl { tcx: cx.tcx, def_id: debug },
            );
        }
    }
}

declare_lint! {
    /// The `anonymous_parameters` lint detects anonymous parameters in trait
    /// definitions.
    ///
    /// ### Example
    ///
    /// ```rust,edition2015,compile_fail
    /// #![deny(anonymous_parameters)]
    /// // edition 2015
    /// pub trait Foo {
    ///     fn foo(usize);
    /// }
    /// fn main() {}
    /// ```
    ///
    /// {{produces}}
    ///
    /// ### Explanation
    ///
    /// This syntax is mostly a historical accident, and can be worked around
    /// quite easily by adding an `_` pattern or a descriptive identifier:
    ///
    /// ```rust
    /// trait Foo {
    ///     fn foo(_: usize);
    /// }
    /// ```
    ///
    /// This syntax is now a hard error in the 2018 edition. In the 2015
    /// edition, this lint is "warn" by default. This lint
    /// enables the [`cargo fix`] tool with the `--edition` flag to
    /// automatically transition old code from the 2015 edition to 2018. The
    /// tool will run this lint and automatically apply the
    /// suggested fix from the compiler (which is to add `_` to each
    /// parameter). This provides a completely automated way to update old
    /// code for a new edition. See [issue #41686] for more details.
    ///
    /// [issue #41686]: https://github.com/rust-lang/rust/issues/41686
    /// [`cargo fix`]: https://doc.rust-lang.org/cargo/commands/cargo-fix.html
    pub ANONYMOUS_PARAMETERS,
    Warn,
    "detects anonymous parameters",
    @future_incompatible = FutureIncompatibleInfo {
        reason: FutureIncompatibilityReason::EditionError(Edition::Edition2018),
        reference: "issue #41686 <https://github.com/rust-lang/rust/issues/41686>",
    };
}

declare_lint_pass!(
    /// Checks for use of anonymous parameters (RFC 1685).
    AnonymousParameters => [ANONYMOUS_PARAMETERS]
);

impl EarlyLintPass for AnonymousParameters {
    fn check_trait_item(&mut self, cx: &EarlyContext<'_>, it: &ast::AssocItem) {
        if cx.sess().edition() != Edition::Edition2015 {
            // This is a hard error in future editions; avoid linting and erroring
            return;
        }
        if let ast::AssocItemKind::Fn(box Fn { ref sig, .. }) = it.kind {
            for arg in sig.decl.inputs.iter() {
                if let ast::PatKind::Missing = arg.pat.kind {
                    let ty_snip = cx.sess().source_map().span_to_snippet(arg.ty.span);

                    let (ty_snip, appl) = if let Ok(ref snip) = ty_snip {
                        (snip.as_str(), Applicability::MachineApplicable)
                    } else {
                        ("<type>", Applicability::HasPlaceholders)
                    };
                    cx.emit_span_lint(
                        ANONYMOUS_PARAMETERS,
                        arg.pat.span,
                        BuiltinAnonymousParams { suggestion: (arg.pat.span, appl), ty_snip },
                    );
                }
            }
        }
    }
}

fn warn_if_doc(cx: &EarlyContext<'_>, node_span: Span, node_kind: &str, attrs: &[ast::Attribute]) {
    use rustc_ast::token::CommentKind;

    let mut attrs = attrs.iter().peekable();

    // Accumulate a single span for sugared doc comments.
    let mut sugared_span: Option<Span> = None;

    while let Some(attr) = attrs.next() {
        let is_doc_comment = attr.is_doc_comment();
        if is_doc_comment {
            sugared_span =
                Some(sugared_span.map_or(attr.span, |span| span.with_hi(attr.span.hi())));
        }

        if attrs.peek().is_some_and(|next_attr| next_attr.is_doc_comment()) {
            continue;
        }

        let span = sugared_span.take().unwrap_or(attr.span);

        if is_doc_comment || attr.has_name(sym::doc) {
            let sub = match attr.kind {
                AttrKind::DocComment(CommentKind::Line, _) | AttrKind::Normal(..) => {
                    BuiltinUnusedDocCommentSub::PlainHelp
                }
                AttrKind::DocComment(CommentKind::Block, _) => {
                    BuiltinUnusedDocCommentSub::BlockHelp
                }
            };
            cx.emit_span_lint(
                UNUSED_DOC_COMMENTS,
                span,
                BuiltinUnusedDocComment { kind: node_kind, label: node_span, sub },
            );
        }
    }
}

impl EarlyLintPass for UnusedDocComment {
    fn check_stmt(&mut self, cx: &EarlyContext<'_>, stmt: &ast::Stmt) {
        let kind = match stmt.kind {
            ast::StmtKind::Let(..) => "statements",
            // Disabled pending discussion in #78306
            ast::StmtKind::Item(..) => return,
            // expressions will be reported by `check_expr`.
            ast::StmtKind::Empty
            | ast::StmtKind::Semi(_)
            | ast::StmtKind::Expr(_)
            | ast::StmtKind::MacCall(_) => return,
        };

        warn_if_doc(cx, stmt.span, kind, stmt.kind.attrs());
    }

    fn check_arm(&mut self, cx: &EarlyContext<'_>, arm: &ast::Arm) {
        if let Some(body) = &arm.body {
            let arm_span = arm.pat.span.with_hi(body.span.hi());
            warn_if_doc(cx, arm_span, "match arms", &arm.attrs);
        }
    }

    fn check_pat(&mut self, cx: &EarlyContext<'_>, pat: &ast::Pat) {
        if let ast::PatKind::Struct(_, _, fields, _) = &pat.kind {
            for field in fields {
                warn_if_doc(cx, field.span, "pattern fields", &field.attrs);
            }
        }
    }

    fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &ast::Expr) {
        warn_if_doc(cx, expr.span, "expressions", &expr.attrs);

        if let ExprKind::Struct(s) = &expr.kind {
            for field in &s.fields {
                warn_if_doc(cx, field.span, "expression fields", &field.attrs);
            }
        }
    }

    fn check_generic_param(&mut self, cx: &EarlyContext<'_>, param: &ast::GenericParam) {
        warn_if_doc(cx, param.ident.span, "generic parameters", &param.attrs);
    }

    fn check_block(&mut self, cx: &EarlyContext<'_>, block: &ast::Block) {
        warn_if_doc(cx, block.span, "blocks", block.attrs());
    }

    fn check_item(&mut self, cx: &EarlyContext<'_>, item: &ast::Item) {
        if let ast::ItemKind::ForeignMod(_) = item.kind {
            warn_if_doc(cx, item.span, "extern blocks", &item.attrs);
        }
    }
}

declare_lint! {
    /// The `no_mangle_const_items` lint detects any `const` items with the
    /// [`no_mangle` attribute].
    ///
    /// [`no_mangle` attribute]: https://doc.rust-lang.org/reference/abi.html#the-no_mangle-attribute
    ///
    /// ### Example
    ///
    /// ```rust,compile_fail,edition2021
    /// #[no_mangle]
    /// const FOO: i32 = 5;
    /// ```
    ///
    /// {{produces}}
    ///
    /// ### Explanation
    ///
    /// Constants do not have their symbols exported, and therefore, this
    /// probably means you meant to use a [`static`], not a [`const`].
    ///
    /// [`static`]: https://doc.rust-lang.org/reference/items/static-items.html
    /// [`const`]: https://doc.rust-lang.org/reference/items/constant-items.html
    NO_MANGLE_CONST_ITEMS,
    Deny,
    "const items will not have their symbols exported"
}

declare_lint! {
    /// The `no_mangle_generic_items` lint detects generic items that must be
    /// mangled.
    ///
    /// ### Example
    ///
    /// ```rust
    /// #[unsafe(no_mangle)]
    /// fn foo<T>(t: T) {}
    ///
    /// #[unsafe(export_name = "bar")]
    /// fn bar<T>(t: T) {}
    /// ```
    ///
    /// {{produces}}
    ///
    /// ### Explanation
    ///
    /// A function with generics must have its symbol mangled to accommodate
    /// the generic parameter. The [`no_mangle`] and [`export_name`] attributes
    /// have no effect in this situation, and should be removed.
    ///
    /// [`no_mangle`]: https://doc.rust-lang.org/reference/abi.html#the-no_mangle-attribute
    /// [`export_name`]: https://doc.rust-lang.org/reference/abi.html#the-export_name-attribute
    NO_MANGLE_GENERIC_ITEMS,
    Warn,
    "generic items must be mangled"
}

declare_lint_pass!(InvalidNoMangleItems => [NO_MANGLE_CONST_ITEMS, NO_MANGLE_GENERIC_ITEMS]);

impl InvalidNoMangleItems {
    fn check_no_mangle_on_generic_fn(
        &self,
        cx: &LateContext<'_>,
        attr_span: Span,
        def_id: LocalDefId,
    ) {
        let generics = cx.tcx.generics_of(def_id);
        if generics.requires_monomorphization(cx.tcx) {
            cx.emit_span_lint(
                NO_MANGLE_GENERIC_ITEMS,
                cx.tcx.def_span(def_id),
                BuiltinNoMangleGeneric { suggestion: attr_span },
            );
        }
    }
}

impl<'tcx> LateLintPass<'tcx> for InvalidNoMangleItems {
    fn check_item(&mut self, cx: &LateContext<'_>, it: &hir::Item<'_>) {
        let attrs = cx.tcx.hir_attrs(it.hir_id());
        match it.kind {
            hir::ItemKind::Fn { .. } => {
                if let Some(attr_span) =
                    find_attr!(attrs, AttributeKind::ExportName {span, ..} => *span)
                        .or_else(|| find_attr!(attrs, AttributeKind::NoMangle(span) => *span))
                {
                    self.check_no_mangle_on_generic_fn(cx, attr_span, it.owner_id.def_id);
                }
            }
            hir::ItemKind::Const(..) => {
                if find_attr!(attrs, AttributeKind::NoMangle(..)) {
                    // account for "pub const" (#45562)
                    let start = cx
                        .tcx
                        .sess
                        .source_map()
                        .span_to_snippet(it.span)
                        .map(|snippet| snippet.find("const").unwrap_or(0))
                        .unwrap_or(0) as u32;
                    // `const` is 5 chars
                    let suggestion = it.span.with_hi(BytePos(it.span.lo().0 + start + 5));

                    // Const items do not refer to a particular location in memory, and therefore
                    // don't have anything to attach a symbol to
                    cx.emit_span_lint(
                        NO_MANGLE_CONST_ITEMS,
                        it.span,
                        BuiltinConstNoMangle { suggestion },
                    );
                }
            }
            _ => {}
        }
    }

    fn check_impl_item(&mut self, cx: &LateContext<'_>, it: &hir::ImplItem<'_>) {
        let attrs = cx.tcx.hir_attrs(it.hir_id());
        match it.kind {
            hir::ImplItemKind::Fn { .. } => {
                if let Some(attr_span) =
                    find_attr!(attrs, AttributeKind::ExportName {span, ..} => *span)
                        .or_else(|| find_attr!(attrs, AttributeKind::NoMangle(span) => *span))
                {
                    self.check_no_mangle_on_generic_fn(cx, attr_span, it.owner_id.def_id);
                }
            }
            _ => {}
        }
    }
}

declare_lint! {
    /// The `mutable_transmutes` lint catches transmuting from `&T` to `&mut
    /// T` because it is [undefined behavior].
    ///
    /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
    ///
    /// ### Example
    ///
    /// ```rust,compile_fail
    /// unsafe {
    ///     let y = std::mem::transmute::<&i32, &mut i32>(&5);
    /// }
    /// ```
    ///
    /// {{produces}}
    ///
    /// ### Explanation
    ///
    /// Certain assumptions are made about aliasing of data, and this transmute
    /// violates those assumptions. Consider using [`UnsafeCell`] instead.
    ///
    /// [`UnsafeCell`]: https://doc.rust-lang.org/std/cell/struct.UnsafeCell.html
    MUTABLE_TRANSMUTES,
    Deny,
    "transmuting &T to &mut T is undefined behavior, even if the reference is unused"
}

declare_lint_pass!(MutableTransmutes => [MUTABLE_TRANSMUTES]);

impl<'tcx> LateLintPass<'tcx> for MutableTransmutes {
    fn check_expr(&mut self, cx: &LateContext<'_>, expr: &hir::Expr<'_>) {
        if let Some((&ty::Ref(_, _, from_mutbl), &ty::Ref(_, _, to_mutbl))) =
            get_transmute_from_to(cx, expr).map(|(ty1, ty2)| (ty1.kind(), ty2.kind()))
        {
            if from_mutbl < to_mutbl {
                cx.emit_span_lint(MUTABLE_TRANSMUTES, expr.span, BuiltinMutablesTransmutes);
            }
        }

        fn get_transmute_from_to<'tcx>(
            cx: &LateContext<'tcx>,
            expr: &hir::Expr<'_>,
        ) -> Option<(Ty<'tcx>, Ty<'tcx>)> {
            let def = if let hir::ExprKind::Path(ref qpath) = expr.kind {
                cx.qpath_res(qpath, expr.hir_id)
            } else {
                return None;
            };
            if let Res::Def(DefKind::Fn, did) = def {
                if !def_id_is_transmute(cx, did) {
                    return None;
                }
                let sig = cx.typeck_results().node_type(expr.hir_id).fn_sig(cx.tcx);
                let from = sig.inputs().skip_binder()[0];
                let to = sig.output().skip_binder();
                return Some((from, to));
            }
            None
        }

        fn def_id_is_transmute(cx: &LateContext<'_>, def_id: DefId) -> bool {
            cx.tcx.is_intrinsic(def_id, sym::transmute)
        }
    }
}

declare_lint! {
    /// The `unstable_features` lint detects uses of `#![feature]`.
    ///
    /// ### Example
    ///
    /// ```rust,compile_fail
    /// #![deny(unstable_features)]
    /// #![feature(test)]
    /// ```
    ///
    /// {{produces}}
    ///
    /// ### Explanation
    ///
    /// In larger nightly-based projects which
    ///
    /// * consist of a multitude of crates where a subset of crates has to compile on
    ///   stable either unconditionally or depending on a `cfg` flag to for example
    ///   allow stable users to depend on them,
    /// * don't use nightly for experimental features but for, e.g., unstable options only,
    ///
    /// this lint may come in handy to enforce policies of these kinds.
    UNSTABLE_FEATURES,
    Allow,
    "enabling unstable features"
}

declare_lint_pass!(
    /// Forbids using the `#[feature(...)]` attribute
    UnstableFeatures => [UNSTABLE_FEATURES]
);

impl<'tcx> LateLintPass<'tcx> for UnstableFeatures {
    fn check_attribute(&mut self, cx: &LateContext<'_>, attr: &hir::Attribute) {
        if attr.has_name(sym::feature)
            && let Some(items) = attr.meta_item_list()
        {
            for item in items {
                cx.emit_span_lint(UNSTABLE_FEATURES, item.span(), BuiltinUnstableFeatures);
            }
        }
    }
}

declare_lint! {
    /// The `ungated_async_fn_track_caller` lint warns when the
    /// `#[track_caller]` attribute is used on an async function
    /// without enabling the corresponding unstable feature flag.
    ///
    /// ### Example
    ///
    /// ```rust
    /// #[track_caller]
    /// async fn foo() {}
    /// ```
    ///
    /// {{produces}}
    ///
    /// ### Explanation
    ///
    /// The attribute must be used in conjunction with the
    /// [`async_fn_track_caller` feature flag]. Otherwise, the `#[track_caller]`
    /// annotation will function as a no-op.
    ///
    /// [`async_fn_track_caller` feature flag]: https://doc.rust-lang.org/beta/unstable-book/language-features/async-fn-track-caller.html
    UNGATED_ASYNC_FN_TRACK_CALLER,
    Warn,
    "enabling track_caller on an async fn is a no-op unless the async_fn_track_caller feature is enabled"
}

declare_lint_pass!(
    /// Explains corresponding feature flag must be enabled for the `#[track_caller]` attribute to
    /// do anything
    UngatedAsyncFnTrackCaller => [UNGATED_ASYNC_FN_TRACK_CALLER]
);

impl<'tcx> LateLintPass<'tcx> for UngatedAsyncFnTrackCaller {
    fn check_fn(
        &mut self,
        cx: &LateContext<'_>,
        fn_kind: HirFnKind<'_>,
        _: &'tcx FnDecl<'_>,
        _: &'tcx Body<'_>,
        span: Span,
        def_id: LocalDefId,
    ) {
        if fn_kind.asyncness().is_async()
            && !cx.tcx.features().async_fn_track_caller()
            // Now, check if the function has the `#[track_caller]` attribute
            && let Some(attr_span) = find_attr!(cx.tcx.get_all_attrs(def_id), AttributeKind::TrackCaller(span) => *span)
        {
            cx.emit_span_lint(
                UNGATED_ASYNC_FN_TRACK_CALLER,
                attr_span,
                BuiltinUngatedAsyncFnTrackCaller { label: span, session: &cx.tcx.sess },
            );
        }
    }
}

declare_lint! {
    /// The `unreachable_pub` lint triggers for `pub` items not reachable from other crates - that
    /// means neither directly accessible, nor reexported (with `pub use`), nor leaked through
    /// things like return types (which the [`unnameable_types`] lint can detect if desired).
    ///
    /// ### Example
    ///
    /// ```rust,compile_fail
    /// #![deny(unreachable_pub)]
    /// mod foo {
    ///     pub mod bar {
    ///
    ///     }
    /// }
    /// ```
    ///
    /// {{produces}}
    ///
    /// ### Explanation
    ///
    /// The `pub` keyword both expresses an intent for an item to be publicly available, and also
    /// signals to the compiler to make the item publicly accessible. The intent can only be
    /// satisfied, however, if all items which contain this item are *also* publicly accessible.
    /// Thus, this lint serves to identify situations where the intent does not match the reality.
    ///
    /// If you wish the item to be accessible elsewhere within the crate, but not outside it, the
    /// `pub(crate)` visibility is recommended to be used instead. This more clearly expresses the
    /// intent that the item is only visible within its own crate.
    ///
    /// This lint is "allow" by default because it will trigger for a large amount of existing Rust code.
    /// Eventually it is desired for this to become warn-by-default.
    ///
    /// [`unnameable_types`]: #unnameable-types
    pub UNREACHABLE_PUB,
    Allow,
    "`pub` items not reachable from crate root"
}

declare_lint_pass!(
    /// Lint for items marked `pub` that aren't reachable from other crates.
    UnreachablePub => [UNREACHABLE_PUB]
);

impl UnreachablePub {
    fn perform_lint(
        &self,
        cx: &LateContext<'_>,
        what: &str,
        def_id: LocalDefId,
        vis_span: Span,
        exportable: bool,
    ) {
        let mut applicability = Applicability::MachineApplicable;
        if cx.tcx.visibility(def_id).is_public() && !cx.effective_visibilities.is_reachable(def_id)
        {
            // prefer suggesting `pub(super)` instead of `pub(crate)` when possible,
            // except when `pub(super) == pub(crate)`
            let new_vis = if let Some(ty::Visibility::Restricted(restricted_did)) =
                cx.effective_visibilities.effective_vis(def_id).map(|effective_vis| {
                    effective_vis.at_level(rustc_middle::middle::privacy::Level::Reachable)
                })
                && let parent_parent = cx
                    .tcx
                    .parent_module_from_def_id(cx.tcx.parent_module_from_def_id(def_id).into())
                && *restricted_did == parent_parent.to_local_def_id()
                && !restricted_did.to_def_id().is_crate_root()
            {
                "pub(super)"
            } else {
                "pub(crate)"
            };

            if vis_span.from_expansion() {
                applicability = Applicability::MaybeIncorrect;
            }
            let def_span = cx.tcx.def_span(def_id);
            cx.emit_span_lint(
                UNREACHABLE_PUB,
                def_span,
                BuiltinUnreachablePub {
                    what,
                    new_vis,
                    suggestion: (vis_span, applicability),
                    help: exportable,
                },
            );
        }
    }
}

impl<'tcx> LateLintPass<'tcx> for UnreachablePub {
    fn check_item(&mut self, cx: &LateContext<'_>, item: &hir::Item<'_>) {
        // Do not warn for fake `use` statements.
        if let hir::ItemKind::Use(_, hir::UseKind::ListStem) = &item.kind {
            return;
        }
        self.perform_lint(cx, "item", item.owner_id.def_id, item.vis_span, true);
    }

    fn check_foreign_item(&mut self, cx: &LateContext<'_>, foreign_item: &hir::ForeignItem<'tcx>) {
        self.perform_lint(cx, "item", foreign_item.owner_id.def_id, foreign_item.vis_span, true);
    }

    fn check_field_def(&mut self, _cx: &LateContext<'_>, _field: &hir::FieldDef<'_>) {
        // - If an ADT definition is reported then we don't need to check fields
        //   (as it would add unnecessary complexity to the source code, the struct
        //   definition is in the immediate proximity to give the "real" visibility).
        // - If an ADT is not reported because it's not `pub` - we don't need to
        //   check fields.
        // - If an ADT is not reported because it's reachable - we also don't need
        //   to check fields because then they are reachable by construction if they
        //   are pub.
        //
        // Therefore in no case we check the fields.
        //
        // cf. https://github.com/rust-lang/rust/pull/126013#issuecomment-2152839205
        // cf. https://github.com/rust-lang/rust/pull/126040#issuecomment-2152944506
    }

    fn check_impl_item(&mut self, cx: &LateContext<'_>, impl_item: &hir::ImplItem<'_>) {
        if let ImplItemImplKind::Inherent { vis_span } = impl_item.impl_kind {
            self.perform_lint(cx, "item", impl_item.owner_id.def_id, vis_span, false);
        }
    }
}

declare_lint! {
    /// The `type_alias_bounds` lint detects bounds in type aliases.
    ///
    /// ### Example
    ///
    /// ```rust
    /// type SendVec<T: Send> = Vec<T>;
    /// ```
    ///
    /// {{produces}}
    ///
    /// ### Explanation
    ///
    /// Trait and lifetime bounds on generic parameters and in where clauses of
    /// type aliases are not checked at usage sites of the type alias. Moreover,
    /// they are not thoroughly checked for correctness at their definition site
    /// either similar to the aliased type.
    ///
    /// This is a known limitation of the type checker that may be lifted in a
    /// future edition. Permitting such bounds in light of this was unintentional.
    ///
    /// While these bounds may have secondary effects such as enabling the use of
    /// "shorthand" associated type paths[^1] and affecting the default trait
    /// object lifetime[^2] of trait object types passed to the type alias, this
    /// should not have been allowed until the aforementioned restrictions of the
    /// type checker have been lifted.
    ///
    /// Using such bounds is highly discouraged as they are actively misleading.
    ///
    /// [^1]: I.e., paths of the form `T::Assoc` where `T` is a type parameter
    /// bounded by trait `Trait` which defines an associated type called `Assoc`
    /// as opposed to a fully qualified path of the form `<T as Trait>::Assoc`.
    /// [^2]: <https://doc.rust-lang.org/reference/lifetime-elision.html#default-trait-object-lifetimes>
    TYPE_ALIAS_BOUNDS,
    Warn,
    "bounds in type aliases are not enforced"
}

declare_lint_pass!(TypeAliasBounds => [TYPE_ALIAS_BOUNDS]);

impl TypeAliasBounds {
    pub(crate) fn affects_object_lifetime_defaults(pred: &hir::WherePredicate<'_>) -> bool {
        // Bounds of the form `T: 'a` with `T` type param affect object lifetime defaults.
        if let hir::WherePredicateKind::BoundPredicate(pred) = pred.kind
            && pred.bounds.iter().any(|bound| matches!(bound, hir::GenericBound::Outlives(_)))
            && pred.bound_generic_params.is_empty() // indeed, even if absent from the RHS
            && pred.bounded_ty.as_generic_param().is_some()
        {
            return true;
        }
        false
    }
}

impl<'tcx> LateLintPass<'tcx> for TypeAliasBounds {
    fn check_item(&mut self, cx: &LateContext<'_>, item: &hir::Item<'_>) {
        let hir::ItemKind::TyAlias(_, generics, hir_ty) = item.kind else { return };

        // There must not be a where clause.
        if generics.predicates.is_empty() {
            return;
        }

        // Bounds of lazy type aliases and TAITs are respected.
        if cx.tcx.type_alias_is_lazy(item.owner_id) {
            return;
        }

        // FIXME(generic_const_exprs): Revisit this before stabilization.
        // See also `tests/ui/const-generics/generic_const_exprs/type-alias-bounds.rs`.
        let ty = cx.tcx.type_of(item.owner_id).instantiate_identity();
        if ty.has_type_flags(ty::TypeFlags::HAS_CT_PROJECTION)
            && cx.tcx.features().generic_const_exprs()
        {
            return;
        }

        // NOTE(inherent_associated_types): While we currently do take some bounds in type
        // aliases into consideration during IAT *selection*, we don't perform full use+def
        // site wfchecking for such type aliases. Therefore TAB should still trigger.
        // See also `tests/ui/associated-inherent-types/type-alias-bounds.rs`.

        let mut where_spans = Vec::new();
        let mut inline_spans = Vec::new();
        let mut inline_sugg = Vec::new();

        for p in generics.predicates {
            let span = p.span;
            if p.kind.in_where_clause() {
                where_spans.push(span);
            } else {
                for b in p.kind.bounds() {
                    inline_spans.push(b.span());
                }
                inline_sugg.push((span, String::new()));
            }
        }

        let mut ty = Some(hir_ty);
        let enable_feat_help = cx.tcx.sess.is_nightly_build();

        if let [.., label_sp] = *where_spans {
            cx.emit_span_lint(
                TYPE_ALIAS_BOUNDS,
                where_spans,
                BuiltinTypeAliasBounds {
                    in_where_clause: true,
                    label: label_sp,
                    enable_feat_help,
                    suggestions: vec![(generics.where_clause_span, String::new())],
                    preds: generics.predicates,
                    ty: ty.take(),
                },
            );
        }
        if let [.., label_sp] = *inline_spans {
            cx.emit_span_lint(
                TYPE_ALIAS_BOUNDS,
                inline_spans,
                BuiltinTypeAliasBounds {
                    in_where_clause: false,
                    label: label_sp,
                    enable_feat_help,
                    suggestions: inline_sugg,
                    preds: generics.predicates,
                    ty,
                },
            );
        }
    }
}

pub(crate) struct ShorthandAssocTyCollector {
    pub(crate) qselves: Vec<Span>,
}

impl hir::intravisit::Visitor<'_> for ShorthandAssocTyCollector {
    fn visit_qpath(&mut self, qpath: &hir::QPath<'_>, id: hir::HirId, _: Span) {
        // Look for "type-parameter shorthand-associated-types". I.e., paths of the
        // form `T::Assoc` with `T` type param. These are reliant on trait bounds.
        if let hir::QPath::TypeRelative(qself, _) = qpath
            && qself.as_generic_param().is_some()
        {
            self.qselves.push(qself.span);
        }
        hir::intravisit::walk_qpath(self, qpath, id)
    }
}

declare_lint! {
    /// The `trivial_bounds` lint detects trait bounds that don't depend on
    /// any type parameters.
    ///
    /// ### Example
    ///
    /// ```rust
    /// #![feature(trivial_bounds)]
    /// pub struct A where i32: Copy;
    /// ```
    ///
    /// {{produces}}
    ///
    /// ### Explanation
    ///
    /// Usually you would not write a trait bound that you know is always
    /// true, or never true. However, when using macros, the macro may not
    /// know whether or not the constraint would hold or not at the time when
    /// generating the code. Currently, the compiler does not alert you if the
    /// constraint is always true, and generates an error if it is never true.
    /// The `trivial_bounds` feature changes this to be a warning in both
    /// cases, giving macros more freedom and flexibility to generate code,
    /// while still providing a signal when writing non-macro code that
    /// something is amiss.
    ///
    /// See [RFC 2056] for more details. This feature is currently only
    /// available on the nightly channel, see [tracking issue #48214].
    ///
    /// [RFC 2056]: https://github.com/rust-lang/rfcs/blob/master/text/2056-allow-trivial-where-clause-constraints.md
    /// [tracking issue #48214]: https://github.com/rust-lang/rust/issues/48214
    TRIVIAL_BOUNDS,
    Warn,
    "these bounds don't depend on an type parameters"
}

declare_lint_pass!(
    /// Lint for trait and lifetime bounds that don't depend on type parameters
    /// which either do nothing, or stop the item from being used.
    TrivialConstraints => [TRIVIAL_BOUNDS]
);

impl<'tcx> LateLintPass<'tcx> for TrivialConstraints {
    fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) {
        use rustc_middle::ty::ClauseKind;

        if cx.tcx.features().trivial_bounds() {
            let predicates = cx.tcx.predicates_of(item.owner_id);
            for &(predicate, span) in predicates.predicates {
                let predicate_kind_name = match predicate.kind().skip_binder() {
                    ClauseKind::Trait(..) => "trait",
                    ClauseKind::TypeOutlives(..) |
                    ClauseKind::RegionOutlives(..) => "lifetime",

                    ClauseKind::UnstableFeature(_)
                    // `ConstArgHasType` is never global as `ct` is always a param
                    | ClauseKind::ConstArgHasType(..)
                    // Ignore projections, as they can only be global
                    // if the trait bound is global
                    | ClauseKind::Projection(..)
                    // Ignore bounds that a user can't type
                    | ClauseKind::WellFormed(..)
                    // FIXME(generic_const_exprs): `ConstEvaluatable` can be written
                    | ClauseKind::ConstEvaluatable(..)
                    // Users don't write this directly, only via another trait ref.
                    | ty::ClauseKind::HostEffect(..) => continue,
                };
                if predicate.is_global() {
                    cx.emit_span_lint(
                        TRIVIAL_BOUNDS,
                        span,
                        BuiltinTrivialBounds { predicate_kind_name, predicate },
                    );
                }
            }
        }
    }
}

declare_lint! {
    /// The `double_negations` lint detects expressions of the form `--x`.
    ///
    /// ### Example
    ///
    /// ```rust
    /// fn main() {
    ///     let x = 1;
    ///     let _b = --x;
    /// }
    /// ```
    ///
    /// {{produces}}
    ///
    /// ### Explanation
    ///
    /// Negating something twice is usually the same as not negating it at all.
    /// However, a double negation in Rust can easily be confused with the
    /// prefix decrement operator that exists in many languages derived from C.
    /// Use `-(-x)` if you really wanted to negate the value twice.
    ///
    /// To decrement a value, use `x -= 1` instead.
    pub DOUBLE_NEGATIONS,
    Warn,
    "detects expressions of the form `--x`"
}

declare_lint_pass!(
    /// Lint for expressions of the form `--x` that can be confused with C's
    /// prefix decrement operator.
    DoubleNegations => [DOUBLE_NEGATIONS]
);

impl EarlyLintPass for DoubleNegations {
    #[inline]
    fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &ast::Expr) {
        // only lint on the innermost `--` in a chain of `-` operators,
        // even if there are 3 or more negations
        if let ExprKind::Unary(UnOp::Neg, ref inner) = expr.kind
            && let ExprKind::Unary(UnOp::Neg, ref inner2) = inner.kind
            && !matches!(inner2.kind, ExprKind::Unary(UnOp::Neg, _))
            // Don't lint if this jumps macro expansion boundary (Issue #143980)
            && expr.span.eq_ctxt(inner.span)
        {
            cx.emit_span_lint(
                DOUBLE_NEGATIONS,
                expr.span,
                BuiltinDoubleNegations {
                    add_parens: BuiltinDoubleNegationsAddParens {
                        start_span: inner.span.shrink_to_lo(),
                        end_span: inner.span.shrink_to_hi(),
                    },
                },
            );
        }
    }
}

declare_lint_pass!(
    /// Does nothing as a lint pass, but registers some `Lint`s
    /// which are used by other parts of the compiler.
    SoftLints => [
        WHILE_TRUE,
        NON_SHORTHAND_FIELD_PATTERNS,
        UNSAFE_CODE,
        MISSING_DOCS,
        MISSING_COPY_IMPLEMENTATIONS,
        MISSING_DEBUG_IMPLEMENTATIONS,
        ANONYMOUS_PARAMETERS,
        UNUSED_DOC_COMMENTS,
        NO_MANGLE_CONST_ITEMS,
        NO_MANGLE_GENERIC_ITEMS,
        MUTABLE_TRANSMUTES,
        UNSTABLE_FEATURES,
        UNREACHABLE_PUB,
        TYPE_ALIAS_BOUNDS,
        TRIVIAL_BOUNDS,
        DOUBLE_NEGATIONS
    ]
);

declare_lint! {
    /// The `ellipsis_inclusive_range_patterns` lint detects the [`...` range
    /// pattern], which is deprecated.
    ///
    /// [`...` range pattern]: https://doc.rust-lang.org/reference/patterns.html#range-patterns
    ///
    /// ### Example
    ///
    /// ```rust,edition2018
    /// let x = 123;
    /// match x {
    ///     0...100 => {}
    ///     _ => {}
    /// }
    /// ```
    ///
    /// {{produces}}
    ///
    /// ### Explanation
    ///
    /// The `...` range pattern syntax was changed to `..=` to avoid potential
    /// confusion with the [`..` range expression]. Use the new form instead.
    ///
    /// [`..` range expression]: https://doc.rust-lang.org/reference/expressions/range-expr.html
    pub ELLIPSIS_INCLUSIVE_RANGE_PATTERNS,
    Warn,
    "`...` range patterns are deprecated",
    @future_incompatible = FutureIncompatibleInfo {
        reason: FutureIncompatibilityReason::EditionError(Edition::Edition2021),
        reference: "<https://doc.rust-lang.org/edition-guide/rust-2021/warnings-promoted-to-error.html>",
    };
}

#[derive(Default)]
pub struct EllipsisInclusiveRangePatterns {
    /// If `Some(_)`, suppress all subsequent pattern
    /// warnings for better diagnostics.
    node_id: Option<ast::NodeId>,
}

impl_lint_pass!(EllipsisInclusiveRangePatterns => [ELLIPSIS_INCLUSIVE_RANGE_PATTERNS]);

impl EarlyLintPass for EllipsisInclusiveRangePatterns {
    fn check_pat(&mut self, cx: &EarlyContext<'_>, pat: &ast::Pat) {
        if self.node_id.is_some() {
            // Don't recursively warn about patterns inside range endpoints.
            return;
        }

        use self::ast::PatKind;
        use self::ast::RangeSyntax::DotDotDot;

        /// If `pat` is a `...` pattern, return the start and end of the range, as well as the span
        /// corresponding to the ellipsis.
        fn matches_ellipsis_pat(pat: &ast::Pat) -> Option<(Option<&Expr>, &Expr, Span)> {
            match &pat.kind {
                PatKind::Range(
                    a,
                    Some(b),
                    Spanned { span, node: RangeEnd::Included(DotDotDot) },
                ) => Some((a.as_deref(), b, *span)),
                _ => None,
            }
        }

        let (parentheses, endpoints) = match &pat.kind {
            PatKind::Ref(subpat, _) => (true, matches_ellipsis_pat(subpat)),
            _ => (false, matches_ellipsis_pat(pat)),
        };

        if let Some((start, end, join)) = endpoints {
            if parentheses {
                self.node_id = Some(pat.id);
                let end = expr_to_string(end);
                let replace = match start {
                    Some(start) => format!("&({}..={})", expr_to_string(start), end),
                    None => format!("&(..={end})"),
                };
                if join.edition() >= Edition::Edition2021 {
                    cx.sess().dcx().emit_err(BuiltinEllipsisInclusiveRangePatterns {
                        span: pat.span,
                        suggestion: pat.span,
                        replace,
                    });
                } else {
                    cx.emit_span_lint(
                        ELLIPSIS_INCLUSIVE_RANGE_PATTERNS,
                        pat.span,
                        BuiltinEllipsisInclusiveRangePatternsLint::Parenthesise {
                            suggestion: pat.span,
                            replace,
                        },
                    );
                }
            } else {
                let replace = "..=";
                if join.edition() >= Edition::Edition2021 {
                    cx.sess().dcx().emit_err(BuiltinEllipsisInclusiveRangePatterns {
                        span: pat.span,
                        suggestion: join,
                        replace: replace.to_string(),
                    });
                } else {
                    cx.emit_span_lint(
                        ELLIPSIS_INCLUSIVE_RANGE_PATTERNS,
                        join,
                        BuiltinEllipsisInclusiveRangePatternsLint::NonParenthesise {
                            suggestion: join,
                        },
                    );
                }
            };
        }
    }

    fn check_pat_post(&mut self, _cx: &EarlyContext<'_>, pat: &ast::Pat) {
        if let Some(node_id) = self.node_id {
            if pat.id == node_id {
                self.node_id = None
            }
        }
    }
}

declare_lint! {
    /// The `keyword_idents_2018` lint detects edition keywords being used as an
    /// identifier.
    ///
    /// ### Example
    ///
    /// ```rust,edition2015,compile_fail
    /// #![deny(keyword_idents_2018)]
    /// // edition 2015
    /// fn dyn() {}
    /// ```
    ///
    /// {{produces}}
    ///
    /// ### Explanation
    ///
    /// Rust [editions] allow the language to evolve without breaking
    /// backwards compatibility. This lint catches code that uses new keywords
    /// that are added to the language that are used as identifiers (such as a
    /// variable name, function name, etc.). If you switch the compiler to a
    /// new edition without updating the code, then it will fail to compile if
    /// you are using a new keyword as an identifier.
    ///
    /// You can manually change the identifiers to a non-keyword, or use a
    /// [raw identifier], for example `r#dyn`, to transition to a new edition.
    ///
    /// This lint solves the problem automatically. It is "allow" by default
    /// because the code is perfectly valid in older editions. The [`cargo
    /// fix`] tool with the `--edition` flag will switch this lint to "warn"
    /// and automatically apply the suggested fix from the compiler (which is
    /// to use a raw identifier). This provides a completely automated way to
    /// update old code for a new edition.
    ///
    /// [editions]: https://doc.rust-lang.org/edition-guide/
    /// [raw identifier]: https://doc.rust-lang.org/reference/identifiers.html
    /// [`cargo fix`]: https://doc.rust-lang.org/cargo/commands/cargo-fix.html
    pub KEYWORD_IDENTS_2018,
    Allow,
    "detects edition keywords being used as an identifier",
    @future_incompatible = FutureIncompatibleInfo {
        reason: FutureIncompatibilityReason::EditionError(Edition::Edition2018),
        reference: "issue #49716 <https://github.com/rust-lang/rust/issues/49716>",
    };
}

declare_lint! {
    /// The `keyword_idents_2024` lint detects edition keywords being used as an
    /// identifier.
    ///
    /// ### Example
    ///
    /// ```rust,edition2015,compile_fail
    /// #![deny(keyword_idents_2024)]
    /// // edition 2015
    /// fn gen() {}
    /// ```
    ///
    /// {{produces}}
    ///
    /// ### Explanation
    ///
    /// Rust [editions] allow the language to evolve without breaking
    /// backwards compatibility. This lint catches code that uses new keywords
    /// that are added to the language that are used as identifiers (such as a
    /// variable name, function name, etc.). If you switch the compiler to a
    /// new edition without updating the code, then it will fail to compile if
    /// you are using a new keyword as an identifier.
    ///
    /// You can manually change the identifiers to a non-keyword, or use a
    /// [raw identifier], for example `r#gen`, to transition to a new edition.
    ///
    /// This lint solves the problem automatically. It is "allow" by default
    /// because the code is perfectly valid in older editions. The [`cargo
    /// fix`] tool with the `--edition` flag will switch this lint to "warn"
    /// and automatically apply the suggested fix from the compiler (which is
    /// to use a raw identifier). This provides a completely automated way to
    /// update old code for a new edition.
    ///
    /// [editions]: https://doc.rust-lang.org/edition-guide/
    /// [raw identifier]: https://doc.rust-lang.org/reference/identifiers.html
    /// [`cargo fix`]: https://doc.rust-lang.org/cargo/commands/cargo-fix.html
    pub KEYWORD_IDENTS_2024,
    Allow,
    "detects edition keywords being used as an identifier",
    @future_incompatible = FutureIncompatibleInfo {
        reason: FutureIncompatibilityReason::EditionError(Edition::Edition2024),
        reference: "<https://doc.rust-lang.org/edition-guide/rust-2024/gen-keyword.html>",
    };
}

declare_lint_pass!(
    /// Check for uses of edition keywords used as an identifier.
    KeywordIdents => [KEYWORD_IDENTS_2018, KEYWORD_IDENTS_2024]
);

struct UnderMacro(bool);

impl KeywordIdents {
    fn check_tokens(&mut self, cx: &EarlyContext<'_>, tokens: &TokenStream) {
        // Check if the preceding token is `$`, because we want to allow `$async`, etc.
        let mut prev_dollar = false;
        for tt in tokens.iter() {
            match tt {
                // Only report non-raw idents.
                TokenTree::Token(token, _) => {
                    if let Some((ident, token::IdentIsRaw::No)) = token.ident() {
                        if !prev_dollar {
                            self.check_ident_token(cx, UnderMacro(true), ident, "");
                        }
                    } else if let Some((ident, token::IdentIsRaw::No)) = token.lifetime() {
                        self.check_ident_token(
                            cx,
                            UnderMacro(true),
                            ident.without_first_quote(),
                            "'",
                        );
                    } else if token.kind == TokenKind::Dollar {
                        prev_dollar = true;
                        continue;
                    }
                }
                TokenTree::Delimited(.., tts) => self.check_tokens(cx, tts),
            }
            prev_dollar = false;
        }
    }

    fn check_ident_token(
        &mut self,
        cx: &EarlyContext<'_>,
        UnderMacro(under_macro): UnderMacro,
        ident: Ident,
        prefix: &'static str,
    ) {
        let (lint, edition) = match ident.name {
            kw::Async | kw::Await | kw::Try => (KEYWORD_IDENTS_2018, Edition::Edition2018),

            // rust-lang/rust#56327: Conservatively do not
            // attempt to report occurrences of `dyn` within
            // macro definitions or invocations, because `dyn`
            // can legitimately occur as a contextual keyword
            // in 2015 code denoting its 2018 meaning, and we
            // do not want rustfix to inject bugs into working
            // code by rewriting such occurrences.
            //
            // But if we see `dyn` outside of a macro, we know
            // its precise role in the parsed AST and thus are
            // assured this is truly an attempt to use it as
            // an identifier.
            kw::Dyn if !under_macro => (KEYWORD_IDENTS_2018, Edition::Edition2018),

            kw::Gen => (KEYWORD_IDENTS_2024, Edition::Edition2024),

            _ => return,
        };

        // Don't lint `r#foo`.
        if ident.span.edition() >= edition
            || cx.sess().psess.raw_identifier_spans.contains(ident.span)
        {
            return;
        }

        cx.emit_span_lint(
            lint,
            ident.span,
            BuiltinKeywordIdents { kw: ident, next: edition, suggestion: ident.span, prefix },
        );
    }
}

impl EarlyLintPass for KeywordIdents {
    fn check_mac_def(&mut self, cx: &EarlyContext<'_>, mac_def: &ast::MacroDef) {
        self.check_tokens(cx, &mac_def.body.tokens);
    }
    fn check_mac(&mut self, cx: &EarlyContext<'_>, mac: &ast::MacCall) {
        self.check_tokens(cx, &mac.args.tokens);
    }
    fn check_ident(&mut self, cx: &EarlyContext<'_>, ident: &Ident) {
        if ident.name.as_str().starts_with('\'') {
            self.check_ident_token(cx, UnderMacro(false), ident.without_first_quote(), "'");
        } else {
            self.check_ident_token(cx, UnderMacro(false), *ident, "");
        }
    }
}

declare_lint_pass!(ExplicitOutlivesRequirements => [EXPLICIT_OUTLIVES_REQUIREMENTS]);

impl ExplicitOutlivesRequirements {
    fn lifetimes_outliving_lifetime<'tcx>(
        tcx: TyCtxt<'tcx>,
        inferred_outlives: impl Iterator<Item = &'tcx (ty::Clause<'tcx>, Span)>,
        item: LocalDefId,
        lifetime: LocalDefId,
    ) -> Vec<ty::Region<'tcx>> {
        let item_generics = tcx.generics_of(item);

        inferred_outlives
            .filter_map(|(clause, _)| match clause.kind().skip_binder() {
                ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(a, b)) => match a.kind() {
                    ty::ReEarlyParam(ebr)
                        if item_generics.region_param(ebr, tcx).def_id == lifetime.to_def_id() =>
                    {
                        Some(b)
                    }
                    _ => None,
                },
                _ => None,
            })
            .collect()
    }

    fn lifetimes_outliving_type<'tcx>(
        inferred_outlives: impl Iterator<Item = &'tcx (ty::Clause<'tcx>, Span)>,
        index: u32,
    ) -> Vec<ty::Region<'tcx>> {
        inferred_outlives
            .filter_map(|(clause, _)| match clause.kind().skip_binder() {
                ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(a, b)) => {
                    a.is_param(index).then_some(b)
                }
                _ => None,
            })
            .collect()
    }

    fn collect_outlives_bound_spans<'tcx>(
        &self,
        tcx: TyCtxt<'tcx>,
        bounds: &hir::GenericBounds<'_>,
        inferred_outlives: &[ty::Region<'tcx>],
        predicate_span: Span,
        item: DefId,
    ) -> Vec<(usize, Span)> {
        use rustc_middle::middle::resolve_bound_vars::ResolvedArg;

        let item_generics = tcx.generics_of(item);

        bounds
            .iter()
            .enumerate()
            .filter_map(|(i, bound)| {
                let hir::GenericBound::Outlives(lifetime) = bound else {
                    return None;
                };

                let is_inferred = match tcx.named_bound_var(lifetime.hir_id) {
                    Some(ResolvedArg::EarlyBound(def_id)) => inferred_outlives
                        .iter()
                        .any(|r| matches!(r.kind(), ty::ReEarlyParam(ebr) if { item_generics.region_param(ebr, tcx).def_id == def_id.to_def_id() })),
                    _ => false,
                };

                if !is_inferred {
                    return None;
                }

                let span = bound.span().find_ancestor_inside(predicate_span)?;
                if span.in_external_macro(tcx.sess.source_map()) {
                    return None;
                }

                Some((i, span))
            })
            .collect()
    }

    fn consolidate_outlives_bound_spans(
        &self,
        lo: Span,
        bounds: &hir::GenericBounds<'_>,
        bound_spans: Vec<(usize, Span)>,
    ) -> Vec<Span> {
        if bounds.is_empty() {
            return Vec::new();
        }
        if bound_spans.len() == bounds.len() {
            let (_, last_bound_span) = bound_spans[bound_spans.len() - 1];
            // If all bounds are inferable, we want to delete the colon, so
            // start from just after the parameter (span passed as argument)
            vec![lo.to(last_bound_span)]
        } else {
            let mut merged = Vec::new();
            let mut last_merged_i = None;

            let mut from_start = true;
            for (i, bound_span) in bound_spans {
                match last_merged_i {
                    // If the first bound is inferable, our span should also eat the leading `+`.
                    None if i == 0 => {
                        merged.push(bound_span.to(bounds[1].span().shrink_to_lo()));
                        last_merged_i = Some(0);
                    }
                    // If consecutive bounds are inferable, merge their spans
                    Some(h) if i == h + 1 => {
                        if let Some(tail) = merged.last_mut() {
                            // Also eat the trailing `+` if the first
                            // more-than-one bound is inferable
                            let to_span = if from_start && i < bounds.len() {
                                bounds[i + 1].span().shrink_to_lo()
                            } else {
                                bound_span
                            };
                            *tail = tail.to(to_span);
                            last_merged_i = Some(i);
                        } else {
                            bug!("another bound-span visited earlier");
                        }
                    }
                    _ => {
                        // When we find a non-inferable bound, subsequent inferable bounds
                        // won't be consecutive from the start (and we'll eat the leading
                        // `+` rather than the trailing one)
                        from_start = false;
                        merged.push(bounds[i - 1].span().shrink_to_hi().to(bound_span));
                        last_merged_i = Some(i);
                    }
                }
            }
            merged
        }
    }
}

impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements {
    fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) {
        use rustc_middle::middle::resolve_bound_vars::ResolvedArg;

        let def_id = item.owner_id.def_id;
        if let hir::ItemKind::Struct(_, generics, _)
        | hir::ItemKind::Enum(_, generics, _)
        | hir::ItemKind::Union(_, generics, _) = item.kind
        {
            let inferred_outlives = cx.tcx.inferred_outlives_of(def_id);
            if inferred_outlives.is_empty() {
                return;
            }

            let ty_generics = cx.tcx.generics_of(def_id);
            let num_where_predicates = generics
                .predicates
                .iter()
                .filter(|predicate| predicate.kind.in_where_clause())
                .count();

            let mut bound_count = 0;
            let mut lint_spans = Vec::new();
            let mut where_lint_spans = Vec::new();
            let mut dropped_where_predicate_count = 0;
            for (i, where_predicate) in generics.predicates.iter().enumerate() {
                let (relevant_lifetimes, bounds, predicate_span, in_where_clause) =
                    match where_predicate.kind {
                        hir::WherePredicateKind::RegionPredicate(predicate) => {
                            if let Some(ResolvedArg::EarlyBound(region_def_id)) =
                                cx.tcx.named_bound_var(predicate.lifetime.hir_id)
                            {
                                (
                                    Self::lifetimes_outliving_lifetime(
                                        cx.tcx,
                                        // don't warn if the inferred span actually came from the predicate we're looking at
                                        // this happens if the type is recursively defined
                                        inferred_outlives.iter().filter(|(_, span)| {
                                            !where_predicate.span.contains(*span)
                                        }),
                                        item.owner_id.def_id,
                                        region_def_id,
                                    ),
                                    &predicate.bounds,
                                    where_predicate.span,
                                    predicate.in_where_clause,
                                )
                            } else {
                                continue;
                            }
                        }
                        hir::WherePredicateKind::BoundPredicate(predicate) => {
                            // FIXME we can also infer bounds on associated types,
                            // and should check for them here.
                            match predicate.bounded_ty.kind {
                                hir::TyKind::Path(hir::QPath::Resolved(None, path)) => {
                                    let Res::Def(DefKind::TyParam, def_id) = path.res else {
                                        continue;
                                    };
                                    let index = ty_generics.param_def_id_to_index[&def_id];
                                    (
                                        Self::lifetimes_outliving_type(
                                            // don't warn if the inferred span actually came from the predicate we're looking at
                                            // this happens if the type is recursively defined
                                            inferred_outlives.iter().filter(|(_, span)| {
                                                !where_predicate.span.contains(*span)
                                            }),
                                            index,
                                        ),
                                        &predicate.bounds,
                                        where_predicate.span,
                                        predicate.origin == PredicateOrigin::WhereClause,
                                    )
                                }
                                _ => {
                                    continue;
                                }
                            }
                        }
                        _ => continue,
                    };
                if relevant_lifetimes.is_empty() {
                    continue;
                }

                let bound_spans = self.collect_outlives_bound_spans(
                    cx.tcx,
                    bounds,
                    &relevant_lifetimes,
                    predicate_span,
                    item.owner_id.to_def_id(),
                );
                bound_count += bound_spans.len();

                let drop_predicate = bound_spans.len() == bounds.len();
                if drop_predicate && in_where_clause {
                    dropped_where_predicate_count += 1;
                }

                if drop_predicate {
                    if !in_where_clause {
                        lint_spans.push(predicate_span);
                    } else if predicate_span.from_expansion() {
                        // Don't try to extend the span if it comes from a macro expansion.
                        where_lint_spans.push(predicate_span);
                    } else if i + 1 < num_where_predicates {
                        // If all the bounds on a predicate were inferable and there are
                        // further predicates, we want to eat the trailing comma.
                        let next_predicate_span = generics.predicates[i + 1].span;
                        if next_predicate_span.from_expansion() {
                            where_lint_spans.push(predicate_span);
                        } else {
                            where_lint_spans
                                .push(predicate_span.to(next_predicate_span.shrink_to_lo()));
                        }
                    } else {
                        // Eat the optional trailing comma after the last predicate.
                        let where_span = generics.where_clause_span;
                        if where_span.from_expansion() {
                            where_lint_spans.push(predicate_span);
                        } else {
                            where_lint_spans.push(predicate_span.to(where_span.shrink_to_hi()));
                        }
                    }
                } else {
                    where_lint_spans.extend(self.consolidate_outlives_bound_spans(
                        predicate_span.shrink_to_lo(),
                        bounds,
                        bound_spans,
                    ));
                }
            }

            // If all predicates in where clause are inferable, drop the entire clause
            // (including the `where`)
            if generics.has_where_clause_predicates
                && dropped_where_predicate_count == num_where_predicates
            {
                let where_span = generics.where_clause_span;
                // Extend the where clause back to the closing `>` of the
                // generics, except for tuple struct, which have the `where`
                // after the fields of the struct.
                let full_where_span =
                    if let hir::ItemKind::Struct(_, _, hir::VariantData::Tuple(..)) = item.kind {
                        where_span
                    } else {
                        generics.span.shrink_to_hi().to(where_span)
                    };

                // Due to macro expansions, the `full_where_span` might not actually contain all
                // predicates.
                if where_lint_spans.iter().all(|&sp| full_where_span.contains(sp)) {
                    lint_spans.push(full_where_span);
                } else {
                    lint_spans.extend(where_lint_spans);
                }
            } else {
                lint_spans.extend(where_lint_spans);
            }

            if !lint_spans.is_empty() {
                // Do not automatically delete outlives requirements from macros.
                let applicability = if lint_spans.iter().all(|sp| sp.can_be_used_for_suggestions())
                {
                    Applicability::MachineApplicable
                } else {
                    Applicability::MaybeIncorrect
                };

                // Due to macros, there might be several predicates with the same span
                // and we only want to suggest removing them once.
                lint_spans.sort_unstable();
                lint_spans.dedup();

                cx.emit_span_lint(
                    EXPLICIT_OUTLIVES_REQUIREMENTS,
                    lint_spans.clone(),
                    BuiltinExplicitOutlives {
                        count: bound_count,
                        suggestion: BuiltinExplicitOutlivesSuggestion {
                            spans: lint_spans,
                            applicability,
                        },
                    },
                );
            }
        }
    }
}

declare_lint! {
    /// The `incomplete_features` lint detects unstable features enabled with
    /// the [`feature` attribute] that may function improperly in some or all
    /// cases.
    ///
    /// [`feature` attribute]: https://doc.rust-lang.org/nightly/unstable-book/
    ///
    /// ### Example
    ///
    /// ```rust
    /// #![feature(generic_const_exprs)]
    /// ```
    ///
    /// {{produces}}
    ///
    /// ### Explanation
    ///
    /// Although it is encouraged for people to experiment with unstable
    /// features, some of them are known to be incomplete or faulty. This lint
    /// is a signal that the feature has not yet been finished, and you may
    /// experience problems with it.
    pub INCOMPLETE_FEATURES,
    Warn,
    "incomplete features that may function improperly in some or all cases"
}

declare_lint! {
    /// The `internal_features` lint detects unstable features enabled with
    /// the [`feature` attribute] that are internal to the compiler or standard
    /// library.
    ///
    /// [`feature` attribute]: https://doc.rust-lang.org/nightly/unstable-book/
    ///
    /// ### Example
    ///
    /// ```rust
    /// #![feature(rustc_attrs)]
    /// ```
    ///
    /// {{produces}}
    ///
    /// ### Explanation
    ///
    /// These features are an implementation detail of the compiler and standard
    /// library and are not supposed to be used in user code.
    pub INTERNAL_FEATURES,
    Warn,
    "internal features are not supposed to be used"
}

declare_lint_pass!(
    /// Check for used feature gates in `INCOMPLETE_FEATURES` in `rustc_feature/src/unstable.rs`.
    IncompleteInternalFeatures => [INCOMPLETE_FEATURES, INTERNAL_FEATURES]
);

impl EarlyLintPass for IncompleteInternalFeatures {
    fn check_crate(&mut self, cx: &EarlyContext<'_>, _: &ast::Crate) {
        let features = cx.builder.features();
        let lang_features =
            features.enabled_lang_features().iter().map(|feat| (feat.gate_name, feat.attr_sp));
        let lib_features =
            features.enabled_lib_features().iter().map(|feat| (feat.gate_name, feat.attr_sp));

        lang_features
            .chain(lib_features)
            .filter(|(name, _)| features.incomplete(*name) || features.internal(*name))
            .for_each(|(name, span)| {
                if features.incomplete(name) {
                    let note = rustc_feature::find_feature_issue(name, GateIssue::Language)
                        .map(|n| BuiltinFeatureIssueNote { n });
                    let help =
                        HAS_MIN_FEATURES.contains(&name).then_some(BuiltinIncompleteFeaturesHelp);

                    cx.emit_span_lint(
                        INCOMPLETE_FEATURES,
                        span,
                        BuiltinIncompleteFeatures { name, note, help },
                    );
                } else {
                    cx.emit_span_lint(INTERNAL_FEATURES, span, BuiltinInternalFeatures { name });
                }
            });
    }
}

const HAS_MIN_FEATURES: &[Symbol] = &[sym::specialization];

declare_lint! {
    /// The `invalid_value` lint detects creating a value that is not valid,
    /// such as a null reference.
    ///
    /// ### Example
    ///
    /// ```rust,no_run
    /// # #![allow(unused)]
    /// unsafe {
    ///     let x: &'static i32 = std::mem::zeroed();
    /// }
    /// ```
    ///
    /// {{produces}}
    ///
    /// ### Explanation
    ///
    /// In some situations the compiler can detect that the code is creating
    /// an invalid value, which should be avoided.
    ///
    /// In particular, this lint will check for improper use of
    /// [`mem::zeroed`], [`mem::uninitialized`], [`mem::transmute`], and
    /// [`MaybeUninit::assume_init`] that can cause [undefined behavior]. The
    /// lint should provide extra information to indicate what the problem is
    /// and a possible solution.
    ///
    /// [`mem::zeroed`]: https://doc.rust-lang.org/std/mem/fn.zeroed.html
    /// [`mem::uninitialized`]: https://doc.rust-lang.org/std/mem/fn.uninitialized.html
    /// [`mem::transmute`]: https://doc.rust-lang.org/std/mem/fn.transmute.html
    /// [`MaybeUninit::assume_init`]: https://doc.rust-lang.org/std/mem/union.MaybeUninit.html#method.assume_init
    /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
    pub INVALID_VALUE,
    Warn,
    "an invalid value is being created (such as a null reference)"
}

declare_lint_pass!(InvalidValue => [INVALID_VALUE]);

/// Information about why a type cannot be initialized this way.
pub struct InitError {
    pub(crate) message: String,
    /// Spans from struct fields and similar that can be obtained from just the type.
    pub(crate) span: Option<Span>,
    /// Used to report a trace through adts.
    pub(crate) nested: Option<Box<InitError>>,
}
impl InitError {
    fn spanned(self, span: Span) -> InitError {
        Self { span: Some(span), ..self }
    }

    fn nested(self, nested: impl Into<Option<InitError>>) -> InitError {
        assert!(self.nested.is_none());
        Self { nested: nested.into().map(Box::new), ..self }
    }
}

impl<'a> From<&'a str> for InitError {
    fn from(s: &'a str) -> Self {
        s.to_owned().into()
    }
}
impl From<String> for InitError {
    fn from(message: String) -> Self {
        Self { message, span: None, nested: None }
    }
}

impl<'tcx> LateLintPass<'tcx> for InvalidValue {
    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &hir::Expr<'_>) {
        #[derive(Debug, Copy, Clone, PartialEq)]
        enum InitKind {
            Zeroed,
            Uninit,
        }

        /// Test if this constant is all-0.
        fn is_zero(expr: &hir::Expr<'_>) -> bool {
            use hir::ExprKind::*;
            use rustc_ast::LitKind::*;
            match &expr.kind {
                Lit(lit) => {
                    if let Int(i, _) = lit.node {
                        i == 0
                    } else {
                        false
                    }
                }
                Tup(tup) => tup.iter().all(is_zero),
                _ => false,
            }
        }

        /// Determine if this expression is a "dangerous initialization".
        fn is_dangerous_init(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> Option<InitKind> {
            if let hir::ExprKind::Call(path_expr, args) = expr.kind
                // Find calls to `mem::{uninitialized,zeroed}` methods.
                && let hir::ExprKind::Path(ref qpath) = path_expr.kind
            {
                let def_id = cx.qpath_res(qpath, path_expr.hir_id).opt_def_id()?;
                match cx.tcx.get_diagnostic_name(def_id) {
                    Some(sym::mem_zeroed) => return Some(InitKind::Zeroed),
                    Some(sym::mem_uninitialized) => return Some(InitKind::Uninit),
                    Some(sym::transmute) if is_zero(&args[0]) => return Some(InitKind::Zeroed),
                    _ => {}
                }
            } else if let hir::ExprKind::MethodCall(_, receiver, ..) = expr.kind {
                // Find problematic calls to `MaybeUninit::assume_init`.
                let def_id = cx.typeck_results().type_dependent_def_id(expr.hir_id)?;
                if cx.tcx.is_diagnostic_item(sym::assume_init, def_id) {
                    // This is a call to *some* method named `assume_init`.
                    // See if the `self` parameter is one of the dangerous constructors.
                    if let hir::ExprKind::Call(path_expr, _) = receiver.kind
                        && let hir::ExprKind::Path(ref qpath) = path_expr.kind
                    {
                        let def_id = cx.qpath_res(qpath, path_expr.hir_id).opt_def_id()?;
                        match cx.tcx.get_diagnostic_name(def_id) {
                            Some(sym::maybe_uninit_zeroed) => return Some(InitKind::Zeroed),
                            Some(sym::maybe_uninit_uninit) => return Some(InitKind::Uninit),
                            _ => {}
                        }
                    }
                }
            }

            None
        }

        fn variant_find_init_error<'tcx>(
            cx: &LateContext<'tcx>,
            ty: Ty<'tcx>,
            variant: &VariantDef,
            args: ty::GenericArgsRef<'tcx>,
            descr: &str,
            init: InitKind,
        ) -> Option<InitError> {
            let mut field_err = variant.fields.iter().find_map(|field| {
                ty_find_init_error(cx, field.ty(cx.tcx, args), init).map(|mut err| {
                    if !field.did.is_local() {
                        err
                    } else if err.span.is_none() {
                        err.span = Some(cx.tcx.def_span(field.did));
                        write!(&mut err.message, " (in this {descr})").unwrap();
                        err
                    } else {
                        InitError::from(format!("in this {descr}"))
                            .spanned(cx.tcx.def_span(field.did))
                            .nested(err)
                    }
                })
            });

            // Check if this ADT has a constrained layout (like `NonNull` and friends).
            if let Ok(layout) = cx.tcx.layout_of(cx.typing_env().as_query_input(ty)) {
                if let BackendRepr::Scalar(scalar) | BackendRepr::ScalarPair(scalar, _) =
                    &layout.backend_repr
                {
                    let range = scalar.valid_range(cx);
                    let msg = if !range.contains(0) {
                        "must be non-null"
                    } else if init == InitKind::Uninit && !scalar.is_always_valid(cx) {
                        // Prefer reporting on the fields over the entire struct for uninit,
                        // as the information bubbles out and it may be unclear why the type can't
                        // be null from just its outside signature.

                        "must be initialized inside its custom valid range"
                    } else {
                        return field_err;
                    };
                    if let Some(field_err) = &mut field_err {
                        // Most of the time, if the field error is the same as the struct error,
                        // the struct error only happens because of the field error.
                        if field_err.message.contains(msg) {
                            field_err.message = format!("because {}", field_err.message);
                        }
                    }
                    return Some(InitError::from(format!("`{ty}` {msg}")).nested(field_err));
                }
            }
            field_err
        }

        /// Return `Some` only if we are sure this type does *not*
        /// allow zero initialization.
        fn ty_find_init_error<'tcx>(
            cx: &LateContext<'tcx>,
            ty: Ty<'tcx>,
            init: InitKind,
        ) -> Option<InitError> {
            let ty = cx.tcx.try_normalize_erasing_regions(cx.typing_env(), ty).unwrap_or(ty);

            match ty.kind() {
                // Primitive types that don't like 0 as a value.
                ty::Ref(..) => Some("references must be non-null".into()),
                ty::Adt(..) if ty.is_box() => Some("`Box` must be non-null".into()),
                ty::FnPtr(..) => Some("function pointers must be non-null".into()),
                ty::Never => Some("the `!` type has no valid value".into()),
                ty::RawPtr(ty, _) if matches!(ty.kind(), ty::Dynamic(..)) =>
                // raw ptr to dyn Trait
                {
                    Some("the vtable of a wide raw pointer must be non-null".into())
                }
                // Primitive types with other constraints.
                ty::Bool if init == InitKind::Uninit => {
                    Some("booleans must be either `true` or `false`".into())
                }
                ty::Char if init == InitKind::Uninit => {
                    Some("characters must be a valid Unicode codepoint".into())
                }
                ty::Int(_) | ty::Uint(_) if init == InitKind::Uninit => {
                    Some("integers must be initialized".into())
                }
                ty::Float(_) if init == InitKind::Uninit => {
                    Some("floats must be initialized".into())
                }
                ty::RawPtr(_, _) if init == InitKind::Uninit => {
                    Some("raw pointers must be initialized".into())
                }
                // Recurse and checks for some compound types. (but not unions)
                ty::Adt(adt_def, args) if !adt_def.is_union() => {
                    // Handle structs.
                    if adt_def.is_struct() {
                        return variant_find_init_error(
                            cx,
                            ty,
                            adt_def.non_enum_variant(),
                            args,
                            "struct field",
                            init,
                        );
                    }
                    // And now, enums.
                    let span = cx.tcx.def_span(adt_def.did());
                    let mut potential_variants = adt_def.variants().iter().filter_map(|variant| {
                        let definitely_inhabited = match variant
                            .inhabited_predicate(cx.tcx, *adt_def)
                            .instantiate(cx.tcx, args)
                            .apply_any_module(cx.tcx, cx.typing_env())
                        {
                            // Entirely skip uninhabited variants.
                            Some(false) => return None,
                            // Forward the others, but remember which ones are definitely inhabited.
                            Some(true) => true,
                            None => false,
                        };
                        Some((variant, definitely_inhabited))
                    });
                    let Some(first_variant) = potential_variants.next() else {
                        return Some(
                            InitError::from("enums with no inhabited variants have no valid value")
                                .spanned(span),
                        );
                    };
                    // So we have at least one potentially inhabited variant. Might we have two?
                    let Some(second_variant) = potential_variants.next() else {
                        // There is only one potentially inhabited variant. So we can recursively
                        // check that variant!
                        return variant_find_init_error(
                            cx,
                            ty,
                            first_variant.0,
                            args,
                            "field of the only potentially inhabited enum variant",
                            init,
                        );
                    };
                    // So we have at least two potentially inhabited variants. If we can prove that
                    // we have at least two *definitely* inhabited variants, then we have a tag and
                    // hence leaving this uninit is definitely disallowed. (Leaving it zeroed could
                    // be okay, depending on which variant is encoded as zero tag.)
                    if init == InitKind::Uninit {
                        let definitely_inhabited = (first_variant.1 as usize)
                            + (second_variant.1 as usize)
                            + potential_variants
                                .filter(|(_variant, definitely_inhabited)| *definitely_inhabited)
                                .count();
                        if definitely_inhabited > 1 {
                            return Some(InitError::from(
                                "enums with multiple inhabited variants have to be initialized to a variant",
                            ).spanned(span));
                        }
                    }
                    // We couldn't find anything wrong here.
                    None
                }
                ty::Tuple(..) => {
                    // Proceed recursively, check all fields.
                    ty.tuple_fields().iter().find_map(|field| ty_find_init_error(cx, field, init))
                }
                ty::Array(ty, len) => {
                    if matches!(len.try_to_target_usize(cx.tcx), Some(v) if v > 0) {
                        // Array length known at array non-empty -- recurse.
                        ty_find_init_error(cx, *ty, init)
                    } else {
                        // Empty array or size unknown.
                        None
                    }
                }
                // Conservative fallback.
                _ => None,
            }
        }

        if let Some(init) = is_dangerous_init(cx, expr) {
            // This conjures an instance of a type out of nothing,
            // using zeroed or uninitialized memory.
            // We are extremely conservative with what we warn about.
            let conjured_ty = cx.typeck_results().expr_ty(expr);
            if let Some(err) = with_no_trimmed_paths!(ty_find_init_error(cx, conjured_ty, init)) {
                let msg = match init {
                    InitKind::Zeroed => fluent::lint_builtin_unpermitted_type_init_zeroed,
                    InitKind::Uninit => fluent::lint_builtin_unpermitted_type_init_uninit,
                };
                let sub = BuiltinUnpermittedTypeInitSub { err };
                cx.emit_span_lint(
                    INVALID_VALUE,
                    expr.span,
                    BuiltinUnpermittedTypeInit {
                        msg,
                        ty: conjured_ty,
                        label: expr.span,
                        sub,
                        tcx: cx.tcx,
                    },
                );
            }
        }
    }
}

declare_lint! {
    /// The `deref_nullptr` lint detects when a null pointer is dereferenced,
    /// which causes [undefined behavior].
    ///
    /// ### Example
    ///
    /// ```rust,no_run
    /// # #![allow(unused)]
    /// use std::ptr;
    /// unsafe {
    ///     let x = &*ptr::null::<i32>();
    ///     let x = ptr::addr_of!(*ptr::null::<i32>());
    ///     let x = *(0 as *const i32);
    /// }
    /// ```
    ///
    /// {{produces}}
    ///
    /// ### Explanation
    ///
    /// Dereferencing a null pointer causes [undefined behavior] if it is accessed
    /// (loaded from or stored to).
    ///
    /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
    pub DEREF_NULLPTR,
    Warn,
    "detects when an null pointer is dereferenced"
}

declare_lint_pass!(DerefNullPtr => [DEREF_NULLPTR]);

impl<'tcx> LateLintPass<'tcx> for DerefNullPtr {
    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &hir::Expr<'_>) {
        /// test if expression is a null ptr
        fn is_null_ptr(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> bool {
            match &expr.kind {
                hir::ExprKind::Cast(expr, ty) => {
                    if let hir::TyKind::Ptr(_) = ty.kind {
                        return is_zero(expr) || is_null_ptr(cx, expr);
                    }
                }
                // check for call to `core::ptr::null` or `core::ptr::null_mut`
                hir::ExprKind::Call(path, _) => {
                    if let hir::ExprKind::Path(ref qpath) = path.kind
                        && let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id()
                    {
                        return matches!(
                            cx.tcx.get_diagnostic_name(def_id),
                            Some(sym::ptr_null | sym::ptr_null_mut)
                        );
                    }
                }
                _ => {}
            }
            false
        }

        /// test if expression is the literal `0`
        fn is_zero(expr: &hir::Expr<'_>) -> bool {
            match &expr.kind {
                hir::ExprKind::Lit(lit) => {
                    if let LitKind::Int(a, _) = lit.node {
                        return a == 0;
                    }
                }
                _ => {}
            }
            false
        }

        if let hir::ExprKind::Unary(hir::UnOp::Deref, expr_deref) = expr.kind
            && is_null_ptr(cx, expr_deref)
        {
            if let hir::Node::Expr(hir::Expr {
                kind: hir::ExprKind::AddrOf(hir::BorrowKind::Raw, ..),
                ..
            }) = cx.tcx.parent_hir_node(expr.hir_id)
            {
                // `&raw *NULL` is ok.
            } else {
                cx.emit_span_lint(
                    DEREF_NULLPTR,
                    expr.span,
                    BuiltinDerefNullptr { label: expr.span },
                );
            }
        }
    }
}

declare_lint! {
    /// The `named_asm_labels` lint detects the use of named labels in the
    /// inline `asm!` macro.
    ///
    /// ### Example
    ///
    /// ```rust,compile_fail
    /// # #![feature(asm_experimental_arch)]
    /// use std::arch::asm;
    ///
    /// fn main() {
    ///     unsafe {
    ///         asm!("foo: bar");
    ///     }
    /// }
    /// ```
    ///
    /// {{produces}}
    ///
    /// ### Explanation
    ///
    /// LLVM is allowed to duplicate inline assembly blocks for any
    /// reason, for example when it is in a function that gets inlined. Because
    /// of this, GNU assembler [local labels] *must* be used instead of labels
    /// with a name. Using named labels might cause assembler or linker errors.
    ///
    /// See the explanation in [Rust By Example] for more details.
    ///
    /// [local labels]: https://sourceware.org/binutils/docs/as/Symbol-Names.html#Local-Labels
    /// [Rust By Example]: https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels
    pub NAMED_ASM_LABELS,
    Deny,
    "named labels in inline assembly",
}

declare_lint! {
    /// The `binary_asm_labels` lint detects the use of numeric labels containing only binary
    /// digits in the inline `asm!` macro.
    ///
    /// ### Example
    ///
    /// ```rust,ignore (fails on non-x86_64)
    /// #![cfg(target_arch = "x86_64")]
    ///
    /// use std::arch::asm;
    ///
    /// fn main() {
    ///     unsafe {
    ///         asm!("0: jmp 0b");
    ///     }
    /// }
    /// ```
    ///
    /// This will produce:
    ///
    /// ```text
    /// error: avoid using labels containing only the digits `0` and `1` in inline assembly
    ///  --> <source>:7:15
    ///   |
    /// 7 |         asm!("0: jmp 0b");
    ///   |               ^ use a different label that doesn't start with `0` or `1`
    ///   |
    ///   = help: start numbering with `2` instead
    ///   = note: an LLVM bug makes these labels ambiguous with a binary literal number on x86
    ///   = note: see <https://github.com/llvm/llvm-project/issues/99547> for more information
    ///   = note: `#[deny(binary_asm_labels)]` on by default
    /// ```
    ///
    /// ### Explanation
    ///
    /// An [LLVM bug] causes this code to fail to compile because it interprets the `0b` as a binary
    /// literal instead of a reference to the previous local label `0`. To work around this bug,
    /// don't use labels that could be confused with a binary literal.
    ///
    /// This behavior is platform-specific to x86 and x86-64.
    ///
    /// See the explanation in [Rust By Example] for more details.
    ///
    /// [LLVM bug]: https://github.com/llvm/llvm-project/issues/99547
    /// [Rust By Example]: https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels
    pub BINARY_ASM_LABELS,
    Deny,
    "labels in inline assembly containing only 0 or 1 digits",
}

declare_lint_pass!(AsmLabels => [NAMED_ASM_LABELS, BINARY_ASM_LABELS]);

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum AsmLabelKind {
    Named,
    FormatArg,
    Binary,
}

impl<'tcx> LateLintPass<'tcx> for AsmLabels {
    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) {
        if let hir::Expr {
            kind:
                hir::ExprKind::InlineAsm(hir::InlineAsm {
                    asm_macro: asm_macro @ (AsmMacro::Asm | AsmMacro::NakedAsm),
                    template_strs,
                    options,
                    ..
                }),
            ..
        } = expr
        {
            // Non-generic naked functions are allowed to define arbitrary
            // labels.
            if *asm_macro == AsmMacro::NakedAsm {
                let def_id = expr.hir_id.owner.def_id;
                if !cx.tcx.generics_of(def_id).requires_monomorphization(cx.tcx) {
                    return;
                }
            }

            // asm with `options(raw)` does not do replacement with `{` and `}`.
            let raw = options.contains(InlineAsmOptions::RAW);

            for (template_sym, template_snippet, template_span) in template_strs.iter() {
                let template_str = template_sym.as_str();
                let find_label_span = |needle: &str| -> Option<Span> {
                    if let Some(template_snippet) = template_snippet {
                        let snippet = template_snippet.as_str();
                        if let Some(pos) = snippet.find(needle) {
                            let end = pos
                                + snippet[pos..]
                                    .find(|c| c == ':')
                                    .unwrap_or(snippet[pos..].len() - 1);
                            let inner = InnerSpan::new(pos, end);
                            return Some(template_span.from_inner(inner));
                        }
                    }

                    None
                };

                // diagnostics are emitted per-template, so this is created here as opposed to the outer loop
                let mut spans = Vec::new();

                // A semicolon might not actually be specified as a separator for all targets, but
                // it seems like LLVM accepts it always.
                let statements = template_str.split(|c| matches!(c, '\n' | ';'));
                for statement in statements {
                    // If there's a comment, trim it from the statement
                    let statement = statement.find("//").map_or(statement, |idx| &statement[..idx]);

                    // In this loop, if there is ever a non-label, no labels can come after it.
                    let mut start_idx = 0;
                    'label_loop: for (idx, _) in statement.match_indices(':') {
                        let possible_label = statement[start_idx..idx].trim();
                        let mut chars = possible_label.chars();

                        let Some(start) = chars.next() else {
                            // Empty string means a leading ':' in this section, which is not a
                            // label.
                            break 'label_loop;
                        };

                        // Whether a { bracket has been seen and its } hasn't been found yet.
                        let mut in_bracket = false;
                        let mut label_kind = AsmLabelKind::Named;

                        // A label can also start with a format arg, if it's not a raw asm block.
                        if !raw && start == '{' {
                            in_bracket = true;
                            label_kind = AsmLabelKind::FormatArg;
                        } else if matches!(start, '0' | '1') {
                            // Binary labels have only the characters `0` or `1`.
                            label_kind = AsmLabelKind::Binary;
                        } else if !(start.is_ascii_alphabetic() || matches!(start, '.' | '_')) {
                            // Named labels start with ASCII letters, `.` or `_`.
                            // anything else is not a label
                            break 'label_loop;
                        }

                        for c in chars {
                            // Inside a template format arg, any character is permitted for the
                            // puproses of label detection because we assume that it can be
                            // replaced with some other valid label string later. `options(raw)`
                            // asm blocks cannot have format args, so they are excluded from this
                            // special case.
                            if !raw && in_bracket {
                                if c == '{' {
                                    // Nested brackets are not allowed in format args, this cannot
                                    // be a label.
                                    break 'label_loop;
                                }

                                if c == '}' {
                                    // The end of the format arg.
                                    in_bracket = false;
                                }
                            } else if !raw && c == '{' {
                                // Start of a format arg.
                                in_bracket = true;
                                label_kind = AsmLabelKind::FormatArg;
                            } else {
                                let can_continue = match label_kind {
                                    // Format arg labels are considered to be named labels for the purposes
                                    // of continuing outside of their {} pair.
                                    AsmLabelKind::Named | AsmLabelKind::FormatArg => {
                                        c.is_ascii_alphanumeric() || matches!(c, '_' | '$')
                                    }
                                    AsmLabelKind::Binary => matches!(c, '0' | '1'),
                                };

                                if !can_continue {
                                    // The potential label had an invalid character inside it, it
                                    // cannot be a label.
                                    break 'label_loop;
                                }
                            }
                        }

                        // If all characters passed the label checks, this is a label.
                        spans.push((find_label_span(possible_label), label_kind));
                        start_idx = idx + 1;
                    }
                }

                for (span, label_kind) in spans {
                    let missing_precise_span = span.is_none();
                    let span = span.unwrap_or(*template_span);
                    match label_kind {
                        AsmLabelKind::Named => {
                            cx.emit_span_lint(
                                NAMED_ASM_LABELS,
                                span,
                                InvalidAsmLabel::Named { missing_precise_span },
                            );
                        }
                        AsmLabelKind::FormatArg => {
                            cx.emit_span_lint(
                                NAMED_ASM_LABELS,
                                span,
                                InvalidAsmLabel::FormatArg { missing_precise_span },
                            );
                        }
                        // the binary asm issue only occurs when using intel syntax on x86 targets
                        AsmLabelKind::Binary
                            if !options.contains(InlineAsmOptions::ATT_SYNTAX)
                                && matches!(
                                    cx.tcx.sess.asm_arch,
                                    Some(InlineAsmArch::X86 | InlineAsmArch::X86_64) | None
                                ) =>
                        {
                            cx.emit_span_lint(
                                BINARY_ASM_LABELS,
                                span,
                                InvalidAsmLabel::Binary { missing_precise_span, span },
                            )
                        }
                        // No lint on anything other than x86
                        AsmLabelKind::Binary => (),
                    };
                }
            }
        }
    }
}

declare_lint! {
    /// The `special_module_name` lint detects module
    /// declarations for files that have a special meaning.
    ///
    /// ### Example
    ///
    /// ```rust,compile_fail
    /// mod lib;
    ///
    /// fn main() {
    ///     lib::run();
    /// }
    /// ```
    ///
    /// {{produces}}
    ///
    /// ### Explanation
    ///
    /// Cargo recognizes `lib.rs` and `main.rs` as the root of a
    /// library or binary crate, so declaring them as modules
    /// will lead to miscompilation of the crate unless configured
    /// explicitly.
    ///
    /// To access a library from a binary target within the same crate,
    /// use `your_crate_name::` as the path instead of `lib::`:
    ///
    /// ```rust,compile_fail
    /// // bar/src/lib.rs
    /// fn run() {
    ///     // ...
    /// }
    ///
    /// // bar/src/main.rs
    /// fn main() {
    ///     bar::run();
    /// }
    /// ```
    ///
    /// Binary targets cannot be used as libraries and so declaring
    /// one as a module is not allowed.
    pub SPECIAL_MODULE_NAME,
    Warn,
    "module declarations for files with a special meaning",
}

declare_lint_pass!(SpecialModuleName => [SPECIAL_MODULE_NAME]);

impl EarlyLintPass for SpecialModuleName {
    fn check_crate(&mut self, cx: &EarlyContext<'_>, krate: &ast::Crate) {
        for item in &krate.items {
            if let ast::ItemKind::Mod(
                _,
                ident,
                ast::ModKind::Unloaded | ast::ModKind::Loaded(_, ast::Inline::No { .. }, _),
            ) = item.kind
            {
                if item.attrs.iter().any(|a| a.has_name(sym::path)) {
                    continue;
                }

                match ident.name.as_str() {
                    "lib" => cx.emit_span_lint(
                        SPECIAL_MODULE_NAME,
                        item.span,
                        BuiltinSpecialModuleNameUsed::Lib,
                    ),
                    "main" => cx.emit_span_lint(
                        SPECIAL_MODULE_NAME,
                        item.span,
                        BuiltinSpecialModuleNameUsed::Main,
                    ),
                    _ => continue,
                }
            }
        }
    }
}
