Skip to main content

rustc_hir_typeck/
expr_use_visitor.rs

1//! A different sort of visitor for walking fn bodies. Unlike the
2//! normal visitor, which just walks the entire body in one shot, the
3//! `ExprUseVisitor` determines how expressions are being used.
4//!
5//! In the compiler, this is only used for upvar inference and diagnostics, but there
6//! are many uses within clippy.
7
8use std::cell::{Ref, RefCell};
9use std::ops::Deref;
10
11use hir::def::DefKind;
12use hir::pat_util::EnumerateAndAdjustIterator as _;
13use rustc_abi::{FIRST_VARIANT, FieldIdx, VariantIdx};
14use rustc_ast::UnsafeBinderCastKind;
15use rustc_data_structures::fx::FxIndexMap;
16use rustc_hir::def::{CtorOf, Res};
17use rustc_hir::def_id::LocalDefId;
18use rustc_hir::{self as hir, HirId, PatExpr, PatExprKind, PatKind};
19use rustc_lint::LateContext;
20use rustc_middle::hir::place::ProjectionKind;
21// Export these here so that Clippy can use them.
22pub use rustc_middle::hir::place::{Place, PlaceBase, PlaceWithHirId, Projection};
23use rustc_middle::mir::FakeReadCause;
24use rustc_middle::thir::DerefPatBorrowMode;
25use rustc_middle::ty::adjustment::DerefAdjustKind;
26use rustc_middle::ty::{
27    self, BorrowKind, Ty, TyCtxt, TypeFoldable, TypeVisitableExt as _, adjustment,
28};
29use rustc_middle::{bug, span_bug};
30use rustc_span::{ErrorGuaranteed, Span};
31use rustc_trait_selection::infer::InferCtxtExt;
32use tracing::{debug, instrument, trace};
33
34use crate::fn_ctxt::FnCtxt;
35
36/// This trait defines the callbacks you can expect to receive when
37/// employing the ExprUseVisitor.
38pub trait Delegate<'tcx> {
39    /// The value found at `place` is moved, depending
40    /// on `mode`. Where `diag_expr_id` is the id used for diagnostics for `place`.
41    ///
42    /// If the value is `Copy`, [`copy`][Self::copy] is called instead, which
43    /// by default falls back to [`borrow`][Self::borrow].
44    ///
45    /// The parameter `diag_expr_id` indicates the HIR id that ought to be used for
46    /// diagnostics. Around pattern matching such as `let pat = expr`, the diagnostic
47    /// id will be the id of the expression `expr` but the place itself will have
48    /// the id of the binding in the pattern `pat`.
49    fn consume(&mut self, place_with_id: &PlaceWithHirId<'tcx>, diag_expr_id: HirId);
50
51    /// The value found at `place` is used, depending
52    /// on `mode`. Where `diag_expr_id` is the id used for diagnostics for `place`.
53    ///
54    /// Use of a `Copy` type in a ByUse context is considered a use
55    /// by `ImmBorrow` and `borrow` is called instead. This is because
56    /// a shared borrow is the "minimum access" that would be needed
57    /// to perform a copy.
58    ///
59    ///
60    /// The parameter `diag_expr_id` indicates the HIR id that ought to be used for
61    /// diagnostics. Around pattern matching such as `let pat = expr`, the diagnostic
62    /// id will be the id of the expression `expr` but the place itself will have
63    /// the id of the binding in the pattern `pat`.
64    fn use_cloned(&mut self, place_with_id: &PlaceWithHirId<'tcx>, diag_expr_id: HirId);
65
66    /// The value found at `place` is being borrowed with kind `bk`.
67    /// `diag_expr_id` is the id used for diagnostics (see `consume` for more details).
68    fn borrow(
69        &mut self,
70        place_with_id: &PlaceWithHirId<'tcx>,
71        diag_expr_id: HirId,
72        bk: ty::BorrowKind,
73    );
74
75    /// The value found at `place` is being copied.
76    /// `diag_expr_id` is the id used for diagnostics (see `consume` for more details).
77    ///
78    /// If an implementation is not provided, use of a `Copy` type in a ByValue context is instead
79    /// considered a use by `ImmBorrow` and `borrow` is called instead. This is because a shared
80    /// borrow is the "minimum access" that would be needed to perform a copy.
81    fn copy(&mut self, place_with_id: &PlaceWithHirId<'tcx>, diag_expr_id: HirId) {
82        // In most cases, copying data from `x` is equivalent to doing `*&x`, so by default
83        // we treat a copy of `x` as a borrow of `x`.
84        self.borrow(place_with_id, diag_expr_id, ty::BorrowKind::Immutable)
85    }
86
87    /// The path at `assignee_place` is being assigned to.
88    /// `diag_expr_id` is the id used for diagnostics (see `consume` for more details).
89    fn mutate(&mut self, assignee_place: &PlaceWithHirId<'tcx>, diag_expr_id: HirId);
90
91    /// The path at `binding_place` is a binding that is being initialized.
92    ///
93    /// This covers cases such as `let x = 42;`
94    fn bind(&mut self, binding_place: &PlaceWithHirId<'tcx>, diag_expr_id: HirId) {
95        // Bindings can normally be treated as a regular assignment, so by default we
96        // forward this to the mutate callback.
97        self.mutate(binding_place, diag_expr_id)
98    }
99
100    /// The `place` should be a fake read because of specified `cause`.
101    fn fake_read(
102        &mut self,
103        place_with_id: &PlaceWithHirId<'tcx>,
104        cause: FakeReadCause,
105        diag_expr_id: HirId,
106    );
107}
108
109impl<'tcx, D: Delegate<'tcx>> Delegate<'tcx> for &mut D {
110    fn consume(&mut self, place_with_id: &PlaceWithHirId<'tcx>, diag_expr_id: HirId) {
111        (**self).consume(place_with_id, diag_expr_id)
112    }
113
114    fn use_cloned(&mut self, place_with_id: &PlaceWithHirId<'tcx>, diag_expr_id: HirId) {
115        (**self).use_cloned(place_with_id, diag_expr_id)
116    }
117
118    fn borrow(
119        &mut self,
120        place_with_id: &PlaceWithHirId<'tcx>,
121        diag_expr_id: HirId,
122        bk: ty::BorrowKind,
123    ) {
124        (**self).borrow(place_with_id, diag_expr_id, bk)
125    }
126
127    fn copy(&mut self, place_with_id: &PlaceWithHirId<'tcx>, diag_expr_id: HirId) {
128        (**self).copy(place_with_id, diag_expr_id)
129    }
130
131    fn mutate(&mut self, assignee_place: &PlaceWithHirId<'tcx>, diag_expr_id: HirId) {
132        (**self).mutate(assignee_place, diag_expr_id)
133    }
134
135    fn bind(&mut self, binding_place: &PlaceWithHirId<'tcx>, diag_expr_id: HirId) {
136        (**self).bind(binding_place, diag_expr_id)
137    }
138
139    fn fake_read(
140        &mut self,
141        place_with_id: &PlaceWithHirId<'tcx>,
142        cause: FakeReadCause,
143        diag_expr_id: HirId,
144    ) {
145        (**self).fake_read(place_with_id, cause, diag_expr_id)
146    }
147}
148
149/// This trait makes `ExprUseVisitor` usable with both [`FnCtxt`]
150/// and [`LateContext`], depending on where in the compiler it is used.
151pub trait TypeInformationCtxt<'tcx> {
152    type TypeckResults<'a>: Deref<Target = ty::TypeckResults<'tcx>>
153    where
154        Self: 'a;
155
156    type Error;
157
158    fn typeck_results(&self) -> Self::TypeckResults<'_>;
159
160    fn resolve_vars_if_possible<T: TypeFoldable<TyCtxt<'tcx>>>(&self, t: T) -> T;
161
162    fn structurally_resolve_type(&self, span: Span, ty: Ty<'tcx>) -> Ty<'tcx>;
163
164    fn report_bug(&self, span: Span, msg: impl ToString) -> Self::Error;
165
166    fn error_reported_in_ty(&self, ty: Ty<'tcx>) -> Result<(), Self::Error>;
167
168    fn tainted_by_errors(&self) -> Result<(), Self::Error>;
169
170    fn type_is_copy_modulo_regions(&self, ty: Ty<'tcx>) -> bool;
171
172    fn type_is_use_cloned_modulo_regions(&self, ty: Ty<'tcx>) -> bool;
173
174    fn body_owner_def_id(&self) -> LocalDefId;
175
176    fn tcx(&self) -> TyCtxt<'tcx>;
177}
178
179impl<'tcx> TypeInformationCtxt<'tcx> for &FnCtxt<'_, 'tcx> {
180    type TypeckResults<'a>
181        = Ref<'a, ty::TypeckResults<'tcx>>
182    where
183        Self: 'a;
184
185    type Error = ErrorGuaranteed;
186
187    fn typeck_results(&self) -> Self::TypeckResults<'_> {
188        self.typeck_results.borrow()
189    }
190
191    fn resolve_vars_if_possible<T: TypeFoldable<TyCtxt<'tcx>>>(&self, t: T) -> T {
192        self.infcx.resolve_vars_if_possible(t)
193    }
194
195    fn structurally_resolve_type(&self, sp: Span, ty: Ty<'tcx>) -> Ty<'tcx> {
196        (**self).structurally_resolve_type(sp, ty)
197    }
198
199    fn report_bug(&self, span: Span, msg: impl ToString) -> Self::Error {
200        self.dcx().span_delayed_bug(span, msg.to_string())
201    }
202
203    fn error_reported_in_ty(&self, ty: Ty<'tcx>) -> Result<(), Self::Error> {
204        ty.error_reported()
205    }
206
207    fn tainted_by_errors(&self) -> Result<(), ErrorGuaranteed> {
208        if let Some(guar) = self.infcx.tainted_by_errors() { Err(guar) } else { Ok(()) }
209    }
210
211    fn type_is_copy_modulo_regions(&self, ty: Ty<'tcx>) -> bool {
212        self.infcx.type_is_copy_modulo_regions(self.param_env, ty)
213    }
214
215    fn type_is_use_cloned_modulo_regions(&self, ty: Ty<'tcx>) -> bool {
216        self.infcx.type_is_use_cloned_modulo_regions(self.param_env, ty)
217    }
218
219    fn body_owner_def_id(&self) -> LocalDefId {
220        self.body_id
221    }
222
223    fn tcx(&self) -> TyCtxt<'tcx> {
224        self.tcx
225    }
226}
227
228impl<'tcx> TypeInformationCtxt<'tcx> for (&LateContext<'tcx>, LocalDefId) {
229    type TypeckResults<'a>
230        = &'tcx ty::TypeckResults<'tcx>
231    where
232        Self: 'a;
233
234    type Error = !;
235
236    fn typeck_results(&self) -> Self::TypeckResults<'_> {
237        self.0.maybe_typeck_results().expect("expected typeck results")
238    }
239
240    fn structurally_resolve_type(&self, _span: Span, ty: Ty<'tcx>) -> Ty<'tcx> {
241        // FIXME: Maybe need to normalize here.
242        ty
243    }
244
245    fn resolve_vars_if_possible<T: TypeFoldable<TyCtxt<'tcx>>>(&self, t: T) -> T {
246        t
247    }
248
249    fn report_bug(&self, span: Span, msg: impl ToString) -> ! {
250        ::rustc_middle::util::bug::span_bug_fmt(span,
    format_args!("{0}", msg.to_string()))span_bug!(span, "{}", msg.to_string())
251    }
252
253    fn error_reported_in_ty(&self, _ty: Ty<'tcx>) -> Result<(), !> {
254        Ok(())
255    }
256
257    fn tainted_by_errors(&self) -> Result<(), !> {
258        Ok(())
259    }
260
261    fn type_is_copy_modulo_regions(&self, ty: Ty<'tcx>) -> bool {
262        self.0.type_is_copy_modulo_regions(ty)
263    }
264
265    fn type_is_use_cloned_modulo_regions(&self, ty: Ty<'tcx>) -> bool {
266        self.0.type_is_use_cloned_modulo_regions(ty)
267    }
268
269    fn body_owner_def_id(&self) -> LocalDefId {
270        self.1
271    }
272
273    fn tcx(&self) -> TyCtxt<'tcx> {
274        self.0.tcx
275    }
276}
277
278/// A visitor that reports how each expression is being used.
279///
280/// See [module-level docs][self] and [`Delegate`] for details.
281pub struct ExprUseVisitor<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> {
282    cx: Cx,
283    /// We use a `RefCell` here so that delegates can mutate themselves, but we can
284    /// still have calls to our own helper functions.
285    delegate: RefCell<D>,
286    upvars: Option<&'tcx FxIndexMap<HirId, hir::Upvar>>,
287}
288
289impl<'a, 'tcx, D: Delegate<'tcx>> ExprUseVisitor<'tcx, (&'a LateContext<'tcx>, LocalDefId), D> {
290    pub fn for_clippy(cx: &'a LateContext<'tcx>, body_def_id: LocalDefId, delegate: D) -> Self {
291        Self::new((cx, body_def_id), delegate)
292    }
293}
294
295impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx, Cx, D> {
296    /// Creates the ExprUseVisitor, configuring it with the various options provided:
297    ///
298    /// - `delegate` -- who receives the callbacks
299    /// - `param_env` --- parameter environment for trait lookups (esp. pertaining to `Copy`)
300    /// - `typeck_results` --- typeck results for the code being analyzed
301    pub(crate) fn new(cx: Cx, delegate: D) -> Self {
302        ExprUseVisitor {
303            delegate: RefCell::new(delegate),
304            upvars: cx.tcx().upvars_mentioned(cx.body_owner_def_id()),
305            cx,
306        }
307    }
308
309    pub fn consume_body(&self, body: &hir::Body<'_>) -> Result<(), Cx::Error> {
310        for param in body.params {
311            let param_ty = self.pat_ty_adjusted(param.pat)?;
312            {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_hir_typeck/src/expr_use_visitor.rs:312",
                        "rustc_hir_typeck::expr_use_visitor",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_hir_typeck/src/expr_use_visitor.rs"),
                        ::tracing_core::__macro_support::Option::Some(312u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_hir_typeck::expr_use_visitor"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                let mut iter = __CALLSITE.metadata().fields().iter();
                __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&format_args!("consume_body: param_ty = {0:?}",
                                                    param_ty) as &dyn Value))])
            });
    } else { ; }
};debug!("consume_body: param_ty = {:?}", param_ty);
313
314            let param_place = self.cat_rvalue(param.hir_id, param_ty);
315
316            self.fake_read_scrutinee(&param_place, false)?;
317            self.walk_pat(&param_place, param.pat, false)?;
318        }
319
320        self.consume_expr(body.value)?;
321
322        Ok(())
323    }
324
325    #[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("consume_or_copy",
                                    "rustc_hir_typeck::expr_use_visitor",
                                    ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("compiler/rustc_hir_typeck/src/expr_use_visitor.rs"),
                                    ::tracing_core::__macro_support::Option::Some(325u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_hir_typeck::expr_use_visitor"),
                                    ::tracing_core::field::FieldSet::new(&["place_with_id",
                                                    "diag_expr_id"],
                                        ::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(&place_with_id)
                                                            as &dyn Value)),
                                                (&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                    ::tracing::__macro_support::Option::Some(&::tracing::field::debug(&diag_expr_id)
                                                            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;
        }
        {
            if self.cx.type_is_copy_modulo_regions(place_with_id.place.ty()) {
                self.delegate.borrow_mut().copy(place_with_id, diag_expr_id);
            } else {
                self.delegate.borrow_mut().consume(place_with_id,
                    diag_expr_id);
            }
        }
    }
}#[instrument(skip(self), level = "debug")]
326    fn consume_or_copy(&self, place_with_id: &PlaceWithHirId<'tcx>, diag_expr_id: HirId) {
327        if self.cx.type_is_copy_modulo_regions(place_with_id.place.ty()) {
328            self.delegate.borrow_mut().copy(place_with_id, diag_expr_id);
329        } else {
330            self.delegate.borrow_mut().consume(place_with_id, diag_expr_id);
331        }
332    }
333
334    #[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("consume_clone_or_copy",
                                    "rustc_hir_typeck::expr_use_visitor",
                                    ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("compiler/rustc_hir_typeck/src/expr_use_visitor.rs"),
                                    ::tracing_core::__macro_support::Option::Some(334u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_hir_typeck::expr_use_visitor"),
                                    ::tracing_core::field::FieldSet::new(&["place_with_id",
                                                    "diag_expr_id"],
                                        ::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(&place_with_id)
                                                            as &dyn Value)),
                                                (&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                    ::tracing::__macro_support::Option::Some(&::tracing::field::debug(&diag_expr_id)
                                                            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;
        }
        {
            if self.cx.type_is_copy_modulo_regions(place_with_id.place.ty()) {
                self.delegate.borrow_mut().copy(place_with_id, diag_expr_id);
            } else if self.cx.type_is_use_cloned_modulo_regions(place_with_id.place.ty())
                {
                self.delegate.borrow_mut().use_cloned(place_with_id,
                    diag_expr_id);
            } else {
                self.delegate.borrow_mut().consume(place_with_id,
                    diag_expr_id);
            }
        }
    }
}#[instrument(skip(self), level = "debug")]
335    pub fn consume_clone_or_copy(&self, place_with_id: &PlaceWithHirId<'tcx>, diag_expr_id: HirId) {
336        // `x.use` will do one of the following
337        // * if it implements `Copy`, it will be a copy
338        // * if it implements `UseCloned`, it will be a call to `clone`
339        // * otherwise, it is a move
340        //
341        // we do a conservative approximation of this, treating it as a move unless we know that it implements copy or `UseCloned`
342        if self.cx.type_is_copy_modulo_regions(place_with_id.place.ty()) {
343            self.delegate.borrow_mut().copy(place_with_id, diag_expr_id);
344        } else if self.cx.type_is_use_cloned_modulo_regions(place_with_id.place.ty()) {
345            self.delegate.borrow_mut().use_cloned(place_with_id, diag_expr_id);
346        } else {
347            self.delegate.borrow_mut().consume(place_with_id, diag_expr_id);
348        }
349    }
350
351    fn consume_exprs(&self, exprs: &[hir::Expr<'_>]) -> Result<(), Cx::Error> {
352        for expr in exprs {
353            self.consume_expr(expr)?;
354        }
355
356        Ok(())
357    }
358
359    // FIXME: It's suspicious that this is public; clippy should probably use `walk_expr`.
360    #[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("consume_expr",
                                    "rustc_hir_typeck::expr_use_visitor",
                                    ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("compiler/rustc_hir_typeck/src/expr_use_visitor.rs"),
                                    ::tracing_core::__macro_support::Option::Some(360u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_hir_typeck::expr_use_visitor"),
                                    ::tracing_core::field::FieldSet::new(&["expr"],
                                        ::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(&expr)
                                                            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: Result<(), Cx::Error> = loop {};
            return __tracing_attr_fake_return;
        }
        {
            let place_with_id = self.cat_expr(expr)?;
            self.consume_or_copy(&place_with_id, place_with_id.hir_id);
            self.walk_expr(expr)?;
            Ok(())
        }
    }
}#[instrument(skip(self), level = "debug")]
361    pub fn consume_expr(&self, expr: &hir::Expr<'_>) -> Result<(), Cx::Error> {
362        let place_with_id = self.cat_expr(expr)?;
363        self.consume_or_copy(&place_with_id, place_with_id.hir_id);
364        self.walk_expr(expr)?;
365        Ok(())
366    }
367
368    #[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("consume_or_clone_expr",
                                    "rustc_hir_typeck::expr_use_visitor",
                                    ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("compiler/rustc_hir_typeck/src/expr_use_visitor.rs"),
                                    ::tracing_core::__macro_support::Option::Some(368u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_hir_typeck::expr_use_visitor"),
                                    ::tracing_core::field::FieldSet::new(&["expr"],
                                        ::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(&expr)
                                                            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: Result<(), Cx::Error> = loop {};
            return __tracing_attr_fake_return;
        }
        {
            let place_with_id = self.cat_expr(expr)?;
            self.consume_clone_or_copy(&place_with_id, place_with_id.hir_id);
            self.walk_expr(expr)?;
            Ok(())
        }
    }
}#[instrument(skip(self), level = "debug")]
369    pub fn consume_or_clone_expr(&self, expr: &hir::Expr<'_>) -> Result<(), Cx::Error> {
370        let place_with_id = self.cat_expr(expr)?;
371        self.consume_clone_or_copy(&place_with_id, place_with_id.hir_id);
372        self.walk_expr(expr)?;
373        Ok(())
374    }
375
376    fn mutate_expr(&self, expr: &hir::Expr<'_>) -> Result<(), Cx::Error> {
377        let place_with_id = self.cat_expr(expr)?;
378        self.delegate.borrow_mut().mutate(&place_with_id, place_with_id.hir_id);
379        self.walk_expr(expr)?;
380        Ok(())
381    }
382
383    #[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("borrow_expr",
                                    "rustc_hir_typeck::expr_use_visitor",
                                    ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("compiler/rustc_hir_typeck/src/expr_use_visitor.rs"),
                                    ::tracing_core::__macro_support::Option::Some(383u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_hir_typeck::expr_use_visitor"),
                                    ::tracing_core::field::FieldSet::new(&["expr", "bk"],
                                        ::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(&expr)
                                                            as &dyn Value)),
                                                (&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                    ::tracing::__macro_support::Option::Some(&::tracing::field::debug(&bk)
                                                            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: Result<(), Cx::Error> = loop {};
            return __tracing_attr_fake_return;
        }
        {
            let place_with_id = self.cat_expr(expr)?;
            self.delegate.borrow_mut().borrow(&place_with_id,
                place_with_id.hir_id, bk);
            self.walk_expr(expr)
        }
    }
}#[instrument(skip(self), level = "debug")]
384    fn borrow_expr(&self, expr: &hir::Expr<'_>, bk: ty::BorrowKind) -> Result<(), Cx::Error> {
385        let place_with_id = self.cat_expr(expr)?;
386        self.delegate.borrow_mut().borrow(&place_with_id, place_with_id.hir_id, bk);
387        self.walk_expr(expr)
388    }
389
390    #[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("walk_expr",
                                    "rustc_hir_typeck::expr_use_visitor",
                                    ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("compiler/rustc_hir_typeck/src/expr_use_visitor.rs"),
                                    ::tracing_core::__macro_support::Option::Some(390u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_hir_typeck::expr_use_visitor"),
                                    ::tracing_core::field::FieldSet::new(&["expr"],
                                        ::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(&expr)
                                                            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: Result<(), Cx::Error> = loop {};
            return __tracing_attr_fake_return;
        }
        {
            self.walk_adjustment(expr)?;
            match expr.kind {
                hir::ExprKind::Path(_) => {}
                hir::ExprKind::Type(subexpr, _) => {
                    self.walk_expr(subexpr)?;
                }
                hir::ExprKind::UnsafeBinderCast(_, subexpr, _) => {
                    self.walk_expr(subexpr)?;
                }
                hir::ExprKind::Unary(hir::UnOp::Deref, base) => {
                    self.walk_expr(base)?;
                }
                hir::ExprKind::Field(base, _) => { self.walk_expr(base)?; }
                hir::ExprKind::Index(lhs, rhs, _) => {
                    self.walk_expr(lhs)?;
                    self.consume_expr(rhs)?;
                }
                hir::ExprKind::Call(callee, args) => {
                    self.consume_expr(callee)?;
                    self.consume_exprs(args)?;
                }
                hir::ExprKind::Use(expr, _) => {
                    self.consume_or_clone_expr(expr)?;
                }
                hir::ExprKind::MethodCall(.., receiver, args, _) => {
                    self.consume_expr(receiver)?;
                    self.consume_exprs(args)?;
                }
                hir::ExprKind::Struct(_, fields, ref opt_with) => {
                    self.walk_struct_expr(fields, opt_with)?;
                }
                hir::ExprKind::Tup(exprs) => { self.consume_exprs(exprs)?; }
                hir::ExprKind::If(cond_expr, then_expr, ref opt_else_expr) =>
                    {
                    self.consume_expr(cond_expr)?;
                    self.consume_expr(then_expr)?;
                    if let Some(else_expr) = *opt_else_expr {
                        self.consume_expr(else_expr)?;
                    }
                }
                hir::ExprKind::Let(hir::LetExpr { pat, init, .. }) => {
                    self.walk_local(init, pat, None,
                            || self.borrow_expr(init, BorrowKind::Immutable))?;
                }
                hir::ExprKind::Match(discr, arms, _) => {
                    let discr_place = self.cat_expr(discr)?;
                    self.fake_read_scrutinee(&discr_place, true)?;
                    self.walk_expr(discr)?;
                    for arm in arms { self.walk_arm(&discr_place, arm)?; }
                }
                hir::ExprKind::Array(exprs) => { self.consume_exprs(exprs)?; }
                hir::ExprKind::AddrOf(_, m, base) => {
                    let bk = ty::BorrowKind::from_mutbl(m);
                    self.borrow_expr(base, bk)?;
                }
                hir::ExprKind::InlineAsm(asm) => {
                    for (op, _op_sp) in asm.operands {
                        match op {
                            hir::InlineAsmOperand::In { expr, .. } => {
                                self.consume_expr(expr)?;
                            }
                            hir::InlineAsmOperand::Out { expr: Some(expr), .. } |
                                hir::InlineAsmOperand::InOut { expr, .. } => {
                                self.mutate_expr(expr)?;
                            }
                            hir::InlineAsmOperand::SplitInOut { in_expr, out_expr, .. }
                                => {
                                self.consume_expr(in_expr)?;
                                if let Some(out_expr) = out_expr {
                                    self.mutate_expr(out_expr)?;
                                }
                            }
                            hir::InlineAsmOperand::Out { expr: None, .. } |
                                hir::InlineAsmOperand::Const { .. } |
                                hir::InlineAsmOperand::SymFn { .. } |
                                hir::InlineAsmOperand::SymStatic { .. } => {}
                            hir::InlineAsmOperand::Label { block } => {
                                self.walk_block(block)?;
                            }
                        }
                    }
                }
                hir::ExprKind::Continue(..) | hir::ExprKind::Lit(..) |
                    hir::ExprKind::ConstBlock(..) | hir::ExprKind::OffsetOf(..)
                    | hir::ExprKind::Err(_) => {}
                hir::ExprKind::Loop(blk, ..) => { self.walk_block(blk)?; }
                hir::ExprKind::Unary(_, lhs) => { self.consume_expr(lhs)?; }
                hir::ExprKind::Binary(_, lhs, rhs) => {
                    self.consume_expr(lhs)?;
                    self.consume_expr(rhs)?;
                }
                hir::ExprKind::Block(blk, _) => { self.walk_block(blk)?; }
                hir::ExprKind::Break(_, ref opt_expr) |
                    hir::ExprKind::Ret(ref opt_expr) => {
                    if let Some(expr) = *opt_expr { self.consume_expr(expr)?; }
                }
                hir::ExprKind::Become(call) => { self.consume_expr(call)?; }
                hir::ExprKind::Assign(lhs, rhs, _) => {
                    self.mutate_expr(lhs)?;
                    self.consume_expr(rhs)?;
                }
                hir::ExprKind::Cast(base, _) => { self.consume_expr(base)?; }
                hir::ExprKind::DropTemps(expr) => {
                    self.consume_expr(expr)?;
                }
                hir::ExprKind::AssignOp(_, lhs, rhs) => {
                    if self.cx.typeck_results().is_method_call(expr) {
                        self.consume_expr(lhs)?;
                    } else { self.mutate_expr(lhs)?; }
                    self.consume_expr(rhs)?;
                }
                hir::ExprKind::Repeat(base, _) => {
                    self.consume_expr(base)?;
                }
                hir::ExprKind::Closure(closure) => {
                    self.walk_captures(closure)?;
                }
                hir::ExprKind::Yield(value, _) => {
                    self.consume_expr(value)?;
                }
            }
            Ok(())
        }
    }
}#[instrument(skip(self), level = "debug")]
391    pub fn walk_expr(&self, expr: &hir::Expr<'_>) -> Result<(), Cx::Error> {
392        self.walk_adjustment(expr)?;
393
394        match expr.kind {
395            hir::ExprKind::Path(_) => {}
396
397            hir::ExprKind::Type(subexpr, _) => {
398                self.walk_expr(subexpr)?;
399            }
400
401            hir::ExprKind::UnsafeBinderCast(_, subexpr, _) => {
402                self.walk_expr(subexpr)?;
403            }
404
405            hir::ExprKind::Unary(hir::UnOp::Deref, base) => {
406                // *base
407                self.walk_expr(base)?;
408            }
409
410            hir::ExprKind::Field(base, _) => {
411                // base.f
412                self.walk_expr(base)?;
413            }
414
415            hir::ExprKind::Index(lhs, rhs, _) => {
416                // lhs[rhs]
417                self.walk_expr(lhs)?;
418                self.consume_expr(rhs)?;
419            }
420
421            hir::ExprKind::Call(callee, args) => {
422                // callee(args)
423                self.consume_expr(callee)?;
424                self.consume_exprs(args)?;
425            }
426
427            hir::ExprKind::Use(expr, _) => {
428                self.consume_or_clone_expr(expr)?;
429            }
430
431            hir::ExprKind::MethodCall(.., receiver, args, _) => {
432                // callee.m(args)
433                self.consume_expr(receiver)?;
434                self.consume_exprs(args)?;
435            }
436
437            hir::ExprKind::Struct(_, fields, ref opt_with) => {
438                self.walk_struct_expr(fields, opt_with)?;
439            }
440
441            hir::ExprKind::Tup(exprs) => {
442                self.consume_exprs(exprs)?;
443            }
444
445            hir::ExprKind::If(cond_expr, then_expr, ref opt_else_expr) => {
446                self.consume_expr(cond_expr)?;
447                self.consume_expr(then_expr)?;
448                if let Some(else_expr) = *opt_else_expr {
449                    self.consume_expr(else_expr)?;
450                }
451            }
452
453            hir::ExprKind::Let(hir::LetExpr { pat, init, .. }) => {
454                self.walk_local(init, pat, None, || self.borrow_expr(init, BorrowKind::Immutable))?;
455            }
456
457            hir::ExprKind::Match(discr, arms, _) => {
458                let discr_place = self.cat_expr(discr)?;
459                self.fake_read_scrutinee(&discr_place, true)?;
460                self.walk_expr(discr)?;
461
462                for arm in arms {
463                    self.walk_arm(&discr_place, arm)?;
464                }
465            }
466
467            hir::ExprKind::Array(exprs) => {
468                self.consume_exprs(exprs)?;
469            }
470
471            hir::ExprKind::AddrOf(_, m, base) => {
472                // &base
473                // make sure that the thing we are pointing out stays valid
474                // for the lifetime `scope_r` of the resulting ptr:
475                let bk = ty::BorrowKind::from_mutbl(m);
476                self.borrow_expr(base, bk)?;
477            }
478
479            hir::ExprKind::InlineAsm(asm) => {
480                for (op, _op_sp) in asm.operands {
481                    match op {
482                        hir::InlineAsmOperand::In { expr, .. } => {
483                            self.consume_expr(expr)?;
484                        }
485                        hir::InlineAsmOperand::Out { expr: Some(expr), .. }
486                        | hir::InlineAsmOperand::InOut { expr, .. } => {
487                            self.mutate_expr(expr)?;
488                        }
489                        hir::InlineAsmOperand::SplitInOut { in_expr, out_expr, .. } => {
490                            self.consume_expr(in_expr)?;
491                            if let Some(out_expr) = out_expr {
492                                self.mutate_expr(out_expr)?;
493                            }
494                        }
495                        hir::InlineAsmOperand::Out { expr: None, .. }
496                        | hir::InlineAsmOperand::Const { .. }
497                        | hir::InlineAsmOperand::SymFn { .. }
498                        | hir::InlineAsmOperand::SymStatic { .. } => {}
499                        hir::InlineAsmOperand::Label { block } => {
500                            self.walk_block(block)?;
501                        }
502                    }
503                }
504            }
505
506            hir::ExprKind::Continue(..)
507            | hir::ExprKind::Lit(..)
508            | hir::ExprKind::ConstBlock(..)
509            | hir::ExprKind::OffsetOf(..)
510            | hir::ExprKind::Err(_) => {}
511
512            hir::ExprKind::Loop(blk, ..) => {
513                self.walk_block(blk)?;
514            }
515
516            hir::ExprKind::Unary(_, lhs) => {
517                self.consume_expr(lhs)?;
518            }
519
520            hir::ExprKind::Binary(_, lhs, rhs) => {
521                self.consume_expr(lhs)?;
522                self.consume_expr(rhs)?;
523            }
524
525            hir::ExprKind::Block(blk, _) => {
526                self.walk_block(blk)?;
527            }
528
529            hir::ExprKind::Break(_, ref opt_expr) | hir::ExprKind::Ret(ref opt_expr) => {
530                if let Some(expr) = *opt_expr {
531                    self.consume_expr(expr)?;
532                }
533            }
534
535            hir::ExprKind::Become(call) => {
536                self.consume_expr(call)?;
537            }
538
539            hir::ExprKind::Assign(lhs, rhs, _) => {
540                self.mutate_expr(lhs)?;
541                self.consume_expr(rhs)?;
542            }
543
544            hir::ExprKind::Cast(base, _) => {
545                self.consume_expr(base)?;
546            }
547
548            hir::ExprKind::DropTemps(expr) => {
549                self.consume_expr(expr)?;
550            }
551
552            hir::ExprKind::AssignOp(_, lhs, rhs) => {
553                if self.cx.typeck_results().is_method_call(expr) {
554                    self.consume_expr(lhs)?;
555                } else {
556                    self.mutate_expr(lhs)?;
557                }
558                self.consume_expr(rhs)?;
559            }
560
561            hir::ExprKind::Repeat(base, _) => {
562                self.consume_expr(base)?;
563            }
564
565            hir::ExprKind::Closure(closure) => {
566                self.walk_captures(closure)?;
567            }
568
569            hir::ExprKind::Yield(value, _) => {
570                self.consume_expr(value)?;
571            }
572        }
573
574        Ok(())
575    }
576
577    fn walk_stmt(&self, stmt: &hir::Stmt<'_>) -> Result<(), Cx::Error> {
578        match stmt.kind {
579            hir::StmtKind::Let(hir::LetStmt { pat, init: Some(expr), els, .. }) => {
580                self.walk_local(expr, pat, *els, || Ok(()))?;
581            }
582
583            hir::StmtKind::Let(_) => {}
584
585            hir::StmtKind::Item(_) => {
586                // We don't visit nested items in this visitor,
587                // only the fn body we were given.
588            }
589
590            hir::StmtKind::Expr(expr) | hir::StmtKind::Semi(expr) => {
591                self.consume_expr(expr)?;
592            }
593        }
594
595        Ok(())
596    }
597
598    #[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("fake_read_scrutinee",
                                    "rustc_hir_typeck::expr_use_visitor",
                                    ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("compiler/rustc_hir_typeck/src/expr_use_visitor.rs"),
                                    ::tracing_core::__macro_support::Option::Some(598u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_hir_typeck::expr_use_visitor"),
                                    ::tracing_core::field::FieldSet::new(&["discr_place",
                                                    "refutable"],
                                        ::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(&discr_place)
                                                            as &dyn Value)),
                                                (&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                    ::tracing::__macro_support::Option::Some(&refutable 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: Result<(), Cx::Error> = loop {};
            return __tracing_attr_fake_return;
        }
        {
            let closure_def_id =
                match discr_place.place.base {
                    PlaceBase::Upvar(upvar_id) =>
                        Some(upvar_id.closure_expr_id),
                    _ => None,
                };
            let cause =
                if refutable {
                    FakeReadCause::ForMatchedPlace(closure_def_id)
                } else { FakeReadCause::ForLet(closure_def_id) };
            self.delegate.borrow_mut().fake_read(discr_place, cause,
                discr_place.hir_id);
            Ok(())
        }
    }
}#[instrument(skip(self), level = "debug")]
599    fn fake_read_scrutinee(
600        &self,
601        discr_place: &PlaceWithHirId<'tcx>,
602        refutable: bool,
603    ) -> Result<(), Cx::Error> {
604        let closure_def_id = match discr_place.place.base {
605            PlaceBase::Upvar(upvar_id) => Some(upvar_id.closure_expr_id),
606            _ => None,
607        };
608
609        let cause = if refutable {
610            FakeReadCause::ForMatchedPlace(closure_def_id)
611        } else {
612            FakeReadCause::ForLet(closure_def_id)
613        };
614
615        self.delegate.borrow_mut().fake_read(discr_place, cause, discr_place.hir_id);
616
617        Ok(())
618    }
619
620    fn walk_local<F>(
621        &self,
622        expr: &hir::Expr<'_>,
623        pat: &hir::Pat<'_>,
624        els: Option<&hir::Block<'_>>,
625        mut f: F,
626    ) -> Result<(), Cx::Error>
627    where
628        F: FnMut() -> Result<(), Cx::Error>,
629    {
630        self.walk_expr(expr)?;
631        let expr_place = self.cat_expr(expr)?;
632        f()?;
633        self.fake_read_scrutinee(&expr_place, els.is_some())?;
634        self.walk_pat(&expr_place, pat, false)?;
635        if let Some(els) = els {
636            self.walk_block(els)?;
637        }
638        Ok(())
639    }
640
641    /// Indicates that the value of `blk` will be consumed, meaning either copied or moved
642    /// depending on its type.
643    #[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("walk_block",
                                    "rustc_hir_typeck::expr_use_visitor",
                                    ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("compiler/rustc_hir_typeck/src/expr_use_visitor.rs"),
                                    ::tracing_core::__macro_support::Option::Some(643u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_hir_typeck::expr_use_visitor"),
                                    ::tracing_core::field::FieldSet::new(&["blk"],
                                        ::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(&blk)
                                                            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: Result<(), Cx::Error> = loop {};
            return __tracing_attr_fake_return;
        }
        {
            for stmt in blk.stmts { self.walk_stmt(stmt)?; }
            if let Some(tail_expr) = blk.expr {
                self.consume_expr(tail_expr)?;
            }
            Ok(())
        }
    }
}#[instrument(skip(self), level = "debug")]
644    fn walk_block(&self, blk: &hir::Block<'_>) -> Result<(), Cx::Error> {
645        for stmt in blk.stmts {
646            self.walk_stmt(stmt)?;
647        }
648
649        if let Some(tail_expr) = blk.expr {
650            self.consume_expr(tail_expr)?;
651        }
652
653        Ok(())
654    }
655
656    fn walk_struct_expr<'hir>(
657        &self,
658        fields: &[hir::ExprField<'_>],
659        opt_with: &hir::StructTailExpr<'hir>,
660    ) -> Result<(), Cx::Error> {
661        // Consume the expressions supplying values for each field.
662        for field in fields {
663            self.consume_expr(field.expr)?;
664
665            // The struct path probably didn't resolve
666            if self.cx.typeck_results().opt_field_index(field.hir_id).is_none() {
667                self.cx
668                    .tcx()
669                    .dcx()
670                    .span_delayed_bug(field.span, "couldn't resolve index for field");
671            }
672        }
673
674        let with_expr = match *opt_with {
675            hir::StructTailExpr::Base(w) => &*w,
676            hir::StructTailExpr::DefaultFields(_)
677            | hir::StructTailExpr::None
678            | hir::StructTailExpr::NoneWithError(_) => {
679                return Ok(());
680            }
681        };
682
683        let with_place = self.cat_expr(with_expr)?;
684
685        // Select just those fields of the `with`
686        // expression that will actually be used
687        match self.cx.structurally_resolve_type(with_expr.span, with_place.place.ty()).kind() {
688            ty::Adt(adt, args) if adt.is_struct() => {
689                // Consume those fields of the with expression that are needed.
690                for (f_index, with_field) in adt.non_enum_variant().fields.iter_enumerated() {
691                    let is_mentioned = fields.iter().any(|f| {
692                        self.cx.typeck_results().opt_field_index(f.hir_id) == Some(f_index)
693                    });
694                    if !is_mentioned {
695                        let field_place = self.cat_projection(
696                            with_expr.hir_id,
697                            with_place.clone(),
698                            with_field.ty(self.cx.tcx(), args).skip_norm_wip(),
699                            ProjectionKind::Field(f_index, FIRST_VARIANT),
700                        );
701                        self.consume_or_copy(&field_place, field_place.hir_id);
702                    }
703                }
704            }
705            _ => {
706                // the base expression should always evaluate to a
707                // struct; however, when EUV is run during typeck, it
708                // may not. This will generate an error earlier in typeck,
709                // so we can just ignore it.
710                if self.cx.tainted_by_errors().is_ok() {
711                    ::rustc_middle::util::bug::span_bug_fmt(with_expr.span,
    format_args!("with expression doesn\'t evaluate to a struct"));span_bug!(with_expr.span, "with expression doesn't evaluate to a struct");
712                }
713            }
714        }
715
716        // walk the with expression so that complex expressions
717        // are properly handled.
718        self.walk_expr(with_expr)?;
719
720        Ok(())
721    }
722
723    /// Invoke the appropriate delegate calls for anything that gets
724    /// consumed or borrowed as part of the automatic adjustment
725    /// process.
726    fn walk_adjustment(&self, expr: &hir::Expr<'_>) -> Result<(), Cx::Error> {
727        let typeck_results = self.cx.typeck_results();
728        let adjustments = typeck_results.expr_adjustments(expr);
729        let mut place_with_id = self.cat_expr_unadjusted(expr)?;
730        for (adjustment_index, adjustment) in adjustments.iter().enumerate() {
731            let is_last_adjustment = adjustment_index + 1 == adjustments.len();
732            {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_hir_typeck/src/expr_use_visitor.rs:732",
                        "rustc_hir_typeck::expr_use_visitor",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_hir_typeck/src/expr_use_visitor.rs"),
                        ::tracing_core::__macro_support::Option::Some(732u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_hir_typeck::expr_use_visitor"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                let mut iter = __CALLSITE.metadata().fields().iter();
                __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&format_args!("walk_adjustment expr={0:?} adj={1:?}",
                                                    expr, adjustment) as &dyn Value))])
            });
    } else { ; }
};debug!("walk_adjustment expr={:?} adj={:?}", expr, adjustment);
733            match adjustment.kind {
734                adjustment::Adjust::NeverToAny | adjustment::Adjust::Pointer(_) => {
735                    // Creating a closure/fn-pointer or unsizing consumes
736                    // the input and stores it into the resulting rvalue.
737                    self.consume_or_copy(&place_with_id, place_with_id.hir_id);
738                }
739
740                adjustment::Adjust::Deref(DerefAdjustKind::Builtin | DerefAdjustKind::Pin) => {}
741
742                // Autoderefs for overloaded Deref calls in fact reference
743                // their receiver. That is, if we have `(*x)` where `x`
744                // is of type `Rc<T>`, then this in fact is equivalent to
745                // `x.deref()`. Since `deref()` is declared with `&self`,
746                // this is an autoref of `x`.
747                adjustment::Adjust::Deref(DerefAdjustKind::Overloaded(deref)) => {
748                    let bk = ty::BorrowKind::from_mutbl(deref.mutbl);
749                    self.delegate.borrow_mut().borrow(&place_with_id, place_with_id.hir_id, bk);
750                }
751
752                adjustment::Adjust::Borrow(ref autoref) => {
753                    self.walk_autoref(expr, &place_with_id, autoref);
754                }
755
756                adjustment::Adjust::GenericReborrow(mutability) if is_last_adjustment => {
757                    let bk = ty::BorrowKind::from_mutbl(mutability);
758                    self.delegate.borrow_mut().borrow(&place_with_id, place_with_id.hir_id, bk);
759                }
760
761                adjustment::Adjust::GenericReborrow(_) => {
762                    ::rustc_middle::util::bug::span_bug_fmt(expr.span,
    format_args!("generic reborrow adjustment must be terminal"));span_bug!(expr.span, "generic reborrow adjustment must be terminal");
763                }
764            }
765            place_with_id = self.cat_expr_adjusted(expr, place_with_id, adjustment)?;
766        }
767
768        Ok(())
769    }
770
771    /// Walks the autoref `autoref` applied to the autoderef'd
772    /// `expr`. `base_place` is `expr` represented as a place,
773    /// after all relevant autoderefs have occurred.
774    fn walk_autoref(
775        &self,
776        expr: &hir::Expr<'_>,
777        base_place: &PlaceWithHirId<'tcx>,
778        autoref: &adjustment::AutoBorrow,
779    ) {
780        {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_hir_typeck/src/expr_use_visitor.rs:780",
                        "rustc_hir_typeck::expr_use_visitor",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_hir_typeck/src/expr_use_visitor.rs"),
                        ::tracing_core::__macro_support::Option::Some(780u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_hir_typeck::expr_use_visitor"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                let mut iter = __CALLSITE.metadata().fields().iter();
                __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&format_args!("walk_autoref(expr.hir_id={0} base_place={1:?} autoref={2:?})",
                                                    expr.hir_id, base_place, autoref) as &dyn Value))])
            });
    } else { ; }
};debug!(
781            "walk_autoref(expr.hir_id={} base_place={:?} autoref={:?})",
782            expr.hir_id, base_place, autoref
783        );
784
785        match *autoref {
786            adjustment::AutoBorrow::Ref(m) => {
787                self.delegate.borrow_mut().borrow(
788                    base_place,
789                    base_place.hir_id,
790                    ty::BorrowKind::from_mutbl(m.into()),
791                );
792            }
793
794            adjustment::AutoBorrow::RawPtr(m) | adjustment::AutoBorrow::Pin(m) => {
795                {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_hir_typeck/src/expr_use_visitor.rs:795",
                        "rustc_hir_typeck::expr_use_visitor",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_hir_typeck/src/expr_use_visitor.rs"),
                        ::tracing_core::__macro_support::Option::Some(795u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_hir_typeck::expr_use_visitor"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                let mut iter = __CALLSITE.metadata().fields().iter();
                __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&format_args!("walk_autoref: expr.hir_id={0} base_place={1:?}",
                                                    expr.hir_id, base_place) as &dyn Value))])
            });
    } else { ; }
};debug!("walk_autoref: expr.hir_id={} base_place={:?}", expr.hir_id, base_place);
796
797                self.delegate.borrow_mut().borrow(
798                    base_place,
799                    base_place.hir_id,
800                    ty::BorrowKind::from_mutbl(m),
801                );
802            }
803        }
804    }
805
806    fn walk_arm(
807        &self,
808        discr_place: &PlaceWithHirId<'tcx>,
809        arm: &hir::Arm<'_>,
810    ) -> Result<(), Cx::Error> {
811        self.walk_pat(discr_place, arm.pat, arm.guard.is_some())?;
812
813        if let Some(ref e) = arm.guard {
814            self.consume_expr(e)?;
815        }
816
817        self.consume_expr(arm.body)?;
818        Ok(())
819    }
820
821    /// The core driver for walking a pattern
822    ///
823    /// This should mirror how pattern-matching gets lowered to MIR, as
824    /// otherwise said lowering will ICE when trying to resolve the upvars.
825    ///
826    /// However, it is okay to approximate it here by doing *more* accesses than
827    /// the actual MIR builder will, which is useful when some checks are too
828    /// cumbersome to perform here, because e.g. they require more typeck results
829    /// than available.
830    ///
831    /// Do note that discrepancies like these do still create obscure corners
832    /// in the semantics of the language, and should be avoided if possible.
833    #[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("walk_pat",
                                    "rustc_hir_typeck::expr_use_visitor",
                                    ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("compiler/rustc_hir_typeck/src/expr_use_visitor.rs"),
                                    ::tracing_core::__macro_support::Option::Some(833u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_hir_typeck::expr_use_visitor"),
                                    ::tracing_core::field::FieldSet::new(&["discr_place", "pat",
                                                    "has_guard"],
                                        ::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(&discr_place)
                                                            as &dyn Value)),
                                                (&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                    ::tracing::__macro_support::Option::Some(&::tracing::field::debug(&pat)
                                                            as &dyn Value)),
                                                (&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                    ::tracing::__macro_support::Option::Some(&has_guard 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: Result<(), Cx::Error> = loop {};
            return __tracing_attr_fake_return;
        }
        {
            let tcx = self.cx.tcx();
            self.cat_pattern(discr_place.clone(), pat,
                &mut |place, pat|
                        {
                            {
                                use ::tracing::__macro_support::Callsite as _;
                                static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                                    {
                                        static META: ::tracing::Metadata<'static> =
                                            {
                                                ::tracing_core::metadata::Metadata::new("event compiler/rustc_hir_typeck/src/expr_use_visitor.rs:842",
                                                    "rustc_hir_typeck::expr_use_visitor",
                                                    ::tracing::Level::DEBUG,
                                                    ::tracing_core::__macro_support::Option::Some("compiler/rustc_hir_typeck/src/expr_use_visitor.rs"),
                                                    ::tracing_core::__macro_support::Option::Some(842u32),
                                                    ::tracing_core::__macro_support::Option::Some("rustc_hir_typeck::expr_use_visitor"),
                                                    ::tracing_core::field::FieldSet::new(&["message"],
                                                        ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                                    ::tracing::metadata::Kind::EVENT)
                                            };
                                        ::tracing::callsite::DefaultCallsite::new(&META)
                                    };
                                let enabled =
                                    ::tracing::Level::DEBUG <=
                                                ::tracing::level_filters::STATIC_MAX_LEVEL &&
                                            ::tracing::Level::DEBUG <=
                                                ::tracing::level_filters::LevelFilter::current() &&
                                        {
                                            let interest = __CALLSITE.interest();
                                            !interest.is_never() &&
                                                ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                                                    interest)
                                        };
                                if enabled {
                                    (|value_set: ::tracing::field::ValueSet|
                                                {
                                                    let meta = __CALLSITE.metadata();
                                                    ::tracing::Event::dispatch(meta, &value_set);
                                                    ;
                                                })({
                                            #[allow(unused_imports)]
                                            use ::tracing::field::{debug, display, Value};
                                            let mut iter = __CALLSITE.metadata().fields().iter();
                                            __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                                ::tracing::__macro_support::Option::Some(&format_args!("walk_pat: pat.kind={0:?}",
                                                                                pat.kind) as &dyn Value))])
                                        });
                                } else { ; }
                            };
                            let read_discriminant =
                                ||
                                    {
                                        self.delegate.borrow_mut().borrow(place, discr_place.hir_id,
                                            BorrowKind::Immutable);
                                    };
                            match pat.kind {
                                PatKind::Binding(_, canonical_id, ..) => {
                                    {
                                        use ::tracing::__macro_support::Callsite as _;
                                        static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                                            {
                                                static META: ::tracing::Metadata<'static> =
                                                    {
                                                        ::tracing_core::metadata::Metadata::new("event compiler/rustc_hir_typeck/src/expr_use_visitor.rs:849",
                                                            "rustc_hir_typeck::expr_use_visitor",
                                                            ::tracing::Level::DEBUG,
                                                            ::tracing_core::__macro_support::Option::Some("compiler/rustc_hir_typeck/src/expr_use_visitor.rs"),
                                                            ::tracing_core::__macro_support::Option::Some(849u32),
                                                            ::tracing_core::__macro_support::Option::Some("rustc_hir_typeck::expr_use_visitor"),
                                                            ::tracing_core::field::FieldSet::new(&["message"],
                                                                ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                                            ::tracing::metadata::Kind::EVENT)
                                                    };
                                                ::tracing::callsite::DefaultCallsite::new(&META)
                                            };
                                        let enabled =
                                            ::tracing::Level::DEBUG <=
                                                        ::tracing::level_filters::STATIC_MAX_LEVEL &&
                                                    ::tracing::Level::DEBUG <=
                                                        ::tracing::level_filters::LevelFilter::current() &&
                                                {
                                                    let interest = __CALLSITE.interest();
                                                    !interest.is_never() &&
                                                        ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                                                            interest)
                                                };
                                        if enabled {
                                            (|value_set: ::tracing::field::ValueSet|
                                                        {
                                                            let meta = __CALLSITE.metadata();
                                                            ::tracing::Event::dispatch(meta, &value_set);
                                                            ;
                                                        })({
                                                    #[allow(unused_imports)]
                                                    use ::tracing::field::{debug, display, Value};
                                                    let mut iter = __CALLSITE.metadata().fields().iter();
                                                    __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                                        ::tracing::__macro_support::Option::Some(&format_args!("walk_pat: binding place={0:?} pat={1:?}",
                                                                                        place, pat) as &dyn Value))])
                                                });
                                        } else { ; }
                                    };
                                    let bm =
                                        self.cx.typeck_results().extract_binding_mode(tcx.sess,
                                            pat.hir_id, pat.span);
                                    {
                                        use ::tracing::__macro_support::Callsite as _;
                                        static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                                            {
                                                static META: ::tracing::Metadata<'static> =
                                                    {
                                                        ::tracing_core::metadata::Metadata::new("event compiler/rustc_hir_typeck/src/expr_use_visitor.rs:854",
                                                            "rustc_hir_typeck::expr_use_visitor",
                                                            ::tracing::Level::DEBUG,
                                                            ::tracing_core::__macro_support::Option::Some("compiler/rustc_hir_typeck/src/expr_use_visitor.rs"),
                                                            ::tracing_core::__macro_support::Option::Some(854u32),
                                                            ::tracing_core::__macro_support::Option::Some("rustc_hir_typeck::expr_use_visitor"),
                                                            ::tracing_core::field::FieldSet::new(&["message"],
                                                                ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                                            ::tracing::metadata::Kind::EVENT)
                                                    };
                                                ::tracing::callsite::DefaultCallsite::new(&META)
                                            };
                                        let enabled =
                                            ::tracing::Level::DEBUG <=
                                                        ::tracing::level_filters::STATIC_MAX_LEVEL &&
                                                    ::tracing::Level::DEBUG <=
                                                        ::tracing::level_filters::LevelFilter::current() &&
                                                {
                                                    let interest = __CALLSITE.interest();
                                                    !interest.is_never() &&
                                                        ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                                                            interest)
                                                };
                                        if enabled {
                                            (|value_set: ::tracing::field::ValueSet|
                                                        {
                                                            let meta = __CALLSITE.metadata();
                                                            ::tracing::Event::dispatch(meta, &value_set);
                                                            ;
                                                        })({
                                                    #[allow(unused_imports)]
                                                    use ::tracing::field::{debug, display, Value};
                                                    let mut iter = __CALLSITE.metadata().fields().iter();
                                                    __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                                        ::tracing::__macro_support::Option::Some(&format_args!("walk_pat: pat.hir_id={0:?} bm={1:?}",
                                                                                        pat.hir_id, bm) as &dyn Value))])
                                                });
                                        } else { ; }
                                    };
                                    let pat_ty = self.node_ty(pat.hir_id)?;
                                    {
                                        use ::tracing::__macro_support::Callsite as _;
                                        static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                                            {
                                                static META: ::tracing::Metadata<'static> =
                                                    {
                                                        ::tracing_core::metadata::Metadata::new("event compiler/rustc_hir_typeck/src/expr_use_visitor.rs:858",
                                                            "rustc_hir_typeck::expr_use_visitor",
                                                            ::tracing::Level::DEBUG,
                                                            ::tracing_core::__macro_support::Option::Some("compiler/rustc_hir_typeck/src/expr_use_visitor.rs"),
                                                            ::tracing_core::__macro_support::Option::Some(858u32),
                                                            ::tracing_core::__macro_support::Option::Some("rustc_hir_typeck::expr_use_visitor"),
                                                            ::tracing_core::field::FieldSet::new(&["message"],
                                                                ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                                            ::tracing::metadata::Kind::EVENT)
                                                    };
                                                ::tracing::callsite::DefaultCallsite::new(&META)
                                            };
                                        let enabled =
                                            ::tracing::Level::DEBUG <=
                                                        ::tracing::level_filters::STATIC_MAX_LEVEL &&
                                                    ::tracing::Level::DEBUG <=
                                                        ::tracing::level_filters::LevelFilter::current() &&
                                                {
                                                    let interest = __CALLSITE.interest();
                                                    !interest.is_never() &&
                                                        ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                                                            interest)
                                                };
                                        if enabled {
                                            (|value_set: ::tracing::field::ValueSet|
                                                        {
                                                            let meta = __CALLSITE.metadata();
                                                            ::tracing::Event::dispatch(meta, &value_set);
                                                            ;
                                                        })({
                                                    #[allow(unused_imports)]
                                                    use ::tracing::field::{debug, display, Value};
                                                    let mut iter = __CALLSITE.metadata().fields().iter();
                                                    __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                                        ::tracing::__macro_support::Option::Some(&format_args!("walk_pat: pat_ty={0:?}",
                                                                                        pat_ty) as &dyn Value))])
                                                });
                                        } else { ; }
                                    };
                                    let def = Res::Local(canonical_id);
                                    if let Ok(ref binding_place) =
                                            self.cat_res(pat.hir_id, pat.span, pat_ty, def) {
                                        self.delegate.borrow_mut().bind(binding_place,
                                            binding_place.hir_id);
                                    }
                                    if has_guard { read_discriminant(); }
                                    match bm.0 {
                                        hir::ByRef::Yes(_, m) => {
                                            let bk = ty::BorrowKind::from_mutbl(m);
                                            self.delegate.borrow_mut().borrow(place, discr_place.hir_id,
                                                bk);
                                        }
                                        hir::ByRef::No => {
                                            {
                                                use ::tracing::__macro_support::Callsite as _;
                                                static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                                                    {
                                                        static META: ::tracing::Metadata<'static> =
                                                            {
                                                                ::tracing_core::metadata::Metadata::new("event compiler/rustc_hir_typeck/src/expr_use_visitor.rs:882",
                                                                    "rustc_hir_typeck::expr_use_visitor",
                                                                    ::tracing::Level::DEBUG,
                                                                    ::tracing_core::__macro_support::Option::Some("compiler/rustc_hir_typeck/src/expr_use_visitor.rs"),
                                                                    ::tracing_core::__macro_support::Option::Some(882u32),
                                                                    ::tracing_core::__macro_support::Option::Some("rustc_hir_typeck::expr_use_visitor"),
                                                                    ::tracing_core::field::FieldSet::new(&["message"],
                                                                        ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                                                    ::tracing::metadata::Kind::EVENT)
                                                            };
                                                        ::tracing::callsite::DefaultCallsite::new(&META)
                                                    };
                                                let enabled =
                                                    ::tracing::Level::DEBUG <=
                                                                ::tracing::level_filters::STATIC_MAX_LEVEL &&
                                                            ::tracing::Level::DEBUG <=
                                                                ::tracing::level_filters::LevelFilter::current() &&
                                                        {
                                                            let interest = __CALLSITE.interest();
                                                            !interest.is_never() &&
                                                                ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                                                                    interest)
                                                        };
                                                if enabled {
                                                    (|value_set: ::tracing::field::ValueSet|
                                                                {
                                                                    let meta = __CALLSITE.metadata();
                                                                    ::tracing::Event::dispatch(meta, &value_set);
                                                                    ;
                                                                })({
                                                            #[allow(unused_imports)]
                                                            use ::tracing::field::{debug, display, Value};
                                                            let mut iter = __CALLSITE.metadata().fields().iter();
                                                            __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                                                ::tracing::__macro_support::Option::Some(&format_args!("walk_pat binding consuming pat")
                                                                                        as &dyn Value))])
                                                        });
                                                } else { ; }
                                            };
                                            self.consume_or_copy(place, discr_place.hir_id);
                                        }
                                    }
                                }
                                PatKind::Deref(subpattern) => {
                                    if let DerefPatBorrowMode::Borrow(mutability) =
                                            self.cx.typeck_results().deref_pat_borrow_mode(place.place.ty(),
                                                subpattern) {
                                        let bk = ty::BorrowKind::from_mutbl(mutability);
                                        self.delegate.borrow_mut().borrow(place, discr_place.hir_id,
                                            bk);
                                    }
                                }
                                PatKind::Never => { read_discriminant(); }
                                PatKind::Expr(PatExpr {
                                    kind: PatExprKind::Path(qpath), hir_id, span }) => {
                                    let res =
                                        self.cx.typeck_results().qpath_res(qpath, *hir_id);
                                    match res {
                                        Res::Def(DefKind::Const { .. }, _) |
                                            Res::Def(DefKind::AssocConst { .. }, _) => {
                                            read_discriminant();
                                        }
                                        _ => {
                                            if self.is_multivariant_adt(place.place.ty(), *span) {
                                                read_discriminant();
                                            }
                                        }
                                    }
                                }
                                PatKind::Expr(_) | PatKind::Range(..) => {
                                    read_discriminant();
                                }
                                PatKind::Struct(..) | PatKind::TupleStruct(..) => {
                                    if self.is_multivariant_adt(place.place.ty(), pat.span) {
                                        read_discriminant();
                                    }
                                }
                                PatKind::Slice(lhs, wild, rhs) => {
                                    if #[allow(non_exhaustive_omitted_patterns)] match (lhs,
                                                    wild, rhs) {
                                                (&[], Some(_), &[]) => true,
                                                _ => false,
                                            } || place.place.ty().peel_refs().is_array()
                                        {} else { read_discriminant(); }
                                }
                                PatKind::Or(_) | PatKind::Box(_) | PatKind::Ref(..) |
                                    PatKind::Guard(..) | PatKind::Tuple(..) | PatKind::Wild |
                                    PatKind::Missing | PatKind::Err(_) => {}
                            }
                            Ok(())
                        })
        }
    }
}#[instrument(skip(self), level = "debug")]
834    fn walk_pat(
835        &self,
836        discr_place: &PlaceWithHirId<'tcx>,
837        pat: &hir::Pat<'_>,
838        has_guard: bool,
839    ) -> Result<(), Cx::Error> {
840        let tcx = self.cx.tcx();
841        self.cat_pattern(discr_place.clone(), pat, &mut |place, pat| {
842            debug!("walk_pat: pat.kind={:?}", pat.kind);
843            let read_discriminant = || {
844                self.delegate.borrow_mut().borrow(place, discr_place.hir_id, BorrowKind::Immutable);
845            };
846
847            match pat.kind {
848                PatKind::Binding(_, canonical_id, ..) => {
849                    debug!("walk_pat: binding place={:?} pat={:?}", place, pat);
850                    let bm = self
851                        .cx
852                        .typeck_results()
853                        .extract_binding_mode(tcx.sess, pat.hir_id, pat.span);
854                    debug!("walk_pat: pat.hir_id={:?} bm={:?}", pat.hir_id, bm);
855
856                    // pat_ty: the type of the binding being produced.
857                    let pat_ty = self.node_ty(pat.hir_id)?;
858                    debug!("walk_pat: pat_ty={:?}", pat_ty);
859
860                    let def = Res::Local(canonical_id);
861                    if let Ok(ref binding_place) = self.cat_res(pat.hir_id, pat.span, pat_ty, def) {
862                        self.delegate.borrow_mut().bind(binding_place, binding_place.hir_id);
863                    }
864
865                    // Subtle: MIR desugaring introduces immutable borrows for each pattern
866                    // binding when lowering pattern guards to ensure that the guard does not
867                    // modify the scrutinee.
868                    if has_guard {
869                        read_discriminant();
870                    }
871
872                    // It is also a borrow or copy/move of the value being matched.
873                    // In a cases of pattern like `let pat = upvar`, don't use the span
874                    // of the pattern, as this just looks confusing, instead use the span
875                    // of the discriminant.
876                    match bm.0 {
877                        hir::ByRef::Yes(_, m) => {
878                            let bk = ty::BorrowKind::from_mutbl(m);
879                            self.delegate.borrow_mut().borrow(place, discr_place.hir_id, bk);
880                        }
881                        hir::ByRef::No => {
882                            debug!("walk_pat binding consuming pat");
883                            self.consume_or_copy(place, discr_place.hir_id);
884                        }
885                    }
886                }
887                PatKind::Deref(subpattern) => {
888                    // A deref pattern is a bit special: the binding mode of its inner bindings
889                    // determines whether to borrow *at the level of the deref pattern* rather than
890                    // borrowing the bound place (since that inner place is inside the temporary that
891                    // stores the result of calling `deref()`/`deref_mut()` so can't be captured).
892                    // Deref patterns on boxes don't borrow, so we ignore them here.
893                    // HACK: this could be a fake pattern corresponding to a deref inserted by match
894                    // ergonomics, in which case `pat.hir_id` will be the id of the subpattern.
895                    if let DerefPatBorrowMode::Borrow(mutability) =
896                        self.cx.typeck_results().deref_pat_borrow_mode(place.place.ty(), subpattern)
897                    {
898                        let bk = ty::BorrowKind::from_mutbl(mutability);
899                        self.delegate.borrow_mut().borrow(place, discr_place.hir_id, bk);
900                    }
901                }
902                PatKind::Never => {
903                    // A `!` pattern always counts as an immutable read of the discriminant,
904                    // even in an irrefutable pattern.
905                    read_discriminant();
906                }
907                PatKind::Expr(PatExpr { kind: PatExprKind::Path(qpath), hir_id, span }) => {
908                    // A `Path` pattern is just a name like `Foo`. This is either a
909                    // named constant or else it refers to an ADT variant
910
911                    let res = self.cx.typeck_results().qpath_res(qpath, *hir_id);
912                    match res {
913                        Res::Def(DefKind::Const { .. }, _)
914                        | Res::Def(DefKind::AssocConst { .. }, _) => {
915                            // Named constants have to be equated with the value
916                            // being matched, so that's a read of the value being matched.
917                            //
918                            // FIXME: Does the MIR code skip this read when matching on a ZST?
919                            // If so, we can also skip it here.
920                            read_discriminant();
921                        }
922                        _ => {
923                            // Otherwise, this is a struct/enum variant, and so it's
924                            // only a read if we need to read the discriminant.
925                            if self.is_multivariant_adt(place.place.ty(), *span) {
926                                read_discriminant();
927                            }
928                        }
929                    }
930                }
931                PatKind::Expr(_) | PatKind::Range(..) => {
932                    // When matching against a literal or range, we need to
933                    // borrow the place to compare it against the pattern.
934                    //
935                    // Note that we do this read even if the range matches all
936                    // possible values, such as 0..=u8::MAX. This is because
937                    // we don't want to depend on consteval here.
938                    //
939                    // FIXME: What if the type being matched only has one
940                    // possible value?
941                    read_discriminant();
942                }
943                PatKind::Struct(..) | PatKind::TupleStruct(..) => {
944                    if self.is_multivariant_adt(place.place.ty(), pat.span) {
945                        read_discriminant();
946                    }
947                }
948                PatKind::Slice(lhs, wild, rhs) => {
949                    // We don't need to test the length if the pattern is `[..]`
950                    if matches!((lhs, wild, rhs), (&[], Some(_), &[]))
951                        // Arrays have a statically known size, so
952                        // there is no need to read their length
953                        || place.place.ty().peel_refs().is_array()
954                    {
955                        // No read necessary
956                    } else {
957                        read_discriminant();
958                    }
959                }
960                PatKind::Or(_)
961                | PatKind::Box(_)
962                | PatKind::Ref(..)
963                | PatKind::Guard(..)
964                | PatKind::Tuple(..)
965                | PatKind::Wild
966                | PatKind::Missing
967                | PatKind::Err(_) => {
968                    // If the PatKind is Or, Box, Ref, Guard, or Tuple, the relevant accesses
969                    // are made later as these patterns contains subpatterns.
970                    // If the PatKind is Missing, Wild or Err, any relevant accesses are made when processing
971                    // the other patterns that are part of the match
972                }
973            }
974
975            Ok(())
976        })
977    }
978
979    /// Handle the case where the current body contains a closure.
980    ///
981    /// When the current body being handled is a closure, then we must make sure that
982    /// - The parent closure only captures Places from the nested closure that are not local to it.
983    ///
984    /// In the following example the closures `c` only captures `p.x` even though `incr`
985    /// is a capture of the nested closure
986    ///
987    /// ```
988    /// struct P { x: i32 }
989    /// let mut p = P { x: 4 };
990    /// let c = || {
991    ///    let incr = 10;
992    ///    let nested = || p.x += incr;
993    /// };
994    /// ```
995    ///
996    /// - When reporting the Place back to the Delegate, ensure that the UpvarId uses the enclosing
997    /// closure as the DefId.
998    #[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("walk_captures",
                                    "rustc_hir_typeck::expr_use_visitor",
                                    ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("compiler/rustc_hir_typeck/src/expr_use_visitor.rs"),
                                    ::tracing_core::__macro_support::Option::Some(998u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_hir_typeck::expr_use_visitor"),
                                    ::tracing_core::field::FieldSet::new(&["closure_expr"],
                                        ::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(&closure_expr)
                                                            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: Result<(), Cx::Error> = loop {};
            return __tracing_attr_fake_return;
        }
        {
            fn upvar_is_local_variable(upvars:
                    Option<&FxIndexMap<HirId, hir::Upvar>>, upvar_id: HirId,
                body_owner_is_closure: bool) -> bool {
                upvars.map(|upvars|
                            !upvars.contains_key(&upvar_id)).unwrap_or(body_owner_is_closure)
            }
            let tcx = self.cx.tcx();
            let closure_def_id = closure_expr.def_id;
            let body_owner_is_closure =
                #[allow(non_exhaustive_omitted_patterns)] match tcx.hir_body_owner_kind(self.cx.body_owner_def_id())
                    {
                    hir::BodyOwnerKind::Closure => true,
                    _ => false,
                };
            if let Some(fake_reads) =
                    self.cx.typeck_results().closure_fake_reads.get(&closure_def_id)
                {
                for (fake_read, cause, hir_id) in fake_reads.iter() {
                    match fake_read.base {
                        PlaceBase::Upvar(upvar_id) => {
                            if upvar_is_local_variable(self.upvars,
                                    upvar_id.var_path.hir_id, body_owner_is_closure) {
                                continue;
                            }
                        }
                        _ => {
                            ::rustc_middle::util::bug::bug_fmt(format_args!("Do not know how to get HirId out of Rvalue and StaticItem {0:?}",
                                    fake_read.base));
                        }
                    };
                    self.delegate.borrow_mut().fake_read(&PlaceWithHirId {
                                place: fake_read.clone(),
                                hir_id: *hir_id,
                            }, *cause, *hir_id);
                }
            }
            if let Some(min_captures) =
                    self.cx.typeck_results().closure_min_captures.get(&closure_def_id)
                {
                for (var_hir_id, min_list) in min_captures.iter() {
                    if self.upvars.map_or(body_owner_is_closure,
                            |upvars| !upvars.contains_key(var_hir_id)) {
                        continue;
                    }
                    for captured_place in min_list {
                        let place = &captured_place.place;
                        let capture_info = captured_place.info;
                        let place_base =
                            if body_owner_is_closure {
                                PlaceBase::Upvar(ty::UpvarId::new(*var_hir_id,
                                        self.cx.body_owner_def_id()))
                            } else { PlaceBase::Local(*var_hir_id) };
                        let closure_hir_id =
                            tcx.local_def_id_to_hir_id(closure_def_id);
                        let place_with_id =
                            PlaceWithHirId::new(capture_info.path_expr_id.unwrap_or(capture_info.capture_kind_expr_id.unwrap_or(closure_hir_id)),
                                place.base_ty, place_base, place.projections.clone());
                        match capture_info.capture_kind {
                            ty::UpvarCapture::ByValue => {
                                self.consume_or_copy(&place_with_id, place_with_id.hir_id);
                            }
                            ty::UpvarCapture::ByUse => {
                                self.consume_clone_or_copy(&place_with_id,
                                    place_with_id.hir_id);
                            }
                            ty::UpvarCapture::ByRef(upvar_borrow) => {
                                self.delegate.borrow_mut().borrow(&place_with_id,
                                    place_with_id.hir_id, upvar_borrow);
                            }
                        }
                    }
                }
            }
            Ok(())
        }
    }
}#[instrument(skip(self), level = "debug")]
999    fn walk_captures(&self, closure_expr: &hir::Closure<'_>) -> Result<(), Cx::Error> {
1000        fn upvar_is_local_variable(
1001            upvars: Option<&FxIndexMap<HirId, hir::Upvar>>,
1002            upvar_id: HirId,
1003            body_owner_is_closure: bool,
1004        ) -> bool {
1005            upvars.map(|upvars| !upvars.contains_key(&upvar_id)).unwrap_or(body_owner_is_closure)
1006        }
1007
1008        let tcx = self.cx.tcx();
1009        let closure_def_id = closure_expr.def_id;
1010        // For purposes of this function, coroutine and closures are equivalent.
1011        let body_owner_is_closure = matches!(
1012            tcx.hir_body_owner_kind(self.cx.body_owner_def_id()),
1013            hir::BodyOwnerKind::Closure
1014        );
1015
1016        // If we have a nested closure, we want to include the fake reads present in the nested
1017        // closure.
1018        if let Some(fake_reads) = self.cx.typeck_results().closure_fake_reads.get(&closure_def_id) {
1019            for (fake_read, cause, hir_id) in fake_reads.iter() {
1020                match fake_read.base {
1021                    PlaceBase::Upvar(upvar_id) => {
1022                        if upvar_is_local_variable(
1023                            self.upvars,
1024                            upvar_id.var_path.hir_id,
1025                            body_owner_is_closure,
1026                        ) {
1027                            // The nested closure might be fake reading the current (enclosing) closure's local variables.
1028                            // The only places we want to fake read before creating the parent closure are the ones that
1029                            // are not local to it/ defined by it.
1030                            //
1031                            // ```rust,ignore(cannot-test-this-because-pseudo-code)
1032                            // let v1 = (0, 1);
1033                            // let c = || { // fake reads: v1
1034                            //    let v2 = (0, 1);
1035                            //    let e = || { // fake reads: v1, v2
1036                            //       let (_, t1) = v1;
1037                            //       let (_, t2) = v2;
1038                            //    }
1039                            // }
1040                            // ```
1041                            // This check is performed when visiting the body of the outermost closure (`c`) and ensures
1042                            // that we don't add a fake read of v2 in c.
1043                            continue;
1044                        }
1045                    }
1046                    _ => {
1047                        bug!(
1048                            "Do not know how to get HirId out of Rvalue and StaticItem {:?}",
1049                            fake_read.base
1050                        );
1051                    }
1052                };
1053                self.delegate.borrow_mut().fake_read(
1054                    &PlaceWithHirId { place: fake_read.clone(), hir_id: *hir_id },
1055                    *cause,
1056                    *hir_id,
1057                );
1058            }
1059        }
1060
1061        if let Some(min_captures) =
1062            self.cx.typeck_results().closure_min_captures.get(&closure_def_id)
1063        {
1064            for (var_hir_id, min_list) in min_captures.iter() {
1065                if self
1066                    .upvars
1067                    .map_or(body_owner_is_closure, |upvars| !upvars.contains_key(var_hir_id))
1068                {
1069                    // The nested closure might be capturing the current (enclosing) closure's local variables.
1070                    // We check if the root variable is ever mentioned within the enclosing closure, if not
1071                    // then for the current body (if it's a closure) these aren't captures, we will ignore them.
1072                    continue;
1073                }
1074                for captured_place in min_list {
1075                    let place = &captured_place.place;
1076                    let capture_info = captured_place.info;
1077
1078                    let place_base = if body_owner_is_closure {
1079                        // Mark the place to be captured by the enclosing closure
1080                        PlaceBase::Upvar(ty::UpvarId::new(*var_hir_id, self.cx.body_owner_def_id()))
1081                    } else {
1082                        // If the body owner isn't a closure then the variable must
1083                        // be a local variable
1084                        PlaceBase::Local(*var_hir_id)
1085                    };
1086                    let closure_hir_id = tcx.local_def_id_to_hir_id(closure_def_id);
1087                    let place_with_id = PlaceWithHirId::new(
1088                        capture_info
1089                            .path_expr_id
1090                            .unwrap_or(capture_info.capture_kind_expr_id.unwrap_or(closure_hir_id)),
1091                        place.base_ty,
1092                        place_base,
1093                        place.projections.clone(),
1094                    );
1095
1096                    match capture_info.capture_kind {
1097                        ty::UpvarCapture::ByValue => {
1098                            self.consume_or_copy(&place_with_id, place_with_id.hir_id);
1099                        }
1100                        ty::UpvarCapture::ByUse => {
1101                            self.consume_clone_or_copy(&place_with_id, place_with_id.hir_id);
1102                        }
1103                        ty::UpvarCapture::ByRef(upvar_borrow) => {
1104                            self.delegate.borrow_mut().borrow(
1105                                &place_with_id,
1106                                place_with_id.hir_id,
1107                                upvar_borrow,
1108                            );
1109                        }
1110                    }
1111                }
1112            }
1113        }
1114
1115        Ok(())
1116    }
1117}
1118
1119/// The job of the methods whose name starts with `cat_` is to analyze
1120/// expressions and construct the corresponding [`Place`]s. The `cat`
1121/// stands for "categorize", this is a leftover from long ago when
1122/// places were called "categorizations".
1123///
1124/// Note that a [`Place`] differs somewhat from the expression itself. For
1125/// example, auto-derefs are explicit. Also, an index `a[b]` is decomposed into
1126/// two operations: a dereference to reach the array data and then an index to
1127/// jump forward to the relevant item.
1128impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx, Cx, D> {
1129    fn expect_and_resolve_type(
1130        &self,
1131        id: HirId,
1132        ty: Option<Ty<'tcx>>,
1133    ) -> Result<Ty<'tcx>, Cx::Error> {
1134        match ty {
1135            Some(ty) => {
1136                let ty = self.cx.resolve_vars_if_possible(ty);
1137                self.cx.error_reported_in_ty(ty)?;
1138                Ok(ty)
1139            }
1140            None => {
1141                // FIXME: We shouldn't be relying on the infcx being tainted.
1142                self.cx.tainted_by_errors()?;
1143                ::rustc_middle::util::bug::bug_fmt(format_args!("no type for node {0} in ExprUseVisitor",
        self.cx.tcx().hir_id_to_string(id)));bug!("no type for node {} in ExprUseVisitor", self.cx.tcx().hir_id_to_string(id));
1144            }
1145        }
1146    }
1147
1148    fn node_ty(&self, hir_id: HirId) -> Result<Ty<'tcx>, Cx::Error> {
1149        self.expect_and_resolve_type(hir_id, self.cx.typeck_results().node_type_opt(hir_id))
1150    }
1151
1152    fn expr_ty(&self, expr: &hir::Expr<'_>) -> Result<Ty<'tcx>, Cx::Error> {
1153        self.expect_and_resolve_type(expr.hir_id, self.cx.typeck_results().expr_ty_opt(expr))
1154    }
1155
1156    fn expr_ty_adjusted(&self, expr: &hir::Expr<'_>) -> Result<Ty<'tcx>, Cx::Error> {
1157        self.expect_and_resolve_type(
1158            expr.hir_id,
1159            self.cx.typeck_results().expr_ty_adjusted_opt(expr),
1160        )
1161    }
1162
1163    /// Returns the type of value that this pattern matches against.
1164    /// Some non-obvious cases:
1165    ///
1166    /// - a `ref x` binding matches against a value of type `T` and gives
1167    ///   `x` the type `&T`; we return `T`.
1168    /// - a pattern with implicit derefs (thanks to default binding
1169    ///   modes #42640) may look like `Some(x)` but in fact have
1170    ///   implicit deref patterns attached (e.g., it is really
1171    ///   `&Some(x)`). In that case, we return the "outermost" type
1172    ///   (e.g., `&Option<T>`).
1173    fn pat_ty_adjusted(&self, pat: &hir::Pat<'_>) -> Result<Ty<'tcx>, Cx::Error> {
1174        // Check for implicit `&` types wrapping the pattern; note
1175        // that these are never attached to binding patterns, so
1176        // actually this is somewhat "disjoint" from the code below
1177        // that aims to account for `ref x`.
1178        if let Some(vec) = self.cx.typeck_results().pat_adjustments().get(pat.hir_id) {
1179            if let Some(first_adjust) = vec.first() {
1180                {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_hir_typeck/src/expr_use_visitor.rs:1180",
                        "rustc_hir_typeck::expr_use_visitor",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_hir_typeck/src/expr_use_visitor.rs"),
                        ::tracing_core::__macro_support::Option::Some(1180u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_hir_typeck::expr_use_visitor"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                let mut iter = __CALLSITE.metadata().fields().iter();
                __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&format_args!("pat_ty(pat={0:?}) found adjustment `{1:?}`",
                                                    pat, first_adjust) as &dyn Value))])
            });
    } else { ; }
};debug!("pat_ty(pat={:?}) found adjustment `{:?}`", pat, first_adjust);
1181                return Ok(first_adjust.source);
1182            }
1183        } else if let PatKind::Ref(subpat, _, _) = pat.kind
1184            && self.cx.typeck_results().skipped_ref_pats().contains(pat.hir_id)
1185        {
1186            return self.pat_ty_adjusted(subpat);
1187        }
1188
1189        self.pat_ty_unadjusted(pat)
1190    }
1191
1192    /// Like [`Self::pat_ty_adjusted`], but ignores implicit `&` patterns.
1193    fn pat_ty_unadjusted(&self, pat: &hir::Pat<'_>) -> Result<Ty<'tcx>, Cx::Error> {
1194        let base_ty = self.node_ty(pat.hir_id)?;
1195        {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_hir_typeck/src/expr_use_visitor.rs:1195",
                        "rustc_hir_typeck::expr_use_visitor",
                        ::tracing::Level::TRACE,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_hir_typeck/src/expr_use_visitor.rs"),
                        ::tracing_core::__macro_support::Option::Some(1195u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_hir_typeck::expr_use_visitor"),
                        ::tracing_core::field::FieldSet::new(&["base_ty"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::TRACE <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::TRACE <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                let mut iter = __CALLSITE.metadata().fields().iter();
                __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&debug(&base_ty) as
                                            &dyn Value))])
            });
    } else { ; }
};trace!(?base_ty);
1196
1197        // This code detects whether we are looking at a `ref x`,
1198        // and if so, figures out what the type *being borrowed* is.
1199        match pat.kind {
1200            PatKind::Binding(..) => {
1201                let bm = *self
1202                    .cx
1203                    .typeck_results()
1204                    .pat_binding_modes()
1205                    .get(pat.hir_id)
1206                    .expect("missing binding mode");
1207
1208                if let hir::ByRef::Yes(pinnedness, _) = bm.0 {
1209                    let base_ty = if pinnedness.is_pinned() {
1210                        base_ty.pinned_ty().ok_or_else(|| {
1211                            {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_hir_typeck/src/expr_use_visitor.rs:1211",
                        "rustc_hir_typeck::expr_use_visitor",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_hir_typeck/src/expr_use_visitor.rs"),
                        ::tracing_core::__macro_support::Option::Some(1211u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_hir_typeck::expr_use_visitor"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                let mut iter = __CALLSITE.metadata().fields().iter();
                __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&format_args!("By-pin-ref binding of non-`Pin` type: {0:?}",
                                                    base_ty) as &dyn Value))])
            });
    } else { ; }
};debug!("By-pin-ref binding of non-`Pin` type: {base_ty:?}");
1212                            self.cx.report_bug(pat.span, "by-pin-ref binding of non-`Pin` type")
1213                        })?
1214                    } else {
1215                        base_ty
1216                    };
1217                    // a bind-by-ref means that the base_ty will be the type of the ident itself,
1218                    // but what we want here is the type of the underlying value being borrowed.
1219                    // So peel off one-level, turning the &T into T.
1220                    match self.cx.structurally_resolve_type(pat.span, base_ty).builtin_deref(false)
1221                    {
1222                        Some(ty) => Ok(ty),
1223                        None => {
1224                            {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_hir_typeck/src/expr_use_visitor.rs:1224",
                        "rustc_hir_typeck::expr_use_visitor",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_hir_typeck/src/expr_use_visitor.rs"),
                        ::tracing_core::__macro_support::Option::Some(1224u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_hir_typeck::expr_use_visitor"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                let mut iter = __CALLSITE.metadata().fields().iter();
                __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&format_args!("By-ref binding of non-derefable type: {0:?}",
                                                    base_ty) as &dyn Value))])
            });
    } else { ; }
};debug!("By-ref binding of non-derefable type: {base_ty:?}");
1225                            Err(self
1226                                .cx
1227                                .report_bug(pat.span, "by-ref binding of non-derefable type"))
1228                        }
1229                    }
1230                } else {
1231                    Ok(base_ty)
1232                }
1233            }
1234            _ => Ok(base_ty),
1235        }
1236    }
1237
1238    fn cat_expr(&self, expr: &hir::Expr<'_>) -> Result<PlaceWithHirId<'tcx>, Cx::Error> {
1239        self.cat_expr_(expr, self.cx.typeck_results().expr_adjustments(expr))
1240    }
1241
1242    /// This recursion helper avoids going through *too many*
1243    /// adjustments, since *only* non-overloaded deref recurses.
1244    fn cat_expr_(
1245        &self,
1246        expr: &hir::Expr<'_>,
1247        adjustments: &[adjustment::Adjustment<'tcx>],
1248    ) -> Result<PlaceWithHirId<'tcx>, Cx::Error> {
1249        match adjustments.split_last() {
1250            None => self.cat_expr_unadjusted(expr),
1251            Some((adjustment, previous)) => {
1252                self.cat_expr_adjusted_with(expr, || self.cat_expr_(expr, previous), adjustment)
1253            }
1254        }
1255    }
1256
1257    fn cat_expr_adjusted(
1258        &self,
1259        expr: &hir::Expr<'_>,
1260        previous: PlaceWithHirId<'tcx>,
1261        adjustment: &adjustment::Adjustment<'tcx>,
1262    ) -> Result<PlaceWithHirId<'tcx>, Cx::Error> {
1263        self.cat_expr_adjusted_with(expr, || Ok(previous), adjustment)
1264    }
1265
1266    fn cat_expr_adjusted_with<F>(
1267        &self,
1268        expr: &hir::Expr<'_>,
1269        previous: F,
1270        adjustment: &adjustment::Adjustment<'tcx>,
1271    ) -> Result<PlaceWithHirId<'tcx>, Cx::Error>
1272    where
1273        F: FnOnce() -> Result<PlaceWithHirId<'tcx>, Cx::Error>,
1274    {
1275        let target = self.cx.resolve_vars_if_possible(adjustment.target);
1276        match adjustment.kind {
1277            adjustment::Adjust::Deref(deref_kind) => {
1278                // Equivalent to *expr or something similar.
1279                let base = if let DerefAdjustKind::Overloaded(deref) = deref_kind {
1280                    let ref_ty = Ty::new_ref(
1281                        self.cx.tcx(),
1282                        self.cx.tcx().lifetimes.re_erased,
1283                        target,
1284                        deref.mutbl,
1285                    );
1286                    self.cat_rvalue(expr.hir_id, ref_ty)
1287                } else {
1288                    previous()?
1289                };
1290                self.cat_deref(expr.hir_id, base)
1291            }
1292
1293            adjustment::Adjust::NeverToAny
1294            | adjustment::Adjust::Pointer(_)
1295            | adjustment::Adjust::Borrow(_)
1296            | adjustment::Adjust::GenericReborrow(..) => {
1297                // Result is an rvalue.
1298                Ok(self.cat_rvalue(expr.hir_id, target))
1299            }
1300        }
1301    }
1302
1303    fn cat_expr_unadjusted(&self, expr: &hir::Expr<'_>) -> Result<PlaceWithHirId<'tcx>, Cx::Error> {
1304        let expr_ty = self.expr_ty(expr)?;
1305        match expr.kind {
1306            hir::ExprKind::Unary(hir::UnOp::Deref, e_base) => {
1307                if self.cx.typeck_results().is_method_call(expr) {
1308                    self.cat_overloaded_place(expr, e_base)
1309                } else {
1310                    let base = self.cat_expr(e_base)?;
1311                    self.cat_deref(expr.hir_id, base)
1312                }
1313            }
1314
1315            hir::ExprKind::Field(base, _) => {
1316                let base = self.cat_expr(base)?;
1317                {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_hir_typeck/src/expr_use_visitor.rs:1317",
                        "rustc_hir_typeck::expr_use_visitor",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_hir_typeck/src/expr_use_visitor.rs"),
                        ::tracing_core::__macro_support::Option::Some(1317u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_hir_typeck::expr_use_visitor"),
                        ::tracing_core::field::FieldSet::new(&["base"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                let mut iter = __CALLSITE.metadata().fields().iter();
                __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&debug(&base) as
                                            &dyn Value))])
            });
    } else { ; }
};debug!(?base);
1318
1319                let field_idx = self
1320                    .cx
1321                    .typeck_results()
1322                    .field_indices()
1323                    .get(expr.hir_id)
1324                    .cloned()
1325                    .expect("Field index not found");
1326
1327                Ok(self.cat_projection(
1328                    expr.hir_id,
1329                    base,
1330                    expr_ty,
1331                    ProjectionKind::Field(field_idx, FIRST_VARIANT),
1332                ))
1333            }
1334
1335            hir::ExprKind::Index(base, _, _) => {
1336                if self.cx.typeck_results().is_method_call(expr) {
1337                    // If this is an index implemented by a method call, then it
1338                    // will include an implicit deref of the result.
1339                    // The call to index() returns a `&T` value, which
1340                    // is an rvalue. That is what we will be
1341                    // dereferencing.
1342                    self.cat_overloaded_place(expr, base)
1343                } else {
1344                    let base = self.cat_expr(base)?;
1345                    Ok(self.cat_projection(expr.hir_id, base, expr_ty, ProjectionKind::Index))
1346                }
1347            }
1348
1349            hir::ExprKind::Path(ref qpath) => {
1350                let res = self.cx.typeck_results().qpath_res(qpath, expr.hir_id);
1351                self.cat_res(expr.hir_id, expr.span, expr_ty, res)
1352            }
1353
1354            // type ascription doesn't affect the place-ness of the subexpression.
1355            hir::ExprKind::Type(e, _) => self.cat_expr(e),
1356
1357            hir::ExprKind::UnsafeBinderCast(UnsafeBinderCastKind::Unwrap, e, _) => {
1358                let base = self.cat_expr(e)?;
1359                Ok(self.cat_projection(
1360                    expr.hir_id,
1361                    base,
1362                    expr_ty,
1363                    ProjectionKind::UnwrapUnsafeBinder,
1364                ))
1365            }
1366
1367            hir::ExprKind::AddrOf(..)
1368            | hir::ExprKind::Call(..)
1369            | hir::ExprKind::Use(..)
1370            | hir::ExprKind::Assign(..)
1371            | hir::ExprKind::AssignOp(..)
1372            | hir::ExprKind::Closure { .. }
1373            | hir::ExprKind::Ret(..)
1374            | hir::ExprKind::Become(..)
1375            | hir::ExprKind::Unary(..)
1376            | hir::ExprKind::Yield(..)
1377            | hir::ExprKind::MethodCall(..)
1378            | hir::ExprKind::Cast(..)
1379            | hir::ExprKind::DropTemps(..)
1380            | hir::ExprKind::Array(..)
1381            | hir::ExprKind::If(..)
1382            | hir::ExprKind::Tup(..)
1383            | hir::ExprKind::Binary(..)
1384            | hir::ExprKind::Block(..)
1385            | hir::ExprKind::Let(..)
1386            | hir::ExprKind::Loop(..)
1387            | hir::ExprKind::Match(..)
1388            | hir::ExprKind::Lit(..)
1389            | hir::ExprKind::ConstBlock(..)
1390            | hir::ExprKind::Break(..)
1391            | hir::ExprKind::Continue(..)
1392            | hir::ExprKind::Struct(..)
1393            | hir::ExprKind::Repeat(..)
1394            | hir::ExprKind::InlineAsm(..)
1395            | hir::ExprKind::OffsetOf(..)
1396            | hir::ExprKind::UnsafeBinderCast(UnsafeBinderCastKind::Wrap, ..)
1397            | hir::ExprKind::Err(_) => Ok(self.cat_rvalue(expr.hir_id, expr_ty)),
1398        }
1399    }
1400
1401    fn cat_res(
1402        &self,
1403        hir_id: HirId,
1404        span: Span,
1405        expr_ty: Ty<'tcx>,
1406        res: Res,
1407    ) -> Result<PlaceWithHirId<'tcx>, Cx::Error> {
1408        match res {
1409            Res::Def(
1410                DefKind::Ctor(..)
1411                | DefKind::Const { .. }
1412                | DefKind::ConstParam
1413                | DefKind::AssocConst { .. }
1414                | DefKind::Fn
1415                | DefKind::AssocFn,
1416                _,
1417            )
1418            | Res::SelfCtor(..) => Ok(self.cat_rvalue(hir_id, expr_ty)),
1419
1420            Res::Def(DefKind::Static { .. }, _) => {
1421                Ok(PlaceWithHirId::new(hir_id, expr_ty, PlaceBase::StaticItem, Vec::new()))
1422            }
1423
1424            Res::Local(var_id) => {
1425                if self.upvars.is_some_and(|upvars| upvars.contains_key(&var_id)) {
1426                    self.cat_upvar(hir_id, var_id)
1427                } else {
1428                    Ok(PlaceWithHirId::new(hir_id, expr_ty, PlaceBase::Local(var_id), Vec::new()))
1429                }
1430            }
1431
1432            def => ::rustc_middle::util::bug::span_bug_fmt(span,
    format_args!("unexpected definition in ExprUseVisitor: {0:?}", def))span_bug!(span, "unexpected definition in ExprUseVisitor: {:?}", def),
1433        }
1434    }
1435
1436    /// Categorize an upvar.
1437    ///
1438    /// Note: the actual upvar access contains invisible derefs of closure
1439    /// environment and upvar reference as appropriate. Only regionck cares
1440    /// about these dereferences, so we let it compute them as needed.
1441    fn cat_upvar(&self, hir_id: HirId, var_id: HirId) -> Result<PlaceWithHirId<'tcx>, Cx::Error> {
1442        let closure_expr_def_id = self.cx.body_owner_def_id();
1443
1444        let upvar_id = ty::UpvarId {
1445            var_path: ty::UpvarPath { hir_id: var_id },
1446            closure_expr_id: closure_expr_def_id,
1447        };
1448        let var_ty = self.node_ty(var_id)?;
1449
1450        Ok(PlaceWithHirId::new(hir_id, var_ty, PlaceBase::Upvar(upvar_id), Vec::new()))
1451    }
1452
1453    fn cat_rvalue(&self, hir_id: HirId, expr_ty: Ty<'tcx>) -> PlaceWithHirId<'tcx> {
1454        PlaceWithHirId::new(hir_id, expr_ty, PlaceBase::Rvalue, Vec::new())
1455    }
1456
1457    fn cat_projection(
1458        &self,
1459        node: HirId,
1460        base_place: PlaceWithHirId<'tcx>,
1461        ty: Ty<'tcx>,
1462        kind: ProjectionKind,
1463    ) -> PlaceWithHirId<'tcx> {
1464        let place_ty = base_place.place.ty();
1465        let mut projections = base_place.place.projections;
1466
1467        let node_ty = self.cx.typeck_results().node_type(node);
1468        if !self.cx.tcx().next_trait_solver_globally() {
1469            // Opaque types can't have field projections, but we can instead convert
1470            // the current place in-place (heh) to the hidden type, and then apply all
1471            // follow up projections on that.
1472            if node_ty != place_ty
1473                && self
1474                    .cx
1475                    .structurally_resolve_type(self.cx.tcx().hir_span(base_place.hir_id), place_ty)
1476                    .is_opaque()
1477            {
1478                projections.push(Projection { kind: ProjectionKind::OpaqueCast, ty: node_ty });
1479            }
1480        }
1481        projections.push(Projection { kind, ty });
1482        PlaceWithHirId::new(node, base_place.place.base_ty, base_place.place.base, projections)
1483    }
1484
1485    fn cat_overloaded_place(
1486        &self,
1487        expr: &hir::Expr<'_>,
1488        base: &hir::Expr<'_>,
1489    ) -> Result<PlaceWithHirId<'tcx>, Cx::Error> {
1490        // Reconstruct the output assuming it's a reference with the
1491        // same region and mutability as the receiver. This holds for
1492        // `Deref(Mut)::Deref(_mut)` and `Index(Mut)::index(_mut)`.
1493        let place_ty = self.expr_ty(expr)?;
1494        let base_ty = self.expr_ty_adjusted(base)?;
1495
1496        let ty::Ref(region, _, mutbl) =
1497            *self.cx.structurally_resolve_type(base.span, base_ty).kind()
1498        else {
1499            ::rustc_middle::util::bug::span_bug_fmt(expr.span,
    format_args!("cat_overloaded_place: base is not a reference"));span_bug!(expr.span, "cat_overloaded_place: base is not a reference");
1500        };
1501        let ref_ty = Ty::new_ref(self.cx.tcx(), region, place_ty, mutbl);
1502
1503        let base = self.cat_rvalue(expr.hir_id, ref_ty);
1504        self.cat_deref(expr.hir_id, base)
1505    }
1506
1507    fn cat_deref(
1508        &self,
1509        node: HirId,
1510        base_place: PlaceWithHirId<'tcx>,
1511    ) -> Result<PlaceWithHirId<'tcx>, Cx::Error> {
1512        let base_curr_ty = base_place.place.ty();
1513        let Some(deref_ty) = self
1514            .cx
1515            .structurally_resolve_type(self.cx.tcx().hir_span(base_place.hir_id), base_curr_ty)
1516            .builtin_deref(true)
1517        else {
1518            {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_hir_typeck/src/expr_use_visitor.rs:1518",
                        "rustc_hir_typeck::expr_use_visitor",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_hir_typeck/src/expr_use_visitor.rs"),
                        ::tracing_core::__macro_support::Option::Some(1518u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_hir_typeck::expr_use_visitor"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                let mut iter = __CALLSITE.metadata().fields().iter();
                __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&format_args!("explicit deref of non-derefable type: {0:?}",
                                                    base_curr_ty) as &dyn Value))])
            });
    } else { ; }
};debug!("explicit deref of non-derefable type: {:?}", base_curr_ty);
1519            return Err(self
1520                .cx
1521                .report_bug(self.cx.tcx().hir_span(node), "explicit deref of non-derefable type"));
1522        };
1523        let mut projections = base_place.place.projections;
1524        projections.push(Projection { kind: ProjectionKind::Deref, ty: deref_ty });
1525
1526        Ok(PlaceWithHirId::new(node, base_place.place.base_ty, base_place.place.base, projections))
1527    }
1528
1529    /// Returns the variant index for an ADT used within a Struct or TupleStruct pattern
1530    /// Here `pat_hir_id` is the HirId of the pattern itself.
1531    fn variant_index_for_adt(
1532        &self,
1533        qpath: &hir::QPath<'_>,
1534        pat_hir_id: HirId,
1535        span: Span,
1536    ) -> Result<VariantIdx, Cx::Error> {
1537        let res = self.cx.typeck_results().qpath_res(qpath, pat_hir_id);
1538        let ty = self.cx.typeck_results().node_type(pat_hir_id);
1539        let ty::Adt(adt_def, _) = self.cx.structurally_resolve_type(span, ty).kind() else {
1540            return Err(self
1541                .cx
1542                .report_bug(span, "struct or tuple struct pattern not applied to an ADT"));
1543        };
1544
1545        match res {
1546            Res::Def(DefKind::Variant, variant_id) => Ok(adt_def.variant_index_with_id(variant_id)),
1547            Res::Def(DefKind::Ctor(CtorOf::Variant, ..), variant_ctor_id) => {
1548                Ok(adt_def.variant_index_with_ctor_id(variant_ctor_id))
1549            }
1550            Res::Def(DefKind::Ctor(CtorOf::Struct, ..), _)
1551            | Res::Def(DefKind::Struct | DefKind::Union | DefKind::TyAlias | DefKind::AssocTy, _)
1552            | Res::SelfCtor(..)
1553            | Res::SelfTyParam { .. }
1554            | Res::SelfTyAlias { .. } => {
1555                // Structs and Unions have only have one variant.
1556                Ok(FIRST_VARIANT)
1557            }
1558            _ => ::rustc_middle::util::bug::bug_fmt(format_args!("expected ADT path, found={0:?}",
        res))bug!("expected ADT path, found={:?}", res),
1559        }
1560    }
1561
1562    /// Returns the total number of fields in an ADT variant used within a pattern.
1563    /// Here `pat_hir_id` is the HirId of the pattern itself.
1564    fn total_fields_in_adt_variant(
1565        &self,
1566        pat_hir_id: HirId,
1567        variant_index: VariantIdx,
1568        span: Span,
1569    ) -> Result<usize, Cx::Error> {
1570        let ty = self.cx.typeck_results().node_type(pat_hir_id);
1571        match self.cx.structurally_resolve_type(span, ty).kind() {
1572            ty::Adt(adt_def, _) => Ok(adt_def.variant(variant_index).fields.len()),
1573            _ => {
1574                self.cx
1575                    .tcx()
1576                    .dcx()
1577                    .span_bug(span, "struct or tuple struct pattern not applied to an ADT");
1578            }
1579        }
1580    }
1581
1582    /// Returns the total number of fields in a tuple used within a Tuple pattern.
1583    /// Here `pat_hir_id` is the HirId of the pattern itself.
1584    fn total_fields_in_tuple(&self, pat_hir_id: HirId, span: Span) -> Result<usize, Cx::Error> {
1585        let ty = self.cx.typeck_results().node_type(pat_hir_id);
1586        match self.cx.structurally_resolve_type(span, ty).kind() {
1587            ty::Tuple(args) => Ok(args.len()),
1588            _ => Err(self.cx.report_bug(span, "tuple pattern not applied to a tuple")),
1589        }
1590    }
1591
1592    /// Here, `place` is the `PlaceWithHirId` being matched and pat is the pattern it
1593    /// is being matched against.
1594    ///
1595    /// In general, the way that this works is that we walk down the pattern,
1596    /// constructing a `PlaceWithHirId` that represents the path that will be taken
1597    /// to reach the value being matched.
1598    fn cat_pattern<F>(
1599        &self,
1600        mut place_with_id: PlaceWithHirId<'tcx>,
1601        pat: &hir::Pat<'_>,
1602        op: &mut F,
1603    ) -> Result<(), Cx::Error>
1604    where
1605        F: FnMut(&PlaceWithHirId<'tcx>, &hir::Pat<'_>) -> Result<(), Cx::Error>,
1606    {
1607        // If (pattern) adjustments are active for this pattern, adjust the `PlaceWithHirId` correspondingly.
1608        // `PlaceWithHirId`s are constructed differently from patterns. For example, in
1609        //
1610        // ```
1611        // match foo {
1612        //     &&Some(x, ) => { ... },
1613        //     _ => { ... },
1614        // }
1615        // ```
1616        //
1617        // the pattern `&&Some(x,)` is represented as `Ref { Ref { TupleStruct }}`. To build the
1618        // corresponding `PlaceWithHirId` we start with the `PlaceWithHirId` for `foo`, and then, by traversing the
1619        // pattern, try to answer the question: given the address of `foo`, how is `x` reached?
1620        //
1621        // `&&Some(x,)` `place_foo`
1622        //  `&Some(x,)` `deref { place_foo}`
1623        //   `Some(x,)` `deref { deref { place_foo }}`
1624        //       `(x,)` `field0 { deref { deref { place_foo }}}` <- resulting place
1625        //
1626        // The above example has no adjustments. If the code were instead the (after adjustments,
1627        // equivalent) version
1628        //
1629        // ```
1630        // match foo {
1631        //     Some(x, ) => { ... },
1632        //     _ => { ... },
1633        // }
1634        // ```
1635        //
1636        // Then we see that to get the same result, we must start with
1637        // `deref { deref { place_foo }}` instead of `place_foo` since the pattern is now `Some(x,)`
1638        // and not `&&Some(x,)`, even though its assigned type is that of `&&Some(x,)`.
1639        let typeck_results = self.cx.typeck_results();
1640        let adjustments: &[adjustment::PatAdjustment<'tcx>] =
1641            typeck_results.pat_adjustments().get(pat.hir_id).map_or(&[], |v| &**v);
1642        let mut adjusts = adjustments.iter().peekable();
1643        while let Some(adjust) = adjusts.next() {
1644            {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_hir_typeck/src/expr_use_visitor.rs:1644",
                        "rustc_hir_typeck::expr_use_visitor",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_hir_typeck/src/expr_use_visitor.rs"),
                        ::tracing_core::__macro_support::Option::Some(1644u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_hir_typeck::expr_use_visitor"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                let mut iter = __CALLSITE.metadata().fields().iter();
                __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&format_args!("applying adjustment to place_with_id={0:?}",
                                                    place_with_id) as &dyn Value))])
            });
    } else { ; }
};debug!("applying adjustment to place_with_id={:?}", place_with_id);
1645            place_with_id = match adjust.kind {
1646                adjustment::PatAdjust::BuiltinDeref => self.cat_deref(pat.hir_id, place_with_id)?,
1647                adjustment::PatAdjust::OverloadedDeref => {
1648                    // This adjustment corresponds to an overloaded deref; unless it's on a box, it
1649                    // borrows the scrutinee to call `Deref::deref` or `DerefMut::deref_mut`. Invoke
1650                    // the callback before setting `place_with_id` to the temporary storing the
1651                    // result of the deref.
1652                    // HACK(dianne): giving the callback a fake deref pattern makes sure it behaves the
1653                    // same as it would if this were an explicit deref pattern (including for boxes).
1654                    op(&place_with_id, &hir::Pat { kind: PatKind::Deref(pat), ..*pat })?;
1655                    let target_ty = match adjusts.peek() {
1656                        Some(&&next_adjust) => next_adjust.source,
1657                        // At the end of the deref chain, we get `pat`'s scrutinee.
1658                        None => self.pat_ty_unadjusted(pat)?,
1659                    };
1660                    self.pat_deref_place(pat.hir_id, place_with_id, pat, target_ty)?
1661                }
1662                adjustment::PatAdjust::PinDeref => {
1663                    {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_hir_typeck/src/expr_use_visitor.rs:1663",
                        "rustc_hir_typeck::expr_use_visitor",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_hir_typeck/src/expr_use_visitor.rs"),
                        ::tracing_core::__macro_support::Option::Some(1663u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_hir_typeck::expr_use_visitor"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                let mut iter = __CALLSITE.metadata().fields().iter();
                __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&format_args!("`PinDeref` of non-pinned-reference type: {0:?}",
                                                    adjust.source) as &dyn Value))])
            });
    } else { ; }
};debug!("`PinDeref` of non-pinned-reference type: {:?}", adjust.source);
1664                    let target_ty = adjust.source.pinned_ty().ok_or_else(|| {
1665                        self.cx.report_bug(
1666                            self.cx.tcx().hir_span(pat.hir_id),
1667                            "`PinDeref` of non-pinned-reference type",
1668                        )
1669                    })?;
1670                    let kind = ProjectionKind::Field(FieldIdx::ZERO, FIRST_VARIANT);
1671                    place_with_id = self.cat_projection(pat.hir_id, place_with_id, target_ty, kind);
1672                    self.cat_deref(pat.hir_id, place_with_id)?
1673                }
1674            };
1675        }
1676        drop(typeck_results); // explicitly release borrow of typeck results, just in case.
1677        let place_with_id = place_with_id; // lose mutability
1678        {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_hir_typeck/src/expr_use_visitor.rs:1678",
                        "rustc_hir_typeck::expr_use_visitor",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_hir_typeck/src/expr_use_visitor.rs"),
                        ::tracing_core::__macro_support::Option::Some(1678u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_hir_typeck::expr_use_visitor"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                let mut iter = __CALLSITE.metadata().fields().iter();
                __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&format_args!("applied adjustment derefs to get place_with_id={0:?}",
                                                    place_with_id) as &dyn Value))])
            });
    } else { ; }
};debug!("applied adjustment derefs to get place_with_id={:?}", place_with_id);
1679
1680        // Invoke the callback, but only now, after the `place_with_id` has adjusted.
1681        //
1682        // To see that this makes sense, consider `match &Some(3) { Some(x) => { ... }}`. In that
1683        // case, the initial `place_with_id` will be that for `&Some(3)` and the pattern is `Some(x)`. We
1684        // don't want to call `op` with these incompatible values. As written, what happens instead
1685        // is that `op` is called with the adjusted place (that for `*&Some(3)`) and the pattern
1686        // `Some(x)` (which matches). Recursing once more, `*&Some(3)` and the pattern `Some(x)`
1687        // result in the place `Downcast<Some>(*&Some(3)).0` associated to `x` and invoke `op` with
1688        // that (where the `ref` on `x` is implied).
1689        op(&place_with_id, pat)?;
1690
1691        match pat.kind {
1692            PatKind::Tuple(subpats, dots_pos) => {
1693                // (p1, ..., pN)
1694                let total_fields = self.total_fields_in_tuple(pat.hir_id, pat.span)?;
1695
1696                for (i, subpat) in subpats.iter().enumerate_and_adjust(total_fields, dots_pos) {
1697                    let subpat_ty = self.pat_ty_adjusted(subpat)?;
1698                    let projection_kind =
1699                        ProjectionKind::Field(FieldIdx::from_usize(i), FIRST_VARIANT);
1700                    let sub_place = self.cat_projection(
1701                        pat.hir_id,
1702                        place_with_id.clone(),
1703                        subpat_ty,
1704                        projection_kind,
1705                    );
1706                    self.cat_pattern(sub_place, subpat, op)?;
1707                }
1708            }
1709
1710            PatKind::TupleStruct(ref qpath, subpats, dots_pos) => {
1711                // S(p1, ..., pN)
1712                let variant_index = self.variant_index_for_adt(qpath, pat.hir_id, pat.span)?;
1713                let total_fields =
1714                    self.total_fields_in_adt_variant(pat.hir_id, variant_index, pat.span)?;
1715
1716                for (i, subpat) in subpats.iter().enumerate_and_adjust(total_fields, dots_pos) {
1717                    let subpat_ty = self.pat_ty_adjusted(subpat)?;
1718                    let projection_kind =
1719                        ProjectionKind::Field(FieldIdx::from_usize(i), variant_index);
1720                    let sub_place = self.cat_projection(
1721                        pat.hir_id,
1722                        place_with_id.clone(),
1723                        subpat_ty,
1724                        projection_kind,
1725                    );
1726                    self.cat_pattern(sub_place, subpat, op)?;
1727                }
1728            }
1729
1730            PatKind::Struct(ref qpath, field_pats, _) => {
1731                // S { f1: p1, ..., fN: pN }
1732
1733                let variant_index = self.variant_index_for_adt(qpath, pat.hir_id, pat.span)?;
1734
1735                for fp in field_pats {
1736                    let field_ty = self.pat_ty_adjusted(fp.pat)?;
1737                    let field_index = self
1738                        .cx
1739                        .typeck_results()
1740                        .field_indices()
1741                        .get(fp.hir_id)
1742                        .cloned()
1743                        .expect("no index for a field");
1744
1745                    let field_place = self.cat_projection(
1746                        pat.hir_id,
1747                        place_with_id.clone(),
1748                        field_ty,
1749                        ProjectionKind::Field(field_index, variant_index),
1750                    );
1751                    self.cat_pattern(field_place, fp.pat, op)?;
1752                }
1753            }
1754
1755            PatKind::Or(pats) => {
1756                for pat in pats {
1757                    self.cat_pattern(place_with_id.clone(), pat, op)?;
1758                }
1759            }
1760
1761            PatKind::Binding(.., Some(subpat)) | PatKind::Guard(subpat, _) => {
1762                self.cat_pattern(place_with_id, subpat, op)?;
1763            }
1764
1765            PatKind::Ref(subpat, _, _)
1766                if self.cx.typeck_results().skipped_ref_pats().contains(pat.hir_id) =>
1767            {
1768                self.cat_pattern(place_with_id, subpat, op)?;
1769            }
1770
1771            PatKind::Box(subpat) | PatKind::Ref(subpat, _, _) => {
1772                // box p1, &p1, &mut p1. we can ignore the mutability of
1773                // PatKind::Ref since that information is already contained
1774                // in the type.
1775                let subplace = self.cat_deref(pat.hir_id, place_with_id)?;
1776                self.cat_pattern(subplace, subpat, op)?;
1777            }
1778            PatKind::Deref(subpat) => {
1779                let ty = self.pat_ty_adjusted(subpat)?;
1780                let place = self.pat_deref_place(pat.hir_id, place_with_id, subpat, ty)?;
1781                self.cat_pattern(place, subpat, op)?;
1782            }
1783
1784            PatKind::Slice(before, ref slice, after) => {
1785                let Some(element_ty) = self
1786                    .cx
1787                    .structurally_resolve_type(pat.span, place_with_id.place.ty())
1788                    .builtin_index()
1789                else {
1790                    {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_hir_typeck/src/expr_use_visitor.rs:1790",
                        "rustc_hir_typeck::expr_use_visitor",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_hir_typeck/src/expr_use_visitor.rs"),
                        ::tracing_core::__macro_support::Option::Some(1790u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_hir_typeck::expr_use_visitor"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                let mut iter = __CALLSITE.metadata().fields().iter();
                __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&format_args!("explicit index of non-indexable type {0:?}",
                                                    place_with_id) as &dyn Value))])
            });
    } else { ; }
};debug!("explicit index of non-indexable type {:?}", place_with_id);
1791                    return Err(self
1792                        .cx
1793                        .report_bug(pat.span, "explicit index of non-indexable type"));
1794                };
1795                let elt_place = self.cat_projection(
1796                    pat.hir_id,
1797                    place_with_id.clone(),
1798                    element_ty,
1799                    ProjectionKind::Index,
1800                );
1801                for before_pat in before {
1802                    self.cat_pattern(elt_place.clone(), before_pat, op)?;
1803                }
1804                if let Some(slice_pat) = *slice {
1805                    let slice_pat_ty = self.pat_ty_adjusted(slice_pat)?;
1806                    let slice_place = self.cat_projection(
1807                        pat.hir_id,
1808                        place_with_id,
1809                        slice_pat_ty,
1810                        ProjectionKind::Subslice,
1811                    );
1812                    self.cat_pattern(slice_place, slice_pat, op)?;
1813                }
1814                for after_pat in after {
1815                    self.cat_pattern(elt_place.clone(), after_pat, op)?;
1816                }
1817            }
1818
1819            PatKind::Binding(.., None)
1820            | PatKind::Expr(..)
1821            | PatKind::Range(..)
1822            | PatKind::Never
1823            | PatKind::Missing
1824            | PatKind::Wild
1825            | PatKind::Err(_) => {
1826                // always ok
1827            }
1828        }
1829
1830        Ok(())
1831    }
1832
1833    /// Represents the place matched on by a deref pattern's interior.
1834    fn pat_deref_place(
1835        &self,
1836        hir_id: HirId,
1837        base_place: PlaceWithHirId<'tcx>,
1838        inner: &hir::Pat<'_>,
1839        target_ty: Ty<'tcx>,
1840    ) -> Result<PlaceWithHirId<'tcx>, Cx::Error> {
1841        match self.cx.typeck_results().deref_pat_borrow_mode(base_place.place.ty(), inner) {
1842            // Deref patterns on boxes are lowered using a built-in deref.
1843            DerefPatBorrowMode::Box => self.cat_deref(hir_id, base_place),
1844            // For other types, we create a temporary to match on.
1845            DerefPatBorrowMode::Borrow(mutability) => {
1846                let re_erased = self.cx.tcx().lifetimes.re_erased;
1847                let ty = Ty::new_ref(self.cx.tcx(), re_erased, target_ty, mutability);
1848                // A deref pattern stores the result of `Deref::deref` or `DerefMut::deref_mut` ...
1849                let base = self.cat_rvalue(hir_id, ty);
1850                // ... and the inner pattern matches on the place behind that reference.
1851                self.cat_deref(hir_id, base)
1852            }
1853        }
1854    }
1855
1856    /// Checks whether a type has multiple variants, and therefore, whether a
1857    /// read of the discriminant might be necessary.
1858    #[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("is_multivariant_adt",
                                    "rustc_hir_typeck::expr_use_visitor",
                                    ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("compiler/rustc_hir_typeck/src/expr_use_visitor.rs"),
                                    ::tracing_core::__macro_support::Option::Some(1858u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_hir_typeck::expr_use_visitor"),
                                    ::tracing_core::field::FieldSet::new(&["ty"],
                                        ::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(&ty)
                                                            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: bool = loop {};
            return __tracing_attr_fake_return;
        }
        {
            if let ty::Adt(def, _) =
                    self.cx.structurally_resolve_type(span, ty).kind() {
                def.variants().len() > 1 ||
                    def.is_variant_list_non_exhaustive()
            } else { false }
        }
    }
}#[instrument(skip(self, span), level = "debug")]
1859    fn is_multivariant_adt(&self, ty: Ty<'tcx>, span: Span) -> bool {
1860        if let ty::Adt(def, _) = self.cx.structurally_resolve_type(span, ty).kind() {
1861            // We treat non-exhaustive enums the same independent of the crate they are
1862            // defined in, to avoid differences in the operational semantics between crates.
1863            def.variants().len() > 1 || def.is_variant_list_non_exhaustive()
1864        } else {
1865            false
1866        }
1867    }
1868}
1869
1870struct ExprPlaceDelegate;
1871
1872impl<'tcx> Delegate<'tcx> for ExprPlaceDelegate {
1873    fn consume(&mut self, _: &PlaceWithHirId<'tcx>, _: HirId) {}
1874
1875    fn use_cloned(&mut self, _: &PlaceWithHirId<'tcx>, _: HirId) {}
1876
1877    fn borrow(&mut self, _: &PlaceWithHirId<'tcx>, _: HirId, _: ty::BorrowKind) {}
1878
1879    fn mutate(&mut self, _: &PlaceWithHirId<'tcx>, _: HirId) {}
1880
1881    fn fake_read(&mut self, _: &PlaceWithHirId<'tcx>, _: FakeReadCause, _: HirId) {}
1882}
1883
1884/// Categorizes `expr` as a place for diagnostic suggestions.
1885///
1886/// This should be used for diagnostics purpose only.
1887pub(crate) fn expr_place<'tcx>(
1888    fcx: &FnCtxt<'_, 'tcx>,
1889    expr: &hir::Expr<'_>,
1890) -> Result<PlaceWithHirId<'tcx>, ErrorGuaranteed> {
1891    ExprUseVisitor::new(fcx, ExprPlaceDelegate).cat_expr(expr)
1892}