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::attrs::AttributeKind;
8use rustc_hir::def::{DefKind, Res};
9use rustc_hir::def_id::DefId;
10use rustc_hir::{self as hir, LangItem, find_attr};
11use rustc_infer::traits::util::elaborate;
12use rustc_middle::ty::{self, Ty, adjustment};
13use rustc_session::{declare_lint, declare_lint_pass, impl_lint_pass};
14use rustc_span::edition::Edition::Edition2015;
15use rustc_span::{BytePos, Span, Symbol, kw, sym};
16use tracing::instrument;
17
18use crate::lints::{
19    PathStatementDrop, PathStatementDropSub, PathStatementNoEffect, UnusedAllocationDiag,
20    UnusedAllocationMutDiag, UnusedClosure, UnusedCoroutine, UnusedDef, UnusedDefSuggestion,
21    UnusedDelim, UnusedDelimSuggestion, UnusedImportBracesDiag, UnusedOp, UnusedOpSuggestion,
22    UnusedResult,
23};
24use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, Lint, LintContext};
25
26#[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! {
27    /// The `unused_must_use` lint detects unused result of a type flagged as
28    /// `#[must_use]`.
29    ///
30    /// ### Example
31    ///
32    /// ```rust
33    /// fn returns_result() -> Result<(), ()> {
34    ///     Ok(())
35    /// }
36    ///
37    /// fn main() {
38    ///     returns_result();
39    /// }
40    /// ```
41    ///
42    /// {{produces}}
43    ///
44    /// ### Explanation
45    ///
46    /// The `#[must_use]` attribute is an indicator that it is a mistake to
47    /// ignore the value. See [the reference] for more details.
48    ///
49    /// [the reference]: https://doc.rust-lang.org/reference/attributes/diagnostics.html#the-must_use-attribute
50    pub UNUSED_MUST_USE,
51    Warn,
52    "unused result of a type flagged as `#[must_use]`",
53    report_in_external_macro
54}
55
56#[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! {
57    /// The `unused_results` lint checks for the unused result of an
58    /// expression in a statement.
59    ///
60    /// ### Example
61    ///
62    /// ```rust,compile_fail
63    /// #![deny(unused_results)]
64    /// fn foo<T>() -> T { panic!() }
65    ///
66    /// fn main() {
67    ///     foo::<usize>();
68    /// }
69    /// ```
70    ///
71    /// {{produces}}
72    ///
73    /// ### Explanation
74    ///
75    /// Ignoring the return value of a function may indicate a mistake. In
76    /// cases were it is almost certain that the result should be used, it is
77    /// recommended to annotate the function with the [`must_use` attribute].
78    /// Failure to use such a return value will trigger the [`unused_must_use`
79    /// lint] which is warn-by-default. The `unused_results` lint is
80    /// essentially the same, but triggers for *all* return values.
81    ///
82    /// This lint is "allow" by default because it can be noisy, and may not be
83    /// an actual problem. For example, calling the `remove` method of a `Vec`
84    /// or `HashMap` returns the previous value, which you may not care about.
85    /// Using this lint would require explicitly ignoring or discarding such
86    /// values.
87    ///
88    /// [`must_use` attribute]: https://doc.rust-lang.org/reference/attributes/diagnostics.html#the-must_use-attribute
89    /// [`unused_must_use` lint]: warn-by-default.html#unused-must-use
90    pub UNUSED_RESULTS,
91    Allow,
92    "unused result of an expression in a statement"
93}
94
95pub 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 {
        <[_]>::into_vec(::alloc::boxed::box_new([UNUSED_MUST_USE,
                        UNUSED_RESULTS]))
    }
}
impl UnusedResults {
    #[allow(unused)]
    pub fn lint_vec() -> ::rustc_lint_defs::LintVec {
        <[_]>::into_vec(::alloc::boxed::box_new([UNUSED_MUST_USE,
                        UNUSED_RESULTS]))
    }
}declare_lint_pass!(UnusedResults => [UNUSED_MUST_USE, UNUSED_RESULTS]);
96
97impl<'tcx> LateLintPass<'tcx> for UnusedResults {
98    fn check_stmt(&mut self, cx: &LateContext<'_>, s: &hir::Stmt<'_>) {
99        let hir::StmtKind::Semi(mut expr) = s.kind else {
100            return;
101        };
102
103        let mut expr_is_from_block = false;
104        while let hir::ExprKind::Block(blk, ..) = expr.kind
105            && let hir::Block { expr: Some(e), .. } = blk
106        {
107            expr = e;
108            expr_is_from_block = true;
109        }
110
111        if let hir::ExprKind::Ret(..) = expr.kind {
112            return;
113        }
114
115        if let hir::ExprKind::Match(await_expr, _arms, hir::MatchSource::AwaitDesugar) = expr.kind
116            && let ty = cx.typeck_results().expr_ty(await_expr)
117            && let ty::Alias(ty::Opaque, ty::AliasTy { def_id: future_def_id, .. }) = ty.kind()
118            && cx.tcx.ty_is_opaque_future(ty)
119            && let async_fn_def_id = cx.tcx.parent(*future_def_id)
120            && #[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)
121            // Check that this `impl Future` actually comes from an `async fn`
122            && cx.tcx.asyncness(async_fn_def_id).is_async()
123            && check_must_use_def(
124                cx,
125                async_fn_def_id,
126                expr.span,
127                "output of future returned by ",
128                "",
129                expr_is_from_block,
130            )
131        {
132            // We have a bare `foo().await;` on an opaque type from an async function that was
133            // annotated with `#[must_use]`.
134            return;
135        }
136
137        let ty = cx.typeck_results().expr_ty(expr);
138
139        let must_use_result = is_ty_must_use(cx, ty, expr, expr.span);
140        let type_lint_emitted_or_suppressed = match must_use_result {
141            Some(path) => {
142                emit_must_use_untranslated(cx, &path, "", "", 1, false, expr_is_from_block);
143                true
144            }
145            None => false,
146        };
147
148        let fn_warned = check_fn_must_use(cx, expr, expr_is_from_block);
149
150        if !fn_warned && type_lint_emitted_or_suppressed {
151            // We don't warn about unused unit or uninhabited types.
152            // (See https://github.com/rust-lang/rust/issues/43806 for details.)
153            return;
154        }
155
156        let must_use_op = match expr.kind {
157            // Hardcoding operators here seemed more expedient than the
158            // refactoring that would be needed to look up the `#[must_use]`
159            // attribute which does exist on the comparison trait methods
160            hir::ExprKind::Binary(bin_op, ..) => match bin_op.node {
161                hir::BinOpKind::Eq
162                | hir::BinOpKind::Lt
163                | hir::BinOpKind::Le
164                | hir::BinOpKind::Ne
165                | hir::BinOpKind::Ge
166                | hir::BinOpKind::Gt => Some("comparison"),
167                hir::BinOpKind::Add
168                | hir::BinOpKind::Sub
169                | hir::BinOpKind::Div
170                | hir::BinOpKind::Mul
171                | hir::BinOpKind::Rem => Some("arithmetic operation"),
172                hir::BinOpKind::And | hir::BinOpKind::Or => Some("logical operation"),
173                hir::BinOpKind::BitXor
174                | hir::BinOpKind::BitAnd
175                | hir::BinOpKind::BitOr
176                | hir::BinOpKind::Shl
177                | hir::BinOpKind::Shr => Some("bitwise operation"),
178            },
179            hir::ExprKind::AddrOf(..) => Some("borrow"),
180            hir::ExprKind::OffsetOf(..) => Some("`offset_of` call"),
181            hir::ExprKind::Unary(..) => Some("unary operation"),
182            // The `offset_of` macro wraps its contents inside a `const` block.
183            hir::ExprKind::ConstBlock(block) => {
184                let body = cx.tcx.hir_body(block.body);
185                if let hir::ExprKind::Block(block, _) = body.value.kind
186                    && let Some(expr) = block.expr
187                    && let hir::ExprKind::OffsetOf(..) = expr.kind
188                {
189                    Some("`offset_of` call")
190                } else {
191                    None
192                }
193            }
194            _ => None,
195        };
196
197        let mut op_warned = false;
198
199        if let Some(must_use_op) = must_use_op {
200            let span = expr.span.find_ancestor_not_from_macro().unwrap_or(expr.span);
201            cx.emit_span_lint(
202                UNUSED_MUST_USE,
203                expr.span,
204                UnusedOp {
205                    op: must_use_op,
206                    label: expr.span,
207                    suggestion: if expr_is_from_block {
208                        UnusedOpSuggestion::BlockTailExpr {
209                            before_span: span.shrink_to_lo(),
210                            after_span: span.shrink_to_hi(),
211                        }
212                    } else {
213                        UnusedOpSuggestion::NormalExpr { span: span.shrink_to_lo() }
214                    },
215                },
216            );
217            op_warned = true;
218        }
219
220        if !(type_lint_emitted_or_suppressed || fn_warned || op_warned) {
221            cx.emit_span_lint(UNUSED_RESULTS, s.span, UnusedResult { ty });
222        }
223
224        fn check_fn_must_use(
225            cx: &LateContext<'_>,
226            expr: &hir::Expr<'_>,
227            expr_is_from_block: bool,
228        ) -> bool {
229            let maybe_def_id = match expr.kind {
230                hir::ExprKind::Call(callee, _) => {
231                    match callee.kind {
232                        hir::ExprKind::Path(ref qpath) => {
233                            match cx.qpath_res(qpath, callee.hir_id) {
234                                Res::Def(DefKind::Fn | DefKind::AssocFn, def_id) => Some(def_id),
235                                // `Res::Local` if it was a closure, for which we
236                                // do not currently support must-use linting
237                                _ => None,
238                            }
239                        }
240                        _ => None,
241                    }
242                }
243                hir::ExprKind::MethodCall(..) => {
244                    cx.typeck_results().type_dependent_def_id(expr.hir_id)
245                }
246                _ => None,
247            };
248            if let Some(def_id) = maybe_def_id {
249                check_must_use_def(
250                    cx,
251                    def_id,
252                    expr.span,
253                    "return value of ",
254                    "",
255                    expr_is_from_block,
256                )
257            } else {
258                false
259            }
260        }
261
262        /// A path through a type to a must_use source. Contains useful info for the lint.
263        #[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)]
264        enum MustUsePath {
265            /// Suppress must_use checking.
266            Suppressed,
267            /// The root of the normal must_use lint with an optional message.
268            Def(Span, DefId, Option<Symbol>),
269            Boxed(Box<Self>),
270            Pinned(Box<Self>),
271            Opaque(Box<Self>),
272            TraitObject(Box<Self>),
273            TupleElement(Vec<(usize, Self)>),
274            Array(Box<Self>, u64),
275            /// The root of the unused_closures lint.
276            Closure(Span),
277            /// The root of the unused_coroutines lint.
278            Coroutine(Span),
279        }
280
281        x;#[instrument(skip(cx, expr), level = "debug", ret)]
282        fn is_ty_must_use<'tcx>(
283            cx: &LateContext<'tcx>,
284            ty: Ty<'tcx>,
285            expr: &hir::Expr<'_>,
286            span: Span,
287        ) -> Option<MustUsePath> {
288            if ty.is_unit() {
289                return Some(MustUsePath::Suppressed);
290            }
291            let parent_mod_did = cx.tcx.parent_module(expr.hir_id).to_def_id();
292            let is_uninhabited =
293                |t: Ty<'tcx>| !t.is_inhabited_from(cx.tcx, parent_mod_did, cx.typing_env());
294            if is_uninhabited(ty) {
295                return Some(MustUsePath::Suppressed);
296            }
297
298            match *ty.kind() {
299                ty::Adt(..) if let Some(boxed) = ty.boxed_ty() => {
300                    is_ty_must_use(cx, boxed, expr, span)
301                        .map(|inner| MustUsePath::Boxed(Box::new(inner)))
302                }
303                ty::Adt(def, args) if cx.tcx.is_lang_item(def.did(), LangItem::Pin) => {
304                    let pinned_ty = args.type_at(0);
305                    is_ty_must_use(cx, pinned_ty, expr, span)
306                        .map(|inner| MustUsePath::Pinned(Box::new(inner)))
307                }
308                // Suppress warnings on `Result<(), Uninhabited>` (e.g. `Result<(), !>`).
309                ty::Adt(def, args)
310                    if cx.tcx.is_diagnostic_item(sym::Result, def.did())
311                        && args.type_at(0).is_unit()
312                        && is_uninhabited(args.type_at(1)) =>
313                {
314                    Some(MustUsePath::Suppressed)
315                }
316                // Suppress warnings on `ControlFlow<Uninhabited, ()>` (e.g. `ControlFlow<!, ()>`).
317                ty::Adt(def, args)
318                    if cx.tcx.is_diagnostic_item(sym::ControlFlow, def.did())
319                        && args.type_at(1).is_unit()
320                        && is_uninhabited(args.type_at(0)) =>
321                {
322                    Some(MustUsePath::Suppressed)
323                }
324                ty::Adt(def, _) => is_def_must_use(cx, def.did(), span),
325                ty::Alias(ty::Opaque | ty::Projection, ty::AliasTy { def_id: def, .. }) => {
326                    elaborate(cx.tcx, cx.tcx.explicit_item_self_bounds(def).iter_identity_copied())
327                        // We only care about self bounds for the impl-trait
328                        .filter_only_self()
329                        .find_map(|(pred, _span)| {
330                            // We only look at the `DefId`, so it is safe to skip the binder here.
331                            if let ty::ClauseKind::Trait(ref poly_trait_predicate) =
332                                pred.kind().skip_binder()
333                            {
334                                let def_id = poly_trait_predicate.trait_ref.def_id;
335
336                                is_def_must_use(cx, def_id, span)
337                            } else {
338                                None
339                            }
340                        })
341                        .map(|inner| MustUsePath::Opaque(Box::new(inner)))
342                }
343                ty::Dynamic(binders, _) => binders.iter().find_map(|predicate| {
344                    if let ty::ExistentialPredicate::Trait(ref trait_ref) = predicate.skip_binder()
345                    {
346                        let def_id = trait_ref.def_id;
347                        is_def_must_use(cx, def_id, span)
348                            .map(|inner| MustUsePath::TraitObject(Box::new(inner)))
349                    } else {
350                        None
351                    }
352                }),
353                ty::Tuple(tys) => {
354                    let elem_exprs = if let hir::ExprKind::Tup(elem_exprs) = expr.kind {
355                        debug_assert_eq!(elem_exprs.len(), tys.len());
356                        elem_exprs
357                    } else {
358                        &[]
359                    };
360
361                    // Default to `expr`.
362                    let elem_exprs = elem_exprs.iter().chain(iter::repeat(expr));
363
364                    let nested_must_use = tys
365                        .iter()
366                        .zip(elem_exprs)
367                        .enumerate()
368                        .filter_map(|(i, (ty, expr))| {
369                            is_ty_must_use(cx, ty, expr, expr.span).map(|path| (i, path))
370                        })
371                        .collect::<Vec<_>>();
372
373                    if !nested_must_use.is_empty() {
374                        Some(MustUsePath::TupleElement(nested_must_use))
375                    } else {
376                        None
377                    }
378                }
379                ty::Array(ty, len) => match len.try_to_target_usize(cx.tcx) {
380                    // If the array is empty we don't lint, to avoid false positives
381                    Some(0) | None => None,
382                    // If the array is definitely non-empty, we can do `#[must_use]` checking.
383                    Some(len) => is_ty_must_use(cx, ty, expr, span)
384                        .map(|inner| MustUsePath::Array(Box::new(inner), len)),
385                },
386                ty::Closure(..) | ty::CoroutineClosure(..) => Some(MustUsePath::Closure(span)),
387                ty::Coroutine(def_id, ..) => {
388                    // async fn should be treated as "implementor of `Future`"
389                    let must_use = if cx.tcx.coroutine_is_async(def_id) {
390                        let def_id = cx.tcx.lang_items().future_trait()?;
391                        is_def_must_use(cx, def_id, span)
392                            .map(|inner| MustUsePath::Opaque(Box::new(inner)))
393                    } else {
394                        None
395                    };
396                    must_use.or(Some(MustUsePath::Coroutine(span)))
397                }
398                _ => None,
399            }
400        }
401
402        fn is_def_must_use(cx: &LateContext<'_>, def_id: DefId, span: Span) -> Option<MustUsePath> {
403            if let Some(reason) = {
    'done:
        {
        for i in cx.tcx.get_all_attrs(def_id) {
            let i: &rustc_hir::Attribute = i;
            match i {
                rustc_hir::Attribute::Parsed(AttributeKind::MustUse { reason,
                    .. }) => {
                    break 'done Some(reason);
                }
                _ => {}
            }
        }
        None
    }
}find_attr!(
404                cx.tcx.get_all_attrs(def_id),
405                AttributeKind::MustUse { reason, .. } => reason
406            ) {
407                // check for #[must_use = "..."]
408                Some(MustUsePath::Def(span, def_id, *reason))
409            } else {
410                None
411            }
412        }
413
414        // Returns whether further errors should be suppressed because either a lint has been
415        // emitted or the type should be ignored.
416        fn check_must_use_def(
417            cx: &LateContext<'_>,
418            def_id: DefId,
419            span: Span,
420            descr_pre_path: &str,
421            descr_post_path: &str,
422            expr_is_from_block: bool,
423        ) -> bool {
424            is_def_must_use(cx, def_id, span)
425                .map(|must_use_path| {
426                    emit_must_use_untranslated(
427                        cx,
428                        &must_use_path,
429                        descr_pre_path,
430                        descr_post_path,
431                        1,
432                        false,
433                        expr_is_from_block,
434                    )
435                })
436                .is_some()
437        }
438
439        #[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(439u32),
                                    ::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")]
440        fn emit_must_use_untranslated(
441            cx: &LateContext<'_>,
442            path: &MustUsePath,
443            descr_pre: &str,
444            descr_post: &str,
445            plural_len: usize,
446            is_inner: bool,
447            expr_is_from_block: bool,
448        ) {
449            let plural_suffix = pluralize!(plural_len);
450
451            match path {
452                MustUsePath::Suppressed => {}
453                MustUsePath::Boxed(path) => {
454                    let descr_pre = &format!("{descr_pre}boxed ");
455                    emit_must_use_untranslated(
456                        cx,
457                        path,
458                        descr_pre,
459                        descr_post,
460                        plural_len,
461                        true,
462                        expr_is_from_block,
463                    );
464                }
465                MustUsePath::Pinned(path) => {
466                    let descr_pre = &format!("{descr_pre}pinned ");
467                    emit_must_use_untranslated(
468                        cx,
469                        path,
470                        descr_pre,
471                        descr_post,
472                        plural_len,
473                        true,
474                        expr_is_from_block,
475                    );
476                }
477                MustUsePath::Opaque(path) => {
478                    let descr_pre = &format!("{descr_pre}implementer{plural_suffix} of ");
479                    emit_must_use_untranslated(
480                        cx,
481                        path,
482                        descr_pre,
483                        descr_post,
484                        plural_len,
485                        true,
486                        expr_is_from_block,
487                    );
488                }
489                MustUsePath::TraitObject(path) => {
490                    let descr_post = &format!(" trait object{plural_suffix}{descr_post}");
491                    emit_must_use_untranslated(
492                        cx,
493                        path,
494                        descr_pre,
495                        descr_post,
496                        plural_len,
497                        true,
498                        expr_is_from_block,
499                    );
500                }
501                MustUsePath::TupleElement(elems) => {
502                    for (index, path) in elems {
503                        let descr_post = &format!(" in tuple element {index}");
504                        emit_must_use_untranslated(
505                            cx,
506                            path,
507                            descr_pre,
508                            descr_post,
509                            plural_len,
510                            true,
511                            expr_is_from_block,
512                        );
513                    }
514                }
515                MustUsePath::Array(path, len) => {
516                    let descr_pre = &format!("{descr_pre}array{plural_suffix} of ");
517                    emit_must_use_untranslated(
518                        cx,
519                        path,
520                        descr_pre,
521                        descr_post,
522                        plural_len.saturating_add(usize::try_from(*len).unwrap_or(usize::MAX)),
523                        true,
524                        expr_is_from_block,
525                    );
526                }
527                MustUsePath::Closure(span) => {
528                    cx.emit_span_lint(
529                        UNUSED_MUST_USE,
530                        *span,
531                        UnusedClosure { count: plural_len, pre: descr_pre, post: descr_post },
532                    );
533                }
534                MustUsePath::Coroutine(span) => {
535                    cx.emit_span_lint(
536                        UNUSED_MUST_USE,
537                        *span,
538                        UnusedCoroutine { count: plural_len, pre: descr_pre, post: descr_post },
539                    );
540                }
541                MustUsePath::Def(span, def_id, reason) => {
542                    let ancenstor_span = span.find_ancestor_not_from_macro().unwrap_or(*span);
543                    let is_redundant_let_ignore = cx
544                        .sess()
545                        .source_map()
546                        .span_to_prev_source(ancenstor_span)
547                        .ok()
548                        .map(|prev| prev.trim_end().ends_with("let _ ="))
549                        .unwrap_or(false);
550                    let suggestion_span =
551                        if is_redundant_let_ignore { *span } else { ancenstor_span };
552                    cx.emit_span_lint(
553                        UNUSED_MUST_USE,
554                        ancenstor_span,
555                        UnusedDef {
556                            pre: descr_pre,
557                            post: descr_post,
558                            cx,
559                            def_id: *def_id,
560                            note: *reason,
561                            suggestion: (!is_inner).then_some(if expr_is_from_block {
562                                UnusedDefSuggestion::BlockTailExpr {
563                                    before_span: suggestion_span.shrink_to_lo(),
564                                    after_span: suggestion_span.shrink_to_hi(),
565                                }
566                            } else {
567                                UnusedDefSuggestion::NormalExpr {
568                                    span: suggestion_span.shrink_to_lo(),
569                                }
570                            }),
571                        },
572                    );
573                }
574            }
575        }
576    }
577}
578
579#[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! {
580    /// The `path_statements` lint detects path statements with no effect.
581    ///
582    /// ### Example
583    ///
584    /// ```rust
585    /// let x = 42;
586    ///
587    /// x;
588    /// ```
589    ///
590    /// {{produces}}
591    ///
592    /// ### Explanation
593    ///
594    /// It is usually a mistake to have a statement that has no effect.
595    pub PATH_STATEMENTS,
596    Warn,
597    "path statements with no effect"
598}
599
600pub 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 {
        <[_]>::into_vec(::alloc::boxed::box_new([PATH_STATEMENTS]))
    }
}
impl PathStatements {
    #[allow(unused)]
    pub fn lint_vec() -> ::rustc_lint_defs::LintVec {
        <[_]>::into_vec(::alloc::boxed::box_new([PATH_STATEMENTS]))
    }
}declare_lint_pass!(PathStatements => [PATH_STATEMENTS]);
601
602impl<'tcx> LateLintPass<'tcx> for PathStatements {
603    fn check_stmt(&mut self, cx: &LateContext<'_>, s: &hir::Stmt<'_>) {
604        if let hir::StmtKind::Semi(expr) = s.kind
605            && let hir::ExprKind::Path(_) = expr.kind
606        {
607            let ty = cx.typeck_results().expr_ty(expr);
608            if ty.needs_drop(cx.tcx, cx.typing_env()) {
609                let sub = if let Ok(snippet) = cx.sess().source_map().span_to_snippet(expr.span) {
610                    PathStatementDropSub::Suggestion { span: s.span, snippet }
611                } else {
612                    PathStatementDropSub::Help { span: s.span }
613                };
614                cx.emit_span_lint(PATH_STATEMENTS, s.span, PathStatementDrop { sub })
615            } else {
616                cx.emit_span_lint(PATH_STATEMENTS, s.span, PathStatementNoEffect);
617            }
618        }
619    }
620}
621
622#[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)]
623enum UnusedDelimsCtx {
624    FunctionArg,
625    MethodArg,
626    AssignedValue,
627    AssignedValueLetElse,
628    IfCond,
629    WhileCond,
630    ForIterExpr,
631    MatchScrutineeExpr,
632    ReturnValue,
633    BlockRetValue,
634    BreakValue,
635    LetScrutineeExpr,
636    ArrayLenExpr,
637    AnonConst,
638    MatchArmExpr,
639    IndexExpr,
640    ClosureBody,
641}
642
643impl From<UnusedDelimsCtx> for &'static str {
644    fn from(ctx: UnusedDelimsCtx) -> &'static str {
645        match ctx {
646            UnusedDelimsCtx::FunctionArg => "function argument",
647            UnusedDelimsCtx::MethodArg => "method argument",
648            UnusedDelimsCtx::AssignedValue | UnusedDelimsCtx::AssignedValueLetElse => {
649                "assigned value"
650            }
651            UnusedDelimsCtx::IfCond => "`if` condition",
652            UnusedDelimsCtx::WhileCond => "`while` condition",
653            UnusedDelimsCtx::ForIterExpr => "`for` iterator expression",
654            UnusedDelimsCtx::MatchScrutineeExpr => "`match` scrutinee expression",
655            UnusedDelimsCtx::ReturnValue => "`return` value",
656            UnusedDelimsCtx::BlockRetValue => "block return value",
657            UnusedDelimsCtx::BreakValue => "`break` value",
658            UnusedDelimsCtx::LetScrutineeExpr => "`let` scrutinee expression",
659            UnusedDelimsCtx::ArrayLenExpr | UnusedDelimsCtx::AnonConst => "const expression",
660            UnusedDelimsCtx::MatchArmExpr => "match arm expression",
661            UnusedDelimsCtx::IndexExpr => "index expression",
662            UnusedDelimsCtx::ClosureBody => "closure body",
663        }
664    }
665}
666
667/// Used by both `UnusedParens` and `UnusedBraces` to prevent code duplication.
668trait UnusedDelimLint {
669    const DELIM_STR: &'static str;
670
671    /// Due to `ref` pattern, there can be a difference between using
672    /// `{ expr }` and `expr` in pattern-matching contexts. This means
673    /// that we should only lint `unused_parens` and not `unused_braces`
674    /// in this case.
675    ///
676    /// ```rust
677    /// let mut a = 7;
678    /// let ref b = { a }; // We actually borrow a copy of `a` here.
679    /// a += 1; // By mutating `a` we invalidate any borrows of `a`.
680    /// assert_eq!(b + 1, a); // `b` does not borrow `a`, so we can still use it here.
681    /// ```
682    const LINT_EXPR_IN_PATTERN_MATCHING_CTX: bool;
683
684    // this cannot be a constant is it refers to a static.
685    fn lint(&self) -> &'static Lint;
686
687    fn check_unused_delims_expr(
688        &self,
689        cx: &EarlyContext<'_>,
690        value: &ast::Expr,
691        ctx: UnusedDelimsCtx,
692        followed_by_block: bool,
693        left_pos: Option<BytePos>,
694        right_pos: Option<BytePos>,
695        is_kw: bool,
696    );
697
698    fn is_expr_delims_necessary(
699        inner: &ast::Expr,
700        ctx: UnusedDelimsCtx,
701        followed_by_block: bool,
702    ) -> bool {
703        let followed_by_else = ctx == UnusedDelimsCtx::AssignedValueLetElse;
704
705        if followed_by_else {
706            match inner.kind {
707                ast::ExprKind::Binary(op, ..) if op.node.is_lazy() => return true,
708                _ if classify::expr_trailing_brace(inner).is_some() => return true,
709                _ => {}
710            }
711        }
712
713        // Check it's range in LetScrutineeExpr
714        if let ast::ExprKind::Range(..) = inner.kind
715            && #[allow(non_exhaustive_omitted_patterns)] match ctx {
    UnusedDelimsCtx::LetScrutineeExpr => true,
    _ => false,
}matches!(ctx, UnusedDelimsCtx::LetScrutineeExpr)
716        {
717            return true;
718        }
719
720        // Do not lint against parentheses around `&raw [const|mut] expr`.
721        // These parentheses will have to be added e.g. when calling a method on the result of this
722        // expression, and we want to avoid churn wrt adding and removing parentheses.
723        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, ..)) {
724            return true;
725        }
726
727        // Check if LHS needs parens to prevent false-positives in cases like
728        // `fn x() -> u8 { ({ 0 } + 1) }`.
729        //
730        // FIXME: https://github.com/rust-lang/rust/issues/119426
731        // The syntax tree in this code is from after macro expansion, so the
732        // current implementation has both false negatives and false positives
733        // related to expressions containing macros.
734        //
735        //     macro_rules! m1 {
736        //         () => {
737        //             1
738        //         };
739        //     }
740        //
741        //     fn f1() -> u8 {
742        //         // Lint says parens are not needed, but they are.
743        //         (m1! {} + 1)
744        //     }
745        //
746        //     macro_rules! m2 {
747        //         () => {
748        //             loop { break 1; }
749        //         };
750        //     }
751        //
752        //     fn f2() -> u8 {
753        //         // Lint says parens are needed, but they are not.
754        //         (m2!() + 1)
755        //     }
756        {
757            let mut innermost = inner;
758            loop {
759                innermost = match &innermost.kind {
760                    ExprKind::Binary(_op, lhs, _rhs) => lhs,
761                    ExprKind::Call(fn_, _params) => fn_,
762                    ExprKind::Cast(expr, _ty) => expr,
763                    ExprKind::Type(expr, _ty) => expr,
764                    ExprKind::Index(base, _subscript, _) => base,
765                    _ => break,
766                };
767                if !classify::expr_requires_semi_to_be_stmt(innermost) {
768                    return true;
769                }
770            }
771        }
772
773        // Check if RHS needs parens to prevent false-positives in cases like `if (() == return)
774        // {}`.
775        if !followed_by_block {
776            return false;
777        }
778
779        // Check if we need parens for `match &( Struct { field:  }) {}`.
780        {
781            let mut innermost = inner;
782            loop {
783                innermost = match &innermost.kind {
784                    ExprKind::AddrOf(_, _, expr) => expr,
785                    _ => {
786                        if parser::contains_exterior_struct_lit(innermost) {
787                            return true;
788                        } else {
789                            break;
790                        }
791                    }
792                }
793            }
794        }
795
796        let mut innermost = inner;
797        loop {
798            innermost = match &innermost.kind {
799                ExprKind::Unary(_op, expr) => expr,
800                ExprKind::Binary(_op, _lhs, rhs) => rhs,
801                ExprKind::AssignOp(_op, _lhs, rhs) => rhs,
802                ExprKind::Assign(_lhs, rhs, _span) => rhs,
803
804                ExprKind::Ret(_) | ExprKind::Yield(..) | ExprKind::Yeet(..) => return true,
805
806                ExprKind::Break(_label, None) => return false,
807                ExprKind::Break(_label, Some(break_expr)) => {
808                    // `if (break 'label i) { ... }` removing parens would make `i { ... }`
809                    // be parsed as a struct literal, so keep parentheses if the break value
810                    // ends with a path (which could be mistaken for a struct name).
811                    return #[allow(non_exhaustive_omitted_patterns)] match break_expr.kind {
    ExprKind::Block(..) | ExprKind::Path(..) => true,
    _ => false,
}matches!(break_expr.kind, ExprKind::Block(..) | ExprKind::Path(..));
812                }
813
814                ExprKind::Range(_lhs, Some(rhs), _limits) => {
815                    return #[allow(non_exhaustive_omitted_patterns)] match rhs.kind {
    ExprKind::Block(..) => true,
    _ => false,
}matches!(rhs.kind, ExprKind::Block(..));
816                }
817
818                _ => return parser::contains_exterior_struct_lit(inner),
819            }
820        }
821    }
822
823    fn emit_unused_delims_expr(
824        &self,
825        cx: &EarlyContext<'_>,
826        value: &ast::Expr,
827        ctx: UnusedDelimsCtx,
828        left_pos: Option<BytePos>,
829        right_pos: Option<BytePos>,
830        is_kw: bool,
831    ) {
832        let span_with_attrs = match value.kind {
833            ast::ExprKind::Block(ref block, None) if let [stmt] = block.stmts.as_slice() => {
834                // For the statements with attributes, like `{ #[allow()] println!("Hello!") }`,
835                // the span should contains the attributes, or the suggestion will remove them.
836                if let Some(attr_lo) = stmt.attrs().iter().map(|attr| attr.span.lo()).min() {
837                    stmt.span.with_lo(attr_lo)
838                } else {
839                    stmt.span
840                }
841            }
842            ast::ExprKind::Paren(ref expr) => {
843                // For the expr with attributes, like `let _ = (#[inline] || println!("Hello!"));`,
844                // the span should contains the attributes, or the suggestion will remove them.
845                if let Some(attr_lo) = expr.attrs.iter().map(|attr| attr.span.lo()).min() {
846                    expr.span.with_lo(attr_lo)
847                } else {
848                    expr.span
849                }
850            }
851            _ => return,
852        };
853        let spans = span_with_attrs
854            .find_ancestor_inside(value.span)
855            .map(|span| (value.span.with_hi(span.lo()), value.span.with_lo(span.hi())));
856        let keep_space = (
857            left_pos.is_some_and(|s| s >= value.span.lo()),
858            right_pos.is_some_and(|s| s <= value.span.hi()),
859        );
860        self.emit_unused_delims(cx, value.span, spans, ctx.into(), keep_space, is_kw);
861    }
862
863    fn emit_unused_delims(
864        &self,
865        cx: &EarlyContext<'_>,
866        value_span: Span,
867        spans: Option<(Span, Span)>,
868        msg: &str,
869        keep_space: (bool, bool),
870        is_kw: bool,
871    ) {
872        let primary_span = if let Some((lo, hi)) = spans {
873            if hi.is_empty() {
874                // do not point at delims that do not exist
875                return;
876            }
877            MultiSpan::from(<[_]>::into_vec(::alloc::boxed::box_new([lo, hi]))vec![lo, hi])
878        } else {
879            MultiSpan::from(value_span)
880        };
881        let suggestion = spans.map(|(lo, hi)| {
882            let sm = cx.sess().source_map();
883            let lo_replace = if (keep_space.0 || is_kw)
884                && let Ok(snip) = sm.span_to_prev_source(lo)
885                && !snip.ends_with(' ')
886            {
887                " "
888            } else if let Ok(snip) = sm.span_to_prev_source(value_span)
889                && snip.ends_with(|c: char| c.is_alphanumeric())
890            {
891                " "
892            } else {
893                ""
894            };
895
896            let hi_replace = if keep_space.1
897                && let Ok(snip) = sm.span_to_next_source(hi)
898                && !snip.starts_with(' ')
899            {
900                " "
901            } else if let Ok(snip) = sm.span_to_prev_source(value_span)
902                && snip.starts_with(|c: char| c.is_alphanumeric())
903            {
904                " "
905            } else {
906                ""
907            };
908            UnusedDelimSuggestion {
909                start_span: lo,
910                start_replace: lo_replace,
911                end_span: hi,
912                end_replace: hi_replace,
913            }
914        });
915        cx.emit_span_lint(
916            self.lint(),
917            primary_span,
918            UnusedDelim { delim: Self::DELIM_STR, item: msg, suggestion },
919        );
920    }
921
922    fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &ast::Expr) {
923        use rustc_ast::ExprKind::*;
924        let (value, ctx, followed_by_block, left_pos, right_pos, is_kw) = match e.kind {
925            // Do not lint `unused_braces` in `if let` expressions.
926            If(ref cond, ref block, _)
927                if !#[allow(non_exhaustive_omitted_patterns)] match cond.kind {
    Let(..) => true,
    _ => false,
}matches!(cond.kind, Let(..)) || Self::LINT_EXPR_IN_PATTERN_MATCHING_CTX =>
928            {
929                let left = e.span.lo() + rustc_span::BytePos(2);
930                let right = block.span.lo();
931                (cond, UnusedDelimsCtx::IfCond, true, Some(left), Some(right), true)
932            }
933
934            // Do not lint `unused_braces` in `while let` expressions.
935            While(ref cond, ref block, ..)
936                if !#[allow(non_exhaustive_omitted_patterns)] match cond.kind {
    Let(..) => true,
    _ => false,
}matches!(cond.kind, Let(..)) || Self::LINT_EXPR_IN_PATTERN_MATCHING_CTX =>
937            {
938                let left = e.span.lo() + rustc_span::BytePos(5);
939                let right = block.span.lo();
940                (cond, UnusedDelimsCtx::WhileCond, true, Some(left), Some(right), true)
941            }
942
943            ForLoop { ref iter, ref body, .. } => {
944                (iter, UnusedDelimsCtx::ForIterExpr, true, None, Some(body.span.lo()), true)
945            }
946
947            Match(ref head, _, ast::MatchKind::Prefix)
948                if Self::LINT_EXPR_IN_PATTERN_MATCHING_CTX =>
949            {
950                let left = e.span.lo() + rustc_span::BytePos(5);
951                (head, UnusedDelimsCtx::MatchScrutineeExpr, true, Some(left), None, true)
952            }
953
954            Ret(Some(ref value)) => {
955                let left = e.span.lo() + rustc_span::BytePos(3);
956                (value, UnusedDelimsCtx::ReturnValue, false, Some(left), None, true)
957            }
958
959            Break(label, Some(ref value)) => {
960                // Don't lint on `break 'label ({...})` - the parens are necessary
961                // to disambiguate from `break 'label {...}` which would be a syntax error.
962                // This avoids conflicts with the `break_with_label_and_loop` lint.
963                if label.is_some()
964                    && #[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)
965                        if matches!(inner.kind, ast::ExprKind::Block(..)))
966                {
967                    return;
968                }
969                (value, UnusedDelimsCtx::BreakValue, false, None, None, true)
970            }
971
972            Index(_, ref value, _) => (value, UnusedDelimsCtx::IndexExpr, false, None, None, false),
973
974            Assign(_, ref value, _) | AssignOp(.., ref value) => {
975                (value, UnusedDelimsCtx::AssignedValue, false, None, None, false)
976            }
977            // either function/method call, or something this lint doesn't care about
978            ref call_or_other => {
979                let (args_to_check, ctx) = match *call_or_other {
980                    Call(_, ref args) => (&args[..], UnusedDelimsCtx::FunctionArg),
981                    MethodCall(ref call) => (&call.args[..], UnusedDelimsCtx::MethodArg),
982                    Closure(ref closure)
983                        if #[allow(non_exhaustive_omitted_patterns)] match closure.fn_decl.output {
    FnRetTy::Default(_) => true,
    _ => false,
}matches!(closure.fn_decl.output, FnRetTy::Default(_)) =>
984                    {
985                        (&[closure.body.clone()][..], UnusedDelimsCtx::ClosureBody)
986                    }
987                    // actual catch-all arm
988                    _ => {
989                        return;
990                    }
991                };
992                // Don't lint if this is a nested macro expansion: otherwise, the lint could
993                // trigger in situations that macro authors shouldn't have to care about, e.g.,
994                // when a parenthesized token tree matched in one macro expansion is matched as
995                // an expression in another and used as a fn/method argument (Issue #47775)
996                if e.span.ctxt().outer_expn_data().call_site.from_expansion() {
997                    return;
998                }
999                for arg in args_to_check {
1000                    self.check_unused_delims_expr(cx, arg, ctx, false, None, None, false);
1001                }
1002                return;
1003            }
1004        };
1005        self.check_unused_delims_expr(
1006            cx,
1007            value,
1008            ctx,
1009            followed_by_block,
1010            left_pos,
1011            right_pos,
1012            is_kw,
1013        );
1014    }
1015
1016    fn check_stmt(&mut self, cx: &EarlyContext<'_>, s: &ast::Stmt) {
1017        match s.kind {
1018            StmtKind::Let(ref local) if Self::LINT_EXPR_IN_PATTERN_MATCHING_CTX => {
1019                if let Some((init, els)) = local.kind.init_else_opt() {
1020                    if els.is_some()
1021                        && let ExprKind::Paren(paren) = &init.kind
1022                        && !init.span.eq_ctxt(paren.span)
1023                    {
1024                        // This branch prevents cases where parentheses wrap an expression
1025                        // resulting from macro expansion, such as:
1026                        // ```
1027                        // macro_rules! x {
1028                        // () => { None::<i32> };
1029                        // }
1030                        // let Some(_) = (x!{}) else { return };
1031                        // // -> let Some(_) = (None::<i32>) else { return };
1032                        // //                  ~           ~ No Lint
1033                        // ```
1034                        return;
1035                    }
1036                    let ctx = match els {
1037                        None => UnusedDelimsCtx::AssignedValue,
1038                        Some(_) => UnusedDelimsCtx::AssignedValueLetElse,
1039                    };
1040                    self.check_unused_delims_expr(cx, init, ctx, false, None, None, false);
1041                }
1042            }
1043            StmtKind::Expr(ref expr) => {
1044                self.check_unused_delims_expr(
1045                    cx,
1046                    expr,
1047                    UnusedDelimsCtx::BlockRetValue,
1048                    false,
1049                    None,
1050                    None,
1051                    false,
1052                );
1053            }
1054            _ => {}
1055        }
1056    }
1057
1058    fn check_item(&mut self, cx: &EarlyContext<'_>, item: &ast::Item) {
1059        use ast::ItemKind::*;
1060
1061        let expr = if let Const(box ast::ConstItem { rhs: Some(rhs), .. }) = &item.kind {
1062            rhs.expr()
1063        } else if let Static(box ast::StaticItem { expr: Some(expr), .. }) = &item.kind {
1064            expr
1065        } else {
1066            return;
1067        };
1068        self.check_unused_delims_expr(
1069            cx,
1070            expr,
1071            UnusedDelimsCtx::AssignedValue,
1072            false,
1073            None,
1074            None,
1075            false,
1076        );
1077    }
1078}
1079
1080#[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! {
1081    /// The `unused_parens` lint detects `if`, `match`, `while` and `return`
1082    /// with parentheses; they do not need them.
1083    ///
1084    /// ### Examples
1085    ///
1086    /// ```rust
1087    /// if(true) {}
1088    /// ```
1089    ///
1090    /// {{produces}}
1091    ///
1092    /// ### Explanation
1093    ///
1094    /// The parentheses are not needed, and should be removed. This is the
1095    /// preferred style for writing these expressions.
1096    pub(super) UNUSED_PARENS,
1097    Warn,
1098    "`if`, `match`, `while` and `return` do not need parentheses"
1099}
1100
1101#[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)]
1102pub(crate) struct UnusedParens {
1103    with_self_ty_parens: bool,
1104    /// `1 as (i32) < 2` parses to ExprKind::Lt
1105    /// `1 as i32 < 2` parses to i32::<2[missing angle bracket]
1106    parens_in_cast_in_lt: Vec<ast::NodeId>,
1107    /// Ty nodes in this map are in TypeNoBounds position. Any bounds they
1108    /// contain may be ambiguous w/r/t trailing `+` operators.
1109    in_no_bounds_pos: FxHashMap<ast::NodeId, NoBoundsException>,
1110}
1111
1112/// Whether parentheses may be omitted from a type without resulting in ambiguity.
1113///
1114/// ```
1115/// type Example = Box<dyn Fn() -> &'static (dyn Send) + Sync>;
1116/// ```
1117///
1118/// Here, `&'static (dyn Send) + Sync` is a `TypeNoBounds`. As such, it may not directly
1119/// contain `ImplTraitType` or `TraitObjectType` which is why `(dyn Send)` is parenthesized.
1120/// However, an exception is made for `ImplTraitTypeOneBound` and `TraitObjectTypeOneBound`.
1121/// The following is accepted because there is no `+`.
1122///
1123/// ```
1124/// type Example = Box<dyn Fn() -> &'static dyn Send>;
1125/// ```
1126enum NoBoundsException {
1127    /// The type must be parenthesized.
1128    None,
1129    /// The type is the last bound of the containing type expression. If it has exactly one bound,
1130    /// parentheses around the type are unnecessary.
1131    OneBound,
1132}
1133
1134impl ::rustc_lint_defs::LintPass for UnusedParens {
    fn name(&self) -> &'static str { "UnusedParens" }
    fn get_lints(&self) -> ::rustc_lint_defs::LintVec {
        <[_]>::into_vec(::alloc::boxed::box_new([UNUSED_PARENS]))
    }
}
impl UnusedParens {
    #[allow(unused)]
    pub fn lint_vec() -> ::rustc_lint_defs::LintVec {
        <[_]>::into_vec(::alloc::boxed::box_new([UNUSED_PARENS]))
    }
}impl_lint_pass!(UnusedParens => [UNUSED_PARENS]);
1135
1136impl UnusedDelimLint for UnusedParens {
1137    const DELIM_STR: &'static str = "parentheses";
1138
1139    const LINT_EXPR_IN_PATTERN_MATCHING_CTX: bool = true;
1140
1141    fn lint(&self) -> &'static Lint {
1142        UNUSED_PARENS
1143    }
1144
1145    fn check_unused_delims_expr(
1146        &self,
1147        cx: &EarlyContext<'_>,
1148        value: &ast::Expr,
1149        ctx: UnusedDelimsCtx,
1150        followed_by_block: bool,
1151        left_pos: Option<BytePos>,
1152        right_pos: Option<BytePos>,
1153        is_kw: bool,
1154    ) {
1155        match value.kind {
1156            ast::ExprKind::Paren(ref inner) => {
1157                if !Self::is_expr_delims_necessary(inner, ctx, followed_by_block)
1158                    && value.attrs.is_empty()
1159                    && !value.span.from_expansion()
1160                    && (ctx != UnusedDelimsCtx::LetScrutineeExpr
1161                        || !#[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(
1162                                rustc_span::source_map::Spanned { node, .. },
1163                                _,
1164                                _,
1165                            ) if node.is_lazy()))
1166                    && !((ctx == UnusedDelimsCtx::ReturnValue
1167                        || ctx == UnusedDelimsCtx::BreakValue)
1168                        && #[allow(non_exhaustive_omitted_patterns)] match inner.kind {
    ast::ExprKind::Assign(_, _, _) => true,
    _ => false,
}matches!(inner.kind, ast::ExprKind::Assign(_, _, _)))
1169                {
1170                    self.emit_unused_delims_expr(cx, value, ctx, left_pos, right_pos, is_kw)
1171                }
1172            }
1173            ast::ExprKind::Let(_, ref expr, _, _) => {
1174                self.check_unused_delims_expr(
1175                    cx,
1176                    expr,
1177                    UnusedDelimsCtx::LetScrutineeExpr,
1178                    followed_by_block,
1179                    None,
1180                    None,
1181                    false,
1182                );
1183            }
1184            _ => {}
1185        }
1186    }
1187}
1188
1189impl UnusedParens {
1190    fn check_unused_parens_pat(
1191        &self,
1192        cx: &EarlyContext<'_>,
1193        value: &ast::Pat,
1194        avoid_or: bool,
1195        avoid_mut: bool,
1196        keep_space: (bool, bool),
1197    ) {
1198        use ast::{BindingMode, PatKind};
1199
1200        if let PatKind::Paren(inner) = &value.kind {
1201            match inner.kind {
1202                // The lint visitor will visit each subpattern of `p`. We do not want to lint
1203                // any range pattern no matter where it occurs in the pattern. For something like
1204                // `&(a..=b)`, there is a recursive `check_pat` on `a` and `b`, but we will assume
1205                // that if there are unnecessary parens they serve a purpose of readability.
1206                PatKind::Range(..) => return,
1207                // Parentheses may be necessary to disambiguate precedence in guard patterns.
1208                PatKind::Guard(..) => return,
1209                // Avoid `p0 | .. | pn` if we should.
1210                PatKind::Or(..) if avoid_or => return,
1211                // Avoid `mut x` and `mut x @ p` if we should:
1212                PatKind::Ident(BindingMode::MUT, ..) if avoid_mut => {
1213                    return;
1214                }
1215                // Otherwise proceed with linting.
1216                _ => {}
1217            }
1218            let spans = if !value.span.from_expansion() {
1219                inner
1220                    .span
1221                    .find_ancestor_inside(value.span)
1222                    .map(|inner| (value.span.with_hi(inner.lo()), value.span.with_lo(inner.hi())))
1223            } else {
1224                None
1225            };
1226            self.emit_unused_delims(cx, value.span, spans, "pattern", keep_space, false);
1227        }
1228    }
1229
1230    fn cast_followed_by_lt(&self, expr: &ast::Expr) -> Option<ast::NodeId> {
1231        if let ExprKind::Binary(op, lhs, _rhs) = &expr.kind
1232            && (op.node == ast::BinOpKind::Lt || op.node == ast::BinOpKind::Shl)
1233        {
1234            let mut cur = lhs;
1235            while let ExprKind::Binary(_, _, rhs) = &cur.kind {
1236                cur = rhs;
1237            }
1238
1239            if let ExprKind::Cast(_, ty) = &cur.kind
1240                && let ast::TyKind::Paren(_) = &ty.kind
1241            {
1242                return Some(ty.id);
1243            }
1244        }
1245        None
1246    }
1247}
1248
1249impl EarlyLintPass for UnusedParens {
1250    #[inline]
1251    fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &ast::Expr) {
1252        if let Some(ty_id) = self.cast_followed_by_lt(e) {
1253            self.parens_in_cast_in_lt.push(ty_id);
1254        }
1255
1256        match e.kind {
1257            ExprKind::Let(ref pat, _, _, _) | ExprKind::ForLoop { ref pat, .. } => {
1258                self.check_unused_parens_pat(cx, pat, false, false, (true, true));
1259            }
1260            // We ignore parens in cases like `if (((let Some(0) = Some(1))))` because we already
1261            // handle a hard error for them during AST lowering in `lower_expr_mut`, but we still
1262            // want to complain about things like `if let 42 = (42)`.
1263            ExprKind::If(ref cond, ref block, ref else_)
1264                if #[allow(non_exhaustive_omitted_patterns)] match cond.peel_parens().kind {
    ExprKind::Let(..) => true,
    _ => false,
}matches!(cond.peel_parens().kind, ExprKind::Let(..)) =>
1265            {
1266                self.check_unused_delims_expr(
1267                    cx,
1268                    cond.peel_parens(),
1269                    UnusedDelimsCtx::LetScrutineeExpr,
1270                    true,
1271                    None,
1272                    None,
1273                    true,
1274                );
1275                for stmt in &block.stmts {
1276                    <Self as UnusedDelimLint>::check_stmt(self, cx, stmt);
1277                }
1278                if let Some(e) = else_ {
1279                    <Self as UnusedDelimLint>::check_expr(self, cx, e);
1280                }
1281                return;
1282            }
1283            ExprKind::Match(ref _expr, ref arm, _) => {
1284                for a in arm {
1285                    if let Some(body) = &a.body {
1286                        self.check_unused_delims_expr(
1287                            cx,
1288                            body,
1289                            UnusedDelimsCtx::MatchArmExpr,
1290                            false,
1291                            None,
1292                            None,
1293                            true,
1294                        );
1295                    }
1296                }
1297            }
1298            _ => {}
1299        }
1300
1301        <Self as UnusedDelimLint>::check_expr(self, cx, e)
1302    }
1303
1304    fn check_expr_post(&mut self, _cx: &EarlyContext<'_>, e: &ast::Expr) {
1305        if let Some(ty_id) = self.cast_followed_by_lt(e) {
1306            let id = self
1307                .parens_in_cast_in_lt
1308                .pop()
1309                .expect("check_expr and check_expr_post must balance");
1310            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!(
1311                id, ty_id,
1312                "check_expr, check_ty, and check_expr_post are called, in that order, by the visitor"
1313            );
1314        }
1315    }
1316
1317    fn check_pat(&mut self, cx: &EarlyContext<'_>, p: &ast::Pat) {
1318        use ast::Mutability;
1319        use ast::PatKind::*;
1320        let keep_space = (false, false);
1321        match &p.kind {
1322            // Do not lint on `(..)` as that will result in the other arms being useless.
1323            Paren(_)
1324            // The other cases do not contain sub-patterns.
1325            | Missing | Wild | Never | Rest | Expr(..) | MacCall(..) | Range(..) | Ident(.., None)
1326            | Path(..) | Err(_) => {},
1327            // These are list-like patterns; parens can always be removed.
1328            TupleStruct(_, _, ps) | Tuple(ps) | Slice(ps) | Or(ps) => for p in ps {
1329                self.check_unused_parens_pat(cx, p, false, false, keep_space);
1330            },
1331            Struct(_, _, fps, _) => for f in fps {
1332                self.check_unused_parens_pat(cx, &f.pat, false, false, keep_space);
1333            },
1334            // Avoid linting on `i @ (p0 | .. | pn)` and `box (p0 | .. | pn)`, #64106.
1335            Ident(.., Some(p)) | Box(p) | Deref(p) | Guard(p, _) => self.check_unused_parens_pat(cx, p, true, false, keep_space),
1336            // Avoid linting on `&(mut x)` as `&mut x` has a different meaning, #55342.
1337            // Also avoid linting on `& mut? (p0 | .. | pn)`, #64106.
1338            // FIXME(pin_ergonomics): check pinned patterns
1339            Ref(p, _, m) => self.check_unused_parens_pat(cx, p, true, *m == Mutability::Not, keep_space),
1340        }
1341    }
1342
1343    fn check_stmt(&mut self, cx: &EarlyContext<'_>, s: &ast::Stmt) {
1344        if let StmtKind::Let(ref local) = s.kind {
1345            self.check_unused_parens_pat(cx, &local.pat, true, false, (true, false));
1346        }
1347
1348        <Self as UnusedDelimLint>::check_stmt(self, cx, s)
1349    }
1350
1351    fn check_param(&mut self, cx: &EarlyContext<'_>, param: &ast::Param) {
1352        self.check_unused_parens_pat(cx, &param.pat, true, false, (false, false));
1353    }
1354
1355    fn check_arm(&mut self, cx: &EarlyContext<'_>, arm: &ast::Arm) {
1356        self.check_unused_parens_pat(cx, &arm.pat, false, false, (false, false));
1357    }
1358
1359    fn check_ty(&mut self, cx: &EarlyContext<'_>, ty: &ast::Ty) {
1360        if let ast::TyKind::Paren(_) = ty.kind
1361            && Some(&ty.id) == self.parens_in_cast_in_lt.last()
1362        {
1363            return;
1364        }
1365        match &ty.kind {
1366            ast::TyKind::Array(_, len) => {
1367                self.check_unused_delims_expr(
1368                    cx,
1369                    &len.value,
1370                    UnusedDelimsCtx::ArrayLenExpr,
1371                    false,
1372                    None,
1373                    None,
1374                    false,
1375                );
1376            }
1377            ast::TyKind::Paren(r) => {
1378                let unused_parens = match &r.kind {
1379                    ast::TyKind::ImplTrait(_, bounds) | ast::TyKind::TraitObject(bounds, _) => {
1380                        match self.in_no_bounds_pos.get(&ty.id) {
1381                            Some(NoBoundsException::None) => false,
1382                            Some(NoBoundsException::OneBound) => bounds.len() <= 1,
1383                            None => true,
1384                        }
1385                    }
1386                    ast::TyKind::FnPtr(b) => {
1387                        !self.with_self_ty_parens || b.generic_params.is_empty()
1388                    }
1389                    _ => true,
1390                };
1391
1392                if unused_parens {
1393                    let spans = (!ty.span.from_expansion())
1394                        .then(|| {
1395                            r.span
1396                                .find_ancestor_inside(ty.span)
1397                                .map(|r| (ty.span.with_hi(r.lo()), ty.span.with_lo(r.hi())))
1398                        })
1399                        .flatten();
1400
1401                    self.emit_unused_delims(cx, ty.span, spans, "type", (false, false), false);
1402                }
1403
1404                self.with_self_ty_parens = false;
1405            }
1406            ast::TyKind::Ref(_, mut_ty) | ast::TyKind::Ptr(mut_ty) => {
1407                // If this type itself appears in no-bounds position, we propagate its
1408                // potentially tighter constraint or risk a false posive (issue 143653).
1409                let own_constraint = self.in_no_bounds_pos.get(&ty.id);
1410                let constraint = match own_constraint {
1411                    Some(NoBoundsException::None) => NoBoundsException::None,
1412                    Some(NoBoundsException::OneBound) => NoBoundsException::OneBound,
1413                    None => NoBoundsException::OneBound,
1414                };
1415                self.in_no_bounds_pos.insert(mut_ty.ty.id, constraint);
1416            }
1417            ast::TyKind::TraitObject(bounds, _) | ast::TyKind::ImplTrait(_, bounds) => {
1418                for i in 0..bounds.len() {
1419                    let is_last = i == bounds.len() - 1;
1420
1421                    if let ast::GenericBound::Trait(poly_trait_ref) = &bounds[i] {
1422                        let fn_with_explicit_ret_ty = if let [.., segment] =
1423                            &*poly_trait_ref.trait_ref.path.segments
1424                            && let Some(args) = segment.args.as_ref()
1425                            && let ast::GenericArgs::Parenthesized(paren_args) = &**args
1426                            && let ast::FnRetTy::Ty(ret_ty) = &paren_args.output
1427                        {
1428                            self.in_no_bounds_pos.insert(
1429                                ret_ty.id,
1430                                if is_last {
1431                                    NoBoundsException::OneBound
1432                                } else {
1433                                    NoBoundsException::None
1434                                },
1435                            );
1436
1437                            true
1438                        } else {
1439                            false
1440                        };
1441
1442                        // In edition 2015, dyn is a contextual keyword and `dyn::foo::Bar` is
1443                        // parsed as a path, so parens are necessary to disambiguate. See
1444                        //  - tests/ui/lint/unused/unused-parens-trait-obj-e2015.rs and
1445                        //  - https://doc.rust-lang.org/reference/types/trait-object.html#r-type.trait-object.syntax-edition2018
1446                        let dyn2015_exception = cx.sess().psess.edition == Edition2015
1447                            && #[allow(non_exhaustive_omitted_patterns)] match ty.kind {
    ast::TyKind::TraitObject(..) => true,
    _ => false,
}matches!(ty.kind, ast::TyKind::TraitObject(..))
1448                            && i == 0
1449                            && poly_trait_ref
1450                                .trait_ref
1451                                .path
1452                                .segments
1453                                .first()
1454                                .map(|s| s.ident.name == kw::PathRoot)
1455                                .unwrap_or(false);
1456
1457                        if let ast::Parens::Yes = poly_trait_ref.parens
1458                            && (is_last || !fn_with_explicit_ret_ty)
1459                            && !dyn2015_exception
1460                        {
1461                            let s = poly_trait_ref.span;
1462                            let spans = (!s.from_expansion()).then(|| {
1463                                (
1464                                    s.with_hi(s.lo() + rustc_span::BytePos(1)),
1465                                    s.with_lo(s.hi() - rustc_span::BytePos(1)),
1466                                )
1467                            });
1468
1469                            self.emit_unused_delims(
1470                                cx,
1471                                poly_trait_ref.span,
1472                                spans,
1473                                "type",
1474                                (false, false),
1475                                false,
1476                            );
1477                        }
1478                    }
1479                }
1480            }
1481            _ => {}
1482        }
1483    }
1484
1485    fn check_item(&mut self, cx: &EarlyContext<'_>, item: &ast::Item) {
1486        <Self as UnusedDelimLint>::check_item(self, cx, item)
1487    }
1488
1489    fn check_item_post(&mut self, _: &EarlyContext<'_>, _: &rustc_ast::Item) {
1490        self.in_no_bounds_pos.clear();
1491    }
1492
1493    fn enter_where_predicate(&mut self, _: &EarlyContext<'_>, pred: &ast::WherePredicate) {
1494        use rustc_ast::{WhereBoundPredicate, WherePredicateKind};
1495        if let WherePredicateKind::BoundPredicate(WhereBoundPredicate {
1496            bounded_ty,
1497            bound_generic_params,
1498            ..
1499        }) = &pred.kind
1500            && let ast::TyKind::Paren(_) = &bounded_ty.kind
1501            && bound_generic_params.is_empty()
1502        {
1503            self.with_self_ty_parens = true;
1504        }
1505    }
1506
1507    fn exit_where_predicate(&mut self, _: &EarlyContext<'_>, _: &ast::WherePredicate) {
1508        if !!self.with_self_ty_parens {
    ::core::panicking::panic("assertion failed: !self.with_self_ty_parens")
};assert!(!self.with_self_ty_parens);
1509    }
1510}
1511
1512#[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! {
1513    /// The `unused_braces` lint detects unnecessary braces around an
1514    /// expression.
1515    ///
1516    /// ### Example
1517    ///
1518    /// ```rust
1519    /// if { true } {
1520    ///     // ...
1521    /// }
1522    /// ```
1523    ///
1524    /// {{produces}}
1525    ///
1526    /// ### Explanation
1527    ///
1528    /// The braces are not needed, and should be removed. This is the
1529    /// preferred style for writing these expressions.
1530    pub(super) UNUSED_BRACES,
1531    Warn,
1532    "unnecessary braces around an expression"
1533}
1534
1535pub 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 {
        <[_]>::into_vec(::alloc::boxed::box_new([UNUSED_BRACES]))
    }
}
impl UnusedBraces {
    #[allow(unused)]
    pub fn lint_vec() -> ::rustc_lint_defs::LintVec {
        <[_]>::into_vec(::alloc::boxed::box_new([UNUSED_BRACES]))
    }
}declare_lint_pass!(UnusedBraces => [UNUSED_BRACES]);
1536
1537impl UnusedDelimLint for UnusedBraces {
1538    const DELIM_STR: &'static str = "braces";
1539
1540    const LINT_EXPR_IN_PATTERN_MATCHING_CTX: bool = false;
1541
1542    fn lint(&self) -> &'static Lint {
1543        UNUSED_BRACES
1544    }
1545
1546    fn check_unused_delims_expr(
1547        &self,
1548        cx: &EarlyContext<'_>,
1549        value: &ast::Expr,
1550        ctx: UnusedDelimsCtx,
1551        followed_by_block: bool,
1552        left_pos: Option<BytePos>,
1553        right_pos: Option<BytePos>,
1554        is_kw: bool,
1555    ) {
1556        match value.kind {
1557            ast::ExprKind::Block(ref inner, None)
1558                if inner.rules == ast::BlockCheckMode::Default =>
1559            {
1560                // emit a warning under the following conditions:
1561                //
1562                // - the block does not have a label
1563                // - the block is not `unsafe`
1564                // - the block contains exactly one expression (do not lint `{ expr; }`)
1565                // - `followed_by_block` is true and the internal expr may contain a `{`
1566                // - the block is not multiline (do not lint multiline match arms)
1567                //      ```
1568                //      match expr {
1569                //          Pattern => {
1570                //              somewhat_long_expression
1571                //          }
1572                //          // ...
1573                //      }
1574                //      ```
1575                // - the block has no attribute and was not created inside a macro
1576                // - if the block is an `anon_const`, the inner expr must be a literal
1577                //   not created by a macro, i.e. do not lint on:
1578                //      ```
1579                //      struct A<const N: usize>;
1580                //      let _: A<{ 2 + 3 }>;
1581                //      let _: A<{produces_literal!()}>;
1582                //      ```
1583                // FIXME(const_generics): handle paths when #67075 is fixed.
1584                if let [stmt] = inner.stmts.as_slice()
1585                    && let ast::StmtKind::Expr(ref expr) = stmt.kind
1586                    && !Self::is_expr_delims_necessary(expr, ctx, followed_by_block)
1587                    && (ctx != UnusedDelimsCtx::AnonConst
1588                        || (#[allow(non_exhaustive_omitted_patterns)] match expr.kind {
    ast::ExprKind::Lit(_) => true,
    _ => false,
}matches!(expr.kind, ast::ExprKind::Lit(_))
1589                            && !expr.span.from_expansion()))
1590                    && ctx != UnusedDelimsCtx::ClosureBody
1591                    && !cx.sess().source_map().is_multiline(value.span)
1592                    && value.attrs.is_empty()
1593                    && !value.span.from_expansion()
1594                    && !inner.span.from_expansion()
1595                {
1596                    self.emit_unused_delims_expr(cx, value, ctx, left_pos, right_pos, is_kw)
1597                }
1598            }
1599            ast::ExprKind::Let(_, ref expr, _, _) => {
1600                self.check_unused_delims_expr(
1601                    cx,
1602                    expr,
1603                    UnusedDelimsCtx::LetScrutineeExpr,
1604                    followed_by_block,
1605                    None,
1606                    None,
1607                    false,
1608                );
1609            }
1610            _ => {}
1611        }
1612    }
1613}
1614
1615impl EarlyLintPass for UnusedBraces {
1616    fn check_stmt(&mut self, cx: &EarlyContext<'_>, s: &ast::Stmt) {
1617        <Self as UnusedDelimLint>::check_stmt(self, cx, s)
1618    }
1619
1620    #[inline]
1621    fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &ast::Expr) {
1622        <Self as UnusedDelimLint>::check_expr(self, cx, e);
1623
1624        if let ExprKind::Repeat(_, ref anon_const) = e.kind {
1625            self.check_unused_delims_expr(
1626                cx,
1627                &anon_const.value,
1628                UnusedDelimsCtx::AnonConst,
1629                false,
1630                None,
1631                None,
1632                false,
1633            );
1634        }
1635    }
1636
1637    fn check_generic_arg(&mut self, cx: &EarlyContext<'_>, arg: &ast::GenericArg) {
1638        if let ast::GenericArg::Const(ct) = arg {
1639            self.check_unused_delims_expr(
1640                cx,
1641                &ct.value,
1642                UnusedDelimsCtx::AnonConst,
1643                false,
1644                None,
1645                None,
1646                false,
1647            );
1648        }
1649    }
1650
1651    fn check_variant(&mut self, cx: &EarlyContext<'_>, v: &ast::Variant) {
1652        if let Some(anon_const) = &v.disr_expr {
1653            self.check_unused_delims_expr(
1654                cx,
1655                &anon_const.value,
1656                UnusedDelimsCtx::AnonConst,
1657                false,
1658                None,
1659                None,
1660                false,
1661            );
1662        }
1663    }
1664
1665    fn check_ty(&mut self, cx: &EarlyContext<'_>, ty: &ast::Ty) {
1666        match ty.kind {
1667            ast::TyKind::Array(_, ref len) => {
1668                self.check_unused_delims_expr(
1669                    cx,
1670                    &len.value,
1671                    UnusedDelimsCtx::ArrayLenExpr,
1672                    false,
1673                    None,
1674                    None,
1675                    false,
1676                );
1677            }
1678
1679            _ => {}
1680        }
1681    }
1682
1683    fn check_item(&mut self, cx: &EarlyContext<'_>, item: &ast::Item) {
1684        <Self as UnusedDelimLint>::check_item(self, cx, item)
1685    }
1686}
1687
1688#[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! {
1689    /// The `unused_import_braces` lint catches unnecessary braces around an
1690    /// imported item.
1691    ///
1692    /// ### Example
1693    ///
1694    /// ```rust,compile_fail
1695    /// #![deny(unused_import_braces)]
1696    /// use test::{A};
1697    ///
1698    /// pub mod test {
1699    ///     pub struct A;
1700    /// }
1701    /// # fn main() {}
1702    /// ```
1703    ///
1704    /// {{produces}}
1705    ///
1706    /// ### Explanation
1707    ///
1708    /// If there is only a single item, then remove the braces (`use test::A;`
1709    /// for example).
1710    ///
1711    /// This lint is "allow" by default because it is only enforcing a
1712    /// stylistic choice.
1713    UNUSED_IMPORT_BRACES,
1714    Allow,
1715    "unnecessary braces around an imported item"
1716}
1717
1718pub 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 {
        <[_]>::into_vec(::alloc::boxed::box_new([UNUSED_IMPORT_BRACES]))
    }
}
impl UnusedImportBraces {
    #[allow(unused)]
    pub fn lint_vec() -> ::rustc_lint_defs::LintVec {
        <[_]>::into_vec(::alloc::boxed::box_new([UNUSED_IMPORT_BRACES]))
    }
}declare_lint_pass!(UnusedImportBraces => [UNUSED_IMPORT_BRACES]);
1719
1720impl UnusedImportBraces {
1721    fn check_use_tree(&self, cx: &EarlyContext<'_>, use_tree: &ast::UseTree, item: &ast::Item) {
1722        if let ast::UseTreeKind::Nested { ref items, .. } = use_tree.kind {
1723            // Recursively check nested UseTrees
1724            for (tree, _) in items {
1725                self.check_use_tree(cx, tree, item);
1726            }
1727
1728            // Trigger the lint only if there is one nested item
1729            let [(tree, _)] = items.as_slice() else { return };
1730
1731            // Trigger the lint if the nested item is a non-self single item
1732            let node_name = match tree.kind {
1733                ast::UseTreeKind::Simple(rename) => {
1734                    let orig_ident = tree.prefix.segments.last().unwrap().ident;
1735                    if orig_ident.name == kw::SelfLower {
1736                        return;
1737                    }
1738                    rename.unwrap_or(orig_ident).name
1739                }
1740                ast::UseTreeKind::Glob => sym::asterisk,
1741                ast::UseTreeKind::Nested { .. } => return,
1742            };
1743
1744            cx.emit_span_lint(
1745                UNUSED_IMPORT_BRACES,
1746                item.span,
1747                UnusedImportBracesDiag { node: node_name },
1748            );
1749        }
1750    }
1751}
1752
1753impl EarlyLintPass for UnusedImportBraces {
1754    fn check_item(&mut self, cx: &EarlyContext<'_>, item: &ast::Item) {
1755        if let ast::ItemKind::Use(ref use_tree) = item.kind {
1756            self.check_use_tree(cx, use_tree, item);
1757        }
1758    }
1759}
1760
1761#[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! {
1762    /// The `unused_allocation` lint detects unnecessary allocations that can
1763    /// be eliminated.
1764    ///
1765    /// ### Example
1766    ///
1767    /// ```rust
1768    /// fn main() {
1769    ///     let a = Box::new([1, 2, 3]).len();
1770    /// }
1771    /// ```
1772    ///
1773    /// {{produces}}
1774    ///
1775    /// ### Explanation
1776    ///
1777    /// When a `box` expression is immediately coerced to a reference, then
1778    /// the allocation is unnecessary, and a reference (using `&` or `&mut`)
1779    /// should be used instead to avoid the allocation.
1780    pub(super) UNUSED_ALLOCATION,
1781    Warn,
1782    "detects unnecessary allocations that can be eliminated"
1783}
1784
1785pub 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 {
        <[_]>::into_vec(::alloc::boxed::box_new([UNUSED_ALLOCATION]))
    }
}
impl UnusedAllocation {
    #[allow(unused)]
    pub fn lint_vec() -> ::rustc_lint_defs::LintVec {
        <[_]>::into_vec(::alloc::boxed::box_new([UNUSED_ALLOCATION]))
    }
}declare_lint_pass!(UnusedAllocation => [UNUSED_ALLOCATION]);
1786
1787impl<'tcx> LateLintPass<'tcx> for UnusedAllocation {
1788    fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &hir::Expr<'_>) {
1789        match e.kind {
1790            hir::ExprKind::Call(path_expr, [_])
1791                if let hir::ExprKind::Path(qpath) = &path_expr.kind
1792                    && let Some(did) = cx.qpath_res(qpath, path_expr.hir_id).opt_def_id()
1793                    && cx.tcx.is_diagnostic_item(sym::box_new, did) => {}
1794            _ => return,
1795        }
1796
1797        for adj in cx.typeck_results().expr_adjustments(e) {
1798            if let adjustment::Adjust::Borrow(adjustment::AutoBorrow::Ref(m)) = adj.kind {
1799                if let ty::Ref(_, inner_ty, _) = adj.target.kind()
1800                    && inner_ty.is_box()
1801                {
1802                    // If the target type is `&Box<T>` or `&mut Box<T>`, the allocation is necessary
1803                    continue;
1804                }
1805                match m {
1806                    adjustment::AutoBorrowMutability::Not => {
1807                        cx.emit_span_lint(UNUSED_ALLOCATION, e.span, UnusedAllocationDiag);
1808                    }
1809                    adjustment::AutoBorrowMutability::Mut { .. } => {
1810                        cx.emit_span_lint(UNUSED_ALLOCATION, e.span, UnusedAllocationMutDiag);
1811                    }
1812                };
1813            }
1814        }
1815    }
1816}