use std::iter;

use rustc_ast::util::{classify, parser};
use rustc_ast::{self as ast, ExprKind, FnRetTy, HasAttrs as _, StmtKind};
use rustc_data_structures::fx::FxHashMap;
use rustc_errors::{MultiSpan, pluralize};
use rustc_hir::attrs::AttributeKind;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::DefId;
use rustc_hir::{self as hir, LangItem, find_attr};
use rustc_infer::traits::util::elaborate;
use rustc_middle::ty::{self, Ty, adjustment};
use rustc_session::{declare_lint, declare_lint_pass, impl_lint_pass};
use rustc_span::edition::Edition::Edition2015;
use rustc_span::{BytePos, Span, Symbol, kw, sym};
use tracing::instrument;

use crate::lints::{
    PathStatementDrop, PathStatementDropSub, PathStatementNoEffect, UnusedAllocationDiag,
    UnusedAllocationMutDiag, UnusedClosure, UnusedCoroutine, UnusedDef, UnusedDefSuggestion,
    UnusedDelim, UnusedDelimSuggestion, UnusedImportBracesDiag, UnusedOp, UnusedOpSuggestion,
    UnusedResult,
};
use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, Lint, LintContext};

declare_lint! {
    /// The `unused_must_use` lint detects unused result of a type flagged as
    /// `#[must_use]`.
    ///
    /// ### Example
    ///
    /// ```rust
    /// fn returns_result() -> Result<(), ()> {
    ///     Ok(())
    /// }
    ///
    /// fn main() {
    ///     returns_result();
    /// }
    /// ```
    ///
    /// {{produces}}
    ///
    /// ### Explanation
    ///
    /// The `#[must_use]` attribute is an indicator that it is a mistake to
    /// ignore the value. See [the reference] for more details.
    ///
    /// [the reference]: https://doc.rust-lang.org/reference/attributes/diagnostics.html#the-must_use-attribute
    pub UNUSED_MUST_USE,
    Warn,
    "unused result of a type flagged as `#[must_use]`",
    report_in_external_macro
}

declare_lint! {
    /// The `unused_results` lint checks for the unused result of an
    /// expression in a statement.
    ///
    /// ### Example
    ///
    /// ```rust,compile_fail
    /// #![deny(unused_results)]
    /// fn foo<T>() -> T { panic!() }
    ///
    /// fn main() {
    ///     foo::<usize>();
    /// }
    /// ```
    ///
    /// {{produces}}
    ///
    /// ### Explanation
    ///
    /// Ignoring the return value of a function may indicate a mistake. In
    /// cases were it is almost certain that the result should be used, it is
    /// recommended to annotate the function with the [`must_use` attribute].
    /// Failure to use such a return value will trigger the [`unused_must_use`
    /// lint] which is warn-by-default. The `unused_results` lint is
    /// essentially the same, but triggers for *all* return values.
    ///
    /// This lint is "allow" by default because it can be noisy, and may not be
    /// an actual problem. For example, calling the `remove` method of a `Vec`
    /// or `HashMap` returns the previous value, which you may not care about.
    /// Using this lint would require explicitly ignoring or discarding such
    /// values.
    ///
    /// [`must_use` attribute]: https://doc.rust-lang.org/reference/attributes/diagnostics.html#the-must_use-attribute
    /// [`unused_must_use` lint]: warn-by-default.html#unused-must-use
    pub UNUSED_RESULTS,
    Allow,
    "unused result of an expression in a statement"
}

declare_lint_pass!(UnusedResults => [UNUSED_MUST_USE, UNUSED_RESULTS]);

impl<'tcx> LateLintPass<'tcx> for UnusedResults {
    fn check_stmt(&mut self, cx: &LateContext<'_>, s: &hir::Stmt<'_>) {
        let hir::StmtKind::Semi(mut expr) = s.kind else {
            return;
        };

        let mut expr_is_from_block = false;
        while let hir::ExprKind::Block(blk, ..) = expr.kind
            && let hir::Block { expr: Some(e), .. } = blk
        {
            expr = e;
            expr_is_from_block = true;
        }

        if let hir::ExprKind::Ret(..) = expr.kind {
            return;
        }

        if let hir::ExprKind::Match(await_expr, _arms, hir::MatchSource::AwaitDesugar) = expr.kind
            && let ty = cx.typeck_results().expr_ty(await_expr)
            && let ty::Alias(ty::Opaque, ty::AliasTy { def_id: future_def_id, .. }) = ty.kind()
            && cx.tcx.ty_is_opaque_future(ty)
            && let async_fn_def_id = cx.tcx.parent(*future_def_id)
            && matches!(cx.tcx.def_kind(async_fn_def_id), DefKind::Fn | DefKind::AssocFn)
            // Check that this `impl Future` actually comes from an `async fn`
            && cx.tcx.asyncness(async_fn_def_id).is_async()
            && check_must_use_def(
                cx,
                async_fn_def_id,
                expr.span,
                "output of future returned by ",
                "",
                expr_is_from_block,
            )
        {
            // We have a bare `foo().await;` on an opaque type from an async function that was
            // annotated with `#[must_use]`.
            return;
        }

        let ty = cx.typeck_results().expr_ty(expr);

        let must_use_result = is_ty_must_use(cx, ty, expr, expr.span);
        let type_lint_emitted_or_suppressed = match must_use_result {
            Some(path) => {
                emit_must_use_untranslated(cx, &path, "", "", 1, false, expr_is_from_block);
                true
            }
            None => false,
        };

        let fn_warned = check_fn_must_use(cx, expr, expr_is_from_block);

        if !fn_warned && type_lint_emitted_or_suppressed {
            // We don't warn about unused unit or uninhabited types.
            // (See https://github.com/rust-lang/rust/issues/43806 for details.)
            return;
        }

        let must_use_op = match expr.kind {
            // Hardcoding operators here seemed more expedient than the
            // refactoring that would be needed to look up the `#[must_use]`
            // attribute which does exist on the comparison trait methods
            hir::ExprKind::Binary(bin_op, ..) => match bin_op.node {
                hir::BinOpKind::Eq
                | hir::BinOpKind::Lt
                | hir::BinOpKind::Le
                | hir::BinOpKind::Ne
                | hir::BinOpKind::Ge
                | hir::BinOpKind::Gt => Some("comparison"),
                hir::BinOpKind::Add
                | hir::BinOpKind::Sub
                | hir::BinOpKind::Div
                | hir::BinOpKind::Mul
                | hir::BinOpKind::Rem => Some("arithmetic operation"),
                hir::BinOpKind::And | hir::BinOpKind::Or => Some("logical operation"),
                hir::BinOpKind::BitXor
                | hir::BinOpKind::BitAnd
                | hir::BinOpKind::BitOr
                | hir::BinOpKind::Shl
                | hir::BinOpKind::Shr => Some("bitwise operation"),
            },
            hir::ExprKind::AddrOf(..) => Some("borrow"),
            hir::ExprKind::OffsetOf(..) => Some("`offset_of` call"),
            hir::ExprKind::Unary(..) => Some("unary operation"),
            _ => None,
        };

        let mut op_warned = false;

        if let Some(must_use_op) = must_use_op {
            let span = expr.span.find_ancestor_not_from_macro().unwrap_or(expr.span);
            cx.emit_span_lint(
                UNUSED_MUST_USE,
                expr.span,
                UnusedOp {
                    op: must_use_op,
                    label: expr.span,
                    suggestion: if expr_is_from_block {
                        UnusedOpSuggestion::BlockTailExpr {
                            before_span: span.shrink_to_lo(),
                            after_span: span.shrink_to_hi(),
                        }
                    } else {
                        UnusedOpSuggestion::NormalExpr { span: span.shrink_to_lo() }
                    },
                },
            );
            op_warned = true;
        }

        if !(type_lint_emitted_or_suppressed || fn_warned || op_warned) {
            cx.emit_span_lint(UNUSED_RESULTS, s.span, UnusedResult { ty });
        }

        fn check_fn_must_use(
            cx: &LateContext<'_>,
            expr: &hir::Expr<'_>,
            expr_is_from_block: bool,
        ) -> bool {
            let maybe_def_id = match expr.kind {
                hir::ExprKind::Call(callee, _) => {
                    match callee.kind {
                        hir::ExprKind::Path(ref qpath) => {
                            match cx.qpath_res(qpath, callee.hir_id) {
                                Res::Def(DefKind::Fn | DefKind::AssocFn, def_id) => Some(def_id),
                                // `Res::Local` if it was a closure, for which we
                                // do not currently support must-use linting
                                _ => None,
                            }
                        }
                        _ => None,
                    }
                }
                hir::ExprKind::MethodCall(..) => {
                    cx.typeck_results().type_dependent_def_id(expr.hir_id)
                }
                _ => None,
            };
            if let Some(def_id) = maybe_def_id {
                check_must_use_def(
                    cx,
                    def_id,
                    expr.span,
                    "return value of ",
                    "",
                    expr_is_from_block,
                )
            } else {
                false
            }
        }

        /// A path through a type to a must_use source. Contains useful info for the lint.
        #[derive(Debug)]
        enum MustUsePath {
            /// Suppress must_use checking.
            Suppressed,
            /// The root of the normal must_use lint with an optional message.
            Def(Span, DefId, Option<Symbol>),
            Boxed(Box<Self>),
            Pinned(Box<Self>),
            Opaque(Box<Self>),
            TraitObject(Box<Self>),
            TupleElement(Vec<(usize, Self)>),
            Array(Box<Self>, u64),
            /// The root of the unused_closures lint.
            Closure(Span),
            /// The root of the unused_coroutines lint.
            Coroutine(Span),
        }

        #[instrument(skip(cx, expr), level = "debug", ret)]
        fn is_ty_must_use<'tcx>(
            cx: &LateContext<'tcx>,
            ty: Ty<'tcx>,
            expr: &hir::Expr<'_>,
            span: Span,
        ) -> Option<MustUsePath> {
            if ty.is_unit()
                || !ty.is_inhabited_from(
                    cx.tcx,
                    cx.tcx.parent_module(expr.hir_id).to_def_id(),
                    cx.typing_env(),
                )
            {
                return Some(MustUsePath::Suppressed);
            }

            match *ty.kind() {
                ty::Adt(..) if let Some(boxed) = ty.boxed_ty() => {
                    is_ty_must_use(cx, boxed, expr, span)
                        .map(|inner| MustUsePath::Boxed(Box::new(inner)))
                }
                ty::Adt(def, args) if cx.tcx.is_lang_item(def.did(), LangItem::Pin) => {
                    let pinned_ty = args.type_at(0);
                    is_ty_must_use(cx, pinned_ty, expr, span)
                        .map(|inner| MustUsePath::Pinned(Box::new(inner)))
                }
                ty::Adt(def, _) => is_def_must_use(cx, def.did(), span),
                ty::Alias(ty::Opaque | ty::Projection, ty::AliasTy { def_id: def, .. }) => {
                    elaborate(cx.tcx, cx.tcx.explicit_item_self_bounds(def).iter_identity_copied())
                        // We only care about self bounds for the impl-trait
                        .filter_only_self()
                        .find_map(|(pred, _span)| {
                            // We only look at the `DefId`, so it is safe to skip the binder here.
                            if let ty::ClauseKind::Trait(ref poly_trait_predicate) =
                                pred.kind().skip_binder()
                            {
                                let def_id = poly_trait_predicate.trait_ref.def_id;

                                is_def_must_use(cx, def_id, span)
                            } else {
                                None
                            }
                        })
                        .map(|inner| MustUsePath::Opaque(Box::new(inner)))
                }
                ty::Dynamic(binders, _, _) => binders.iter().find_map(|predicate| {
                    if let ty::ExistentialPredicate::Trait(ref trait_ref) = predicate.skip_binder()
                    {
                        let def_id = trait_ref.def_id;
                        is_def_must_use(cx, def_id, span)
                            .map(|inner| MustUsePath::TraitObject(Box::new(inner)))
                    } else {
                        None
                    }
                }),
                ty::Tuple(tys) => {
                    let elem_exprs = if let hir::ExprKind::Tup(elem_exprs) = expr.kind {
                        debug_assert_eq!(elem_exprs.len(), tys.len());
                        elem_exprs
                    } else {
                        &[]
                    };

                    // Default to `expr`.
                    let elem_exprs = elem_exprs.iter().chain(iter::repeat(expr));

                    let nested_must_use = tys
                        .iter()
                        .zip(elem_exprs)
                        .enumerate()
                        .filter_map(|(i, (ty, expr))| {
                            is_ty_must_use(cx, ty, expr, expr.span).map(|path| (i, path))
                        })
                        .collect::<Vec<_>>();

                    if !nested_must_use.is_empty() {
                        Some(MustUsePath::TupleElement(nested_must_use))
                    } else {
                        None
                    }
                }
                ty::Array(ty, len) => match len.try_to_target_usize(cx.tcx) {
                    // If the array is empty we don't lint, to avoid false positives
                    Some(0) | None => None,
                    // If the array is definitely non-empty, we can do `#[must_use]` checking.
                    Some(len) => is_ty_must_use(cx, ty, expr, span)
                        .map(|inner| MustUsePath::Array(Box::new(inner), len)),
                },
                ty::Closure(..) | ty::CoroutineClosure(..) => Some(MustUsePath::Closure(span)),
                ty::Coroutine(def_id, ..) => {
                    // async fn should be treated as "implementor of `Future`"
                    let must_use = if cx.tcx.coroutine_is_async(def_id) {
                        let def_id = cx.tcx.lang_items().future_trait()?;
                        is_def_must_use(cx, def_id, span)
                            .map(|inner| MustUsePath::Opaque(Box::new(inner)))
                    } else {
                        None
                    };
                    must_use.or(Some(MustUsePath::Coroutine(span)))
                }
                _ => None,
            }
        }

        fn is_def_must_use(cx: &LateContext<'_>, def_id: DefId, span: Span) -> Option<MustUsePath> {
            if let Some(reason) = find_attr!(
                cx.tcx.get_all_attrs(def_id),
                AttributeKind::MustUse { reason, .. } => reason
            ) {
                // check for #[must_use = "..."]
                Some(MustUsePath::Def(span, def_id, *reason))
            } else {
                None
            }
        }

        // Returns whether further errors should be suppressed because either a lint has been
        // emitted or the type should be ignored.
        fn check_must_use_def(
            cx: &LateContext<'_>,
            def_id: DefId,
            span: Span,
            descr_pre_path: &str,
            descr_post_path: &str,
            expr_is_from_block: bool,
        ) -> bool {
            is_def_must_use(cx, def_id, span)
                .map(|must_use_path| {
                    emit_must_use_untranslated(
                        cx,
                        &must_use_path,
                        descr_pre_path,
                        descr_post_path,
                        1,
                        false,
                        expr_is_from_block,
                    )
                })
                .is_some()
        }

        #[instrument(skip(cx), level = "debug")]
        fn emit_must_use_untranslated(
            cx: &LateContext<'_>,
            path: &MustUsePath,
            descr_pre: &str,
            descr_post: &str,
            plural_len: usize,
            is_inner: bool,
            expr_is_from_block: bool,
        ) {
            let plural_suffix = pluralize!(plural_len);

            match path {
                MustUsePath::Suppressed => {}
                MustUsePath::Boxed(path) => {
                    let descr_pre = &format!("{descr_pre}boxed ");
                    emit_must_use_untranslated(
                        cx,
                        path,
                        descr_pre,
                        descr_post,
                        plural_len,
                        true,
                        expr_is_from_block,
                    );
                }
                MustUsePath::Pinned(path) => {
                    let descr_pre = &format!("{descr_pre}pinned ");
                    emit_must_use_untranslated(
                        cx,
                        path,
                        descr_pre,
                        descr_post,
                        plural_len,
                        true,
                        expr_is_from_block,
                    );
                }
                MustUsePath::Opaque(path) => {
                    let descr_pre = &format!("{descr_pre}implementer{plural_suffix} of ");
                    emit_must_use_untranslated(
                        cx,
                        path,
                        descr_pre,
                        descr_post,
                        plural_len,
                        true,
                        expr_is_from_block,
                    );
                }
                MustUsePath::TraitObject(path) => {
                    let descr_post = &format!(" trait object{plural_suffix}{descr_post}");
                    emit_must_use_untranslated(
                        cx,
                        path,
                        descr_pre,
                        descr_post,
                        plural_len,
                        true,
                        expr_is_from_block,
                    );
                }
                MustUsePath::TupleElement(elems) => {
                    for (index, path) in elems {
                        let descr_post = &format!(" in tuple element {index}");
                        emit_must_use_untranslated(
                            cx,
                            path,
                            descr_pre,
                            descr_post,
                            plural_len,
                            true,
                            expr_is_from_block,
                        );
                    }
                }
                MustUsePath::Array(path, len) => {
                    let descr_pre = &format!("{descr_pre}array{plural_suffix} of ");
                    emit_must_use_untranslated(
                        cx,
                        path,
                        descr_pre,
                        descr_post,
                        plural_len.saturating_add(usize::try_from(*len).unwrap_or(usize::MAX)),
                        true,
                        expr_is_from_block,
                    );
                }
                MustUsePath::Closure(span) => {
                    cx.emit_span_lint(
                        UNUSED_MUST_USE,
                        *span,
                        UnusedClosure { count: plural_len, pre: descr_pre, post: descr_post },
                    );
                }
                MustUsePath::Coroutine(span) => {
                    cx.emit_span_lint(
                        UNUSED_MUST_USE,
                        *span,
                        UnusedCoroutine { count: plural_len, pre: descr_pre, post: descr_post },
                    );
                }
                MustUsePath::Def(span, def_id, reason) => {
                    let span = span.find_ancestor_not_from_macro().unwrap_or(*span);
                    cx.emit_span_lint(
                        UNUSED_MUST_USE,
                        span,
                        UnusedDef {
                            pre: descr_pre,
                            post: descr_post,
                            cx,
                            def_id: *def_id,
                            note: *reason,
                            suggestion: (!is_inner).then_some(if expr_is_from_block {
                                UnusedDefSuggestion::BlockTailExpr {
                                    before_span: span.shrink_to_lo(),
                                    after_span: span.shrink_to_hi(),
                                }
                            } else {
                                UnusedDefSuggestion::NormalExpr { span: span.shrink_to_lo() }
                            }),
                        },
                    );
                }
            }
        }
    }
}

declare_lint! {
    /// The `path_statements` lint detects path statements with no effect.
    ///
    /// ### Example
    ///
    /// ```rust
    /// let x = 42;
    ///
    /// x;
    /// ```
    ///
    /// {{produces}}
    ///
    /// ### Explanation
    ///
    /// It is usually a mistake to have a statement that has no effect.
    pub PATH_STATEMENTS,
    Warn,
    "path statements with no effect"
}

declare_lint_pass!(PathStatements => [PATH_STATEMENTS]);

impl<'tcx> LateLintPass<'tcx> for PathStatements {
    fn check_stmt(&mut self, cx: &LateContext<'_>, s: &hir::Stmt<'_>) {
        if let hir::StmtKind::Semi(expr) = s.kind
            && let hir::ExprKind::Path(_) = expr.kind
        {
            let ty = cx.typeck_results().expr_ty(expr);
            if ty.needs_drop(cx.tcx, cx.typing_env()) {
                let sub = if let Ok(snippet) = cx.sess().source_map().span_to_snippet(expr.span) {
                    PathStatementDropSub::Suggestion { span: s.span, snippet }
                } else {
                    PathStatementDropSub::Help { span: s.span }
                };
                cx.emit_span_lint(PATH_STATEMENTS, s.span, PathStatementDrop { sub })
            } else {
                cx.emit_span_lint(PATH_STATEMENTS, s.span, PathStatementNoEffect);
            }
        }
    }
}

#[derive(Copy, Clone, Debug, PartialEq, Eq)]
enum UnusedDelimsCtx {
    FunctionArg,
    MethodArg,
    AssignedValue,
    AssignedValueLetElse,
    IfCond,
    WhileCond,
    ForIterExpr,
    MatchScrutineeExpr,
    ReturnValue,
    BlockRetValue,
    BreakValue,
    LetScrutineeExpr,
    ArrayLenExpr,
    AnonConst,
    MatchArmExpr,
    IndexExpr,
    ClosureBody,
}

impl From<UnusedDelimsCtx> for &'static str {
    fn from(ctx: UnusedDelimsCtx) -> &'static str {
        match ctx {
            UnusedDelimsCtx::FunctionArg => "function argument",
            UnusedDelimsCtx::MethodArg => "method argument",
            UnusedDelimsCtx::AssignedValue | UnusedDelimsCtx::AssignedValueLetElse => {
                "assigned value"
            }
            UnusedDelimsCtx::IfCond => "`if` condition",
            UnusedDelimsCtx::WhileCond => "`while` condition",
            UnusedDelimsCtx::ForIterExpr => "`for` iterator expression",
            UnusedDelimsCtx::MatchScrutineeExpr => "`match` scrutinee expression",
            UnusedDelimsCtx::ReturnValue => "`return` value",
            UnusedDelimsCtx::BlockRetValue => "block return value",
            UnusedDelimsCtx::BreakValue => "`break` value",
            UnusedDelimsCtx::LetScrutineeExpr => "`let` scrutinee expression",
            UnusedDelimsCtx::ArrayLenExpr | UnusedDelimsCtx::AnonConst => "const expression",
            UnusedDelimsCtx::MatchArmExpr => "match arm expression",
            UnusedDelimsCtx::IndexExpr => "index expression",
            UnusedDelimsCtx::ClosureBody => "closure body",
        }
    }
}

/// Used by both `UnusedParens` and `UnusedBraces` to prevent code duplication.
trait UnusedDelimLint {
    const DELIM_STR: &'static str;

    /// Due to `ref` pattern, there can be a difference between using
    /// `{ expr }` and `expr` in pattern-matching contexts. This means
    /// that we should only lint `unused_parens` and not `unused_braces`
    /// in this case.
    ///
    /// ```rust
    /// let mut a = 7;
    /// let ref b = { a }; // We actually borrow a copy of `a` here.
    /// a += 1; // By mutating `a` we invalidate any borrows of `a`.
    /// assert_eq!(b + 1, a); // `b` does not borrow `a`, so we can still use it here.
    /// ```
    const LINT_EXPR_IN_PATTERN_MATCHING_CTX: bool;

    // this cannot be a constant is it refers to a static.
    fn lint(&self) -> &'static Lint;

    fn check_unused_delims_expr(
        &self,
        cx: &EarlyContext<'_>,
        value: &ast::Expr,
        ctx: UnusedDelimsCtx,
        followed_by_block: bool,
        left_pos: Option<BytePos>,
        right_pos: Option<BytePos>,
        is_kw: bool,
    );

    fn is_expr_delims_necessary(
        inner: &ast::Expr,
        ctx: UnusedDelimsCtx,
        followed_by_block: bool,
    ) -> bool {
        let followed_by_else = ctx == UnusedDelimsCtx::AssignedValueLetElse;

        if followed_by_else {
            match inner.kind {
                ast::ExprKind::Binary(op, ..) if op.node.is_lazy() => return true,
                _ if classify::expr_trailing_brace(inner).is_some() => return true,
                _ => {}
            }
        }

        // Check it's range in LetScrutineeExpr
        if let ast::ExprKind::Range(..) = inner.kind
            && matches!(ctx, UnusedDelimsCtx::LetScrutineeExpr)
        {
            return true;
        }

        // Do not lint against parentheses around `&raw [const|mut] expr`.
        // These parentheses will have to be added e.g. when calling a method on the result of this
        // expression, and we want to avoid churn wrt adding and removing parentheses.
        if matches!(inner.kind, ast::ExprKind::AddrOf(ast::BorrowKind::Raw, ..)) {
            return true;
        }

        // Check if LHS needs parens to prevent false-positives in cases like
        // `fn x() -> u8 { ({ 0 } + 1) }`.
        //
        // FIXME: https://github.com/rust-lang/rust/issues/119426
        // The syntax tree in this code is from after macro expansion, so the
        // current implementation has both false negatives and false positives
        // related to expressions containing macros.
        //
        //     macro_rules! m1 {
        //         () => {
        //             1
        //         };
        //     }
        //
        //     fn f1() -> u8 {
        //         // Lint says parens are not needed, but they are.
        //         (m1! {} + 1)
        //     }
        //
        //     macro_rules! m2 {
        //         () => {
        //             loop { break 1; }
        //         };
        //     }
        //
        //     fn f2() -> u8 {
        //         // Lint says parens are needed, but they are not.
        //         (m2!() + 1)
        //     }
        {
            let mut innermost = inner;
            loop {
                innermost = match &innermost.kind {
                    ExprKind::Binary(_op, lhs, _rhs) => lhs,
                    ExprKind::Call(fn_, _params) => fn_,
                    ExprKind::Cast(expr, _ty) => expr,
                    ExprKind::Type(expr, _ty) => expr,
                    ExprKind::Index(base, _subscript, _) => base,
                    _ => break,
                };
                if !classify::expr_requires_semi_to_be_stmt(innermost) {
                    return true;
                }
            }
        }

        // Check if RHS needs parens to prevent false-positives in cases like `if (() == return)
        // {}`.
        if !followed_by_block {
            return false;
        }

        // Check if we need parens for `match &( Struct { field:  }) {}`.
        {
            let mut innermost = inner;
            loop {
                innermost = match &innermost.kind {
                    ExprKind::AddrOf(_, _, expr) => expr,
                    _ => {
                        if parser::contains_exterior_struct_lit(innermost) {
                            return true;
                        } else {
                            break;
                        }
                    }
                }
            }
        }

        let mut innermost = inner;
        loop {
            innermost = match &innermost.kind {
                ExprKind::Unary(_op, expr) => expr,
                ExprKind::Binary(_op, _lhs, rhs) => rhs,
                ExprKind::AssignOp(_op, _lhs, rhs) => rhs,
                ExprKind::Assign(_lhs, rhs, _span) => rhs,

                ExprKind::Ret(_) | ExprKind::Yield(..) | ExprKind::Yeet(..) => return true,

                ExprKind::Break(_label, None) => return false,
                ExprKind::Break(_label, Some(break_expr)) => {
                    return matches!(break_expr.kind, ExprKind::Block(..));
                }

                ExprKind::Range(_lhs, Some(rhs), _limits) => {
                    return matches!(rhs.kind, ExprKind::Block(..));
                }

                _ => return parser::contains_exterior_struct_lit(inner),
            }
        }
    }

    fn emit_unused_delims_expr(
        &self,
        cx: &EarlyContext<'_>,
        value: &ast::Expr,
        ctx: UnusedDelimsCtx,
        left_pos: Option<BytePos>,
        right_pos: Option<BytePos>,
        is_kw: bool,
    ) {
        let span_with_attrs = match value.kind {
            ast::ExprKind::Block(ref block, None) if let [stmt] = block.stmts.as_slice() => {
                // For the statements with attributes, like `{ #[allow()] println!("Hello!") }`,
                // the span should contains the attributes, or the suggestion will remove them.
                if let Some(attr_lo) = stmt.attrs().iter().map(|attr| attr.span.lo()).min() {
                    stmt.span.with_lo(attr_lo)
                } else {
                    stmt.span
                }
            }
            ast::ExprKind::Paren(ref expr) => {
                // For the expr with attributes, like `let _ = (#[inline] || println!("Hello!"));`,
                // the span should contains the attributes, or the suggestion will remove them.
                if let Some(attr_lo) = expr.attrs.iter().map(|attr| attr.span.lo()).min() {
                    expr.span.with_lo(attr_lo)
                } else {
                    expr.span
                }
            }
            _ => return,
        };
        let spans = span_with_attrs
            .find_ancestor_inside(value.span)
            .map(|span| (value.span.with_hi(span.lo()), value.span.with_lo(span.hi())));
        let keep_space = (
            left_pos.is_some_and(|s| s >= value.span.lo()),
            right_pos.is_some_and(|s| s <= value.span.hi()),
        );
        self.emit_unused_delims(cx, value.span, spans, ctx.into(), keep_space, is_kw);
    }

    fn emit_unused_delims(
        &self,
        cx: &EarlyContext<'_>,
        value_span: Span,
        spans: Option<(Span, Span)>,
        msg: &str,
        keep_space: (bool, bool),
        is_kw: bool,
    ) {
        let primary_span = if let Some((lo, hi)) = spans {
            if hi.is_empty() {
                // do not point at delims that do not exist
                return;
            }
            MultiSpan::from(vec![lo, hi])
        } else {
            MultiSpan::from(value_span)
        };
        let suggestion = spans.map(|(lo, hi)| {
            let sm = cx.sess().source_map();
            let lo_replace = if (keep_space.0 || is_kw)
                && let Ok(snip) = sm.span_to_prev_source(lo)
                && !snip.ends_with(' ')
            {
                " "
            } else {
                ""
            };

            let hi_replace = if keep_space.1
                && let Ok(snip) = sm.span_to_next_source(hi)
                && !snip.starts_with(' ')
            {
                " "
            } else {
                ""
            };
            UnusedDelimSuggestion {
                start_span: lo,
                start_replace: lo_replace,
                end_span: hi,
                end_replace: hi_replace,
            }
        });
        cx.emit_span_lint(
            self.lint(),
            primary_span,
            UnusedDelim { delim: Self::DELIM_STR, item: msg, suggestion },
        );
    }

    fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &ast::Expr) {
        use rustc_ast::ExprKind::*;
        let (value, ctx, followed_by_block, left_pos, right_pos, is_kw) = match e.kind {
            // Do not lint `unused_braces` in `if let` expressions.
            If(ref cond, ref block, _)
                if !matches!(cond.kind, Let(..)) || Self::LINT_EXPR_IN_PATTERN_MATCHING_CTX =>
            {
                let left = e.span.lo() + rustc_span::BytePos(2);
                let right = block.span.lo();
                (cond, UnusedDelimsCtx::IfCond, true, Some(left), Some(right), true)
            }

            // Do not lint `unused_braces` in `while let` expressions.
            While(ref cond, ref block, ..)
                if !matches!(cond.kind, Let(..)) || Self::LINT_EXPR_IN_PATTERN_MATCHING_CTX =>
            {
                let left = e.span.lo() + rustc_span::BytePos(5);
                let right = block.span.lo();
                (cond, UnusedDelimsCtx::WhileCond, true, Some(left), Some(right), true)
            }

            ForLoop { ref iter, ref body, .. } => {
                (iter, UnusedDelimsCtx::ForIterExpr, true, None, Some(body.span.lo()), true)
            }

            Match(ref head, _, ast::MatchKind::Prefix)
                if Self::LINT_EXPR_IN_PATTERN_MATCHING_CTX =>
            {
                let left = e.span.lo() + rustc_span::BytePos(5);
                (head, UnusedDelimsCtx::MatchScrutineeExpr, true, Some(left), None, true)
            }

            Ret(Some(ref value)) => {
                let left = e.span.lo() + rustc_span::BytePos(3);
                (value, UnusedDelimsCtx::ReturnValue, false, Some(left), None, true)
            }

            Break(_, Some(ref value)) => {
                (value, UnusedDelimsCtx::BreakValue, false, None, None, true)
            }

            Index(_, ref value, _) => (value, UnusedDelimsCtx::IndexExpr, false, None, None, false),

            Assign(_, ref value, _) | AssignOp(.., ref value) => {
                (value, UnusedDelimsCtx::AssignedValue, false, None, None, false)
            }
            // either function/method call, or something this lint doesn't care about
            ref call_or_other => {
                let (args_to_check, ctx) = match *call_or_other {
                    Call(_, ref args) => (&args[..], UnusedDelimsCtx::FunctionArg),
                    MethodCall(ref call) => (&call.args[..], UnusedDelimsCtx::MethodArg),
                    Closure(ref closure)
                        if matches!(closure.fn_decl.output, FnRetTy::Default(_)) =>
                    {
                        (&[closure.body.clone()][..], UnusedDelimsCtx::ClosureBody)
                    }
                    // actual catch-all arm
                    _ => {
                        return;
                    }
                };
                // Don't lint if this is a nested macro expansion: otherwise, the lint could
                // trigger in situations that macro authors shouldn't have to care about, e.g.,
                // when a parenthesized token tree matched in one macro expansion is matched as
                // an expression in another and used as a fn/method argument (Issue #47775)
                if e.span.ctxt().outer_expn_data().call_site.from_expansion() {
                    return;
                }
                for arg in args_to_check {
                    self.check_unused_delims_expr(cx, arg, ctx, false, None, None, false);
                }
                return;
            }
        };
        self.check_unused_delims_expr(
            cx,
            value,
            ctx,
            followed_by_block,
            left_pos,
            right_pos,
            is_kw,
        );
    }

    fn check_stmt(&mut self, cx: &EarlyContext<'_>, s: &ast::Stmt) {
        match s.kind {
            StmtKind::Let(ref local) if Self::LINT_EXPR_IN_PATTERN_MATCHING_CTX => {
                if let Some((init, els)) = local.kind.init_else_opt() {
                    if els.is_some()
                        && let ExprKind::Paren(paren) = &init.kind
                        && !init.span.eq_ctxt(paren.span)
                    {
                        // This branch prevents cases where parentheses wrap an expression
                        // resulting from macro expansion, such as:
                        // ```
                        // macro_rules! x {
                        // () => { None::<i32> };
                        // }
                        // let Some(_) = (x!{}) else { return };
                        // // -> let Some(_) = (None::<i32>) else { return };
                        // //                  ~           ~ No Lint
                        // ```
                        return;
                    }
                    let ctx = match els {
                        None => UnusedDelimsCtx::AssignedValue,
                        Some(_) => UnusedDelimsCtx::AssignedValueLetElse,
                    };
                    self.check_unused_delims_expr(cx, init, ctx, false, None, None, false);
                }
            }
            StmtKind::Expr(ref expr) => {
                self.check_unused_delims_expr(
                    cx,
                    expr,
                    UnusedDelimsCtx::BlockRetValue,
                    false,
                    None,
                    None,
                    false,
                );
            }
            _ => {}
        }
    }

    fn check_item(&mut self, cx: &EarlyContext<'_>, item: &ast::Item) {
        use ast::ItemKind::*;

        if let Const(box ast::ConstItem { expr: Some(expr), .. })
        | Static(box ast::StaticItem { expr: Some(expr), .. }) = &item.kind
        {
            self.check_unused_delims_expr(
                cx,
                expr,
                UnusedDelimsCtx::AssignedValue,
                false,
                None,
                None,
                false,
            );
        }
    }
}

declare_lint! {
    /// The `unused_parens` lint detects `if`, `match`, `while` and `return`
    /// with parentheses; they do not need them.
    ///
    /// ### Examples
    ///
    /// ```rust
    /// if(true) {}
    /// ```
    ///
    /// {{produces}}
    ///
    /// ### Explanation
    ///
    /// The parentheses are not needed, and should be removed. This is the
    /// preferred style for writing these expressions.
    pub(super) UNUSED_PARENS,
    Warn,
    "`if`, `match`, `while` and `return` do not need parentheses"
}

#[derive(Default)]
pub(crate) struct UnusedParens {
    with_self_ty_parens: bool,
    /// `1 as (i32) < 2` parses to ExprKind::Lt
    /// `1 as i32 < 2` parses to i32::<2[missing angle bracket]
    parens_in_cast_in_lt: Vec<ast::NodeId>,
    /// Ty nodes in this map are in TypeNoBounds position. Any bounds they
    /// contain may be ambiguous w/r/t trailing `+` operators.
    in_no_bounds_pos: FxHashMap<ast::NodeId, NoBoundsException>,
}

/// Whether parentheses may be omitted from a type without resulting in ambiguity.
///
/// ```
/// type Example = Box<dyn Fn() -> &'static (dyn Send) + Sync>;
/// ```
///
/// Here, `&'static (dyn Send) + Sync` is a `TypeNoBounds`. As such, it may not directly
/// contain `ImplTraitType` or `TraitObjectType` which is why `(dyn Send)` is parenthesized.
/// However, an exception is made for `ImplTraitTypeOneBound` and `TraitObjectTypeOneBound`.
/// The following is accepted because there is no `+`.
///
/// ```
/// type Example = Box<dyn Fn() -> &'static dyn Send>;
/// ```
enum NoBoundsException {
    /// The type must be parenthesized.
    None,
    /// The type is the last bound of the containing type expression. If it has exactly one bound,
    /// parentheses around the type are unnecessary.
    OneBound,
}

impl_lint_pass!(UnusedParens => [UNUSED_PARENS]);

impl UnusedDelimLint for UnusedParens {
    const DELIM_STR: &'static str = "parentheses";

    const LINT_EXPR_IN_PATTERN_MATCHING_CTX: bool = true;

    fn lint(&self) -> &'static Lint {
        UNUSED_PARENS
    }

    fn check_unused_delims_expr(
        &self,
        cx: &EarlyContext<'_>,
        value: &ast::Expr,
        ctx: UnusedDelimsCtx,
        followed_by_block: bool,
        left_pos: Option<BytePos>,
        right_pos: Option<BytePos>,
        is_kw: bool,
    ) {
        match value.kind {
            ast::ExprKind::Paren(ref inner) => {
                if !Self::is_expr_delims_necessary(inner, ctx, followed_by_block)
                    && value.attrs.is_empty()
                    && !value.span.from_expansion()
                    && (ctx != UnusedDelimsCtx::LetScrutineeExpr
                        || !matches!(inner.kind, ast::ExprKind::Binary(
                                rustc_span::source_map::Spanned { node, .. },
                                _,
                                _,
                            ) if node.is_lazy()))
                    && !((ctx == UnusedDelimsCtx::ReturnValue
                        || ctx == UnusedDelimsCtx::BreakValue)
                        && matches!(inner.kind, ast::ExprKind::Assign(_, _, _)))
                {
                    self.emit_unused_delims_expr(cx, value, ctx, left_pos, right_pos, is_kw)
                }
            }
            ast::ExprKind::Let(_, ref expr, _, _) => {
                self.check_unused_delims_expr(
                    cx,
                    expr,
                    UnusedDelimsCtx::LetScrutineeExpr,
                    followed_by_block,
                    None,
                    None,
                    false,
                );
            }
            _ => {}
        }
    }
}

impl UnusedParens {
    fn check_unused_parens_pat(
        &self,
        cx: &EarlyContext<'_>,
        value: &ast::Pat,
        avoid_or: bool,
        avoid_mut: bool,
        keep_space: (bool, bool),
    ) {
        use ast::{BindingMode, PatKind};

        if let PatKind::Paren(inner) = &value.kind {
            match inner.kind {
                // The lint visitor will visit each subpattern of `p`. We do not want to lint
                // any range pattern no matter where it occurs in the pattern. For something like
                // `&(a..=b)`, there is a recursive `check_pat` on `a` and `b`, but we will assume
                // that if there are unnecessary parens they serve a purpose of readability.
                PatKind::Range(..) => return,
                // Avoid `p0 | .. | pn` if we should.
                PatKind::Or(..) if avoid_or => return,
                // Avoid `mut x` and `mut x @ p` if we should:
                PatKind::Ident(BindingMode::MUT, ..) if avoid_mut => {
                    return;
                }
                // Otherwise proceed with linting.
                _ => {}
            }
            let spans = if !value.span.from_expansion() {
                inner
                    .span
                    .find_ancestor_inside(value.span)
                    .map(|inner| (value.span.with_hi(inner.lo()), value.span.with_lo(inner.hi())))
            } else {
                None
            };
            self.emit_unused_delims(cx, value.span, spans, "pattern", keep_space, false);
        }
    }

    fn cast_followed_by_lt(&self, expr: &ast::Expr) -> Option<ast::NodeId> {
        if let ExprKind::Binary(op, lhs, _rhs) = &expr.kind
            && (op.node == ast::BinOpKind::Lt || op.node == ast::BinOpKind::Shl)
        {
            let mut cur = lhs;
            while let ExprKind::Binary(_, _, rhs) = &cur.kind {
                cur = rhs;
            }

            if let ExprKind::Cast(_, ty) = &cur.kind
                && let ast::TyKind::Paren(_) = &ty.kind
            {
                return Some(ty.id);
            }
        }
        None
    }
}

impl EarlyLintPass for UnusedParens {
    #[inline]
    fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &ast::Expr) {
        if let Some(ty_id) = self.cast_followed_by_lt(e) {
            self.parens_in_cast_in_lt.push(ty_id);
        }

        match e.kind {
            ExprKind::Let(ref pat, _, _, _) | ExprKind::ForLoop { ref pat, .. } => {
                self.check_unused_parens_pat(cx, pat, false, false, (true, true));
            }
            // We ignore parens in cases like `if (((let Some(0) = Some(1))))` because we already
            // handle a hard error for them during AST lowering in `lower_expr_mut`, but we still
            // want to complain about things like `if let 42 = (42)`.
            ExprKind::If(ref cond, ref block, ref else_)
                if matches!(cond.peel_parens().kind, ExprKind::Let(..)) =>
            {
                self.check_unused_delims_expr(
                    cx,
                    cond.peel_parens(),
                    UnusedDelimsCtx::LetScrutineeExpr,
                    true,
                    None,
                    None,
                    true,
                );
                for stmt in &block.stmts {
                    <Self as UnusedDelimLint>::check_stmt(self, cx, stmt);
                }
                if let Some(e) = else_ {
                    <Self as UnusedDelimLint>::check_expr(self, cx, e);
                }
                return;
            }
            ExprKind::Match(ref _expr, ref arm, _) => {
                for a in arm {
                    if let Some(body) = &a.body {
                        self.check_unused_delims_expr(
                            cx,
                            body,
                            UnusedDelimsCtx::MatchArmExpr,
                            false,
                            None,
                            None,
                            true,
                        );
                    }
                }
            }
            _ => {}
        }

        <Self as UnusedDelimLint>::check_expr(self, cx, e)
    }

    fn check_expr_post(&mut self, _cx: &EarlyContext<'_>, e: &ast::Expr) {
        if let Some(ty_id) = self.cast_followed_by_lt(e) {
            let id = self
                .parens_in_cast_in_lt
                .pop()
                .expect("check_expr and check_expr_post must balance");
            assert_eq!(
                id, ty_id,
                "check_expr, check_ty, and check_expr_post are called, in that order, by the visitor"
            );
        }
    }

    fn check_pat(&mut self, cx: &EarlyContext<'_>, p: &ast::Pat) {
        use ast::Mutability;
        use ast::PatKind::*;
        let keep_space = (false, false);
        match &p.kind {
            // Do not lint on `(..)` as that will result in the other arms being useless.
            Paren(_)
            // The other cases do not contain sub-patterns.
            | Missing | Wild | Never | Rest | Expr(..) | MacCall(..) | Range(..) | Ident(.., None)
            | Path(..) | Err(_) => {},
            // These are list-like patterns; parens can always be removed.
            TupleStruct(_, _, ps) | Tuple(ps) | Slice(ps) | Or(ps) => for p in ps {
                self.check_unused_parens_pat(cx, p, false, false, keep_space);
            },
            Struct(_, _, fps, _) => for f in fps {
                self.check_unused_parens_pat(cx, &f.pat, false, false, keep_space);
            },
            // Avoid linting on `i @ (p0 | .. | pn)` and `box (p0 | .. | pn)`, #64106.
            Ident(.., Some(p)) | Box(p) | Deref(p) | Guard(p, _) => self.check_unused_parens_pat(cx, p, true, false, keep_space),
            // Avoid linting on `&(mut x)` as `&mut x` has a different meaning, #55342.
            // Also avoid linting on `& mut? (p0 | .. | pn)`, #64106.
            Ref(p, m) => self.check_unused_parens_pat(cx, p, true, *m == Mutability::Not, keep_space),
        }
    }

    fn check_stmt(&mut self, cx: &EarlyContext<'_>, s: &ast::Stmt) {
        if let StmtKind::Let(ref local) = s.kind {
            self.check_unused_parens_pat(cx, &local.pat, true, false, (true, false));
        }

        <Self as UnusedDelimLint>::check_stmt(self, cx, s)
    }

    fn check_param(&mut self, cx: &EarlyContext<'_>, param: &ast::Param) {
        self.check_unused_parens_pat(cx, &param.pat, true, false, (false, false));
    }

    fn check_arm(&mut self, cx: &EarlyContext<'_>, arm: &ast::Arm) {
        self.check_unused_parens_pat(cx, &arm.pat, false, false, (false, false));
    }

    fn check_ty(&mut self, cx: &EarlyContext<'_>, ty: &ast::Ty) {
        if let ast::TyKind::Paren(_) = ty.kind
            && Some(&ty.id) == self.parens_in_cast_in_lt.last()
        {
            return;
        }
        match &ty.kind {
            ast::TyKind::Array(_, len) => {
                self.check_unused_delims_expr(
                    cx,
                    &len.value,
                    UnusedDelimsCtx::ArrayLenExpr,
                    false,
                    None,
                    None,
                    false,
                );
            }
            ast::TyKind::Paren(r) => {
                let unused_parens = match &r.kind {
                    ast::TyKind::ImplTrait(_, bounds) | ast::TyKind::TraitObject(bounds, _) => {
                        match self.in_no_bounds_pos.get(&ty.id) {
                            Some(NoBoundsException::None) => false,
                            Some(NoBoundsException::OneBound) => bounds.len() <= 1,
                            None => true,
                        }
                    }
                    ast::TyKind::FnPtr(b) => {
                        !self.with_self_ty_parens || b.generic_params.is_empty()
                    }
                    _ => true,
                };

                if unused_parens {
                    let spans = (!ty.span.from_expansion())
                        .then(|| {
                            r.span
                                .find_ancestor_inside(ty.span)
                                .map(|r| (ty.span.with_hi(r.lo()), ty.span.with_lo(r.hi())))
                        })
                        .flatten();

                    self.emit_unused_delims(cx, ty.span, spans, "type", (false, false), false);
                }

                self.with_self_ty_parens = false;
            }
            ast::TyKind::Ref(_, mut_ty) | ast::TyKind::Ptr(mut_ty) => {
                // If this type itself appears in no-bounds position, we propagate its
                // potentially tighter constraint or risk a false posive (issue 143653).
                let own_constraint = self.in_no_bounds_pos.get(&ty.id);
                let constraint = match own_constraint {
                    Some(NoBoundsException::None) => NoBoundsException::None,
                    Some(NoBoundsException::OneBound) => NoBoundsException::OneBound,
                    None => NoBoundsException::OneBound,
                };
                self.in_no_bounds_pos.insert(mut_ty.ty.id, constraint);
            }
            ast::TyKind::TraitObject(bounds, _) | ast::TyKind::ImplTrait(_, bounds) => {
                for i in 0..bounds.len() {
                    let is_last = i == bounds.len() - 1;

                    if let ast::GenericBound::Trait(poly_trait_ref) = &bounds[i] {
                        let fn_with_explicit_ret_ty = if let [.., segment] =
                            &*poly_trait_ref.trait_ref.path.segments
                            && let Some(args) = segment.args.as_ref()
                            && let ast::GenericArgs::Parenthesized(paren_args) = &**args
                            && let ast::FnRetTy::Ty(ret_ty) = &paren_args.output
                        {
                            self.in_no_bounds_pos.insert(
                                ret_ty.id,
                                if is_last {
                                    NoBoundsException::OneBound
                                } else {
                                    NoBoundsException::None
                                },
                            );

                            true
                        } else {
                            false
                        };

                        // In edition 2015, dyn is a contextual keyword and `dyn::foo::Bar` is
                        // parsed as a path, so parens are necessary to disambiguate. See
                        //  - tests/ui/lint/unused/unused-parens-trait-obj-e2015.rs and
                        //  - https://doc.rust-lang.org/reference/types/trait-object.html#r-type.trait-object.syntax-edition2018
                        let dyn2015_exception = cx.sess().psess.edition == Edition2015
                            && matches!(ty.kind, ast::TyKind::TraitObject(..))
                            && i == 0
                            && poly_trait_ref
                                .trait_ref
                                .path
                                .segments
                                .first()
                                .map(|s| s.ident.name == kw::PathRoot)
                                .unwrap_or(false);

                        if let ast::Parens::Yes = poly_trait_ref.parens
                            && (is_last || !fn_with_explicit_ret_ty)
                            && !dyn2015_exception
                        {
                            let s = poly_trait_ref.span;
                            let spans = (!s.from_expansion()).then(|| {
                                (
                                    s.with_hi(s.lo() + rustc_span::BytePos(1)),
                                    s.with_lo(s.hi() - rustc_span::BytePos(1)),
                                )
                            });

                            self.emit_unused_delims(
                                cx,
                                poly_trait_ref.span,
                                spans,
                                "type",
                                (false, false),
                                false,
                            );
                        }
                    }
                }
            }
            _ => {}
        }
    }

    fn check_item(&mut self, cx: &EarlyContext<'_>, item: &ast::Item) {
        <Self as UnusedDelimLint>::check_item(self, cx, item)
    }

    fn check_item_post(&mut self, _: &EarlyContext<'_>, _: &rustc_ast::Item) {
        self.in_no_bounds_pos.clear();
    }

    fn enter_where_predicate(&mut self, _: &EarlyContext<'_>, pred: &ast::WherePredicate) {
        use rustc_ast::{WhereBoundPredicate, WherePredicateKind};
        if let WherePredicateKind::BoundPredicate(WhereBoundPredicate {
            bounded_ty,
            bound_generic_params,
            ..
        }) = &pred.kind
            && let ast::TyKind::Paren(_) = &bounded_ty.kind
            && bound_generic_params.is_empty()
        {
            self.with_self_ty_parens = true;
        }
    }

    fn exit_where_predicate(&mut self, _: &EarlyContext<'_>, _: &ast::WherePredicate) {
        assert!(!self.with_self_ty_parens);
    }
}

declare_lint! {
    /// The `unused_braces` lint detects unnecessary braces around an
    /// expression.
    ///
    /// ### Example
    ///
    /// ```rust
    /// if { true } {
    ///     // ...
    /// }
    /// ```
    ///
    /// {{produces}}
    ///
    /// ### Explanation
    ///
    /// The braces are not needed, and should be removed. This is the
    /// preferred style for writing these expressions.
    pub(super) UNUSED_BRACES,
    Warn,
    "unnecessary braces around an expression"
}

declare_lint_pass!(UnusedBraces => [UNUSED_BRACES]);

impl UnusedDelimLint for UnusedBraces {
    const DELIM_STR: &'static str = "braces";

    const LINT_EXPR_IN_PATTERN_MATCHING_CTX: bool = false;

    fn lint(&self) -> &'static Lint {
        UNUSED_BRACES
    }

    fn check_unused_delims_expr(
        &self,
        cx: &EarlyContext<'_>,
        value: &ast::Expr,
        ctx: UnusedDelimsCtx,
        followed_by_block: bool,
        left_pos: Option<BytePos>,
        right_pos: Option<BytePos>,
        is_kw: bool,
    ) {
        match value.kind {
            ast::ExprKind::Block(ref inner, None)
                if inner.rules == ast::BlockCheckMode::Default =>
            {
                // emit a warning under the following conditions:
                //
                // - the block does not have a label
                // - the block is not `unsafe`
                // - the block contains exactly one expression (do not lint `{ expr; }`)
                // - `followed_by_block` is true and the internal expr may contain a `{`
                // - the block is not multiline (do not lint multiline match arms)
                //      ```
                //      match expr {
                //          Pattern => {
                //              somewhat_long_expression
                //          }
                //          // ...
                //      }
                //      ```
                // - the block has no attribute and was not created inside a macro
                // - if the block is an `anon_const`, the inner expr must be a literal
                //   not created by a macro, i.e. do not lint on:
                //      ```
                //      struct A<const N: usize>;
                //      let _: A<{ 2 + 3 }>;
                //      let _: A<{produces_literal!()}>;
                //      ```
                // FIXME(const_generics): handle paths when #67075 is fixed.
                if let [stmt] = inner.stmts.as_slice()
                    && let ast::StmtKind::Expr(ref expr) = stmt.kind
                    && !Self::is_expr_delims_necessary(expr, ctx, followed_by_block)
                    && (ctx != UnusedDelimsCtx::AnonConst
                        || (matches!(expr.kind, ast::ExprKind::Lit(_))
                            && !expr.span.from_expansion()))
                    && ctx != UnusedDelimsCtx::ClosureBody
                    && !cx.sess().source_map().is_multiline(value.span)
                    && value.attrs.is_empty()
                    && !value.span.from_expansion()
                    && !inner.span.from_expansion()
                {
                    self.emit_unused_delims_expr(cx, value, ctx, left_pos, right_pos, is_kw)
                }
            }
            ast::ExprKind::Let(_, ref expr, _, _) => {
                self.check_unused_delims_expr(
                    cx,
                    expr,
                    UnusedDelimsCtx::LetScrutineeExpr,
                    followed_by_block,
                    None,
                    None,
                    false,
                );
            }
            _ => {}
        }
    }
}

impl EarlyLintPass for UnusedBraces {
    fn check_stmt(&mut self, cx: &EarlyContext<'_>, s: &ast::Stmt) {
        <Self as UnusedDelimLint>::check_stmt(self, cx, s)
    }

    #[inline]
    fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &ast::Expr) {
        <Self as UnusedDelimLint>::check_expr(self, cx, e);

        if let ExprKind::Repeat(_, ref anon_const) = e.kind {
            self.check_unused_delims_expr(
                cx,
                &anon_const.value,
                UnusedDelimsCtx::AnonConst,
                false,
                None,
                None,
                false,
            );
        }
    }

    fn check_generic_arg(&mut self, cx: &EarlyContext<'_>, arg: &ast::GenericArg) {
        if let ast::GenericArg::Const(ct) = arg {
            self.check_unused_delims_expr(
                cx,
                &ct.value,
                UnusedDelimsCtx::AnonConst,
                false,
                None,
                None,
                false,
            );
        }
    }

    fn check_variant(&mut self, cx: &EarlyContext<'_>, v: &ast::Variant) {
        if let Some(anon_const) = &v.disr_expr {
            self.check_unused_delims_expr(
                cx,
                &anon_const.value,
                UnusedDelimsCtx::AnonConst,
                false,
                None,
                None,
                false,
            );
        }
    }

    fn check_ty(&mut self, cx: &EarlyContext<'_>, ty: &ast::Ty) {
        match ty.kind {
            ast::TyKind::Array(_, ref len) => {
                self.check_unused_delims_expr(
                    cx,
                    &len.value,
                    UnusedDelimsCtx::ArrayLenExpr,
                    false,
                    None,
                    None,
                    false,
                );
            }

            ast::TyKind::Typeof(ref anon_const) => {
                self.check_unused_delims_expr(
                    cx,
                    &anon_const.value,
                    UnusedDelimsCtx::AnonConst,
                    false,
                    None,
                    None,
                    false,
                );
            }

            _ => {}
        }
    }

    fn check_item(&mut self, cx: &EarlyContext<'_>, item: &ast::Item) {
        <Self as UnusedDelimLint>::check_item(self, cx, item)
    }
}

declare_lint! {
    /// The `unused_import_braces` lint catches unnecessary braces around an
    /// imported item.
    ///
    /// ### Example
    ///
    /// ```rust,compile_fail
    /// #![deny(unused_import_braces)]
    /// use test::{A};
    ///
    /// pub mod test {
    ///     pub struct A;
    /// }
    /// # fn main() {}
    /// ```
    ///
    /// {{produces}}
    ///
    /// ### Explanation
    ///
    /// If there is only a single item, then remove the braces (`use test::A;`
    /// for example).
    ///
    /// This lint is "allow" by default because it is only enforcing a
    /// stylistic choice.
    UNUSED_IMPORT_BRACES,
    Allow,
    "unnecessary braces around an imported item"
}

declare_lint_pass!(UnusedImportBraces => [UNUSED_IMPORT_BRACES]);

impl UnusedImportBraces {
    fn check_use_tree(&self, cx: &EarlyContext<'_>, use_tree: &ast::UseTree, item: &ast::Item) {
        if let ast::UseTreeKind::Nested { ref items, .. } = use_tree.kind {
            // Recursively check nested UseTrees
            for (tree, _) in items {
                self.check_use_tree(cx, tree, item);
            }

            // Trigger the lint only if there is one nested item
            let [(tree, _)] = items.as_slice() else { return };

            // Trigger the lint if the nested item is a non-self single item
            let node_name = match tree.kind {
                ast::UseTreeKind::Simple(rename) => {
                    let orig_ident = tree.prefix.segments.last().unwrap().ident;
                    if orig_ident.name == kw::SelfLower {
                        return;
                    }
                    rename.unwrap_or(orig_ident).name
                }
                ast::UseTreeKind::Glob => sym::asterisk,
                ast::UseTreeKind::Nested { .. } => return,
            };

            cx.emit_span_lint(
                UNUSED_IMPORT_BRACES,
                item.span,
                UnusedImportBracesDiag { node: node_name },
            );
        }
    }
}

impl EarlyLintPass for UnusedImportBraces {
    fn check_item(&mut self, cx: &EarlyContext<'_>, item: &ast::Item) {
        if let ast::ItemKind::Use(ref use_tree) = item.kind {
            self.check_use_tree(cx, use_tree, item);
        }
    }
}

declare_lint! {
    /// The `unused_allocation` lint detects unnecessary allocations that can
    /// be eliminated.
    ///
    /// ### Example
    ///
    /// ```rust
    /// fn main() {
    ///     let a = Box::new([1, 2, 3]).len();
    /// }
    /// ```
    ///
    /// {{produces}}
    ///
    /// ### Explanation
    ///
    /// When a `box` expression is immediately coerced to a reference, then
    /// the allocation is unnecessary, and a reference (using `&` or `&mut`)
    /// should be used instead to avoid the allocation.
    pub(super) UNUSED_ALLOCATION,
    Warn,
    "detects unnecessary allocations that can be eliminated"
}

declare_lint_pass!(UnusedAllocation => [UNUSED_ALLOCATION]);

impl<'tcx> LateLintPass<'tcx> for UnusedAllocation {
    fn check_expr(&mut self, cx: &LateContext<'_>, e: &hir::Expr<'_>) {
        match e.kind {
            hir::ExprKind::Call(path_expr, [_])
                if let hir::ExprKind::Path(qpath) = &path_expr.kind
                    && let Some(did) = cx.qpath_res(qpath, path_expr.hir_id).opt_def_id()
                    && cx.tcx.is_diagnostic_item(sym::box_new, did) => {}
            _ => return,
        }

        for adj in cx.typeck_results().expr_adjustments(e) {
            if let adjustment::Adjust::Borrow(adjustment::AutoBorrow::Ref(m)) = adj.kind {
                match m {
                    adjustment::AutoBorrowMutability::Not => {
                        cx.emit_span_lint(UNUSED_ALLOCATION, e.span, UnusedAllocationDiag);
                    }
                    adjustment::AutoBorrowMutability::Mut { .. } => {
                        cx.emit_span_lint(UNUSED_ALLOCATION, e.span, UnusedAllocationMutDiag);
                    }
                };
            }
        }
    }
}
