Skip to main content

rustc_lint/
unused.rs

1use std::iter;
2
3use rustc_ast::util::{classify, parser};
4use rustc_ast::{self as ast, ExprKind, FnRetTy, HasAttrs as _, StmtKind};
5use rustc_data_structures::fx::FxHashMap;
6use rustc_errors::{MultiSpan, pluralize};
7use rustc_hir::def::{DefKind, Res};
8use rustc_hir::def_id::DefId;
9use rustc_hir::{self as hir, LangItem, find_attr};
10use rustc_infer::traits::util::elaborate;
11use rustc_middle::ty::{self, Ty, adjustment};
12use rustc_session::{declare_lint, declare_lint_pass, impl_lint_pass};
13use rustc_span::edition::Edition::Edition2015;
14use rustc_span::{BytePos, Span, Symbol, kw, sym};
15use tracing::instrument;
16
17use crate::lints::{
18    PathStatementDrop, PathStatementDropSub, PathStatementNoEffect, UnusedAllocationDiag,
19    UnusedAllocationMutDiag, UnusedClosure, UnusedCoroutine, UnusedDef, UnusedDefSuggestion,
20    UnusedDelim, UnusedDelimSuggestion, UnusedImportBracesDiag, UnusedOp, UnusedOpSuggestion,
21    UnusedResult,
22};
23use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, Lint, LintContext};
24
25#[doc =
r" The `unused_must_use` lint detects unused result of a type flagged as"]
#[doc = r" `#[must_use]`."]
#[doc = r""]
#[doc = r" ### Example"]
#[doc = r""]
#[doc = r" ```rust"]
#[doc = r" fn returns_result() -> Result<(), ()> {"]
#[doc = r"     Ok(())"]
#[doc = r" }"]
#[doc = r""]
#[doc = r" fn main() {"]
#[doc = r"     returns_result();"]
#[doc = r" }"]
#[doc = r" ```"]
#[doc = r""]
#[doc = r" {{produces}}"]
#[doc = r""]
#[doc = r" ### Explanation"]
#[doc = r""]
#[doc =
r" The `#[must_use]` attribute is an indicator that it is a mistake to"]
#[doc = r" ignore the value. See [the reference] for more details."]
#[doc = r""]
#[doc =
r" [the reference]: https://doc.rust-lang.org/reference/attributes/diagnostics.html#the-must_use-attribute"]
pub static UNUSED_MUST_USE: &::rustc_lint_defs::Lint =
    &::rustc_lint_defs::Lint {
            name: "UNUSED_MUST_USE",
            default_level: ::rustc_lint_defs::Warn,
            desc: "unused result of a type flagged as `#[must_use]`",
            is_externally_loaded: false,
            report_in_external_macro: true,
            ..::rustc_lint_defs::Lint::default_fields_for_macro()
        };declare_lint! {
26    /// The `unused_must_use` lint detects unused result of a type flagged as
27    /// `#[must_use]`.
28    ///
29    /// ### Example
30    ///
31    /// ```rust
32    /// fn returns_result() -> Result<(), ()> {
33    ///     Ok(())
34    /// }
35    ///
36    /// fn main() {
37    ///     returns_result();
38    /// }
39    /// ```
40    ///
41    /// {{produces}}
42    ///
43    /// ### Explanation
44    ///
45    /// The `#[must_use]` attribute is an indicator that it is a mistake to
46    /// ignore the value. See [the reference] for more details.
47    ///
48    /// [the reference]: https://doc.rust-lang.org/reference/attributes/diagnostics.html#the-must_use-attribute
49    pub UNUSED_MUST_USE,
50    Warn,
51    "unused result of a type flagged as `#[must_use]`",
52    report_in_external_macro
53}
54
55#[doc = r" The `unused_results` lint checks for the unused result of an"]
#[doc = r" expression in a statement."]
#[doc = r""]
#[doc = r" ### Example"]
#[doc = r""]
#[doc = r" ```rust,compile_fail"]
#[doc = r" #![deny(unused_results)]"]
#[doc = r" fn foo<T>() -> T { panic!() }"]
#[doc = r""]
#[doc = r" fn main() {"]
#[doc = r"     foo::<usize>();"]
#[doc = r" }"]
#[doc = r" ```"]
#[doc = r""]
#[doc = r" {{produces}}"]
#[doc = r""]
#[doc = r" ### Explanation"]
#[doc = r""]
#[doc =
r" Ignoring the return value of a function may indicate a mistake. In"]
#[doc =
r" cases were it is almost certain that the result should be used, it is"]
#[doc =
r" recommended to annotate the function with the [`must_use` attribute]."]
#[doc =
r" Failure to use such a return value will trigger the [`unused_must_use`"]
#[doc = r" lint] which is warn-by-default. The `unused_results` lint is"]
#[doc = r" essentially the same, but triggers for *all* return values."]
#[doc = r""]
#[doc =
r#" This lint is "allow" by default because it can be noisy, and may not be"#]
#[doc =
r" an actual problem. For example, calling the `remove` method of a `Vec`"]
#[doc =
r" or `HashMap` returns the previous value, which you may not care about."]
#[doc =
r" Using this lint would require explicitly ignoring or discarding such"]
#[doc = r" values."]
#[doc = r""]
#[doc =
r" [`must_use` attribute]: https://doc.rust-lang.org/reference/attributes/diagnostics.html#the-must_use-attribute"]
#[doc = r" [`unused_must_use` lint]: warn-by-default.html#unused-must-use"]
pub static UNUSED_RESULTS: &::rustc_lint_defs::Lint =
    &::rustc_lint_defs::Lint {
            name: "UNUSED_RESULTS",
            default_level: ::rustc_lint_defs::Allow,
            desc: "unused result of an expression in a statement",
            is_externally_loaded: false,
            ..::rustc_lint_defs::Lint::default_fields_for_macro()
        };declare_lint! {
56    /// The `unused_results` lint checks for the unused result of an
57    /// expression in a statement.
58    ///
59    /// ### Example
60    ///
61    /// ```rust,compile_fail
62    /// #![deny(unused_results)]
63    /// fn foo<T>() -> T { panic!() }
64    ///
65    /// fn main() {
66    ///     foo::<usize>();
67    /// }
68    /// ```
69    ///
70    /// {{produces}}
71    ///
72    /// ### Explanation
73    ///
74    /// Ignoring the return value of a function may indicate a mistake. In
75    /// cases were it is almost certain that the result should be used, it is
76    /// recommended to annotate the function with the [`must_use` attribute].
77    /// Failure to use such a return value will trigger the [`unused_must_use`
78    /// lint] which is warn-by-default. The `unused_results` lint is
79    /// essentially the same, but triggers for *all* return values.
80    ///
81    /// This lint is "allow" by default because it can be noisy, and may not be
82    /// an actual problem. For example, calling the `remove` method of a `Vec`
83    /// or `HashMap` returns the previous value, which you may not care about.
84    /// Using this lint would require explicitly ignoring or discarding such
85    /// values.
86    ///
87    /// [`must_use` attribute]: https://doc.rust-lang.org/reference/attributes/diagnostics.html#the-must_use-attribute
88    /// [`unused_must_use` lint]: warn-by-default.html#unused-must-use
89    pub UNUSED_RESULTS,
90    Allow,
91    "unused result of an expression in a statement"
92}
93
94pub struct UnusedResults;
#[automatically_derived]
impl ::core::marker::Copy for UnusedResults { }
#[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for UnusedResults { }
#[automatically_derived]
impl ::core::clone::Clone for UnusedResults {
    #[inline]
    fn clone(&self) -> UnusedResults { *self }
}
impl ::rustc_lint_defs::LintPass for UnusedResults {
    fn name(&self) -> &'static str { "UnusedResults" }
    fn get_lints(&self) -> ::rustc_lint_defs::LintVec {
        ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
                [UNUSED_MUST_USE, UNUSED_RESULTS]))
    }
}
impl UnusedResults {
    #[allow(unused)]
    pub fn lint_vec() -> ::rustc_lint_defs::LintVec {
        ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
                [UNUSED_MUST_USE, UNUSED_RESULTS]))
    }
}declare_lint_pass!(UnusedResults => [UNUSED_MUST_USE, UNUSED_RESULTS]);
95
96impl<'tcx> LateLintPass<'tcx> for UnusedResults {
97    fn check_stmt(&mut self, cx: &LateContext<'_>, s: &hir::Stmt<'_>) {
98        let hir::StmtKind::Semi(mut expr) = s.kind else {
99            return;
100        };
101
102        let mut expr_is_from_block = false;
103        while let hir::ExprKind::Block(blk, ..) = expr.kind
104            && let hir::Block { expr: Some(e), .. } = blk
105        {
106            expr = e;
107            expr_is_from_block = true;
108        }
109
110        if let hir::ExprKind::Ret(..) = expr.kind {
111            return;
112        }
113
114        if let hir::ExprKind::Match(await_expr, _arms, hir::MatchSource::AwaitDesugar) = expr.kind
115            && let ty = cx.typeck_results().expr_ty(await_expr)
116            && let ty::Alias(ty::Opaque, ty::AliasTy { def_id: future_def_id, .. }) = ty.kind()
117            && cx.tcx.ty_is_opaque_future(ty)
118            && let async_fn_def_id = cx.tcx.parent(*future_def_id)
119            && #[allow(non_exhaustive_omitted_patterns)] match cx.tcx.def_kind(async_fn_def_id)
    {
    DefKind::Fn | DefKind::AssocFn => true,
    _ => false,
}matches!(cx.tcx.def_kind(async_fn_def_id), DefKind::Fn | DefKind::AssocFn)
120            // Check that this `impl Future` actually comes from an `async fn`
121            && cx.tcx.asyncness(async_fn_def_id).is_async()
122            && check_must_use_def(
123                cx,
124                async_fn_def_id,
125                expr.span,
126                "output of future returned by ",
127                "",
128                expr_is_from_block,
129            )
130        {
131            // We have a bare `foo().await;` on an opaque type from an async function that was
132            // annotated with `#[must_use]`.
133            return;
134        }
135
136        let ty = cx.typeck_results().expr_ty(expr);
137
138        let must_use_result = is_ty_must_use(cx, ty, expr, expr.span);
139        let type_lint_emitted_or_suppressed = match must_use_result {
140            Some(path) => {
141                emit_must_use_untranslated(cx, &path, "", "", 1, false, expr_is_from_block);
142                true
143            }
144            None => false,
145        };
146
147        let fn_warned = check_fn_must_use(cx, expr, expr_is_from_block);
148
149        if !fn_warned && type_lint_emitted_or_suppressed {
150            // We don't warn about unused unit or uninhabited types.
151            // (See https://github.com/rust-lang/rust/issues/43806 for details.)
152            return;
153        }
154
155        let must_use_op = match expr.kind {
156            // Hardcoding operators here seemed more expedient than the
157            // refactoring that would be needed to look up the `#[must_use]`
158            // attribute which does exist on the comparison trait methods
159            hir::ExprKind::Binary(bin_op, ..) => match bin_op.node {
160                hir::BinOpKind::Eq
161                | hir::BinOpKind::Lt
162                | hir::BinOpKind::Le
163                | hir::BinOpKind::Ne
164                | hir::BinOpKind::Ge
165                | hir::BinOpKind::Gt => Some("comparison"),
166                hir::BinOpKind::Add
167                | hir::BinOpKind::Sub
168                | hir::BinOpKind::Div
169                | hir::BinOpKind::Mul
170                | hir::BinOpKind::Rem => Some("arithmetic operation"),
171                hir::BinOpKind::And | hir::BinOpKind::Or => Some("logical operation"),
172                hir::BinOpKind::BitXor
173                | hir::BinOpKind::BitAnd
174                | hir::BinOpKind::BitOr
175                | hir::BinOpKind::Shl
176                | hir::BinOpKind::Shr => Some("bitwise operation"),
177            },
178            hir::ExprKind::AddrOf(..) => Some("borrow"),
179            hir::ExprKind::OffsetOf(..) => Some("`offset_of` call"),
180            hir::ExprKind::Unary(..) => Some("unary operation"),
181            // The `offset_of` macro wraps its contents inside a `const` block.
182            hir::ExprKind::ConstBlock(block) => {
183                let body = cx.tcx.hir_body(block.body);
184                if let hir::ExprKind::Block(block, _) = body.value.kind
185                    && let Some(expr) = block.expr
186                    && let hir::ExprKind::OffsetOf(..) = expr.kind
187                {
188                    Some("`offset_of` call")
189                } else {
190                    None
191                }
192            }
193            _ => None,
194        };
195
196        let mut op_warned = false;
197
198        if let Some(must_use_op) = must_use_op {
199            let span = expr.span.find_ancestor_not_from_macro().unwrap_or(expr.span);
200            cx.emit_span_lint(
201                UNUSED_MUST_USE,
202                expr.span,
203                UnusedOp {
204                    op: must_use_op,
205                    label: expr.span,
206                    suggestion: if expr_is_from_block {
207                        UnusedOpSuggestion::BlockTailExpr {
208                            before_span: span.shrink_to_lo(),
209                            after_span: span.shrink_to_hi(),
210                        }
211                    } else {
212                        UnusedOpSuggestion::NormalExpr { span: span.shrink_to_lo() }
213                    },
214                },
215            );
216            op_warned = true;
217        }
218
219        if !(type_lint_emitted_or_suppressed || fn_warned || op_warned) {
220            cx.emit_span_lint(UNUSED_RESULTS, s.span, UnusedResult { ty });
221        }
222
223        fn check_fn_must_use(
224            cx: &LateContext<'_>,
225            expr: &hir::Expr<'_>,
226            expr_is_from_block: bool,
227        ) -> bool {
228            let maybe_def_id = match expr.kind {
229                hir::ExprKind::Call(callee, _) => {
230                    match callee.kind {
231                        hir::ExprKind::Path(ref qpath) => {
232                            match cx.qpath_res(qpath, callee.hir_id) {
233                                Res::Def(DefKind::Fn | DefKind::AssocFn, def_id) => Some(def_id),
234                                // `Res::Local` if it was a closure, for which we
235                                // do not currently support must-use linting
236                                _ => None,
237                            }
238                        }
239                        _ => None,
240                    }
241                }
242                hir::ExprKind::MethodCall(..) => {
243                    cx.typeck_results().type_dependent_def_id(expr.hir_id)
244                }
245                _ => None,
246            };
247            if let Some(def_id) = maybe_def_id {
248                check_must_use_def(
249                    cx,
250                    def_id,
251                    expr.span,
252                    "return value of ",
253                    "",
254                    expr_is_from_block,
255                )
256            } else {
257                false
258            }
259        }
260
261        /// A path through a type to a must_use source. Contains useful info for the lint.
262        #[derive(#[automatically_derived]
impl ::core::fmt::Debug for MustUsePath {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            MustUsePath::Suppressed =>
                ::core::fmt::Formatter::write_str(f, "Suppressed"),
            MustUsePath::Def(__self_0, __self_1, __self_2) =>
                ::core::fmt::Formatter::debug_tuple_field3_finish(f, "Def",
                    __self_0, __self_1, &__self_2),
            MustUsePath::Boxed(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Boxed",
                    &__self_0),
            MustUsePath::Pinned(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Pinned",
                    &__self_0),
            MustUsePath::Opaque(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Opaque",
                    &__self_0),
            MustUsePath::TraitObject(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "TraitObject", &__self_0),
            MustUsePath::TupleElement(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "TupleElement", &__self_0),
            MustUsePath::Array(__self_0, __self_1) =>
                ::core::fmt::Formatter::debug_tuple_field2_finish(f, "Array",
                    __self_0, &__self_1),
            MustUsePath::Closure(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "Closure", &__self_0),
            MustUsePath::Coroutine(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "Coroutine", &__self_0),
        }
    }
}Debug)]
263        enum MustUsePath {
264            /// Suppress must_use checking.
265            Suppressed,
266            /// The root of the normal must_use lint with an optional message.
267            Def(Span, DefId, Option<Symbol>),
268            Boxed(Box<Self>),
269            Pinned(Box<Self>),
270            Opaque(Box<Self>),
271            TraitObject(Box<Self>),
272            TupleElement(Vec<(usize, Self)>),
273            Array(Box<Self>, u64),
274            /// The root of the unused_closures lint.
275            Closure(Span),
276            /// The root of the unused_coroutines lint.
277            Coroutine(Span),
278        }
279
280        x;#[instrument(skip(cx, expr), level = "debug", ret)]
281        fn is_ty_must_use<'tcx>(
282            cx: &LateContext<'tcx>,
283            ty: Ty<'tcx>,
284            expr: &hir::Expr<'_>,
285            span: Span,
286        ) -> Option<MustUsePath> {
287            if ty.is_unit() {
288                return Some(MustUsePath::Suppressed);
289            }
290            let parent_mod_did = cx.tcx.parent_module(expr.hir_id).to_def_id();
291            let is_uninhabited =
292                |t: Ty<'tcx>| !t.is_inhabited_from(cx.tcx, parent_mod_did, cx.typing_env());
293            if is_uninhabited(ty) {
294                return Some(MustUsePath::Suppressed);
295            }
296
297            match *ty.kind() {
298                ty::Adt(..) if let Some(boxed) = ty.boxed_ty() => {
299                    is_ty_must_use(cx, boxed, expr, span)
300                        .map(|inner| MustUsePath::Boxed(Box::new(inner)))
301                }
302                ty::Adt(def, args) if cx.tcx.is_lang_item(def.did(), LangItem::Pin) => {
303                    let pinned_ty = args.type_at(0);
304                    is_ty_must_use(cx, pinned_ty, expr, span)
305                        .map(|inner| MustUsePath::Pinned(Box::new(inner)))
306                }
307                // Suppress warnings on `Result<(), Uninhabited>` (e.g. `Result<(), !>`).
308                ty::Adt(def, args)
309                    if cx.tcx.is_diagnostic_item(sym::Result, def.did())
310                        && args.type_at(0).is_unit()
311                        && is_uninhabited(args.type_at(1)) =>
312                {
313                    Some(MustUsePath::Suppressed)
314                }
315                // Suppress warnings on `ControlFlow<Uninhabited, ()>` (e.g. `ControlFlow<!, ()>`).
316                ty::Adt(def, args)
317                    if cx.tcx.is_diagnostic_item(sym::ControlFlow, def.did())
318                        && args.type_at(1).is_unit()
319                        && is_uninhabited(args.type_at(0)) =>
320                {
321                    Some(MustUsePath::Suppressed)
322                }
323                ty::Adt(def, _) => is_def_must_use(cx, def.did(), span),
324                ty::Alias(ty::Opaque | ty::Projection, ty::AliasTy { def_id: def, .. }) => {
325                    elaborate(cx.tcx, cx.tcx.explicit_item_self_bounds(def).iter_identity_copied())
326                        // We only care about self bounds for the impl-trait
327                        .filter_only_self()
328                        .find_map(|(pred, _span)| {
329                            // We only look at the `DefId`, so it is safe to skip the binder here.
330                            if let ty::ClauseKind::Trait(ref poly_trait_predicate) =
331                                pred.kind().skip_binder()
332                            {
333                                let def_id = poly_trait_predicate.trait_ref.def_id;
334
335                                is_def_must_use(cx, def_id, span)
336                            } else {
337                                None
338                            }
339                        })
340                        .map(|inner| MustUsePath::Opaque(Box::new(inner)))
341                }
342                ty::Dynamic(binders, _) => binders.iter().find_map(|predicate| {
343                    if let ty::ExistentialPredicate::Trait(ref trait_ref) = predicate.skip_binder()
344                    {
345                        let def_id = trait_ref.def_id;
346                        is_def_must_use(cx, def_id, span)
347                            .map(|inner| MustUsePath::TraitObject(Box::new(inner)))
348                    } else {
349                        None
350                    }
351                }),
352                ty::Tuple(tys) => {
353                    let elem_exprs = if let hir::ExprKind::Tup(elem_exprs) = expr.kind {
354                        debug_assert_eq!(elem_exprs.len(), tys.len());
355                        elem_exprs
356                    } else {
357                        &[]
358                    };
359
360                    // Default to `expr`.
361                    let elem_exprs = elem_exprs.iter().chain(iter::repeat(expr));
362
363                    let nested_must_use = tys
364                        .iter()
365                        .zip(elem_exprs)
366                        .enumerate()
367                        .filter_map(|(i, (ty, expr))| {
368                            is_ty_must_use(cx, ty, expr, expr.span).map(|path| (i, path))
369                        })
370                        .collect::<Vec<_>>();
371
372                    if !nested_must_use.is_empty() {
373                        Some(MustUsePath::TupleElement(nested_must_use))
374                    } else {
375                        None
376                    }
377                }
378                ty::Array(ty, len) => match len.try_to_target_usize(cx.tcx) {
379                    // If the array is empty we don't lint, to avoid false positives
380                    Some(0) | None => None,
381                    // If the array is definitely non-empty, we can do `#[must_use]` checking.
382                    Some(len) => is_ty_must_use(cx, ty, expr, span)
383                        .map(|inner| MustUsePath::Array(Box::new(inner), len)),
384                },
385                ty::Closure(..) | ty::CoroutineClosure(..) => Some(MustUsePath::Closure(span)),
386                ty::Coroutine(def_id, ..) => {
387                    // async fn should be treated as "implementor of `Future`"
388                    let must_use = if cx.tcx.coroutine_is_async(def_id) {
389                        let def_id = cx.tcx.lang_items().future_trait()?;
390                        is_def_must_use(cx, def_id, span)
391                            .map(|inner| MustUsePath::Opaque(Box::new(inner)))
392                    } else {
393                        None
394                    };
395                    must_use.or(Some(MustUsePath::Coroutine(span)))
396                }
397                _ => None,
398            }
399        }
400
401        fn is_def_must_use(cx: &LateContext<'_>, def_id: DefId, span: Span) -> Option<MustUsePath> {
402            if let Some(reason) = {

    #[allow(deprecated)]
    {
        {
            'done:
                {
                for i in cx.tcx.get_all_attrs(def_id) {
                    #[allow(unused_imports)]
                    use rustc_hir::attrs::AttributeKind::*;
                    let i: &rustc_hir::Attribute = i;
                    match i {
                        rustc_hir::Attribute::Parsed(MustUse { reason, .. }) => {
                            break 'done Some(reason);
                        }
                        rustc_hir::Attribute::Unparsed(..) =>
                            {}
                            #[deny(unreachable_patterns)]
                            _ => {}
                    }
                }
                None
            }
        }
    }
}find_attr!(
403                cx.tcx, def_id,
404                MustUse { reason, .. } => reason
405            ) {
406                // check for #[must_use = "..."]
407                Some(MustUsePath::Def(span, def_id, *reason))
408            } else {
409                None
410            }
411        }
412
413        // Returns whether further errors should be suppressed because either a lint has been
414        // emitted or the type should be ignored.
415        fn check_must_use_def(
416            cx: &LateContext<'_>,
417            def_id: DefId,
418            span: Span,
419            descr_pre_path: &str,
420            descr_post_path: &str,
421            expr_is_from_block: bool,
422        ) -> bool {
423            is_def_must_use(cx, def_id, span)
424                .map(|must_use_path| {
425                    emit_must_use_untranslated(
426                        cx,
427                        &must_use_path,
428                        descr_pre_path,
429                        descr_post_path,
430                        1,
431                        false,
432                        expr_is_from_block,
433                    )
434                })
435                .is_some()
436        }
437
438        #[allow(clippy :: suspicious_else_formatting)]
{
    let __tracing_attr_span;
    let __tracing_attr_guard;
    if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() ||
            { false } {
        __tracing_attr_span =
            {
                use ::tracing::__macro_support::Callsite as _;
                static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                    {
                        static META: ::tracing::Metadata<'static> =
                            {
                                ::tracing_core::metadata::Metadata::new("emit_must_use_untranslated",
                                    "rustc_lint::unused", ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("compiler/rustc_lint/src/unused.rs"),
                                    ::tracing_core::__macro_support::Option::Some(438u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_lint::unused"),
                                    ::tracing_core::field::FieldSet::new(&["path", "descr_pre",
                                                    "descr_post", "plural_len", "is_inner",
                                                    "expr_is_from_block"],
                                        ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                    ::tracing::metadata::Kind::SPAN)
                            };
                        ::tracing::callsite::DefaultCallsite::new(&META)
                    };
                let mut interest = ::tracing::subscriber::Interest::never();
                if ::tracing::Level::DEBUG <=
                                    ::tracing::level_filters::STATIC_MAX_LEVEL &&
                                ::tracing::Level::DEBUG <=
                                    ::tracing::level_filters::LevelFilter::current() &&
                            { interest = __CALLSITE.interest(); !interest.is_never() }
                        &&
                        ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                            interest) {
                    let meta = __CALLSITE.metadata();
                    ::tracing::Span::new(meta,
                        &{
                                #[allow(unused_imports)]
                                use ::tracing::field::{debug, display, Value};
                                let mut iter = meta.fields().iter();
                                meta.fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                    ::tracing::__macro_support::Option::Some(&::tracing::field::debug(&path)
                                                            as &dyn Value)),
                                                (&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                    ::tracing::__macro_support::Option::Some(&descr_pre as
                                                            &dyn Value)),
                                                (&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                    ::tracing::__macro_support::Option::Some(&descr_post as
                                                            &dyn Value)),
                                                (&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                    ::tracing::__macro_support::Option::Some(&plural_len as
                                                            &dyn Value)),
                                                (&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                    ::tracing::__macro_support::Option::Some(&is_inner as
                                                            &dyn Value)),
                                                (&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                    ::tracing::__macro_support::Option::Some(&expr_is_from_block
                                                            as &dyn Value))])
                            })
                } else {
                    let span =
                        ::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
                    {};
                    span
                }
            };
        __tracing_attr_guard = __tracing_attr_span.enter();
    }

    #[warn(clippy :: suspicious_else_formatting)]
    {

        #[allow(unknown_lints, unreachable_code, clippy ::
        diverging_sub_expression, clippy :: empty_loop, clippy ::
        let_unit_value, clippy :: let_with_type_underscore, clippy ::
        needless_return, clippy :: unreachable)]
        if false {
            let __tracing_attr_fake_return: () = loop {};
            return __tracing_attr_fake_return;
        }
        {
            let plural_suffix = if plural_len == 1 { "" } else { "s" };
            match path {
                MustUsePath::Suppressed => {}
                MustUsePath::Boxed(path) => {
                    let descr_pre =
                        &::alloc::__export::must_use({
                                    ::alloc::fmt::format(format_args!("{0}boxed ", descr_pre))
                                });
                    emit_must_use_untranslated(cx, path, descr_pre, descr_post,
                        plural_len, true, expr_is_from_block);
                }
                MustUsePath::Pinned(path) => {
                    let descr_pre =
                        &::alloc::__export::must_use({
                                    ::alloc::fmt::format(format_args!("{0}pinned ", descr_pre))
                                });
                    emit_must_use_untranslated(cx, path, descr_pre, descr_post,
                        plural_len, true, expr_is_from_block);
                }
                MustUsePath::Opaque(path) => {
                    let descr_pre =
                        &::alloc::__export::must_use({
                                    ::alloc::fmt::format(format_args!("{0}implementer{1} of ",
                                            descr_pre, plural_suffix))
                                });
                    emit_must_use_untranslated(cx, path, descr_pre, descr_post,
                        plural_len, true, expr_is_from_block);
                }
                MustUsePath::TraitObject(path) => {
                    let descr_post =
                        &::alloc::__export::must_use({
                                    ::alloc::fmt::format(format_args!(" trait object{0}{1}",
                                            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 =
                            &::alloc::__export::must_use({
                                        ::alloc::fmt::format(format_args!(" in tuple element {0}",
                                                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 =
                        &::alloc::__export::must_use({
                                    ::alloc::fmt::format(format_args!("{0}array{1} of ",
                                            descr_pre, plural_suffix))
                                });
                    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 ancenstor_span =
                        span.find_ancestor_not_from_macro().unwrap_or(*span);
                    let is_redundant_let_ignore =
                        cx.sess().source_map().span_to_prev_source(ancenstor_span).ok().map(|prev|
                                    prev.trim_end().ends_with("let _ =")).unwrap_or(false);
                    let suggestion_span =
                        if is_redundant_let_ignore {
                            *span
                        } else { ancenstor_span };
                    cx.emit_span_lint(UNUSED_MUST_USE, ancenstor_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: suggestion_span.shrink_to_lo(),
                                        after_span: suggestion_span.shrink_to_hi(),
                                    }
                                } else {
                                    UnusedDefSuggestion::NormalExpr {
                                        span: suggestion_span.shrink_to_lo(),
                                    }
                                }),
                        });
                }
            }
        }
    }
}#[instrument(skip(cx), level = "debug")]
439        fn emit_must_use_untranslated(
440            cx: &LateContext<'_>,
441            path: &MustUsePath,
442            descr_pre: &str,
443            descr_post: &str,
444            plural_len: usize,
445            is_inner: bool,
446            expr_is_from_block: bool,
447        ) {
448            let plural_suffix = pluralize!(plural_len);
449
450            match path {
451                MustUsePath::Suppressed => {}
452                MustUsePath::Boxed(path) => {
453                    let descr_pre = &format!("{descr_pre}boxed ");
454                    emit_must_use_untranslated(
455                        cx,
456                        path,
457                        descr_pre,
458                        descr_post,
459                        plural_len,
460                        true,
461                        expr_is_from_block,
462                    );
463                }
464                MustUsePath::Pinned(path) => {
465                    let descr_pre = &format!("{descr_pre}pinned ");
466                    emit_must_use_untranslated(
467                        cx,
468                        path,
469                        descr_pre,
470                        descr_post,
471                        plural_len,
472                        true,
473                        expr_is_from_block,
474                    );
475                }
476                MustUsePath::Opaque(path) => {
477                    let descr_pre = &format!("{descr_pre}implementer{plural_suffix} of ");
478                    emit_must_use_untranslated(
479                        cx,
480                        path,
481                        descr_pre,
482                        descr_post,
483                        plural_len,
484                        true,
485                        expr_is_from_block,
486                    );
487                }
488                MustUsePath::TraitObject(path) => {
489                    let descr_post = &format!(" trait object{plural_suffix}{descr_post}");
490                    emit_must_use_untranslated(
491                        cx,
492                        path,
493                        descr_pre,
494                        descr_post,
495                        plural_len,
496                        true,
497                        expr_is_from_block,
498                    );
499                }
500                MustUsePath::TupleElement(elems) => {
501                    for (index, path) in elems {
502                        let descr_post = &format!(" in tuple element {index}");
503                        emit_must_use_untranslated(
504                            cx,
505                            path,
506                            descr_pre,
507                            descr_post,
508                            plural_len,
509                            true,
510                            expr_is_from_block,
511                        );
512                    }
513                }
514                MustUsePath::Array(path, len) => {
515                    let descr_pre = &format!("{descr_pre}array{plural_suffix} of ");
516                    emit_must_use_untranslated(
517                        cx,
518                        path,
519                        descr_pre,
520                        descr_post,
521                        plural_len.saturating_add(usize::try_from(*len).unwrap_or(usize::MAX)),
522                        true,
523                        expr_is_from_block,
524                    );
525                }
526                MustUsePath::Closure(span) => {
527                    cx.emit_span_lint(
528                        UNUSED_MUST_USE,
529                        *span,
530                        UnusedClosure { count: plural_len, pre: descr_pre, post: descr_post },
531                    );
532                }
533                MustUsePath::Coroutine(span) => {
534                    cx.emit_span_lint(
535                        UNUSED_MUST_USE,
536                        *span,
537                        UnusedCoroutine { count: plural_len, pre: descr_pre, post: descr_post },
538                    );
539                }
540                MustUsePath::Def(span, def_id, reason) => {
541                    let ancenstor_span = span.find_ancestor_not_from_macro().unwrap_or(*span);
542                    let is_redundant_let_ignore = cx
543                        .sess()
544                        .source_map()
545                        .span_to_prev_source(ancenstor_span)
546                        .ok()
547                        .map(|prev| prev.trim_end().ends_with("let _ ="))
548                        .unwrap_or(false);
549                    let suggestion_span =
550                        if is_redundant_let_ignore { *span } else { ancenstor_span };
551                    cx.emit_span_lint(
552                        UNUSED_MUST_USE,
553                        ancenstor_span,
554                        UnusedDef {
555                            pre: descr_pre,
556                            post: descr_post,
557                            cx,
558                            def_id: *def_id,
559                            note: *reason,
560                            suggestion: (!is_inner).then_some(if expr_is_from_block {
561                                UnusedDefSuggestion::BlockTailExpr {
562                                    before_span: suggestion_span.shrink_to_lo(),
563                                    after_span: suggestion_span.shrink_to_hi(),
564                                }
565                            } else {
566                                UnusedDefSuggestion::NormalExpr {
567                                    span: suggestion_span.shrink_to_lo(),
568                                }
569                            }),
570                        },
571                    );
572                }
573            }
574        }
575    }
576}
577
578#[doc =
r" The `path_statements` lint detects path statements with no effect."]
#[doc = r""]
#[doc = r" ### Example"]
#[doc = r""]
#[doc = r" ```rust"]
#[doc = r" let x = 42;"]
#[doc = r""]
#[doc = r" x;"]
#[doc = r" ```"]
#[doc = r""]
#[doc = r" {{produces}}"]
#[doc = r""]
#[doc = r" ### Explanation"]
#[doc = r""]
#[doc = r" It is usually a mistake to have a statement that has no effect."]
pub static PATH_STATEMENTS: &::rustc_lint_defs::Lint =
    &::rustc_lint_defs::Lint {
            name: "PATH_STATEMENTS",
            default_level: ::rustc_lint_defs::Warn,
            desc: "path statements with no effect",
            is_externally_loaded: false,
            ..::rustc_lint_defs::Lint::default_fields_for_macro()
        };declare_lint! {
579    /// The `path_statements` lint detects path statements with no effect.
580    ///
581    /// ### Example
582    ///
583    /// ```rust
584    /// let x = 42;
585    ///
586    /// x;
587    /// ```
588    ///
589    /// {{produces}}
590    ///
591    /// ### Explanation
592    ///
593    /// It is usually a mistake to have a statement that has no effect.
594    pub PATH_STATEMENTS,
595    Warn,
596    "path statements with no effect"
597}
598
599pub struct PathStatements;
#[automatically_derived]
impl ::core::marker::Copy for PathStatements { }
#[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for PathStatements { }
#[automatically_derived]
impl ::core::clone::Clone for PathStatements {
    #[inline]
    fn clone(&self) -> PathStatements { *self }
}
impl ::rustc_lint_defs::LintPass for PathStatements {
    fn name(&self) -> &'static str { "PathStatements" }
    fn get_lints(&self) -> ::rustc_lint_defs::LintVec {
        ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
                [PATH_STATEMENTS]))
    }
}
impl PathStatements {
    #[allow(unused)]
    pub fn lint_vec() -> ::rustc_lint_defs::LintVec {
        ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
                [PATH_STATEMENTS]))
    }
}declare_lint_pass!(PathStatements => [PATH_STATEMENTS]);
600
601impl<'tcx> LateLintPass<'tcx> for PathStatements {
602    fn check_stmt(&mut self, cx: &LateContext<'_>, s: &hir::Stmt<'_>) {
603        if let hir::StmtKind::Semi(expr) = s.kind
604            && let hir::ExprKind::Path(_) = expr.kind
605        {
606            let ty = cx.typeck_results().expr_ty(expr);
607            if ty.needs_drop(cx.tcx, cx.typing_env()) {
608                let sub = if let Ok(snippet) = cx.sess().source_map().span_to_snippet(expr.span) {
609                    PathStatementDropSub::Suggestion { span: s.span, snippet }
610                } else {
611                    PathStatementDropSub::Help { span: s.span }
612                };
613                cx.emit_span_lint(PATH_STATEMENTS, s.span, PathStatementDrop { sub })
614            } else {
615                cx.emit_span_lint(PATH_STATEMENTS, s.span, PathStatementNoEffect);
616            }
617        }
618    }
619}
620
621#[derive(#[automatically_derived]
impl ::core::marker::Copy for UnusedDelimsCtx { }Copy, #[automatically_derived]
impl ::core::clone::Clone for UnusedDelimsCtx {
    #[inline]
    fn clone(&self) -> UnusedDelimsCtx { *self }
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for UnusedDelimsCtx {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f,
            match self {
                UnusedDelimsCtx::FunctionArg => "FunctionArg",
                UnusedDelimsCtx::MethodArg => "MethodArg",
                UnusedDelimsCtx::AssignedValue => "AssignedValue",
                UnusedDelimsCtx::AssignedValueLetElse =>
                    "AssignedValueLetElse",
                UnusedDelimsCtx::IfCond => "IfCond",
                UnusedDelimsCtx::WhileCond => "WhileCond",
                UnusedDelimsCtx::ForIterExpr => "ForIterExpr",
                UnusedDelimsCtx::MatchScrutineeExpr => "MatchScrutineeExpr",
                UnusedDelimsCtx::ReturnValue => "ReturnValue",
                UnusedDelimsCtx::BlockRetValue => "BlockRetValue",
                UnusedDelimsCtx::BreakValue => "BreakValue",
                UnusedDelimsCtx::LetScrutineeExpr => "LetScrutineeExpr",
                UnusedDelimsCtx::ArrayLenExpr => "ArrayLenExpr",
                UnusedDelimsCtx::AnonConst => "AnonConst",
                UnusedDelimsCtx::MatchArmExpr => "MatchArmExpr",
                UnusedDelimsCtx::IndexExpr => "IndexExpr",
                UnusedDelimsCtx::ClosureBody => "ClosureBody",
            })
    }
}Debug, #[automatically_derived]
impl ::core::cmp::PartialEq for UnusedDelimsCtx {
    #[inline]
    fn eq(&self, other: &UnusedDelimsCtx) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr
    }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for UnusedDelimsCtx {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_receiver_is_total_eq(&self) {}
}Eq)]
622enum UnusedDelimsCtx {
623    FunctionArg,
624    MethodArg,
625    AssignedValue,
626    AssignedValueLetElse,
627    IfCond,
628    WhileCond,
629    ForIterExpr,
630    MatchScrutineeExpr,
631    ReturnValue,
632    BlockRetValue,
633    BreakValue,
634    LetScrutineeExpr,
635    ArrayLenExpr,
636    AnonConst,
637    MatchArmExpr,
638    IndexExpr,
639    ClosureBody,
640}
641
642impl From<UnusedDelimsCtx> for &'static str {
643    fn from(ctx: UnusedDelimsCtx) -> &'static str {
644        match ctx {
645            UnusedDelimsCtx::FunctionArg => "function argument",
646            UnusedDelimsCtx::MethodArg => "method argument",
647            UnusedDelimsCtx::AssignedValue | UnusedDelimsCtx::AssignedValueLetElse => {
648                "assigned value"
649            }
650            UnusedDelimsCtx::IfCond => "`if` condition",
651            UnusedDelimsCtx::WhileCond => "`while` condition",
652            UnusedDelimsCtx::ForIterExpr => "`for` iterator expression",
653            UnusedDelimsCtx::MatchScrutineeExpr => "`match` scrutinee expression",
654            UnusedDelimsCtx::ReturnValue => "`return` value",
655            UnusedDelimsCtx::BlockRetValue => "block return value",
656            UnusedDelimsCtx::BreakValue => "`break` value",
657            UnusedDelimsCtx::LetScrutineeExpr => "`let` scrutinee expression",
658            UnusedDelimsCtx::ArrayLenExpr | UnusedDelimsCtx::AnonConst => "const expression",
659            UnusedDelimsCtx::MatchArmExpr => "match arm expression",
660            UnusedDelimsCtx::IndexExpr => "index expression",
661            UnusedDelimsCtx::ClosureBody => "closure body",
662        }
663    }
664}
665
666/// Used by both `UnusedParens` and `UnusedBraces` to prevent code duplication.
667trait UnusedDelimLint {
668    const DELIM_STR: &'static str;
669
670    /// Due to `ref` pattern, there can be a difference between using
671    /// `{ expr }` and `expr` in pattern-matching contexts. This means
672    /// that we should only lint `unused_parens` and not `unused_braces`
673    /// in this case.
674    ///
675    /// ```rust
676    /// let mut a = 7;
677    /// let ref b = { a }; // We actually borrow a copy of `a` here.
678    /// a += 1; // By mutating `a` we invalidate any borrows of `a`.
679    /// assert_eq!(b + 1, a); // `b` does not borrow `a`, so we can still use it here.
680    /// ```
681    const LINT_EXPR_IN_PATTERN_MATCHING_CTX: bool;
682
683    // this cannot be a constant is it refers to a static.
684    fn lint(&self) -> &'static Lint;
685
686    fn check_unused_delims_expr(
687        &self,
688        cx: &EarlyContext<'_>,
689        value: &ast::Expr,
690        ctx: UnusedDelimsCtx,
691        followed_by_block: bool,
692        left_pos: Option<BytePos>,
693        right_pos: Option<BytePos>,
694        is_kw: bool,
695    );
696
697    fn is_expr_delims_necessary(
698        inner: &ast::Expr,
699        ctx: UnusedDelimsCtx,
700        followed_by_block: bool,
701    ) -> bool {
702        let followed_by_else = ctx == UnusedDelimsCtx::AssignedValueLetElse;
703
704        if followed_by_else {
705            match inner.kind {
706                ast::ExprKind::Binary(op, ..) if op.node.is_lazy() => return true,
707                _ if classify::expr_trailing_brace(inner).is_some() => return true,
708                _ => {}
709            }
710        }
711
712        // Check it's range in LetScrutineeExpr
713        if let ast::ExprKind::Range(..) = inner.kind
714            && #[allow(non_exhaustive_omitted_patterns)] match ctx {
    UnusedDelimsCtx::LetScrutineeExpr => true,
    _ => false,
}matches!(ctx, UnusedDelimsCtx::LetScrutineeExpr)
715        {
716            return true;
717        }
718
719        // Do not lint against parentheses around `&raw [const|mut] expr`.
720        // These parentheses will have to be added e.g. when calling a method on the result of this
721        // expression, and we want to avoid churn wrt adding and removing parentheses.
722        if #[allow(non_exhaustive_omitted_patterns)] match inner.kind {
    ast::ExprKind::AddrOf(ast::BorrowKind::Raw, ..) => true,
    _ => false,
}matches!(inner.kind, ast::ExprKind::AddrOf(ast::BorrowKind::Raw, ..)) {
723            return true;
724        }
725
726        // Check if LHS needs parens to prevent false-positives in cases like
727        // `fn x() -> u8 { ({ 0 } + 1) }`.
728        //
729        // FIXME: https://github.com/rust-lang/rust/issues/119426
730        // The syntax tree in this code is from after macro expansion, so the
731        // current implementation has both false negatives and false positives
732        // related to expressions containing macros.
733        //
734        //     macro_rules! m1 {
735        //         () => {
736        //             1
737        //         };
738        //     }
739        //
740        //     fn f1() -> u8 {
741        //         // Lint says parens are not needed, but they are.
742        //         (m1! {} + 1)
743        //     }
744        //
745        //     macro_rules! m2 {
746        //         () => {
747        //             loop { break 1; }
748        //         };
749        //     }
750        //
751        //     fn f2() -> u8 {
752        //         // Lint says parens are needed, but they are not.
753        //         (m2!() + 1)
754        //     }
755        {
756            let mut innermost = inner;
757            loop {
758                innermost = match &innermost.kind {
759                    ExprKind::Binary(_op, lhs, _rhs) => lhs,
760                    ExprKind::Call(fn_, _params) => fn_,
761                    ExprKind::Cast(expr, _ty) => expr,
762                    ExprKind::Type(expr, _ty) => expr,
763                    ExprKind::Index(base, _subscript, _) => base,
764                    _ => break,
765                };
766                if !classify::expr_requires_semi_to_be_stmt(innermost) {
767                    return true;
768                }
769            }
770        }
771
772        // Check if RHS needs parens to prevent false-positives in cases like `if (() == return)
773        // {}`.
774        if !followed_by_block {
775            return false;
776        }
777
778        // Check if we need parens for `match &( Struct { field:  }) {}`.
779        {
780            let mut innermost = inner;
781            loop {
782                innermost = match &innermost.kind {
783                    ExprKind::AddrOf(_, _, expr) => expr,
784                    _ => {
785                        if parser::contains_exterior_struct_lit(innermost) {
786                            return true;
787                        } else {
788                            break;
789                        }
790                    }
791                }
792            }
793        }
794
795        let mut innermost = inner;
796        loop {
797            innermost = match &innermost.kind {
798                ExprKind::Unary(_op, expr) => expr,
799                ExprKind::Binary(_op, _lhs, rhs) => rhs,
800                ExprKind::AssignOp(_op, _lhs, rhs) => rhs,
801                ExprKind::Assign(_lhs, rhs, _span) => rhs,
802
803                ExprKind::Ret(_) | ExprKind::Yield(..) | ExprKind::Yeet(..) => return true,
804
805                ExprKind::Break(_label, None) => return false,
806                ExprKind::Break(_label, Some(break_expr)) => {
807                    // `if (break 'label i) { ... }` removing parens would make `i { ... }`
808                    // be parsed as a struct literal, so keep parentheses if the break value
809                    // ends with a path (which could be mistaken for a struct name).
810                    return #[allow(non_exhaustive_omitted_patterns)] match break_expr.kind {
    ExprKind::Block(..) | ExprKind::Path(..) => true,
    _ => false,
}matches!(break_expr.kind, ExprKind::Block(..) | ExprKind::Path(..));
811                }
812
813                ExprKind::Range(_lhs, Some(rhs), _limits) => {
814                    return #[allow(non_exhaustive_omitted_patterns)] match rhs.kind {
    ExprKind::Block(..) => true,
    _ => false,
}matches!(rhs.kind, ExprKind::Block(..));
815                }
816
817                _ => return parser::contains_exterior_struct_lit(inner),
818            }
819        }
820    }
821
822    fn emit_unused_delims_expr(
823        &self,
824        cx: &EarlyContext<'_>,
825        value: &ast::Expr,
826        ctx: UnusedDelimsCtx,
827        left_pos: Option<BytePos>,
828        right_pos: Option<BytePos>,
829        is_kw: bool,
830    ) {
831        let span_with_attrs = match value.kind {
832            ast::ExprKind::Block(ref block, None) if let [stmt] = block.stmts.as_slice() => {
833                // For the statements with attributes, like `{ #[allow()] println!("Hello!") }`,
834                // the span should contains the attributes, or the suggestion will remove them.
835                if let Some(attr_lo) = stmt.attrs().iter().map(|attr| attr.span.lo()).min() {
836                    stmt.span.with_lo(attr_lo)
837                } else {
838                    stmt.span
839                }
840            }
841            ast::ExprKind::Paren(ref expr) => {
842                // For the expr with attributes, like `let _ = (#[inline] || println!("Hello!"));`,
843                // the span should contains the attributes, or the suggestion will remove them.
844                if let Some(attr_lo) = expr.attrs.iter().map(|attr| attr.span.lo()).min() {
845                    expr.span.with_lo(attr_lo)
846                } else {
847                    expr.span
848                }
849            }
850            _ => return,
851        };
852        let spans = span_with_attrs
853            .find_ancestor_inside(value.span)
854            .map(|span| (value.span.with_hi(span.lo()), value.span.with_lo(span.hi())));
855        let keep_space = (
856            left_pos.is_some_and(|s| s >= value.span.lo()),
857            right_pos.is_some_and(|s| s <= value.span.hi()),
858        );
859        self.emit_unused_delims(cx, value.span, spans, ctx.into(), keep_space, is_kw);
860    }
861
862    fn emit_unused_delims(
863        &self,
864        cx: &EarlyContext<'_>,
865        value_span: Span,
866        spans: Option<(Span, Span)>,
867        msg: &str,
868        keep_space: (bool, bool),
869        is_kw: bool,
870    ) {
871        let primary_span = if let Some((lo, hi)) = spans {
872            if hi.is_empty() {
873                // do not point at delims that do not exist
874                return;
875            }
876            MultiSpan::from(::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [lo, hi]))vec![lo, hi])
877        } else {
878            MultiSpan::from(value_span)
879        };
880        let suggestion = spans.map(|(lo, hi)| {
881            let sm = cx.sess().source_map();
882            let lo_replace = if (keep_space.0 || is_kw)
883                && let Ok(snip) = sm.span_to_prev_source(lo)
884                && !snip.ends_with(' ')
885            {
886                " "
887            } else if let Ok(snip) = sm.span_to_prev_source(value_span)
888                && snip.ends_with(|c: char| c.is_alphanumeric())
889            {
890                " "
891            } else {
892                ""
893            };
894
895            let hi_replace = if keep_space.1
896                && let Ok(snip) = sm.span_to_next_source(hi)
897                && !snip.starts_with(' ')
898            {
899                " "
900            } else if let Ok(snip) = sm.span_to_prev_source(value_span)
901                && snip.starts_with(|c: char| c.is_alphanumeric())
902            {
903                " "
904            } else {
905                ""
906            };
907            UnusedDelimSuggestion {
908                start_span: lo,
909                start_replace: lo_replace,
910                end_span: hi,
911                end_replace: hi_replace,
912            }
913        });
914        cx.emit_span_lint(
915            self.lint(),
916            primary_span,
917            UnusedDelim { delim: Self::DELIM_STR, item: msg, suggestion },
918        );
919    }
920
921    fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &ast::Expr) {
922        use rustc_ast::ExprKind::*;
923        let (value, ctx, followed_by_block, left_pos, right_pos, is_kw) = match e.kind {
924            // Do not lint `unused_braces` in `if let` expressions.
925            If(ref cond, ref block, _)
926                if !#[allow(non_exhaustive_omitted_patterns)] match cond.kind {
    Let(..) => true,
    _ => false,
}matches!(cond.kind, Let(..)) || Self::LINT_EXPR_IN_PATTERN_MATCHING_CTX =>
927            {
928                let left = e.span.lo() + rustc_span::BytePos(2);
929                let right = block.span.lo();
930                (cond, UnusedDelimsCtx::IfCond, true, Some(left), Some(right), true)
931            }
932
933            // Do not lint `unused_braces` in `while let` expressions.
934            While(ref cond, ref block, ..)
935                if !#[allow(non_exhaustive_omitted_patterns)] match cond.kind {
    Let(..) => true,
    _ => false,
}matches!(cond.kind, Let(..)) || Self::LINT_EXPR_IN_PATTERN_MATCHING_CTX =>
936            {
937                let left = e.span.lo() + rustc_span::BytePos(5);
938                let right = block.span.lo();
939                (cond, UnusedDelimsCtx::WhileCond, true, Some(left), Some(right), true)
940            }
941
942            ForLoop { ref iter, ref body, .. } => {
943                (iter, UnusedDelimsCtx::ForIterExpr, true, None, Some(body.span.lo()), true)
944            }
945
946            Match(ref head, _, ast::MatchKind::Prefix)
947                if Self::LINT_EXPR_IN_PATTERN_MATCHING_CTX =>
948            {
949                let left = e.span.lo() + rustc_span::BytePos(5);
950                (head, UnusedDelimsCtx::MatchScrutineeExpr, true, Some(left), None, true)
951            }
952
953            Ret(Some(ref value)) => {
954                let left = e.span.lo() + rustc_span::BytePos(3);
955                (value, UnusedDelimsCtx::ReturnValue, false, Some(left), None, true)
956            }
957
958            Break(label, Some(ref value)) => {
959                // Don't lint on `break 'label ({...})` - the parens are necessary
960                // to disambiguate from `break 'label {...}` which would be a syntax error.
961                // This avoids conflicts with the `break_with_label_and_loop` lint.
962                if label.is_some()
963                    && #[allow(non_exhaustive_omitted_patterns)] match value.kind {
    ast::ExprKind::Paren(ref inner) if
        #[allow(non_exhaustive_omitted_patterns)] match inner.kind {
            ast::ExprKind::Block(..) => true,
            _ => false,
        } => true,
    _ => false,
}matches!(value.kind, ast::ExprKind::Paren(ref inner)
964                        if matches!(inner.kind, ast::ExprKind::Block(..)))
965                {
966                    return;
967                }
968                (value, UnusedDelimsCtx::BreakValue, false, None, None, true)
969            }
970
971            Index(_, ref value, _) => (value, UnusedDelimsCtx::IndexExpr, false, None, None, false),
972
973            Assign(_, ref value, _) | AssignOp(.., ref value) => {
974                (value, UnusedDelimsCtx::AssignedValue, false, None, None, false)
975            }
976            // either function/method call, or something this lint doesn't care about
977            ref call_or_other => {
978                let (args_to_check, ctx) = match *call_or_other {
979                    Call(_, ref args) => (&args[..], UnusedDelimsCtx::FunctionArg),
980                    MethodCall(ref call) => (&call.args[..], UnusedDelimsCtx::MethodArg),
981                    Closure(ref closure)
982                        if #[allow(non_exhaustive_omitted_patterns)] match closure.fn_decl.output {
    FnRetTy::Default(_) => true,
    _ => false,
}matches!(closure.fn_decl.output, FnRetTy::Default(_)) =>
983                    {
984                        (&[closure.body.clone()][..], UnusedDelimsCtx::ClosureBody)
985                    }
986                    // actual catch-all arm
987                    _ => {
988                        return;
989                    }
990                };
991                // Don't lint if this is a nested macro expansion: otherwise, the lint could
992                // trigger in situations that macro authors shouldn't have to care about, e.g.,
993                // when a parenthesized token tree matched in one macro expansion is matched as
994                // an expression in another and used as a fn/method argument (Issue #47775)
995                if e.span.ctxt().outer_expn_data().call_site.from_expansion() {
996                    return;
997                }
998                for arg in args_to_check {
999                    self.check_unused_delims_expr(cx, arg, ctx, false, None, None, false);
1000                }
1001                return;
1002            }
1003        };
1004        self.check_unused_delims_expr(
1005            cx,
1006            value,
1007            ctx,
1008            followed_by_block,
1009            left_pos,
1010            right_pos,
1011            is_kw,
1012        );
1013    }
1014
1015    fn check_stmt(&mut self, cx: &EarlyContext<'_>, s: &ast::Stmt) {
1016        match s.kind {
1017            StmtKind::Let(ref local) if Self::LINT_EXPR_IN_PATTERN_MATCHING_CTX => {
1018                if let Some((init, els)) = local.kind.init_else_opt() {
1019                    if els.is_some()
1020                        && let ExprKind::Paren(paren) = &init.kind
1021                        && !init.span.eq_ctxt(paren.span)
1022                    {
1023                        // This branch prevents cases where parentheses wrap an expression
1024                        // resulting from macro expansion, such as:
1025                        // ```
1026                        // macro_rules! x {
1027                        // () => { None::<i32> };
1028                        // }
1029                        // let Some(_) = (x!{}) else { return };
1030                        // // -> let Some(_) = (None::<i32>) else { return };
1031                        // //                  ~           ~ No Lint
1032                        // ```
1033                        return;
1034                    }
1035                    let ctx = match els {
1036                        None => UnusedDelimsCtx::AssignedValue,
1037                        Some(_) => UnusedDelimsCtx::AssignedValueLetElse,
1038                    };
1039                    self.check_unused_delims_expr(cx, init, ctx, false, None, None, false);
1040                }
1041            }
1042            StmtKind::Expr(ref expr) => {
1043                self.check_unused_delims_expr(
1044                    cx,
1045                    expr,
1046                    UnusedDelimsCtx::BlockRetValue,
1047                    false,
1048                    None,
1049                    None,
1050                    false,
1051                );
1052            }
1053            _ => {}
1054        }
1055    }
1056
1057    fn check_item(&mut self, cx: &EarlyContext<'_>, item: &ast::Item) {
1058        use ast::ItemKind::*;
1059
1060        let expr = if let Const(box ast::ConstItem { rhs_kind, .. }) = &item.kind {
1061            if let Some(e) = rhs_kind.expr() { e } else { return }
1062        } else if let Static(box ast::StaticItem { expr: Some(expr), .. }) = &item.kind {
1063            expr
1064        } else {
1065            return;
1066        };
1067        self.check_unused_delims_expr(
1068            cx,
1069            expr,
1070            UnusedDelimsCtx::AssignedValue,
1071            false,
1072            None,
1073            None,
1074            false,
1075        );
1076    }
1077}
1078
1079#[doc =
r" The `unused_parens` lint detects `if`, `match`, `while` and `return`"]
#[doc = r" with parentheses; they do not need them."]
#[doc = r""]
#[doc = r" ### Examples"]
#[doc = r""]
#[doc = r" ```rust"]
#[doc = r" if(true) {}"]
#[doc = r" ```"]
#[doc = r""]
#[doc = r" {{produces}}"]
#[doc = r""]
#[doc = r" ### Explanation"]
#[doc = r""]
#[doc =
r" The parentheses are not needed, and should be removed. This is the"]
#[doc = r" preferred style for writing these expressions."]
pub(super) static UNUSED_PARENS: &::rustc_lint_defs::Lint =
    &::rustc_lint_defs::Lint {
            name: "UNUSED_PARENS",
            default_level: ::rustc_lint_defs::Warn,
            desc: "`if`, `match`, `while` and `return` do not need parentheses",
            is_externally_loaded: false,
            ..::rustc_lint_defs::Lint::default_fields_for_macro()
        };declare_lint! {
1080    /// The `unused_parens` lint detects `if`, `match`, `while` and `return`
1081    /// with parentheses; they do not need them.
1082    ///
1083    /// ### Examples
1084    ///
1085    /// ```rust
1086    /// if(true) {}
1087    /// ```
1088    ///
1089    /// {{produces}}
1090    ///
1091    /// ### Explanation
1092    ///
1093    /// The parentheses are not needed, and should be removed. This is the
1094    /// preferred style for writing these expressions.
1095    pub(super) UNUSED_PARENS,
1096    Warn,
1097    "`if`, `match`, `while` and `return` do not need parentheses"
1098}
1099
1100#[derive(#[automatically_derived]
impl ::core::default::Default for UnusedParens {
    #[inline]
    fn default() -> UnusedParens {
        UnusedParens {
            with_self_ty_parens: ::core::default::Default::default(),
            parens_in_cast_in_lt: ::core::default::Default::default(),
            in_no_bounds_pos: ::core::default::Default::default(),
        }
    }
}Default)]
1101pub(crate) struct UnusedParens {
1102    with_self_ty_parens: bool,
1103    /// `1 as (i32) < 2` parses to ExprKind::Lt
1104    /// `1 as i32 < 2` parses to i32::<2[missing angle bracket]
1105    parens_in_cast_in_lt: Vec<ast::NodeId>,
1106    /// Ty nodes in this map are in TypeNoBounds position. Any bounds they
1107    /// contain may be ambiguous w/r/t trailing `+` operators.
1108    in_no_bounds_pos: FxHashMap<ast::NodeId, NoBoundsException>,
1109}
1110
1111/// Whether parentheses may be omitted from a type without resulting in ambiguity.
1112///
1113/// ```
1114/// type Example = Box<dyn Fn() -> &'static (dyn Send) + Sync>;
1115/// ```
1116///
1117/// Here, `&'static (dyn Send) + Sync` is a `TypeNoBounds`. As such, it may not directly
1118/// contain `ImplTraitType` or `TraitObjectType` which is why `(dyn Send)` is parenthesized.
1119/// However, an exception is made for `ImplTraitTypeOneBound` and `TraitObjectTypeOneBound`.
1120/// The following is accepted because there is no `+`.
1121///
1122/// ```
1123/// type Example = Box<dyn Fn() -> &'static dyn Send>;
1124/// ```
1125enum NoBoundsException {
1126    /// The type must be parenthesized.
1127    None,
1128    /// The type is the last bound of the containing type expression. If it has exactly one bound,
1129    /// parentheses around the type are unnecessary.
1130    OneBound,
1131}
1132
1133impl ::rustc_lint_defs::LintPass for UnusedParens {
    fn name(&self) -> &'static str { "UnusedParens" }
    fn get_lints(&self) -> ::rustc_lint_defs::LintVec {
        ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
                [UNUSED_PARENS]))
    }
}
impl UnusedParens {
    #[allow(unused)]
    pub fn lint_vec() -> ::rustc_lint_defs::LintVec {
        ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
                [UNUSED_PARENS]))
    }
}impl_lint_pass!(UnusedParens => [UNUSED_PARENS]);
1134
1135impl UnusedDelimLint for UnusedParens {
1136    const DELIM_STR: &'static str = "parentheses";
1137
1138    const LINT_EXPR_IN_PATTERN_MATCHING_CTX: bool = true;
1139
1140    fn lint(&self) -> &'static Lint {
1141        UNUSED_PARENS
1142    }
1143
1144    fn check_unused_delims_expr(
1145        &self,
1146        cx: &EarlyContext<'_>,
1147        value: &ast::Expr,
1148        ctx: UnusedDelimsCtx,
1149        followed_by_block: bool,
1150        left_pos: Option<BytePos>,
1151        right_pos: Option<BytePos>,
1152        is_kw: bool,
1153    ) {
1154        match value.kind {
1155            ast::ExprKind::Paren(ref inner) => {
1156                if !Self::is_expr_delims_necessary(inner, ctx, followed_by_block)
1157                    && value.attrs.is_empty()
1158                    && !value.span.from_expansion()
1159                    && (ctx != UnusedDelimsCtx::LetScrutineeExpr
1160                        || !#[allow(non_exhaustive_omitted_patterns)] match inner.kind {
    ast::ExprKind::Binary(rustc_span::source_map::Spanned { node, .. }, _, _)
        if node.is_lazy() => true,
    _ => false,
}matches!(inner.kind, ast::ExprKind::Binary(
1161                                rustc_span::source_map::Spanned { node, .. },
1162                                _,
1163                                _,
1164                            ) if node.is_lazy()))
1165                    && !((ctx == UnusedDelimsCtx::ReturnValue
1166                        || ctx == UnusedDelimsCtx::BreakValue)
1167                        && #[allow(non_exhaustive_omitted_patterns)] match inner.kind {
    ast::ExprKind::Assign(_, _, _) => true,
    _ => false,
}matches!(inner.kind, ast::ExprKind::Assign(_, _, _)))
1168                {
1169                    self.emit_unused_delims_expr(cx, value, ctx, left_pos, right_pos, is_kw)
1170                }
1171            }
1172            ast::ExprKind::Let(_, ref expr, _, _) => {
1173                self.check_unused_delims_expr(
1174                    cx,
1175                    expr,
1176                    UnusedDelimsCtx::LetScrutineeExpr,
1177                    followed_by_block,
1178                    None,
1179                    None,
1180                    false,
1181                );
1182            }
1183            _ => {}
1184        }
1185    }
1186}
1187
1188impl UnusedParens {
1189    fn check_unused_parens_pat(
1190        &self,
1191        cx: &EarlyContext<'_>,
1192        value: &ast::Pat,
1193        avoid_or: bool,
1194        avoid_mut: bool,
1195        keep_space: (bool, bool),
1196    ) {
1197        use ast::{BindingMode, PatKind};
1198
1199        if let PatKind::Paren(inner) = &value.kind {
1200            match inner.kind {
1201                // The lint visitor will visit each subpattern of `p`. We do not want to lint
1202                // any range pattern no matter where it occurs in the pattern. For something like
1203                // `&(a..=b)`, there is a recursive `check_pat` on `a` and `b`, but we will assume
1204                // that if there are unnecessary parens they serve a purpose of readability.
1205                PatKind::Range(..) => return,
1206                // Parentheses may be necessary to disambiguate precedence in guard patterns.
1207                PatKind::Guard(..) => return,
1208                // Avoid `p0 | .. | pn` if we should.
1209                PatKind::Or(..) if avoid_or => return,
1210                // Avoid `mut x` and `mut x @ p` if we should:
1211                PatKind::Ident(BindingMode::MUT, ..) if avoid_mut => {
1212                    return;
1213                }
1214                // Otherwise proceed with linting.
1215                _ => {}
1216            }
1217            let spans = if !value.span.from_expansion() {
1218                inner
1219                    .span
1220                    .find_ancestor_inside(value.span)
1221                    .map(|inner| (value.span.with_hi(inner.lo()), value.span.with_lo(inner.hi())))
1222            } else {
1223                None
1224            };
1225            self.emit_unused_delims(cx, value.span, spans, "pattern", keep_space, false);
1226        }
1227    }
1228
1229    fn cast_followed_by_lt(&self, expr: &ast::Expr) -> Option<ast::NodeId> {
1230        if let ExprKind::Binary(op, lhs, _rhs) = &expr.kind
1231            && (op.node == ast::BinOpKind::Lt || op.node == ast::BinOpKind::Shl)
1232        {
1233            let mut cur = lhs;
1234            while let ExprKind::Binary(_, _, rhs) = &cur.kind {
1235                cur = rhs;
1236            }
1237
1238            if let ExprKind::Cast(_, ty) = &cur.kind
1239                && let ast::TyKind::Paren(_) = &ty.kind
1240            {
1241                return Some(ty.id);
1242            }
1243        }
1244        None
1245    }
1246}
1247
1248impl EarlyLintPass for UnusedParens {
1249    #[inline]
1250    fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &ast::Expr) {
1251        if let Some(ty_id) = self.cast_followed_by_lt(e) {
1252            self.parens_in_cast_in_lt.push(ty_id);
1253        }
1254
1255        match e.kind {
1256            ExprKind::Let(ref pat, _, _, _) | ExprKind::ForLoop { ref pat, .. } => {
1257                self.check_unused_parens_pat(cx, pat, false, false, (true, true));
1258            }
1259            // We ignore parens in cases like `if (((let Some(0) = Some(1))))` because we already
1260            // handle a hard error for them during AST lowering in `lower_expr_mut`, but we still
1261            // want to complain about things like `if let 42 = (42)`.
1262            ExprKind::If(ref cond, ref block, ref else_)
1263                if #[allow(non_exhaustive_omitted_patterns)] match cond.peel_parens().kind {
    ExprKind::Let(..) => true,
    _ => false,
}matches!(cond.peel_parens().kind, ExprKind::Let(..)) =>
1264            {
1265                self.check_unused_delims_expr(
1266                    cx,
1267                    cond.peel_parens(),
1268                    UnusedDelimsCtx::LetScrutineeExpr,
1269                    true,
1270                    None,
1271                    None,
1272                    true,
1273                );
1274                for stmt in &block.stmts {
1275                    <Self as UnusedDelimLint>::check_stmt(self, cx, stmt);
1276                }
1277                if let Some(e) = else_ {
1278                    <Self as UnusedDelimLint>::check_expr(self, cx, e);
1279                }
1280                return;
1281            }
1282            ExprKind::Match(ref _expr, ref arm, _) => {
1283                for a in arm {
1284                    if let Some(body) = &a.body {
1285                        self.check_unused_delims_expr(
1286                            cx,
1287                            body,
1288                            UnusedDelimsCtx::MatchArmExpr,
1289                            false,
1290                            None,
1291                            None,
1292                            true,
1293                        );
1294                    }
1295                }
1296            }
1297            _ => {}
1298        }
1299
1300        <Self as UnusedDelimLint>::check_expr(self, cx, e)
1301    }
1302
1303    fn check_expr_post(&mut self, _cx: &EarlyContext<'_>, e: &ast::Expr) {
1304        if let Some(ty_id) = self.cast_followed_by_lt(e) {
1305            let id = self
1306                .parens_in_cast_in_lt
1307                .pop()
1308                .expect("check_expr and check_expr_post must balance");
1309            match (&id, &ty_id) {
    (left_val, right_val) => {
        if !(*left_val == *right_val) {
            let kind = ::core::panicking::AssertKind::Eq;
            ::core::panicking::assert_failed(kind, &*left_val, &*right_val,
                ::core::option::Option::Some(format_args!("check_expr, check_ty, and check_expr_post are called, in that order, by the visitor")));
        }
    }
};assert_eq!(
1310                id, ty_id,
1311                "check_expr, check_ty, and check_expr_post are called, in that order, by the visitor"
1312            );
1313        }
1314    }
1315
1316    fn check_pat(&mut self, cx: &EarlyContext<'_>, p: &ast::Pat) {
1317        use ast::Mutability;
1318        use ast::PatKind::*;
1319        let keep_space = (false, false);
1320        match &p.kind {
1321            // Do not lint on `(..)` as that will result in the other arms being useless.
1322            Paren(_)
1323            // The other cases do not contain sub-patterns.
1324            | Missing | Wild | Never | Rest | Expr(..) | MacCall(..) | Range(..) | Ident(.., None)
1325            | Path(..) | Err(_) => {},
1326            // These are list-like patterns; parens can always be removed.
1327            TupleStruct(_, _, ps) | Tuple(ps) | Slice(ps) | Or(ps) => for p in ps {
1328                self.check_unused_parens_pat(cx, p, false, false, keep_space);
1329            },
1330            Struct(_, _, fps, _) => for f in fps {
1331                self.check_unused_parens_pat(cx, &f.pat, false, false, keep_space);
1332            },
1333            // Avoid linting on `i @ (p0 | .. | pn)` and `box (p0 | .. | pn)`, #64106.
1334            Ident(.., Some(p)) | Box(p) | Deref(p) | Guard(p, _) => self.check_unused_parens_pat(cx, p, true, false, keep_space),
1335            // Avoid linting on `&(mut x)` as `&mut x` has a different meaning, #55342.
1336            // Also avoid linting on `& mut? (p0 | .. | pn)`, #64106.
1337            // FIXME(pin_ergonomics): check pinned patterns
1338            Ref(p, _, m) => self.check_unused_parens_pat(cx, p, true, *m == Mutability::Not, keep_space),
1339        }
1340    }
1341
1342    fn check_stmt(&mut self, cx: &EarlyContext<'_>, s: &ast::Stmt) {
1343        if let StmtKind::Let(ref local) = s.kind {
1344            self.check_unused_parens_pat(cx, &local.pat, true, false, (true, false));
1345        }
1346
1347        <Self as UnusedDelimLint>::check_stmt(self, cx, s)
1348    }
1349
1350    fn check_param(&mut self, cx: &EarlyContext<'_>, param: &ast::Param) {
1351        self.check_unused_parens_pat(cx, &param.pat, true, false, (false, false));
1352    }
1353
1354    fn check_arm(&mut self, cx: &EarlyContext<'_>, arm: &ast::Arm) {
1355        self.check_unused_parens_pat(cx, &arm.pat, false, false, (false, false));
1356    }
1357
1358    fn check_ty(&mut self, cx: &EarlyContext<'_>, ty: &ast::Ty) {
1359        if let ast::TyKind::Paren(_) = ty.kind
1360            && Some(&ty.id) == self.parens_in_cast_in_lt.last()
1361        {
1362            return;
1363        }
1364        match &ty.kind {
1365            ast::TyKind::Array(_, len) => {
1366                self.check_unused_delims_expr(
1367                    cx,
1368                    &len.value,
1369                    UnusedDelimsCtx::ArrayLenExpr,
1370                    false,
1371                    None,
1372                    None,
1373                    false,
1374                );
1375            }
1376            ast::TyKind::Paren(r) => {
1377                let unused_parens = match &r.kind {
1378                    ast::TyKind::ImplTrait(_, bounds) | ast::TyKind::TraitObject(bounds, _) => {
1379                        match self.in_no_bounds_pos.get(&ty.id) {
1380                            Some(NoBoundsException::None) => false,
1381                            Some(NoBoundsException::OneBound) => bounds.len() <= 1,
1382                            None => true,
1383                        }
1384                    }
1385                    ast::TyKind::FnPtr(b) => {
1386                        !self.with_self_ty_parens || b.generic_params.is_empty()
1387                    }
1388                    _ => true,
1389                };
1390
1391                if unused_parens {
1392                    let spans = (!ty.span.from_expansion())
1393                        .then(|| {
1394                            r.span
1395                                .find_ancestor_inside(ty.span)
1396                                .map(|r| (ty.span.with_hi(r.lo()), ty.span.with_lo(r.hi())))
1397                        })
1398                        .flatten();
1399
1400                    self.emit_unused_delims(cx, ty.span, spans, "type", (false, false), false);
1401                }
1402
1403                self.with_self_ty_parens = false;
1404            }
1405            ast::TyKind::Ref(_, mut_ty) | ast::TyKind::Ptr(mut_ty) => {
1406                // If this type itself appears in no-bounds position, we propagate its
1407                // potentially tighter constraint or risk a false posive (issue 143653).
1408                let own_constraint = self.in_no_bounds_pos.get(&ty.id);
1409                let constraint = match own_constraint {
1410                    Some(NoBoundsException::None) => NoBoundsException::None,
1411                    Some(NoBoundsException::OneBound) => NoBoundsException::OneBound,
1412                    None => NoBoundsException::OneBound,
1413                };
1414                self.in_no_bounds_pos.insert(mut_ty.ty.id, constraint);
1415            }
1416            ast::TyKind::TraitObject(bounds, _) | ast::TyKind::ImplTrait(_, bounds) => {
1417                for i in 0..bounds.len() {
1418                    let is_last = i == bounds.len() - 1;
1419
1420                    if let ast::GenericBound::Trait(poly_trait_ref) = &bounds[i] {
1421                        let fn_with_explicit_ret_ty = if let [.., segment] =
1422                            &*poly_trait_ref.trait_ref.path.segments
1423                            && let Some(args) = segment.args.as_ref()
1424                            && let ast::GenericArgs::Parenthesized(paren_args) = &**args
1425                            && let ast::FnRetTy::Ty(ret_ty) = &paren_args.output
1426                        {
1427                            self.in_no_bounds_pos.insert(
1428                                ret_ty.id,
1429                                if is_last {
1430                                    NoBoundsException::OneBound
1431                                } else {
1432                                    NoBoundsException::None
1433                                },
1434                            );
1435
1436                            true
1437                        } else {
1438                            false
1439                        };
1440
1441                        // In edition 2015, dyn is a contextual keyword and `dyn::foo::Bar` is
1442                        // parsed as a path, so parens are necessary to disambiguate. See
1443                        //  - tests/ui/lint/unused/unused-parens-trait-obj-e2015.rs and
1444                        //  - https://doc.rust-lang.org/reference/types/trait-object.html#r-type.trait-object.syntax-edition2018
1445                        let dyn2015_exception = cx.sess().psess.edition == Edition2015
1446                            && #[allow(non_exhaustive_omitted_patterns)] match ty.kind {
    ast::TyKind::TraitObject(..) => true,
    _ => false,
}matches!(ty.kind, ast::TyKind::TraitObject(..))
1447                            && i == 0
1448                            && poly_trait_ref
1449                                .trait_ref
1450                                .path
1451                                .segments
1452                                .first()
1453                                .map(|s| s.ident.name == kw::PathRoot)
1454                                .unwrap_or(false);
1455
1456                        if let ast::Parens::Yes = poly_trait_ref.parens
1457                            && (is_last || !fn_with_explicit_ret_ty)
1458                            && !dyn2015_exception
1459                        {
1460                            let s = poly_trait_ref.span;
1461                            let spans = (!s.from_expansion()).then(|| {
1462                                (
1463                                    s.with_hi(s.lo() + rustc_span::BytePos(1)),
1464                                    s.with_lo(s.hi() - rustc_span::BytePos(1)),
1465                                )
1466                            });
1467
1468                            self.emit_unused_delims(
1469                                cx,
1470                                poly_trait_ref.span,
1471                                spans,
1472                                "type",
1473                                (false, false),
1474                                false,
1475                            );
1476                        }
1477                    }
1478                }
1479            }
1480            _ => {}
1481        }
1482    }
1483
1484    fn check_item(&mut self, cx: &EarlyContext<'_>, item: &ast::Item) {
1485        <Self as UnusedDelimLint>::check_item(self, cx, item)
1486    }
1487
1488    fn check_item_post(&mut self, _: &EarlyContext<'_>, _: &rustc_ast::Item) {
1489        self.in_no_bounds_pos.clear();
1490    }
1491
1492    fn enter_where_predicate(&mut self, _: &EarlyContext<'_>, pred: &ast::WherePredicate) {
1493        use rustc_ast::{WhereBoundPredicate, WherePredicateKind};
1494        if let WherePredicateKind::BoundPredicate(WhereBoundPredicate {
1495            bounded_ty,
1496            bound_generic_params,
1497            ..
1498        }) = &pred.kind
1499            && let ast::TyKind::Paren(_) = &bounded_ty.kind
1500            && bound_generic_params.is_empty()
1501        {
1502            self.with_self_ty_parens = true;
1503        }
1504    }
1505
1506    fn exit_where_predicate(&mut self, _: &EarlyContext<'_>, _: &ast::WherePredicate) {
1507        if !!self.with_self_ty_parens {
    ::core::panicking::panic("assertion failed: !self.with_self_ty_parens")
};assert!(!self.with_self_ty_parens);
1508    }
1509}
1510
1511#[doc = r" The `unused_braces` lint detects unnecessary braces around an"]
#[doc = r" expression."]
#[doc = r""]
#[doc = r" ### Example"]
#[doc = r""]
#[doc = r" ```rust"]
#[doc = r" if { true } {"]
#[doc = r"     // ..."]
#[doc = r" }"]
#[doc = r" ```"]
#[doc = r""]
#[doc = r" {{produces}}"]
#[doc = r""]
#[doc = r" ### Explanation"]
#[doc = r""]
#[doc = r" The braces are not needed, and should be removed. This is the"]
#[doc = r" preferred style for writing these expressions."]
pub(super) static UNUSED_BRACES: &::rustc_lint_defs::Lint =
    &::rustc_lint_defs::Lint {
            name: "UNUSED_BRACES",
            default_level: ::rustc_lint_defs::Warn,
            desc: "unnecessary braces around an expression",
            is_externally_loaded: false,
            ..::rustc_lint_defs::Lint::default_fields_for_macro()
        };declare_lint! {
1512    /// The `unused_braces` lint detects unnecessary braces around an
1513    /// expression.
1514    ///
1515    /// ### Example
1516    ///
1517    /// ```rust
1518    /// if { true } {
1519    ///     // ...
1520    /// }
1521    /// ```
1522    ///
1523    /// {{produces}}
1524    ///
1525    /// ### Explanation
1526    ///
1527    /// The braces are not needed, and should be removed. This is the
1528    /// preferred style for writing these expressions.
1529    pub(super) UNUSED_BRACES,
1530    Warn,
1531    "unnecessary braces around an expression"
1532}
1533
1534pub struct UnusedBraces;
#[automatically_derived]
impl ::core::marker::Copy for UnusedBraces { }
#[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for UnusedBraces { }
#[automatically_derived]
impl ::core::clone::Clone for UnusedBraces {
    #[inline]
    fn clone(&self) -> UnusedBraces { *self }
}
impl ::rustc_lint_defs::LintPass for UnusedBraces {
    fn name(&self) -> &'static str { "UnusedBraces" }
    fn get_lints(&self) -> ::rustc_lint_defs::LintVec {
        ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
                [UNUSED_BRACES]))
    }
}
impl UnusedBraces {
    #[allow(unused)]
    pub fn lint_vec() -> ::rustc_lint_defs::LintVec {
        ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
                [UNUSED_BRACES]))
    }
}declare_lint_pass!(UnusedBraces => [UNUSED_BRACES]);
1535
1536impl UnusedDelimLint for UnusedBraces {
1537    const DELIM_STR: &'static str = "braces";
1538
1539    const LINT_EXPR_IN_PATTERN_MATCHING_CTX: bool = false;
1540
1541    fn lint(&self) -> &'static Lint {
1542        UNUSED_BRACES
1543    }
1544
1545    fn check_unused_delims_expr(
1546        &self,
1547        cx: &EarlyContext<'_>,
1548        value: &ast::Expr,
1549        ctx: UnusedDelimsCtx,
1550        followed_by_block: bool,
1551        left_pos: Option<BytePos>,
1552        right_pos: Option<BytePos>,
1553        is_kw: bool,
1554    ) {
1555        match value.kind {
1556            ast::ExprKind::Block(ref inner, None)
1557                if inner.rules == ast::BlockCheckMode::Default =>
1558            {
1559                // emit a warning under the following conditions:
1560                //
1561                // - the block does not have a label
1562                // - the block is not `unsafe`
1563                // - the block contains exactly one expression (do not lint `{ expr; }`)
1564                // - `followed_by_block` is true and the internal expr may contain a `{`
1565                // - the block is not multiline (do not lint multiline match arms)
1566                //      ```
1567                //      match expr {
1568                //          Pattern => {
1569                //              somewhat_long_expression
1570                //          }
1571                //          // ...
1572                //      }
1573                //      ```
1574                // - the block has no attribute and was not created inside a macro
1575                // - if the block is an `anon_const`, the inner expr must be a literal
1576                //   not created by a macro, i.e. do not lint on:
1577                //      ```
1578                //      struct A<const N: usize>;
1579                //      let _: A<{ 2 + 3 }>;
1580                //      let _: A<{produces_literal!()}>;
1581                //      ```
1582                // FIXME(const_generics): handle paths when #67075 is fixed.
1583                if let [stmt] = inner.stmts.as_slice()
1584                    && let ast::StmtKind::Expr(ref expr) = stmt.kind
1585                    && !Self::is_expr_delims_necessary(expr, ctx, followed_by_block)
1586                    && (ctx != UnusedDelimsCtx::AnonConst
1587                        || (#[allow(non_exhaustive_omitted_patterns)] match expr.kind {
    ast::ExprKind::Lit(_) => true,
    _ => false,
}matches!(expr.kind, ast::ExprKind::Lit(_))
1588                            && !expr.span.from_expansion()))
1589                    && ctx != UnusedDelimsCtx::ClosureBody
1590                    && !cx.sess().source_map().is_multiline(value.span)
1591                    && value.attrs.is_empty()
1592                    && !value.span.from_expansion()
1593                    && !inner.span.from_expansion()
1594                {
1595                    self.emit_unused_delims_expr(cx, value, ctx, left_pos, right_pos, is_kw)
1596                }
1597            }
1598            ast::ExprKind::Let(_, ref expr, _, _) => {
1599                self.check_unused_delims_expr(
1600                    cx,
1601                    expr,
1602                    UnusedDelimsCtx::LetScrutineeExpr,
1603                    followed_by_block,
1604                    None,
1605                    None,
1606                    false,
1607                );
1608            }
1609            _ => {}
1610        }
1611    }
1612}
1613
1614impl EarlyLintPass for UnusedBraces {
1615    fn check_stmt(&mut self, cx: &EarlyContext<'_>, s: &ast::Stmt) {
1616        <Self as UnusedDelimLint>::check_stmt(self, cx, s)
1617    }
1618
1619    #[inline]
1620    fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &ast::Expr) {
1621        <Self as UnusedDelimLint>::check_expr(self, cx, e);
1622
1623        if let ExprKind::Repeat(_, ref anon_const) = e.kind {
1624            self.check_unused_delims_expr(
1625                cx,
1626                &anon_const.value,
1627                UnusedDelimsCtx::AnonConst,
1628                false,
1629                None,
1630                None,
1631                false,
1632            );
1633        }
1634    }
1635
1636    fn check_generic_arg(&mut self, cx: &EarlyContext<'_>, arg: &ast::GenericArg) {
1637        if let ast::GenericArg::Const(ct) = arg {
1638            self.check_unused_delims_expr(
1639                cx,
1640                &ct.value,
1641                UnusedDelimsCtx::AnonConst,
1642                false,
1643                None,
1644                None,
1645                false,
1646            );
1647        }
1648    }
1649
1650    fn check_variant(&mut self, cx: &EarlyContext<'_>, v: &ast::Variant) {
1651        if let Some(anon_const) = &v.disr_expr {
1652            self.check_unused_delims_expr(
1653                cx,
1654                &anon_const.value,
1655                UnusedDelimsCtx::AnonConst,
1656                false,
1657                None,
1658                None,
1659                false,
1660            );
1661        }
1662    }
1663
1664    fn check_ty(&mut self, cx: &EarlyContext<'_>, ty: &ast::Ty) {
1665        match ty.kind {
1666            ast::TyKind::Array(_, ref len) => {
1667                self.check_unused_delims_expr(
1668                    cx,
1669                    &len.value,
1670                    UnusedDelimsCtx::ArrayLenExpr,
1671                    false,
1672                    None,
1673                    None,
1674                    false,
1675                );
1676            }
1677
1678            _ => {}
1679        }
1680    }
1681
1682    fn check_item(&mut self, cx: &EarlyContext<'_>, item: &ast::Item) {
1683        <Self as UnusedDelimLint>::check_item(self, cx, item)
1684    }
1685}
1686
1687#[doc =
r" The `unused_import_braces` lint catches unnecessary braces around an"]
#[doc = r" imported item."]
#[doc = r""]
#[doc = r" ### Example"]
#[doc = r""]
#[doc = r" ```rust,compile_fail"]
#[doc = r" #![deny(unused_import_braces)]"]
#[doc = r" use test::{A};"]
#[doc = r""]
#[doc = r" pub mod test {"]
#[doc = r"     pub struct A;"]
#[doc = r" }"]
#[doc = r" # fn main() {}"]
#[doc = r" ```"]
#[doc = r""]
#[doc = r" {{produces}}"]
#[doc = r""]
#[doc = r" ### Explanation"]
#[doc = r""]
#[doc =
r" If there is only a single item, then remove the braces (`use test::A;`"]
#[doc = r" for example)."]
#[doc = r""]
#[doc = r#" This lint is "allow" by default because it is only enforcing a"#]
#[doc = r" stylistic choice."]
static UNUSED_IMPORT_BRACES: &::rustc_lint_defs::Lint =
    &::rustc_lint_defs::Lint {
            name: "UNUSED_IMPORT_BRACES",
            default_level: ::rustc_lint_defs::Allow,
            desc: "unnecessary braces around an imported item",
            is_externally_loaded: false,
            ..::rustc_lint_defs::Lint::default_fields_for_macro()
        };declare_lint! {
1688    /// The `unused_import_braces` lint catches unnecessary braces around an
1689    /// imported item.
1690    ///
1691    /// ### Example
1692    ///
1693    /// ```rust,compile_fail
1694    /// #![deny(unused_import_braces)]
1695    /// use test::{A};
1696    ///
1697    /// pub mod test {
1698    ///     pub struct A;
1699    /// }
1700    /// # fn main() {}
1701    /// ```
1702    ///
1703    /// {{produces}}
1704    ///
1705    /// ### Explanation
1706    ///
1707    /// If there is only a single item, then remove the braces (`use test::A;`
1708    /// for example).
1709    ///
1710    /// This lint is "allow" by default because it is only enforcing a
1711    /// stylistic choice.
1712    UNUSED_IMPORT_BRACES,
1713    Allow,
1714    "unnecessary braces around an imported item"
1715}
1716
1717pub struct UnusedImportBraces;
#[automatically_derived]
impl ::core::marker::Copy for UnusedImportBraces { }
#[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for UnusedImportBraces { }
#[automatically_derived]
impl ::core::clone::Clone for UnusedImportBraces {
    #[inline]
    fn clone(&self) -> UnusedImportBraces { *self }
}
impl ::rustc_lint_defs::LintPass for UnusedImportBraces {
    fn name(&self) -> &'static str { "UnusedImportBraces" }
    fn get_lints(&self) -> ::rustc_lint_defs::LintVec {
        ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
                [UNUSED_IMPORT_BRACES]))
    }
}
impl UnusedImportBraces {
    #[allow(unused)]
    pub fn lint_vec() -> ::rustc_lint_defs::LintVec {
        ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
                [UNUSED_IMPORT_BRACES]))
    }
}declare_lint_pass!(UnusedImportBraces => [UNUSED_IMPORT_BRACES]);
1718
1719impl UnusedImportBraces {
1720    fn check_use_tree(&self, cx: &EarlyContext<'_>, use_tree: &ast::UseTree, item: &ast::Item) {
1721        if let ast::UseTreeKind::Nested { ref items, .. } = use_tree.kind {
1722            // Recursively check nested UseTrees
1723            for (tree, _) in items {
1724                self.check_use_tree(cx, tree, item);
1725            }
1726
1727            // Trigger the lint only if there is one nested item
1728            let [(tree, _)] = items.as_slice() else { return };
1729
1730            // Trigger the lint if the nested item is a non-self single item
1731            let node_name = match tree.kind {
1732                ast::UseTreeKind::Simple(rename) => {
1733                    let orig_ident = tree.prefix.segments.last().unwrap().ident;
1734                    if orig_ident.name == kw::SelfLower {
1735                        return;
1736                    }
1737                    rename.unwrap_or(orig_ident).name
1738                }
1739                ast::UseTreeKind::Glob => sym::asterisk,
1740                ast::UseTreeKind::Nested { .. } => return,
1741            };
1742
1743            cx.emit_span_lint(
1744                UNUSED_IMPORT_BRACES,
1745                item.span,
1746                UnusedImportBracesDiag { node: node_name },
1747            );
1748        }
1749    }
1750}
1751
1752impl EarlyLintPass for UnusedImportBraces {
1753    fn check_item(&mut self, cx: &EarlyContext<'_>, item: &ast::Item) {
1754        if let ast::ItemKind::Use(ref use_tree) = item.kind {
1755            self.check_use_tree(cx, use_tree, item);
1756        }
1757    }
1758}
1759
1760#[doc =
r" The `unused_allocation` lint detects unnecessary allocations that can"]
#[doc = r" be eliminated."]
#[doc = r""]
#[doc = r" ### Example"]
#[doc = r""]
#[doc = r" ```rust"]
#[doc = r" fn main() {"]
#[doc = r"     let a = Box::new([1, 2, 3]).len();"]
#[doc = r" }"]
#[doc = r" ```"]
#[doc = r""]
#[doc = r" {{produces}}"]
#[doc = r""]
#[doc = r" ### Explanation"]
#[doc = r""]
#[doc =
r" When a `box` expression is immediately coerced to a reference, then"]
#[doc =
r" the allocation is unnecessary, and a reference (using `&` or `&mut`)"]
#[doc = r" should be used instead to avoid the allocation."]
pub(super) static UNUSED_ALLOCATION: &::rustc_lint_defs::Lint =
    &::rustc_lint_defs::Lint {
            name: "UNUSED_ALLOCATION",
            default_level: ::rustc_lint_defs::Warn,
            desc: "detects unnecessary allocations that can be eliminated",
            is_externally_loaded: false,
            ..::rustc_lint_defs::Lint::default_fields_for_macro()
        };declare_lint! {
1761    /// The `unused_allocation` lint detects unnecessary allocations that can
1762    /// be eliminated.
1763    ///
1764    /// ### Example
1765    ///
1766    /// ```rust
1767    /// fn main() {
1768    ///     let a = Box::new([1, 2, 3]).len();
1769    /// }
1770    /// ```
1771    ///
1772    /// {{produces}}
1773    ///
1774    /// ### Explanation
1775    ///
1776    /// When a `box` expression is immediately coerced to a reference, then
1777    /// the allocation is unnecessary, and a reference (using `&` or `&mut`)
1778    /// should be used instead to avoid the allocation.
1779    pub(super) UNUSED_ALLOCATION,
1780    Warn,
1781    "detects unnecessary allocations that can be eliminated"
1782}
1783
1784pub struct UnusedAllocation;
#[automatically_derived]
impl ::core::marker::Copy for UnusedAllocation { }
#[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for UnusedAllocation { }
#[automatically_derived]
impl ::core::clone::Clone for UnusedAllocation {
    #[inline]
    fn clone(&self) -> UnusedAllocation { *self }
}
impl ::rustc_lint_defs::LintPass for UnusedAllocation {
    fn name(&self) -> &'static str { "UnusedAllocation" }
    fn get_lints(&self) -> ::rustc_lint_defs::LintVec {
        ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
                [UNUSED_ALLOCATION]))
    }
}
impl UnusedAllocation {
    #[allow(unused)]
    pub fn lint_vec() -> ::rustc_lint_defs::LintVec {
        ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
                [UNUSED_ALLOCATION]))
    }
}declare_lint_pass!(UnusedAllocation => [UNUSED_ALLOCATION]);
1785
1786impl<'tcx> LateLintPass<'tcx> for UnusedAllocation {
1787    fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &hir::Expr<'_>) {
1788        match e.kind {
1789            hir::ExprKind::Call(path_expr, [_])
1790                if let hir::ExprKind::Path(qpath) = &path_expr.kind
1791                    && let Some(did) = cx.qpath_res(qpath, path_expr.hir_id).opt_def_id()
1792                    && cx.tcx.is_diagnostic_item(sym::box_new, did) => {}
1793            _ => return,
1794        }
1795
1796        for adj in cx.typeck_results().expr_adjustments(e) {
1797            if let adjustment::Adjust::Borrow(adjustment::AutoBorrow::Ref(m)) = adj.kind {
1798                if let ty::Ref(_, inner_ty, _) = adj.target.kind()
1799                    && inner_ty.is_box()
1800                {
1801                    // If the target type is `&Box<T>` or `&mut Box<T>`, the allocation is necessary
1802                    continue;
1803                }
1804                match m {
1805                    adjustment::AutoBorrowMutability::Not => {
1806                        cx.emit_span_lint(UNUSED_ALLOCATION, e.span, UnusedAllocationDiag);
1807                    }
1808                    adjustment::AutoBorrowMutability::Mut { .. } => {
1809                        cx.emit_span_lint(UNUSED_ALLOCATION, e.span, UnusedAllocationMutDiag);
1810                    }
1811                };
1812            }
1813        }
1814    }
1815}