//! 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<'_>) {
        // The result shouldn't be tainted, otherwise it will cause ICE.
        if let PatKind::Struct(ref qpath, field_pats, _) = pat.kind
            && cx.typeck_results().tainted_by_errors.is_none()
        {
            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(hir::Attribute::Parsed(AttributeKind::AllowInternalUnsafe(span))) =
                    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, 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().is_some() {
        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();

        features
            .enabled_features_iter_stable_order()
            .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
                            // purposes 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,
                }
            }
        }
    }
}
