Skip to main content

rustc_mir_build/thir/cx/
expr.rs

1use itertools::Itertools;
2use rustc_abi::{FIRST_VARIANT, FieldIdx, Size, VariantIdx};
3use rustc_ast::UnsafeBinderCastKind;
4use rustc_data_structures::stack::ensure_sufficient_stack;
5use rustc_data_structures::thin_vec::ThinVec;
6use rustc_hir as hir;
7use rustc_hir::attrs::{AttributeKind, HasAttrs};
8use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
9use rustc_hir::{HirId, LangItem, find_attr};
10use rustc_index::Idx;
11use rustc_middle::hir::place::{
12    Place as HirPlace, PlaceBase as HirPlaceBase, ProjectionKind as HirProjectionKind,
13};
14use rustc_middle::middle::region;
15use rustc_middle::mir::{self, AssignOp, BinOp, BorrowKind, UnOp};
16use rustc_middle::thir::*;
17use rustc_middle::ty::adjustment::{
18    Adjust, Adjustment, AutoBorrow, AutoBorrowMutability, DerefAdjustKind, PointerCoercion,
19};
20use rustc_middle::ty::{
21    self, AdtKind, GenericArgs, InlineConstArgs, InlineConstArgsParts, ScalarInt, Ty, TyCtxt,
22    UpvarArgs,
23};
24use rustc_middle::{bug, span_bug};
25use rustc_span::Span;
26use tracing::{debug, info, instrument, trace};
27
28use crate::diagnostics::*;
29use crate::thir::cx::ThirBuildCx;
30
31fn parsed_attrs(id: HirId, tcx: TyCtxt<'_>) -> ThinVec<AttributeKind> {
32    HasAttrs::get_attrs(id, &tcx)
33        .into_iter()
34        .filter_map(|attr| match attr {
35            hir::Attribute::Parsed(attrkind) => Some(attrkind.clone()),
36            hir::Attribute::Unparsed(_) => None,
37        })
38        .collect()
39}
40
41impl<'tcx> ThirBuildCx<'tcx> {
42    /// Create a THIR expression for the given HIR expression. This expands all
43    /// adjustments and directly adds the type information from the
44    /// `typeck_results`. See the [dev-guide] for more details.
45    ///
46    /// (The term "mirror" in this case does not refer to "flipped" or
47    /// "reversed".)
48    ///
49    /// [dev-guide]: https://rustc-dev-guide.rust-lang.org/thir.html
50    pub(crate) fn mirror_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) -> ExprId {
51        // `mirror_expr` is recursing very deep. Make sure the stack doesn't overflow.
52        ensure_sufficient_stack(|| self.mirror_expr_inner(expr))
53    }
54
55    pub(crate) fn mirror_exprs(&mut self, exprs: &'tcx [hir::Expr<'tcx>]) -> Box<[ExprId]> {
56        // `mirror_exprs` may also recurse deeply, so it needs protection from stack overflow.
57        // Note that we *could* forward to `mirror_expr` for that, but we can consolidate the
58        // overhead of stack growth by doing it outside the iteration.
59        ensure_sufficient_stack(|| exprs.iter().map(|expr| self.mirror_expr_inner(expr)).collect())
60    }
61
62    #[allow(clippy :: suspicious_else_formatting)]
{
    let __tracing_attr_span;
    let __tracing_attr_guard;
    if ::tracing::Level::TRACE <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::TRACE <=
                    ::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("mirror_expr_inner",
                                    "rustc_mir_build::thir::cx::expr", ::tracing::Level::TRACE,
                                    ::tracing_core::__macro_support::Option::Some("compiler/rustc_mir_build/src/thir/cx/expr.rs"),
                                    ::tracing_core::__macro_support::Option::Some(62u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_mir_build::thir::cx::expr"),
                                    ::tracing_core::field::FieldSet::new(&[],
                                        ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                    ::tracing::metadata::Kind::SPAN)
                            };
                        ::tracing::callsite::DefaultCallsite::new(&META)
                    };
                let mut interest = ::tracing::subscriber::Interest::never();
                if ::tracing::Level::TRACE <=
                                    ::tracing::level_filters::STATIC_MAX_LEVEL &&
                                ::tracing::Level::TRACE <=
                                    ::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,
                        &{ meta.fields().value_set(&[]) })
                } 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: ExprId = loop {};
            return __tracing_attr_fake_return;
        }
        {
            let expr_scope =
                region::Scope {
                    local_id: hir_expr.hir_id.local_id,
                    data: region::ScopeData::Node,
                };
            {
                use ::tracing::__macro_support::Callsite as _;
                static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                    {
                        static META: ::tracing::Metadata<'static> =
                            {
                                ::tracing_core::metadata::Metadata::new("event compiler/rustc_mir_build/src/thir/cx/expr.rs:67",
                                    "rustc_mir_build::thir::cx::expr", ::tracing::Level::TRACE,
                                    ::tracing_core::__macro_support::Option::Some("compiler/rustc_mir_build/src/thir/cx/expr.rs"),
                                    ::tracing_core::__macro_support::Option::Some(67u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_mir_build::thir::cx::expr"),
                                    ::tracing_core::field::FieldSet::new(&["hir_expr.hir_id",
                                                    "hir_expr.span"],
                                        ::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(&hir_expr.hir_id)
                                                        as &dyn Value)),
                                            (&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                ::tracing::__macro_support::Option::Some(&debug(&hir_expr.span)
                                                        as &dyn Value))])
                        });
                } else { ; }
            };
            let mut expr = self.make_mirror_unadjusted(hir_expr);
            {
                use ::tracing::__macro_support::Callsite as _;
                static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                    {
                        static META: ::tracing::Metadata<'static> =
                            {
                                ::tracing_core::metadata::Metadata::new("event compiler/rustc_mir_build/src/thir/cx/expr.rs:71",
                                    "rustc_mir_build::thir::cx::expr", ::tracing::Level::TRACE,
                                    ::tracing_core::__macro_support::Option::Some("compiler/rustc_mir_build/src/thir/cx/expr.rs"),
                                    ::tracing_core::__macro_support::Option::Some(71u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_mir_build::thir::cx::expr"),
                                    ::tracing_core::field::FieldSet::new(&["expr.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(&expr.ty) as
                                                        &dyn Value))])
                        });
                } else { ; }
            };
            let mut attrs = ThinVec::new();
            if let ExprKind::Loop { .. } = expr.kind {
                if let hir::Node::Block(_) =
                        self.tcx.parent_hir_node(hir_expr.hir_id) {
                    attrs = parsed_attrs(hir_expr.hir_id, self.tcx);
                }
                if let hir::Node::Arm(arm) =
                                self.tcx.parent_hir_node(hir_expr.hir_id) &&
                            let hir::Node::Expr(expr) =
                                self.tcx.parent_hir_node(arm.hir_id) &&
                        let hir::Node::Expr(expr) =
                            self.tcx.parent_hir_node(expr.hir_id) {
                    attrs = parsed_attrs(expr.hir_id, self.tcx);
                }
            }
            if self.apply_adjustments {
                for adjustment in
                    self.typeck_results.expr_adjustments(hir_expr) {
                    {
                        use ::tracing::__macro_support::Callsite as _;
                        static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                            {
                                static META: ::tracing::Metadata<'static> =
                                    {
                                        ::tracing_core::metadata::Metadata::new("event compiler/rustc_mir_build/src/thir/cx/expr.rs:93",
                                            "rustc_mir_build::thir::cx::expr", ::tracing::Level::TRACE,
                                            ::tracing_core::__macro_support::Option::Some("compiler/rustc_mir_build/src/thir/cx/expr.rs"),
                                            ::tracing_core::__macro_support::Option::Some(93u32),
                                            ::tracing_core::__macro_support::Option::Some("rustc_mir_build::thir::cx::expr"),
                                            ::tracing_core::field::FieldSet::new(&["expr",
                                                            "adjustment"],
                                                ::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(&expr) as
                                                                &dyn Value)),
                                                    (&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                        ::tracing::__macro_support::Option::Some(&debug(&adjustment)
                                                                as &dyn Value))])
                                });
                        } else { ; }
                    };
                    let span = expr.span;
                    expr =
                        self.apply_adjustment(hir_expr, expr, adjustment, 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_mir_build/src/thir/cx/expr.rs:99",
                                    "rustc_mir_build::thir::cx::expr", ::tracing::Level::TRACE,
                                    ::tracing_core::__macro_support::Option::Some("compiler/rustc_mir_build/src/thir/cx/expr.rs"),
                                    ::tracing_core::__macro_support::Option::Some(99u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_mir_build::thir::cx::expr"),
                                    ::tracing_core::field::FieldSet::new(&["message",
                                                    "expr.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(&format_args!("after adjustments")
                                                        as &dyn Value)),
                                            (&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                ::tracing::__macro_support::Option::Some(&debug(&expr.ty) as
                                                        &dyn Value))])
                        });
                } else { ; }
            };
            let ty = expr.ty;
            let value = self.thir.exprs.push(expr);
            if !attrs.is_empty() {
                self.thir.attributes.insert(value, attrs);
            }
            expr =
                Expr {
                    temp_scope_id: expr_scope.local_id,
                    ty,
                    span: hir_expr.span,
                    kind: ExprKind::Scope {
                        region_scope: expr_scope,
                        value,
                        hir_id: hir_expr.hir_id,
                    },
                };
            self.thir.exprs.push(expr)
        }
    }
}#[instrument(level = "trace", skip(self, hir_expr))]
63    pub(super) fn mirror_expr_inner(&mut self, hir_expr: &'tcx hir::Expr<'tcx>) -> ExprId {
64        let expr_scope =
65            region::Scope { local_id: hir_expr.hir_id.local_id, data: region::ScopeData::Node };
66
67        trace!(?hir_expr.hir_id, ?hir_expr.span);
68
69        let mut expr = self.make_mirror_unadjusted(hir_expr);
70
71        trace!(?expr.ty);
72
73        let mut attrs = ThinVec::new();
74
75        if let ExprKind::Loop { .. } = expr.kind {
76            // For loops defined with loop and while, the expr already has the attrs
77            if let hir::Node::Block(_) = self.tcx.parent_hir_node(hir_expr.hir_id) {
78                attrs = parsed_attrs(hir_expr.hir_id, self.tcx);
79            }
80
81            // For loop desugaring puts us pretty deep down the HIR tree
82            if let hir::Node::Arm(arm) = self.tcx.parent_hir_node(hir_expr.hir_id)
83                && let hir::Node::Expr(expr) = self.tcx.parent_hir_node(arm.hir_id)
84                && let hir::Node::Expr(expr) = self.tcx.parent_hir_node(expr.hir_id)
85            {
86                attrs = parsed_attrs(expr.hir_id, self.tcx);
87            }
88        }
89
90        // Now apply adjustments, if any.
91        if self.apply_adjustments {
92            for adjustment in self.typeck_results.expr_adjustments(hir_expr) {
93                trace!(?expr, ?adjustment);
94                let span = expr.span;
95                expr = self.apply_adjustment(hir_expr, expr, adjustment, span);
96            }
97        }
98
99        trace!(?expr.ty, "after adjustments");
100
101        let ty = expr.ty;
102        let value = self.thir.exprs.push(expr);
103
104        if !attrs.is_empty() {
105            self.thir.attributes.insert(value, attrs);
106        }
107
108        // Finally, wrap this up in the expr's scope.
109        expr = Expr {
110            temp_scope_id: expr_scope.local_id,
111            ty,
112            span: hir_expr.span,
113            kind: ExprKind::Scope { region_scope: expr_scope, value, hir_id: hir_expr.hir_id },
114        };
115
116        // OK, all done!
117        self.thir.exprs.push(expr)
118    }
119
120    #[allow(clippy :: suspicious_else_formatting)]
{
    let __tracing_attr_span;
    let __tracing_attr_guard;
    if ::tracing::Level::TRACE <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::TRACE <=
                    ::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("apply_adjustment",
                                    "rustc_mir_build::thir::cx::expr", ::tracing::Level::TRACE,
                                    ::tracing_core::__macro_support::Option::Some("compiler/rustc_mir_build/src/thir/cx/expr.rs"),
                                    ::tracing_core::__macro_support::Option::Some(120u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_mir_build::thir::cx::expr"),
                                    ::tracing_core::field::FieldSet::new(&["hir_expr",
                                                    "adjustment"],
                                        ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                    ::tracing::metadata::Kind::SPAN)
                            };
                        ::tracing::callsite::DefaultCallsite::new(&META)
                    };
                let mut interest = ::tracing::subscriber::Interest::never();
                if ::tracing::Level::TRACE <=
                                    ::tracing::level_filters::STATIC_MAX_LEVEL &&
                                ::tracing::Level::TRACE <=
                                    ::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(&hir_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(&adjustment)
                                                            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: Expr<'tcx> = loop {};
            return __tracing_attr_fake_return;
        }
        {
            let Expr { temp_scope_id, .. } = expr;
            let mut adjust_span =
                |expr: &mut Expr<'tcx>|
                    {
                        if let ExprKind::Block { block } = expr.kind &&
                                let Some(last_expr) = self.thir[block].expr {
                            span = self.thir[last_expr].span;
                            expr.span = span;
                        }
                    };
            let kind =
                match adjustment.kind {
                    Adjust::Pointer(cast) => {
                        if cast == PointerCoercion::Unsize {
                            adjust_span(&mut expr);
                        }
                        let is_from_as_cast =
                            if let hir::Node::Expr(hir::Expr {
                                    kind: hir::ExprKind::Cast(..), span: cast_span, .. }) =
                                    self.tcx.parent_hir_node(hir_expr.hir_id) {
                                span = *cast_span;
                                true
                            } else { false };
                        ExprKind::PointerCoercion {
                            cast,
                            source: self.thir.exprs.push(expr),
                            is_from_as_cast,
                        }
                    }
                    Adjust::NeverToAny if adjustment.target.is_never() =>
                        return expr,
                    Adjust::NeverToAny =>
                        ExprKind::NeverToAny { source: self.thir.exprs.push(expr) },
                    Adjust::Deref(DerefAdjustKind::Builtin) => {
                        adjust_span(&mut expr);
                        ExprKind::Deref { arg: self.thir.exprs.push(expr) }
                    }
                    Adjust::Deref(DerefAdjustKind::Pin) => {
                        adjust_span(&mut expr);
                        let pin_ty =
                            expr.ty.pinned_ty().expect("Deref(Pin) with non-Pin type");
                        let pointer_target =
                            ExprKind::Field {
                                lhs: self.thir.exprs.push(expr),
                                variant_index: FIRST_VARIANT,
                                name: FieldIdx::ZERO,
                            };
                        let expr =
                            Expr {
                                temp_scope_id,
                                ty: pin_ty,
                                span,
                                kind: pointer_target,
                            };
                        ExprKind::Deref { arg: self.thir.exprs.push(expr) }
                    }
                    Adjust::Deref(DerefAdjustKind::Overloaded(deref)) => {
                        let call_def_id = deref.method_call(self.tcx);
                        let overloaded_callee =
                            Ty::new_fn_def(self.tcx, call_def_id,
                                self.tcx.mk_args(&[expr.ty.into()]));
                        expr =
                            Expr {
                                temp_scope_id,
                                ty: Ty::new_ref(self.tcx, self.tcx.lifetimes.re_erased,
                                    expr.ty, deref.mutbl),
                                span,
                                kind: ExprKind::Borrow {
                                    borrow_kind: deref.mutbl.to_borrow_kind(),
                                    arg: self.thir.exprs.push(expr),
                                },
                            };
                        let expr = Box::new([self.thir.exprs.push(expr)]);
                        self.overloaded_place(hir_expr, adjustment.target,
                            Some(overloaded_callee), expr, deref.span)
                    }
                    Adjust::Borrow(AutoBorrow::Ref(m)) =>
                        ExprKind::Borrow {
                            borrow_kind: m.to_borrow_kind(),
                            arg: self.thir.exprs.push(expr),
                        },
                    Adjust::Borrow(AutoBorrow::RawPtr(mutability)) => {
                        ExprKind::RawBorrow {
                            mutability,
                            arg: self.thir.exprs.push(expr),
                        }
                    }
                    Adjust::Borrow(AutoBorrow::Pin(mutbl)) => {
                        let borrow_kind =
                            match mutbl {
                                hir::Mutability::Mut =>
                                    BorrowKind::Mut { kind: mir::MutBorrowKind::Default },
                                hir::Mutability::Not => BorrowKind::Shared,
                            };
                        let new_pin_target =
                            Ty::new_ref(self.tcx, self.tcx.lifetimes.re_erased, expr.ty,
                                mutbl);
                        let arg = self.thir.exprs.push(expr);
                        let expr =
                            self.thir.exprs.push(Expr {
                                    temp_scope_id,
                                    ty: new_pin_target,
                                    span,
                                    kind: ExprKind::Borrow { borrow_kind, arg },
                                });
                        let pin_did =
                            self.tcx.require_lang_item(rustc_hir::LangItem::Pin, span);
                        let args = self.tcx.mk_args(&[new_pin_target.into()]);
                        let kind =
                            ExprKind::Adt(Box::new(AdtExpr {
                                        adt_def: self.tcx.adt_def(pin_did),
                                        variant_index: FIRST_VARIANT,
                                        args,
                                        fields: Box::new([FieldExpr {
                                                        name: FieldIdx::ZERO,
                                                        expr,
                                                    }]),
                                        user_ty: None,
                                        base: AdtExprBase::None,
                                    }));
                        {
                            use ::tracing::__macro_support::Callsite as _;
                            static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                                {
                                    static META: ::tracing::Metadata<'static> =
                                        {
                                            ::tracing_core::metadata::Metadata::new("event compiler/rustc_mir_build/src/thir/cx/expr.rs:254",
                                                "rustc_mir_build::thir::cx::expr", ::tracing::Level::DEBUG,
                                                ::tracing_core::__macro_support::Option::Some("compiler/rustc_mir_build/src/thir/cx/expr.rs"),
                                                ::tracing_core::__macro_support::Option::Some(254u32),
                                                ::tracing_core::__macro_support::Option::Some("rustc_mir_build::thir::cx::expr"),
                                                ::tracing_core::field::FieldSet::new(&["kind"],
                                                    ::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(&kind) as
                                                                    &dyn Value))])
                                    });
                            } else { ; }
                        };
                        kind
                    }
                    Adjust::GenericReborrow(mutability) => {
                        let expr = self.thir.exprs.push(expr);
                        let kind =
                            ExprKind::Reborrow {
                                source: expr,
                                mutability,
                                target: adjustment.target,
                            };
                        kind
                    }
                };
            Expr { temp_scope_id, ty: adjustment.target, span, kind }
        }
    }
}#[instrument(level = "trace", skip(self, expr, span))]
121    fn apply_adjustment(
122        &mut self,
123        hir_expr: &'tcx hir::Expr<'tcx>,
124        mut expr: Expr<'tcx>,
125        adjustment: &Adjustment<'tcx>,
126        mut span: Span,
127    ) -> Expr<'tcx> {
128        let Expr { temp_scope_id, .. } = expr;
129
130        // Adjust the span from the block, to the last expression of the
131        // block. This is a better span when returning a mutable reference
132        // with too short a lifetime. The error message will use the span
133        // from the assignment to the return place, which should only point
134        // at the returned value, not the entire function body.
135        //
136        // fn return_short_lived<'a>(x: &'a mut i32) -> &'static mut i32 {
137        //      x
138        //   // ^ error message points at this expression.
139        // }
140        let mut adjust_span = |expr: &mut Expr<'tcx>| {
141            if let ExprKind::Block { block } = expr.kind
142                && let Some(last_expr) = self.thir[block].expr
143            {
144                span = self.thir[last_expr].span;
145                expr.span = span;
146            }
147        };
148
149        let kind = match adjustment.kind {
150            Adjust::Pointer(cast) => {
151                if cast == PointerCoercion::Unsize {
152                    adjust_span(&mut expr);
153                }
154
155                let is_from_as_cast = if let hir::Node::Expr(hir::Expr {
156                    kind: hir::ExprKind::Cast(..),
157                    span: cast_span,
158                    ..
159                }) = self.tcx.parent_hir_node(hir_expr.hir_id)
160                {
161                    // Use the whole span of the `x as T` expression for the coercion.
162                    span = *cast_span;
163                    true
164                } else {
165                    false
166                };
167                ExprKind::PointerCoercion {
168                    cast,
169                    source: self.thir.exprs.push(expr),
170                    is_from_as_cast,
171                }
172            }
173            Adjust::NeverToAny if adjustment.target.is_never() => return expr,
174            Adjust::NeverToAny => ExprKind::NeverToAny { source: self.thir.exprs.push(expr) },
175            Adjust::Deref(DerefAdjustKind::Builtin) => {
176                adjust_span(&mut expr);
177                ExprKind::Deref { arg: self.thir.exprs.push(expr) }
178            }
179            Adjust::Deref(DerefAdjustKind::Pin) => {
180                adjust_span(&mut expr);
181                // pointer = ($expr).pointer
182                let pin_ty = expr.ty.pinned_ty().expect("Deref(Pin) with non-Pin type");
183                let pointer_target = ExprKind::Field {
184                    lhs: self.thir.exprs.push(expr),
185                    variant_index: FIRST_VARIANT,
186                    name: FieldIdx::ZERO,
187                };
188                let expr = Expr { temp_scope_id, ty: pin_ty, span, kind: pointer_target };
189                // expr = *pointer
190                ExprKind::Deref { arg: self.thir.exprs.push(expr) }
191            }
192            Adjust::Deref(DerefAdjustKind::Overloaded(deref)) => {
193                // We don't need to do call adjust_span here since
194                // deref coercions always start with a built-in deref.
195                let call_def_id = deref.method_call(self.tcx);
196                let overloaded_callee =
197                    Ty::new_fn_def(self.tcx, call_def_id, self.tcx.mk_args(&[expr.ty.into()]));
198
199                expr = Expr {
200                    temp_scope_id,
201                    ty: Ty::new_ref(self.tcx, self.tcx.lifetimes.re_erased, expr.ty, deref.mutbl),
202                    span,
203                    kind: ExprKind::Borrow {
204                        borrow_kind: deref.mutbl.to_borrow_kind(),
205                        arg: self.thir.exprs.push(expr),
206                    },
207                };
208
209                let expr = Box::new([self.thir.exprs.push(expr)]);
210
211                self.overloaded_place(
212                    hir_expr,
213                    adjustment.target,
214                    Some(overloaded_callee),
215                    expr,
216                    deref.span,
217                )
218            }
219            Adjust::Borrow(AutoBorrow::Ref(m)) => ExprKind::Borrow {
220                borrow_kind: m.to_borrow_kind(),
221                arg: self.thir.exprs.push(expr),
222            },
223            Adjust::Borrow(AutoBorrow::RawPtr(mutability)) => {
224                ExprKind::RawBorrow { mutability, arg: self.thir.exprs.push(expr) }
225            }
226            Adjust::Borrow(AutoBorrow::Pin(mutbl)) => {
227                // expr = &pin (mut|const|) arget
228                let borrow_kind = match mutbl {
229                    hir::Mutability::Mut => BorrowKind::Mut { kind: mir::MutBorrowKind::Default },
230                    hir::Mutability::Not => BorrowKind::Shared,
231                };
232                let new_pin_target =
233                    Ty::new_ref(self.tcx, self.tcx.lifetimes.re_erased, expr.ty, mutbl);
234                let arg = self.thir.exprs.push(expr);
235                let expr = self.thir.exprs.push(Expr {
236                    temp_scope_id,
237                    ty: new_pin_target,
238                    span,
239                    kind: ExprKind::Borrow { borrow_kind, arg },
240                });
241
242                // kind = Pin { pointer }
243                let pin_did = self.tcx.require_lang_item(rustc_hir::LangItem::Pin, span);
244                let args = self.tcx.mk_args(&[new_pin_target.into()]);
245                let kind = ExprKind::Adt(Box::new(AdtExpr {
246                    adt_def: self.tcx.adt_def(pin_did),
247                    variant_index: FIRST_VARIANT,
248                    args,
249                    fields: Box::new([FieldExpr { name: FieldIdx::ZERO, expr }]),
250                    user_ty: None,
251                    base: AdtExprBase::None,
252                }));
253
254                debug!(?kind);
255                kind
256            }
257            Adjust::GenericReborrow(mutability) => {
258                let expr = self.thir.exprs.push(expr);
259                let kind =
260                    ExprKind::Reborrow { source: expr, mutability, target: adjustment.target };
261
262                kind
263            }
264        };
265
266        Expr { temp_scope_id, ty: adjustment.target, span, kind }
267    }
268
269    /// Lowers a cast expression.
270    ///
271    /// Dealing with user type annotations is left to the caller.
272    fn mirror_expr_cast(
273        &mut self,
274        source: &'tcx hir::Expr<'tcx>,
275        temp_scope_id: hir::ItemLocalId,
276        span: Span,
277    ) -> ExprKind<'tcx> {
278        let tcx = self.tcx;
279
280        // Check to see if this cast is a "coercion cast", where the cast is actually done
281        // using a coercion (or is a no-op).
282        if self.typeck_results.is_coercion_cast(source.hir_id) {
283            // Convert the lexpr to a vexpr.
284            ExprKind::Use { source: self.mirror_expr(source) }
285        } else if self.typeck_results.expr_ty(source).is_ref() {
286            // Special cased so that we can type check that the element
287            // type of the source matches the pointed to type of the
288            // destination.
289            ExprKind::PointerCoercion {
290                source: self.mirror_expr(source),
291                cast: PointerCoercion::ArrayToPointer,
292                is_from_as_cast: true,
293            }
294        } else if let hir::ExprKind::Path(ref qpath) = source.kind
295            && let res = self.typeck_results.qpath_res(qpath, source.hir_id)
296            && let ty = self.typeck_results.node_type(source.hir_id)
297            && let ty::Adt(adt_def, args) = ty.kind()
298            && let Res::Def(DefKind::Ctor(CtorOf::Variant, CtorKind::Const), variant_ctor_id) = res
299        {
300            // Check whether this is casting an enum variant discriminant.
301            // To prevent cycles, we refer to the discriminant initializer,
302            // which is always an integer and thus doesn't need to know the
303            // enum's layout (or its tag type) to compute it during const eval.
304            // Example:
305            // enum Foo {
306            //     A,
307            //     B = A as isize + 4,
308            // }
309            // The correct solution would be to add symbolic computations to miri,
310            // so we wouldn't have to compute and store the actual value
311
312            let idx = adt_def.variant_index_with_ctor_id(variant_ctor_id);
313            let (discr_did, discr_offset) = adt_def.discriminant_def_for_variant(idx);
314
315            use rustc_middle::ty::util::IntTypeExt;
316            let ty = adt_def.repr().discr_type();
317            let discr_ty = ty.to_ty(tcx);
318
319            let size = tcx
320                .layout_of(self.typing_env.as_query_input(discr_ty))
321                .unwrap_or_else(|e| {
    ::core::panicking::panic_fmt(format_args!("could not compute layout for {0:?}: {1:?}",
            discr_ty, e));
}panic!("could not compute layout for {discr_ty:?}: {e:?}"))
322                .size;
323
324            let (lit, overflowing) = ScalarInt::truncate_from_uint(discr_offset as u128, size);
325            if overflowing {
326                // An erroneous enum with too many variants for its repr will emit E0081 and E0370
327                self.tcx.dcx().span_delayed_bug(
328                    source.span,
329                    "overflowing enum wasn't rejected by hir analysis",
330                );
331            }
332            let kind = ExprKind::NonHirLiteral { lit, user_ty: None };
333            let offset = self.thir.exprs.push(Expr { temp_scope_id, ty: discr_ty, span, kind });
334
335            let source = match discr_did {
336                // in case we are offsetting from a computed discriminant
337                // and not the beginning of discriminants (which is always `0`)
338                Some(did) => {
339                    let kind = ExprKind::NamedConst { def_id: did, args, user_ty: None };
340                    let lhs =
341                        self.thir.exprs.push(Expr { temp_scope_id, ty: discr_ty, span, kind });
342                    let bin = ExprKind::Binary { op: BinOp::Add, lhs, rhs: offset };
343                    self.thir.exprs.push(Expr { temp_scope_id, ty: discr_ty, span, kind: bin })
344                }
345                None => offset,
346            };
347
348            ExprKind::Cast { source }
349        } else {
350            // Default to `ExprKind::Cast` for all explicit casts.
351            // MIR building then picks the right MIR casts based on the types.
352            ExprKind::Cast { source: self.mirror_expr(source) }
353        }
354    }
355
356    x;#[instrument(level = "debug", skip(self), ret)]
357    fn make_mirror_unadjusted(&mut self, expr: &'tcx hir::Expr<'tcx>) -> Expr<'tcx> {
358        let tcx = self.tcx;
359        let expr_ty = self.typeck_results.expr_ty(expr);
360        let mk_expr =
361            |kind, ty| Expr { temp_scope_id: expr.hir_id.local_id, span: expr.span, ty, kind };
362
363        let kind = match expr.kind {
364            // Here comes the interesting stuff:
365            hir::ExprKind::MethodCall(segment, receiver, args, fn_span) => {
366                // Rewrite a.b(c) into UFCS form like Trait::b(a, c)
367                let expr = self.method_callee(expr, segment.ident.span, None);
368                info!("Using method span: {:?}", expr.span);
369                let args = std::iter::once(receiver)
370                    .chain(args.iter())
371                    .map(|expr| self.mirror_expr(expr))
372                    .collect();
373                ExprKind::Call {
374                    ty: expr.ty,
375                    fun: self.thir.exprs.push(expr),
376                    args,
377                    from_hir_call: true,
378                    fn_span,
379                }
380            }
381
382            hir::ExprKind::Call(fun, ref args) => {
383                if self.typeck_results.is_method_call(expr) {
384                    // The callee is something implementing Fn, FnMut, or FnOnce.
385                    // Find the actual method implementation being called and
386                    // build the appropriate UFCS call expression with the
387                    // callee-object as expr parameter.
388
389                    // rewrite f(u, v) into FnOnce::call_once(f, (u, v))
390
391                    let method = self.method_callee(expr, fun.span, None);
392
393                    let arg_tys = args.iter().map(|e| self.typeck_results.expr_ty_adjusted(e));
394                    let tupled_args = Expr {
395                        ty: Ty::new_tup_from_iter(tcx, arg_tys),
396                        temp_scope_id: expr.hir_id.local_id,
397                        span: expr.span,
398                        kind: ExprKind::Tuple { fields: self.mirror_exprs(args) },
399                    };
400                    let tupled_args = self.thir.exprs.push(tupled_args);
401
402                    ExprKind::Call {
403                        ty: method.ty,
404                        fun: self.thir.exprs.push(method),
405                        args: Box::new([self.mirror_expr(fun), tupled_args]),
406                        from_hir_call: true,
407                        fn_span: expr.span,
408                    }
409                } else {
410                    // Tuple-like ADTs are represented as ExprKind::Call. We convert them here.
411                    let adt_data = if let hir::ExprKind::Path(ref qpath) = fun.kind
412                        && let Some(adt_def) = expr_ty.ty_adt_def()
413                    {
414                        match qpath {
415                            hir::QPath::Resolved(_, path) => match path.res {
416                                Res::Def(DefKind::Ctor(_, CtorKind::Fn), ctor_id) => {
417                                    Some((adt_def, adt_def.variant_index_with_ctor_id(ctor_id)))
418                                }
419                                Res::SelfCtor(..) => Some((adt_def, FIRST_VARIANT)),
420                                _ => None,
421                            },
422                            hir::QPath::TypeRelative(_ty, _) => {
423                                if let Some((DefKind::Ctor(_, CtorKind::Fn), ctor_id)) =
424                                    self.typeck_results.type_dependent_def(fun.hir_id)
425                                {
426                                    Some((adt_def, adt_def.variant_index_with_ctor_id(ctor_id)))
427                                } else {
428                                    None
429                                }
430                            }
431                        }
432                    } else {
433                        None
434                    };
435                    if let Some((adt_def, index)) = adt_data {
436                        let node_args = self.typeck_results.node_args(fun.hir_id);
437                        let user_provided_types = self.typeck_results.user_provided_types();
438                        let user_ty =
439                            user_provided_types.get(fun.hir_id).copied().map(|mut u_ty| {
440                                if let ty::UserTypeKind::TypeOf(did, _) = &mut u_ty.value.kind {
441                                    *did = adt_def.did();
442                                }
443                                Box::new(u_ty)
444                            });
445                        debug!("make_mirror_unadjusted: (call) user_ty={:?}", user_ty);
446
447                        let field_refs = args
448                            .iter()
449                            .enumerate()
450                            .map(|(idx, e)| FieldExpr {
451                                name: FieldIdx::new(idx),
452                                expr: self.mirror_expr(e),
453                            })
454                            .collect();
455                        ExprKind::Adt(Box::new(AdtExpr {
456                            adt_def,
457                            args: node_args,
458                            variant_index: index,
459                            fields: field_refs,
460                            user_ty,
461                            base: AdtExprBase::None,
462                        }))
463                    } else {
464                        ExprKind::Call {
465                            ty: self.typeck_results.node_type(fun.hir_id),
466                            fun: self.mirror_expr(fun),
467                            args: self.mirror_exprs(args),
468                            from_hir_call: true,
469                            fn_span: expr.span,
470                        }
471                    }
472                }
473            }
474
475            hir::ExprKind::Use(expr, span) => {
476                ExprKind::ByUse { expr: self.mirror_expr(expr), span }
477            }
478
479            hir::ExprKind::AddrOf(hir::BorrowKind::Ref, mutbl, arg) => {
480                ExprKind::Borrow { borrow_kind: mutbl.to_borrow_kind(), arg: self.mirror_expr(arg) }
481            }
482
483            hir::ExprKind::AddrOf(hir::BorrowKind::Raw, mutability, arg) => {
484                ExprKind::RawBorrow { mutability, arg: self.mirror_expr(arg) }
485            }
486
487            // Make `&pin mut $expr` and `&pin const $expr` into
488            // `Pin { __pointer: &mut { $expr } }` and `Pin { __pointer: &$expr }`.
489            hir::ExprKind::AddrOf(hir::BorrowKind::Pin, mutbl, arg_expr) => match expr_ty.kind() {
490                &ty::Adt(adt_def, args) if tcx.is_lang_item(adt_def.did(), hir::LangItem::Pin) => {
491                    let ty = args.type_at(0);
492                    let arg_ty = self.typeck_results.expr_ty(arg_expr);
493                    let mut arg = self.mirror_expr(arg_expr);
494                    // For `&pin mut $place` where `$place` is not `Unpin`, move the place
495                    // `$place` to ensure it will not be used afterwards.
496                    if mutbl.is_mut() && !arg_ty.is_unpin(self.tcx, self.typing_env) {
497                        let block = self.thir.blocks.push(Block {
498                            targeted_by_break: false,
499                            region_scope: region::Scope {
500                                local_id: arg_expr.hir_id.local_id,
501                                data: region::ScopeData::Node,
502                            },
503                            span: arg_expr.span,
504                            stmts: Box::new([]),
505                            expr: Some(arg),
506                            safety_mode: BlockSafety::Safe,
507                        });
508                        arg = self.thir.exprs.push(Expr {
509                            temp_scope_id: arg_expr.hir_id.local_id,
510                            ty: arg_ty,
511                            span: arg_expr.span,
512                            kind: ExprKind::Block { block },
513                        });
514                    }
515                    let expr = self.thir.exprs.push(Expr {
516                        temp_scope_id: expr.hir_id.local_id,
517                        ty,
518                        span: expr.span,
519                        kind: ExprKind::Borrow { borrow_kind: mutbl.to_borrow_kind(), arg },
520                    });
521                    ExprKind::Adt(Box::new(AdtExpr {
522                        adt_def,
523                        variant_index: FIRST_VARIANT,
524                        args,
525                        fields: Box::new([FieldExpr { name: FieldIdx::from(0u32), expr }]),
526                        user_ty: None,
527                        base: AdtExprBase::None,
528                    }))
529                }
530                _ => span_bug!(expr.span, "unexpected type for pinned borrow: {:?}", expr_ty),
531            },
532
533            hir::ExprKind::Block(blk, _) => ExprKind::Block { block: self.mirror_block(blk) },
534
535            hir::ExprKind::Assign(lhs, rhs, _) => {
536                ExprKind::Assign { lhs: self.mirror_expr(lhs), rhs: self.mirror_expr(rhs) }
537            }
538
539            hir::ExprKind::AssignOp(op, lhs, rhs) => {
540                if self.typeck_results.is_method_call(expr) {
541                    let lhs = self.mirror_expr(lhs);
542                    let rhs = self.mirror_expr(rhs);
543                    self.overloaded_operator(expr, Box::new([lhs, rhs]))
544                } else {
545                    ExprKind::AssignOp {
546                        op: assign_op(op.node),
547                        lhs: self.mirror_expr(lhs),
548                        rhs: self.mirror_expr(rhs),
549                    }
550                }
551            }
552
553            hir::ExprKind::Lit(lit) => ExprKind::Literal { lit, neg: false },
554
555            hir::ExprKind::Binary(op, lhs, rhs) => {
556                if self.typeck_results.is_method_call(expr) {
557                    let lhs = self.mirror_expr(lhs);
558                    let rhs = self.mirror_expr(rhs);
559                    self.overloaded_operator(expr, Box::new([lhs, rhs]))
560                } else {
561                    match op.node {
562                        hir::BinOpKind::And => ExprKind::LogicalOp {
563                            op: LogicalOp::And,
564                            lhs: self.mirror_expr(lhs),
565                            rhs: self.mirror_expr(rhs),
566                        },
567                        hir::BinOpKind::Or => ExprKind::LogicalOp {
568                            op: LogicalOp::Or,
569                            lhs: self.mirror_expr(lhs),
570                            rhs: self.mirror_expr(rhs),
571                        },
572                        _ => {
573                            let op = bin_op(op.node);
574                            ExprKind::Binary {
575                                op,
576                                lhs: self.mirror_expr(lhs),
577                                rhs: self.mirror_expr(rhs),
578                            }
579                        }
580                    }
581                }
582            }
583
584            hir::ExprKind::Index(lhs, index, brackets_span) => {
585                if self.typeck_results.is_method_call(expr) {
586                    let lhs = self.mirror_expr(lhs);
587                    let index = self.mirror_expr(index);
588                    self.overloaded_place(
589                        expr,
590                        expr_ty,
591                        None,
592                        Box::new([lhs, index]),
593                        brackets_span,
594                    )
595                } else {
596                    ExprKind::Index { lhs: self.mirror_expr(lhs), index: self.mirror_expr(index) }
597                }
598            }
599
600            hir::ExprKind::Unary(hir::UnOp::Deref, arg) => {
601                if self.typeck_results.is_method_call(expr) {
602                    let arg = self.mirror_expr(arg);
603                    self.overloaded_place(expr, expr_ty, None, Box::new([arg]), expr.span)
604                } else {
605                    ExprKind::Deref { arg: self.mirror_expr(arg) }
606                }
607            }
608
609            hir::ExprKind::Unary(hir::UnOp::Not, arg) => {
610                if self.typeck_results.is_method_call(expr) {
611                    let arg = self.mirror_expr(arg);
612                    self.overloaded_operator(expr, Box::new([arg]))
613                } else {
614                    ExprKind::Unary { op: UnOp::Not, arg: self.mirror_expr(arg) }
615                }
616            }
617
618            hir::ExprKind::Unary(hir::UnOp::Neg, arg) => {
619                if self.typeck_results.is_method_call(expr) {
620                    let arg = self.mirror_expr(arg);
621                    self.overloaded_operator(expr, Box::new([arg]))
622                } else if let hir::ExprKind::Lit(lit) = arg.kind {
623                    ExprKind::Literal { lit, neg: true }
624                } else {
625                    ExprKind::Unary { op: UnOp::Neg, arg: self.mirror_expr(arg) }
626                }
627            }
628
629            hir::ExprKind::Struct(qpath, fields, ref base) => match expr_ty.kind() {
630                ty::Adt(adt, args) => match adt.adt_kind() {
631                    AdtKind::Struct | AdtKind::Union => {
632                        let user_provided_types = self.typeck_results.user_provided_types();
633                        let user_ty = user_provided_types.get(expr.hir_id).copied().map(Box::new);
634                        debug!("make_mirror_unadjusted: (struct/union) user_ty={:?}", user_ty);
635                        ExprKind::Adt(Box::new(AdtExpr {
636                            adt_def: *adt,
637                            variant_index: FIRST_VARIANT,
638                            args,
639                            user_ty,
640                            fields: self.field_refs(fields),
641                            base: match base {
642                                hir::StructTailExpr::Base(base) => AdtExprBase::Base(FruInfo {
643                                    base: self.mirror_expr(base),
644                                    field_types: self.typeck_results.fru_field_types()[expr.hir_id]
645                                        .iter()
646                                        .copied()
647                                        .collect(),
648                                }),
649                                hir::StructTailExpr::DefaultFields(_) => {
650                                    AdtExprBase::DefaultFields(
651                                        self.typeck_results.fru_field_types()[expr.hir_id]
652                                            .iter()
653                                            .copied()
654                                            .collect(),
655                                    )
656                                }
657                                hir::StructTailExpr::None
658                                | hir::StructTailExpr::NoneWithError(_) => AdtExprBase::None,
659                            },
660                        }))
661                    }
662                    AdtKind::Enum => {
663                        let res = self.typeck_results.qpath_res(qpath, expr.hir_id);
664                        match res {
665                            Res::Def(DefKind::Variant, variant_id) => {
666                                assert!(matches!(
667                                    base,
668                                    hir::StructTailExpr::None
669                                        | hir::StructTailExpr::DefaultFields(_)
670                                        | hir::StructTailExpr::NoneWithError(_)
671                                ));
672
673                                let index = adt.variant_index_with_id(variant_id);
674                                let user_provided_types = self.typeck_results.user_provided_types();
675                                let user_ty =
676                                    user_provided_types.get(expr.hir_id).copied().map(Box::new);
677                                debug!("make_mirror_unadjusted: (variant) user_ty={:?}", user_ty);
678                                ExprKind::Adt(Box::new(AdtExpr {
679                                    adt_def: *adt,
680                                    variant_index: index,
681                                    args,
682                                    user_ty,
683                                    fields: self.field_refs(fields),
684                                    base: match base {
685                                        hir::StructTailExpr::DefaultFields(_) => {
686                                            AdtExprBase::DefaultFields(
687                                                self.typeck_results.fru_field_types()[expr.hir_id]
688                                                    .iter()
689                                                    .copied()
690                                                    .collect(),
691                                            )
692                                        }
693                                        hir::StructTailExpr::Base(base) => {
694                                            span_bug!(base.span, "unexpected res: {:?}", res);
695                                        }
696                                        hir::StructTailExpr::None
697                                        | hir::StructTailExpr::NoneWithError(_) => {
698                                            AdtExprBase::None
699                                        }
700                                    },
701                                }))
702                            }
703                            _ => {
704                                span_bug!(expr.span, "unexpected res: {:?}", res);
705                            }
706                        }
707                    }
708                },
709                _ => {
710                    span_bug!(expr.span, "unexpected type for struct literal: {:?}", expr_ty);
711                }
712            },
713
714            hir::ExprKind::Closure(hir::Closure { .. }) => {
715                let closure_ty = self.typeck_results.expr_ty(expr);
716                let (def_id, args, movability) = match *closure_ty.kind() {
717                    ty::Closure(def_id, args) => (def_id, UpvarArgs::Closure(args), None),
718                    ty::Coroutine(def_id, args) => {
719                        (def_id, UpvarArgs::Coroutine(args), Some(tcx.coroutine_movability(def_id)))
720                    }
721                    ty::CoroutineClosure(def_id, args) => {
722                        (def_id, UpvarArgs::CoroutineClosure(args), None)
723                    }
724                    _ => {
725                        span_bug!(expr.span, "closure expr w/o closure type: {:?}", closure_ty);
726                    }
727                };
728                let def_id = def_id.expect_local();
729
730                let upvars = self
731                    .tcx
732                    .closure_captures(def_id)
733                    .iter()
734                    .zip_eq(args.upvar_tys())
735                    .map(|(captured_place, ty)| {
736                        let upvars = self.capture_upvar(expr, captured_place, ty);
737                        self.thir.exprs.push(upvars)
738                    })
739                    .collect();
740
741                // Convert the closure fake reads, if any, from hir `Place` to ExprRef
742                let fake_reads = match self.typeck_results.closure_fake_reads.get(&def_id) {
743                    Some(fake_reads) => fake_reads
744                        .iter()
745                        .map(|(place, cause, hir_id)| {
746                            let expr = self.convert_captured_hir_place(expr, place.clone());
747                            (self.thir.exprs.push(expr), *cause, *hir_id)
748                        })
749                        .collect(),
750                    None => Vec::new(),
751                };
752
753                ExprKind::Closure(Box::new(ClosureExpr {
754                    closure_id: def_id,
755                    args,
756                    upvars,
757                    movability,
758                    fake_reads,
759                }))
760            }
761
762            hir::ExprKind::Path(ref qpath) => {
763                let res = self.typeck_results.qpath_res(qpath, expr.hir_id);
764                self.convert_path_expr(expr, res)
765            }
766
767            hir::ExprKind::InlineAsm(asm) => ExprKind::InlineAsm(Box::new(InlineAsmExpr {
768                asm_macro: asm.asm_macro,
769                template: asm.template,
770                operands: asm
771                    .operands
772                    .iter()
773                    .map(|(op, _op_sp)| match *op {
774                        hir::InlineAsmOperand::In { reg, expr } => {
775                            InlineAsmOperand::In { reg, expr: self.mirror_expr(expr) }
776                        }
777                        hir::InlineAsmOperand::Out { reg, late, ref expr } => {
778                            InlineAsmOperand::Out {
779                                reg,
780                                late,
781                                expr: expr.map(|expr| self.mirror_expr(expr)),
782                            }
783                        }
784                        hir::InlineAsmOperand::InOut { reg, late, expr } => {
785                            InlineAsmOperand::InOut { reg, late, expr: self.mirror_expr(expr) }
786                        }
787                        hir::InlineAsmOperand::SplitInOut { reg, late, in_expr, ref out_expr } => {
788                            InlineAsmOperand::SplitInOut {
789                                reg,
790                                late,
791                                in_expr: self.mirror_expr(in_expr),
792                                out_expr: out_expr.map(|expr| self.mirror_expr(expr)),
793                            }
794                        }
795                        hir::InlineAsmOperand::Const { ref anon_const } => {
796                            let ty = self.typeck_results.node_type(anon_const.hir_id);
797                            let did = anon_const.def_id;
798                            let typeck_root_def_id = tcx.typeck_root_def_id_local(did);
799                            let parent_args = tcx.erase_and_anonymize_regions(
800                                GenericArgs::identity_for_item(tcx, typeck_root_def_id),
801                            );
802                            let args =
803                                InlineConstArgs::new(tcx, InlineConstArgsParts { parent_args, ty })
804                                    .args;
805
806                            let uneval = mir::UnevaluatedConst::new(did.to_def_id(), args);
807                            let value = mir::Const::Unevaluated(uneval, ty);
808                            InlineAsmOperand::Const { value, span: tcx.def_span(did) }
809                        }
810                        hir::InlineAsmOperand::SymFn { expr } => {
811                            InlineAsmOperand::SymFn { value: self.mirror_expr(expr) }
812                        }
813                        hir::InlineAsmOperand::SymStatic { path: _, def_id } => {
814                            InlineAsmOperand::SymStatic { def_id }
815                        }
816                        hir::InlineAsmOperand::Label { block } => {
817                            InlineAsmOperand::Label { block: self.mirror_block(block) }
818                        }
819                    })
820                    .collect(),
821                options: asm.options,
822                line_spans: asm.line_spans,
823            })),
824
825            hir::ExprKind::OffsetOf(_, _) => {
826                let offset_of_intrinsic = tcx.require_lang_item(LangItem::OffsetOf, expr.span);
827                let mk_u32_kind = |val: u32| ExprKind::NonHirLiteral {
828                    lit: ScalarInt::try_from_uint(val, Size::from_bits(32)).unwrap(),
829                    user_ty: None,
830                };
831                let mk_usize_kind = |val: u64| ExprKind::NonHirLiteral {
832                    lit: ScalarInt::try_from_target_usize(val, tcx).unwrap(),
833                    user_ty: None,
834                };
835                let mk_call =
836                    |thir: &mut Thir<'tcx>, ty: Ty<'tcx>, variant: VariantIdx, field: FieldIdx| {
837                        let fun_ty =
838                            Ty::new_fn_def(tcx, offset_of_intrinsic, [ty::GenericArg::from(ty)]);
839                        let fun = thir
840                            .exprs
841                            .push(mk_expr(ExprKind::ZstLiteral { user_ty: None }, fun_ty));
842                        let variant =
843                            thir.exprs.push(mk_expr(mk_u32_kind(variant.as_u32()), tcx.types.u32));
844                        let field =
845                            thir.exprs.push(mk_expr(mk_u32_kind(field.as_u32()), tcx.types.u32));
846                        let args = Box::new([variant, field]);
847                        ExprKind::Call {
848                            ty: fun_ty,
849                            fun,
850                            args,
851                            from_hir_call: false,
852                            fn_span: expr.span,
853                        }
854                    };
855
856                let indices = self.typeck_results.offset_of_data().get(expr.hir_id).unwrap();
857                let mut expr = None::<ExprKind<'_>>;
858
859                for &(container, variant, field) in indices.iter() {
860                    let next = mk_call(&mut self.thir, container, variant, field);
861                    expr = Some(match expr.take() {
862                        None => next,
863                        Some(last) => {
864                            let last = self.thir.exprs.push(mk_expr(last, tcx.types.usize));
865                            let next = self.thir.exprs.push(mk_expr(next, tcx.types.usize));
866                            ExprKind::Binary { op: BinOp::Add, lhs: last, rhs: next }
867                        }
868                    });
869                }
870
871                expr.unwrap_or_else(|| mk_usize_kind(0))
872            }
873
874            hir::ExprKind::ConstBlock(ref anon_const) => {
875                let ty = self.typeck_results.node_type(anon_const.hir_id);
876                let did = anon_const.def_id;
877                let typeck_root_def_id = tcx.typeck_root_def_id_local(did);
878                let parent_args = tcx.erase_and_anonymize_regions(GenericArgs::identity_for_item(
879                    tcx,
880                    typeck_root_def_id,
881                ));
882                let args = InlineConstArgs::new(tcx, InlineConstArgsParts { parent_args, ty }).args;
883
884                ExprKind::ConstBlock { did: did.to_def_id(), args }
885            }
886            // Now comes the rote stuff:
887            hir::ExprKind::Repeat(v, _) => {
888                let ty = self.typeck_results.expr_ty(expr);
889                let ty::Array(_, count) = ty.kind() else {
890                    span_bug!(expr.span, "unexpected repeat expr ty: {:?}", ty);
891                };
892
893                ExprKind::Repeat { value: self.mirror_expr(v), count: *count }
894            }
895            hir::ExprKind::Ret(v) => ExprKind::Return { value: v.map(|v| self.mirror_expr(v)) },
896            hir::ExprKind::Become(call) => ExprKind::Become { value: self.mirror_expr(call) },
897            hir::ExprKind::Break(dest, ref value) => {
898                if find_attr!(self.tcx, expr.hir_id, ConstContinue(_)) {
899                    match dest.target_id {
900                        Ok(target_id) => {
901                            let (Some(value), Some(_)) = (value, dest.label) else {
902                                let span = expr.span;
903                                self.tcx.dcx().emit_fatal(ConstContinueMissingLabelOrValue { span })
904                            };
905
906                            ExprKind::ConstContinue {
907                                label: region::Scope {
908                                    local_id: target_id.local_id,
909                                    data: region::ScopeData::Node,
910                                },
911                                value: self.mirror_expr(value),
912                            }
913                        }
914                        Err(err) => bug!("invalid loop id for break: {}", err),
915                    }
916                } else {
917                    match dest.target_id {
918                        Ok(target_id) => ExprKind::Break {
919                            label: region::Scope {
920                                local_id: target_id.local_id,
921                                data: region::ScopeData::Node,
922                            },
923                            value: value.map(|value| self.mirror_expr(value)),
924                        },
925                        Err(err) => bug!("invalid loop id for break: {}", err),
926                    }
927                }
928            }
929            hir::ExprKind::Continue(dest) => match dest.target_id {
930                Ok(loop_id) => ExprKind::Continue {
931                    label: region::Scope {
932                        local_id: loop_id.local_id,
933                        data: region::ScopeData::Node,
934                    },
935                },
936                Err(err) => bug!("invalid loop id for continue: {}", err),
937            },
938            hir::ExprKind::Let(let_expr) => ExprKind::Let {
939                expr: self.mirror_expr(let_expr.init),
940                pat: self.pattern_from_hir(let_expr.pat),
941            },
942            hir::ExprKind::If(cond, then, else_opt) => ExprKind::If {
943                if_then_scope: region::Scope {
944                    local_id: then.hir_id.local_id,
945                    data: {
946                        if expr.span.at_least_rust_2024() {
947                            region::ScopeData::IfThenRescope
948                        } else {
949                            region::ScopeData::IfThen
950                        }
951                    },
952                },
953                cond: self.mirror_expr(cond),
954                then: self.mirror_expr(then),
955                else_opt: else_opt.map(|el| self.mirror_expr(el)),
956            },
957            hir::ExprKind::Match(discr, arms, match_source) => ExprKind::Match {
958                scrutinee: self.mirror_expr(discr),
959                arms: arms.iter().map(|a| self.convert_arm(a)).collect(),
960                match_source,
961            },
962            hir::ExprKind::Loop(body, ..) => {
963                if find_attr!(self.tcx, expr.hir_id, LoopMatch(_)) {
964                    let dcx = self.tcx.dcx();
965
966                    // Accept either `state = expr` or `state = expr;`.
967                    let loop_body_expr = match body.stmts {
968                        [] => match body.expr {
969                            Some(expr) => expr,
970                            None => dcx.emit_fatal(LoopMatchMissingAssignment { span: body.span }),
971                        },
972                        [single] if body.expr.is_none() => match single.kind {
973                            hir::StmtKind::Expr(expr) | hir::StmtKind::Semi(expr) => expr,
974                            _ => dcx.emit_fatal(LoopMatchMissingAssignment { span: body.span }),
975                        },
976                        [first @ last] | [first, .., last] => dcx
977                            .emit_fatal(LoopMatchBadStatements { span: first.span.to(last.span) }),
978                    };
979
980                    let hir::ExprKind::Assign(state, rhs_expr, _) = loop_body_expr.kind else {
981                        dcx.emit_fatal(LoopMatchMissingAssignment { span: loop_body_expr.span })
982                    };
983
984                    let hir::ExprKind::Block(block_body, _) = rhs_expr.kind else {
985                        dcx.emit_fatal(LoopMatchBadRhs { span: rhs_expr.span })
986                    };
987
988                    // The labeled block should contain one match expression, but defining items is
989                    // allowed.
990                    for stmt in block_body.stmts {
991                        if !matches!(stmt.kind, rustc_hir::StmtKind::Item(_)) {
992                            dcx.emit_fatal(LoopMatchBadStatements { span: stmt.span })
993                        }
994                    }
995
996                    let Some(block_body_expr) = block_body.expr else {
997                        dcx.emit_fatal(LoopMatchBadRhs { span: block_body.span })
998                    };
999
1000                    let hir::ExprKind::Match(scrutinee, arms, _match_source) = block_body_expr.kind
1001                    else {
1002                        dcx.emit_fatal(LoopMatchBadRhs { span: block_body_expr.span })
1003                    };
1004
1005                    fn local(
1006                        cx: &mut ThirBuildCx<'_>,
1007                        expr: &rustc_hir::Expr<'_>,
1008                    ) -> Option<hir::HirId> {
1009                        if let hir::ExprKind::Path(hir::QPath::Resolved(_, path)) = expr.kind
1010                            && let Res::Local(hir_id) = path.res
1011                            && !cx.is_upvar(hir_id)
1012                        {
1013                            return Some(hir_id);
1014                        }
1015
1016                        None
1017                    }
1018
1019                    let Some(scrutinee_hir_id) = local(self, scrutinee) else {
1020                        dcx.emit_fatal(LoopMatchInvalidMatch { span: scrutinee.span })
1021                    };
1022
1023                    if local(self, state) != Some(scrutinee_hir_id) {
1024                        dcx.emit_fatal(LoopMatchInvalidUpdate {
1025                            scrutinee: scrutinee.span,
1026                            lhs: state.span,
1027                        })
1028                    }
1029
1030                    ExprKind::LoopMatch {
1031                        state: self.mirror_expr(state),
1032                        region_scope: region::Scope {
1033                            local_id: block_body.hir_id.local_id,
1034                            data: region::ScopeData::Node,
1035                        },
1036
1037                        match_data: Box::new(LoopMatchMatchData {
1038                            scrutinee: self.mirror_expr(scrutinee),
1039                            arms: arms.iter().map(|a| self.convert_arm(a)).collect(),
1040                            span: block_body_expr.span,
1041                        }),
1042                    }
1043                } else {
1044                    let block_ty = self.typeck_results.node_type(body.hir_id);
1045                    let block = self.mirror_block(body);
1046                    let body = self.thir.exprs.push(Expr {
1047                        ty: block_ty,
1048                        temp_scope_id: body.hir_id.local_id,
1049                        span: self.thir[block].span,
1050                        kind: ExprKind::Block { block },
1051                    });
1052                    ExprKind::Loop { body }
1053                }
1054            }
1055            hir::ExprKind::Field(source, ..) => ExprKind::Field {
1056                lhs: self.mirror_expr(source),
1057                variant_index: FIRST_VARIANT,
1058                name: self.typeck_results.field_index(expr.hir_id),
1059            },
1060            hir::ExprKind::Cast(source, cast_ty) => {
1061                // Check for a user-given type annotation on this `cast`
1062                let user_provided_types = self.typeck_results.user_provided_types();
1063                let user_ty = user_provided_types.get(cast_ty.hir_id);
1064
1065                debug!(
1066                    "cast({:?}) has ty w/ hir_id {:?} and user provided ty {:?}",
1067                    expr, cast_ty.hir_id, user_ty,
1068                );
1069
1070                let cast = self.mirror_expr_cast(source, expr.hir_id.local_id, expr.span);
1071
1072                if let Some(user_ty) = user_ty {
1073                    // NOTE: Creating a new Expr and wrapping a Cast inside of it may be
1074                    //       inefficient, revisit this when performance becomes an issue.
1075                    let cast_expr = self.thir.exprs.push(Expr {
1076                        temp_scope_id: expr.hir_id.local_id,
1077                        ty: expr_ty,
1078                        span: expr.span,
1079                        kind: cast,
1080                    });
1081                    debug!("make_mirror_unadjusted: (cast) user_ty={:?}", user_ty);
1082
1083                    ExprKind::ValueTypeAscription {
1084                        source: cast_expr,
1085                        user_ty: Some(Box::new(*user_ty)),
1086                        user_ty_span: cast_ty.span,
1087                    }
1088                } else {
1089                    cast
1090                }
1091            }
1092            hir::ExprKind::Type(source, ty) => {
1093                let user_provided_types = self.typeck_results.user_provided_types();
1094                let user_ty = user_provided_types.get(ty.hir_id).copied().map(Box::new);
1095                debug!("make_mirror_unadjusted: (type) user_ty={:?}", user_ty);
1096                let mirrored = self.mirror_expr(source);
1097                if source.is_syntactic_place_expr() {
1098                    ExprKind::PlaceTypeAscription {
1099                        source: mirrored,
1100                        user_ty,
1101                        user_ty_span: ty.span,
1102                    }
1103                } else {
1104                    ExprKind::ValueTypeAscription {
1105                        source: mirrored,
1106                        user_ty,
1107                        user_ty_span: ty.span,
1108                    }
1109                }
1110            }
1111
1112            hir::ExprKind::UnsafeBinderCast(UnsafeBinderCastKind::Unwrap, source, _ty) => {
1113                // FIXME(unsafe_binders): Take into account the ascribed type, too.
1114                let mirrored = self.mirror_expr(source);
1115                if source.is_syntactic_place_expr() {
1116                    ExprKind::PlaceUnwrapUnsafeBinder { source: mirrored }
1117                } else {
1118                    ExprKind::ValueUnwrapUnsafeBinder { source: mirrored }
1119                }
1120            }
1121            hir::ExprKind::UnsafeBinderCast(UnsafeBinderCastKind::Wrap, source, _ty) => {
1122                // FIXME(unsafe_binders): Take into account the ascribed type, too.
1123                let mirrored = self.mirror_expr(source);
1124                ExprKind::WrapUnsafeBinder { source: mirrored }
1125            }
1126
1127            hir::ExprKind::DropTemps(source) => ExprKind::Use { source: self.mirror_expr(source) },
1128            hir::ExprKind::Array(fields) => ExprKind::Array { fields: self.mirror_exprs(fields) },
1129            hir::ExprKind::Tup(fields) => ExprKind::Tuple { fields: self.mirror_exprs(fields) },
1130
1131            hir::ExprKind::Yield(v, _) => ExprKind::Yield { value: self.mirror_expr(v) },
1132            hir::ExprKind::Err(_) => unreachable!("cannot lower a `hir::ExprKind::Err` to THIR"),
1133        };
1134
1135        mk_expr(kind, expr_ty)
1136    }
1137
1138    fn user_args_applied_to_res(
1139        &mut self,
1140        hir_id: hir::HirId,
1141        res: Res,
1142    ) -> Option<Box<ty::CanonicalUserType<'tcx>>> {
1143        {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_mir_build/src/thir/cx/expr.rs:1143",
                        "rustc_mir_build::thir::cx::expr", ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_mir_build/src/thir/cx/expr.rs"),
                        ::tracing_core::__macro_support::Option::Some(1143u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_mir_build::thir::cx::expr"),
                        ::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!("user_args_applied_to_res: res={0:?}",
                                                    res) as &dyn Value))])
            });
    } else { ; }
};debug!("user_args_applied_to_res: res={:?}", res);
1144        let user_provided_type = match res {
1145            // A reference to something callable -- e.g., a fn, method, or
1146            // a tuple-struct or tuple-variant. This has the type of a
1147            // `Fn` but with the user-given generic parameters.
1148            Res::Def(DefKind::Fn, _)
1149            | Res::Def(DefKind::AssocFn, _)
1150            | Res::Def(DefKind::Ctor(_, CtorKind::Fn), _)
1151            | Res::Def(DefKind::Const { .. }, _)
1152            | Res::Def(DefKind::AssocConst { .. }, _) => {
1153                self.typeck_results.user_provided_types().get(hir_id).copied().map(Box::new)
1154            }
1155
1156            // A unit struct/variant which is used as a value (e.g.,
1157            // `None`). This has the type of the enum/struct that defines
1158            // this variant -- but with the generic parameters given by the
1159            // user.
1160            Res::Def(DefKind::Ctor(_, CtorKind::Const), _) => {
1161                self.user_args_applied_to_ty_of_hir_id(hir_id).map(Box::new)
1162            }
1163
1164            // `Self` is used in expression as a tuple struct constructor or a unit struct constructor
1165            Res::SelfCtor(_) => self.user_args_applied_to_ty_of_hir_id(hir_id).map(Box::new),
1166
1167            _ => ::rustc_middle::util::bug::bug_fmt(format_args!("user_args_applied_to_res: unexpected res {0:?} at {1:?}",
        res, hir_id))bug!("user_args_applied_to_res: unexpected res {:?} at {:?}", res, hir_id),
1168        };
1169        {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_mir_build/src/thir/cx/expr.rs:1169",
                        "rustc_mir_build::thir::cx::expr", ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_mir_build/src/thir/cx/expr.rs"),
                        ::tracing_core::__macro_support::Option::Some(1169u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_mir_build::thir::cx::expr"),
                        ::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!("user_args_applied_to_res: user_provided_type={0:?}",
                                                    user_provided_type) as &dyn Value))])
            });
    } else { ; }
};debug!("user_args_applied_to_res: user_provided_type={:?}", user_provided_type);
1170        user_provided_type
1171    }
1172
1173    fn method_callee(
1174        &mut self,
1175        expr: &hir::Expr<'_>,
1176        span: Span,
1177        overloaded_callee: Option<Ty<'tcx>>,
1178    ) -> Expr<'tcx> {
1179        let (ty, user_ty) = match overloaded_callee {
1180            Some(fn_def) => (fn_def, None),
1181            None => {
1182                let (kind, def_id) =
1183                    self.typeck_results.type_dependent_def(expr.hir_id).unwrap_or_else(|| {
1184                        ::rustc_middle::util::bug::span_bug_fmt(expr.span,
    format_args!("no type-dependent def for method callee"))span_bug!(expr.span, "no type-dependent def for method callee")
1185                    });
1186                let user_ty = self.user_args_applied_to_res(expr.hir_id, Res::Def(kind, def_id));
1187                {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_mir_build/src/thir/cx/expr.rs:1187",
                        "rustc_mir_build::thir::cx::expr", ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_mir_build/src/thir/cx/expr.rs"),
                        ::tracing_core::__macro_support::Option::Some(1187u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_mir_build::thir::cx::expr"),
                        ::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!("method_callee: user_ty={0:?}",
                                                    user_ty) as &dyn Value))])
            });
    } else { ; }
};debug!("method_callee: user_ty={:?}", user_ty);
1188                (
1189                    Ty::new_fn_def(self.tcx, def_id, self.typeck_results.node_args(expr.hir_id)),
1190                    user_ty,
1191                )
1192            }
1193        };
1194        Expr {
1195            temp_scope_id: expr.hir_id.local_id,
1196            ty,
1197            span,
1198            kind: ExprKind::ZstLiteral { user_ty },
1199        }
1200    }
1201
1202    fn convert_arm(&mut self, arm: &'tcx hir::Arm<'tcx>) -> ArmId {
1203        let arm = Arm {
1204            pattern: self.pattern_from_hir(&arm.pat),
1205            guard: arm.guard.as_ref().map(|g| self.mirror_expr(g)),
1206            body: self.mirror_expr(arm.body),
1207            hir_id: arm.hir_id,
1208            scope: region::Scope { local_id: arm.hir_id.local_id, data: region::ScopeData::Node },
1209            span: arm.span,
1210        };
1211        self.thir.arms.push(arm)
1212    }
1213
1214    fn convert_path_expr(&mut self, expr: &'tcx hir::Expr<'tcx>, res: Res) -> ExprKind<'tcx> {
1215        let args = self.typeck_results.node_args(expr.hir_id);
1216        match res {
1217            // A regular function, constructor function or a constant.
1218            Res::Def(DefKind::Fn, _)
1219            | Res::Def(DefKind::AssocFn, _)
1220            | Res::Def(DefKind::Ctor(_, CtorKind::Fn), _)
1221            | Res::SelfCtor(_) => {
1222                let user_ty = self.user_args_applied_to_res(expr.hir_id, res);
1223                ExprKind::ZstLiteral { user_ty }
1224            }
1225
1226            Res::Def(DefKind::ConstParam, def_id) => {
1227                let hir_id = self.tcx.local_def_id_to_hir_id(def_id.expect_local());
1228                let generics = self.tcx.generics_of(hir_id.owner);
1229                let Some(&index) = generics.param_def_id_to_index.get(&def_id) else {
1230                    ::rustc_middle::util::bug::span_bug_fmt(expr.span,
    format_args!("Should have already errored about late bound consts: {0:?}",
        def_id));span_bug!(
1231                        expr.span,
1232                        "Should have already errored about late bound consts: {def_id:?}"
1233                    );
1234                };
1235                let name = self.tcx.hir_name(hir_id);
1236                let param = ty::ParamConst::new(index, name);
1237
1238                ExprKind::ConstParam { param, def_id }
1239            }
1240
1241            Res::Def(DefKind::Const { .. }, def_id)
1242            | Res::Def(DefKind::AssocConst { .. }, def_id) => {
1243                let user_ty = self.user_args_applied_to_res(expr.hir_id, res);
1244                ExprKind::NamedConst { def_id, args, user_ty }
1245            }
1246
1247            Res::Def(DefKind::Ctor(_, CtorKind::Const), def_id) => {
1248                let user_provided_types = self.typeck_results.user_provided_types();
1249                let user_ty = user_provided_types.get(expr.hir_id).copied().map(Box::new);
1250                {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_mir_build/src/thir/cx/expr.rs:1250",
                        "rustc_mir_build::thir::cx::expr", ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_mir_build/src/thir/cx/expr.rs"),
                        ::tracing_core::__macro_support::Option::Some(1250u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_mir_build::thir::cx::expr"),
                        ::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!("convert_path_expr: user_ty={0:?}",
                                                    user_ty) as &dyn Value))])
            });
    } else { ; }
};debug!("convert_path_expr: user_ty={:?}", user_ty);
1251                let ty = self.typeck_results.node_type(expr.hir_id);
1252                match ty.kind() {
1253                    // A unit struct/variant which is used as a value.
1254                    // We return a completely different ExprKind here to account for this special case.
1255                    ty::Adt(adt_def, args) => ExprKind::Adt(Box::new(AdtExpr {
1256                        adt_def: *adt_def,
1257                        variant_index: adt_def.variant_index_with_ctor_id(def_id),
1258                        args,
1259                        user_ty,
1260                        fields: Box::new([]),
1261                        base: AdtExprBase::None,
1262                    })),
1263                    _ => ::rustc_middle::util::bug::bug_fmt(format_args!("unexpected ty: {0:?}", ty))bug!("unexpected ty: {:?}", ty),
1264                }
1265            }
1266
1267            // A source Rust `path::to::STATIC` is a place expr like *&ident is.
1268            // In THIR, we make them exactly equivalent by inserting the implied *& or *&raw,
1269            // but distinguish between &STATIC and &THREAD_LOCAL as they have different semantics
1270            Res::Def(DefKind::Static { .. }, id) => {
1271                // this is &raw for extern static or static mut, and & for other statics
1272                let ty = self.tcx.static_ptr_ty(id, self.typing_env);
1273                let kind = if self.tcx.is_thread_local_static(id) {
1274                    ExprKind::ThreadLocalRef(id)
1275                } else {
1276                    let alloc_id = self.tcx.reserve_and_set_static_alloc(id);
1277                    ExprKind::StaticRef { alloc_id, ty, def_id: id }
1278                };
1279                ExprKind::Deref {
1280                    arg: self.thir.exprs.push(Expr {
1281                        ty,
1282                        temp_scope_id: expr.hir_id.local_id,
1283                        span: expr.span,
1284                        kind,
1285                    }),
1286                }
1287            }
1288
1289            Res::Local(var_hir_id) => self.convert_var(var_hir_id),
1290
1291            _ => ::rustc_middle::util::bug::span_bug_fmt(expr.span,
    format_args!("res `{0:?}` not yet implemented", res))span_bug!(expr.span, "res `{:?}` not yet implemented", res),
1292        }
1293    }
1294
1295    fn convert_var(&mut self, var_hir_id: hir::HirId) -> ExprKind<'tcx> {
1296        // We want upvars here not captures.
1297        // Captures will be handled in MIR.
1298        let is_upvar = self.is_upvar(var_hir_id);
1299
1300        {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_mir_build/src/thir/cx/expr.rs:1300",
                        "rustc_mir_build::thir::cx::expr", ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_mir_build/src/thir/cx/expr.rs"),
                        ::tracing_core::__macro_support::Option::Some(1300u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_mir_build::thir::cx::expr"),
                        ::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!("convert_var({0:?}): is_upvar={1}, body_owner={2:?}",
                                                    var_hir_id, is_upvar, self.body_owner) as &dyn Value))])
            });
    } else { ; }
};debug!(
1301            "convert_var({:?}): is_upvar={}, body_owner={:?}",
1302            var_hir_id, is_upvar, self.body_owner
1303        );
1304
1305        if is_upvar {
1306            ExprKind::UpvarRef {
1307                closure_def_id: self.body_owner,
1308                var_hir_id: LocalVarId(var_hir_id),
1309            }
1310        } else {
1311            ExprKind::VarRef { id: LocalVarId(var_hir_id) }
1312        }
1313    }
1314
1315    fn overloaded_operator(
1316        &mut self,
1317        expr: &'tcx hir::Expr<'tcx>,
1318        args: Box<[ExprId]>,
1319    ) -> ExprKind<'tcx> {
1320        let fun = self.method_callee(expr, expr.span, None);
1321        let fun = self.thir.exprs.push(fun);
1322        ExprKind::Call {
1323            ty: self.thir[fun].ty,
1324            fun,
1325            args,
1326            from_hir_call: false,
1327            fn_span: expr.span,
1328        }
1329    }
1330
1331    fn overloaded_place(
1332        &mut self,
1333        expr: &'tcx hir::Expr<'tcx>,
1334        place_ty: Ty<'tcx>,
1335        overloaded_callee: Option<Ty<'tcx>>,
1336        args: Box<[ExprId]>,
1337        span: Span,
1338    ) -> ExprKind<'tcx> {
1339        // For an overloaded *x or x[y] expression of type T, the method
1340        // call returns an &T and we must add the deref so that the types
1341        // line up (this is because `*x` and `x[y]` represent places):
1342
1343        // Reconstruct the output assuming it's a reference with the
1344        // same region and mutability as the receiver. This holds for
1345        // `Deref(Mut)::deref(_mut)` and `Index(Mut)::index(_mut)`.
1346        let ty::Ref(region, _, mutbl) = *self.thir[args[0]].ty.kind() else {
1347            ::rustc_middle::util::bug::span_bug_fmt(span,
    format_args!("overloaded_place: receiver is not a reference"));span_bug!(span, "overloaded_place: receiver is not a reference");
1348        };
1349        let ref_ty = Ty::new_ref(self.tcx, region, place_ty, mutbl);
1350
1351        // construct the complete expression `foo()` for the overloaded call,
1352        // which will yield the &T type
1353        let fun = self.method_callee(expr, span, overloaded_callee);
1354        let fun = self.thir.exprs.push(fun);
1355        let fun_ty = self.thir[fun].ty;
1356        let ref_expr = self.thir.exprs.push(Expr {
1357            temp_scope_id: expr.hir_id.local_id,
1358            ty: ref_ty,
1359            span,
1360            kind: ExprKind::Call { ty: fun_ty, fun, args, from_hir_call: false, fn_span: span },
1361        });
1362
1363        // construct and return a deref wrapper `*foo()`
1364        ExprKind::Deref { arg: ref_expr }
1365    }
1366
1367    fn convert_captured_hir_place(
1368        &mut self,
1369        closure_expr: &'tcx hir::Expr<'tcx>,
1370        place: HirPlace<'tcx>,
1371    ) -> Expr<'tcx> {
1372        let temp_scope_id = closure_expr.hir_id.local_id;
1373        let var_ty = place.base_ty;
1374
1375        // The result of capture analysis in `rustc_hir_typeck/src/upvar.rs` represents a captured path
1376        // as it's seen for use within the closure and not at the time of closure creation.
1377        //
1378        // That is we see expect to see it start from a captured upvar and not something that is local
1379        // to the closure's parent.
1380        let var_hir_id = match place.base {
1381            HirPlaceBase::Upvar(upvar_id) => upvar_id.var_path.hir_id,
1382            base => ::rustc_middle::util::bug::bug_fmt(format_args!("Expected an upvar, found {0:?}",
        base))bug!("Expected an upvar, found {:?}", base),
1383        };
1384
1385        let mut captured_place_expr = Expr {
1386            temp_scope_id,
1387            ty: var_ty,
1388            span: closure_expr.span,
1389            kind: self.convert_var(var_hir_id),
1390        };
1391
1392        for proj in place.projections.iter() {
1393            let kind = match proj.kind {
1394                HirProjectionKind::Deref => {
1395                    ExprKind::Deref { arg: self.thir.exprs.push(captured_place_expr) }
1396                }
1397                HirProjectionKind::Field(field, variant_index) => ExprKind::Field {
1398                    lhs: self.thir.exprs.push(captured_place_expr),
1399                    variant_index,
1400                    name: field,
1401                },
1402                HirProjectionKind::OpaqueCast => {
1403                    ExprKind::Use { source: self.thir.exprs.push(captured_place_expr) }
1404                }
1405                HirProjectionKind::UnwrapUnsafeBinder => ExprKind::PlaceUnwrapUnsafeBinder {
1406                    source: self.thir.exprs.push(captured_place_expr),
1407                },
1408                HirProjectionKind::Index | HirProjectionKind::Subslice => {
1409                    // We don't capture these projections, so we can ignore them here
1410                    continue;
1411                }
1412            };
1413
1414            captured_place_expr =
1415                Expr { temp_scope_id, ty: proj.ty, span: closure_expr.span, kind };
1416        }
1417
1418        captured_place_expr
1419    }
1420
1421    fn capture_upvar(
1422        &mut self,
1423        closure_expr: &'tcx hir::Expr<'tcx>,
1424        captured_place: &'tcx ty::CapturedPlace<'tcx>,
1425        upvar_ty: Ty<'tcx>,
1426    ) -> Expr<'tcx> {
1427        let upvar_capture = captured_place.info.capture_kind;
1428        let captured_place_expr =
1429            self.convert_captured_hir_place(closure_expr, captured_place.place.clone());
1430        let temp_scope_id = closure_expr.hir_id.local_id;
1431
1432        match upvar_capture {
1433            ty::UpvarCapture::ByValue => captured_place_expr,
1434            ty::UpvarCapture::ByUse => {
1435                let span = captured_place_expr.span;
1436                let expr_id = self.thir.exprs.push(captured_place_expr);
1437
1438                Expr {
1439                    temp_scope_id,
1440                    ty: upvar_ty,
1441                    span: closure_expr.span,
1442                    kind: ExprKind::ByUse { expr: expr_id, span },
1443                }
1444            }
1445            ty::UpvarCapture::ByRef(upvar_borrow) => {
1446                let borrow_kind = match upvar_borrow {
1447                    ty::BorrowKind::Immutable => BorrowKind::Shared,
1448                    ty::BorrowKind::UniqueImmutable => {
1449                        BorrowKind::Mut { kind: mir::MutBorrowKind::ClosureCapture }
1450                    }
1451                    ty::BorrowKind::Mutable => {
1452                        BorrowKind::Mut { kind: mir::MutBorrowKind::Default }
1453                    }
1454                };
1455                Expr {
1456                    temp_scope_id,
1457                    ty: upvar_ty,
1458                    span: closure_expr.span,
1459                    kind: ExprKind::Borrow {
1460                        borrow_kind,
1461                        arg: self.thir.exprs.push(captured_place_expr),
1462                    },
1463                }
1464            }
1465        }
1466    }
1467
1468    fn is_upvar(&mut self, var_hir_id: hir::HirId) -> bool {
1469        self.tcx
1470            .upvars_mentioned(self.body_owner)
1471            .is_some_and(|upvars| upvars.contains_key(&var_hir_id))
1472    }
1473
1474    /// Converts a list of named fields (i.e., for struct-like struct/enum ADTs) into FieldExpr.
1475    fn field_refs(&mut self, fields: &'tcx [hir::ExprField<'tcx>]) -> Box<[FieldExpr]> {
1476        fields
1477            .iter()
1478            .map(|field| FieldExpr {
1479                name: self.typeck_results.field_index(field.hir_id),
1480                expr: self.mirror_expr(field.expr),
1481            })
1482            .collect()
1483    }
1484}
1485
1486trait ToBorrowKind {
1487    fn to_borrow_kind(&self) -> BorrowKind;
1488}
1489
1490impl ToBorrowKind for AutoBorrowMutability {
1491    fn to_borrow_kind(&self) -> BorrowKind {
1492        use rustc_middle::ty::adjustment::AllowTwoPhase;
1493        match *self {
1494            AutoBorrowMutability::Mut { allow_two_phase_borrow } => BorrowKind::Mut {
1495                kind: match allow_two_phase_borrow {
1496                    AllowTwoPhase::Yes => mir::MutBorrowKind::TwoPhaseBorrow,
1497                    AllowTwoPhase::No => mir::MutBorrowKind::Default,
1498                },
1499            },
1500            AutoBorrowMutability::Not => BorrowKind::Shared,
1501        }
1502    }
1503}
1504
1505impl ToBorrowKind for hir::Mutability {
1506    fn to_borrow_kind(&self) -> BorrowKind {
1507        match *self {
1508            hir::Mutability::Mut => BorrowKind::Mut { kind: mir::MutBorrowKind::Default },
1509            hir::Mutability::Not => BorrowKind::Shared,
1510        }
1511    }
1512}
1513
1514fn bin_op(op: hir::BinOpKind) -> BinOp {
1515    match op {
1516        hir::BinOpKind::Add => BinOp::Add,
1517        hir::BinOpKind::Sub => BinOp::Sub,
1518        hir::BinOpKind::Mul => BinOp::Mul,
1519        hir::BinOpKind::Div => BinOp::Div,
1520        hir::BinOpKind::Rem => BinOp::Rem,
1521        hir::BinOpKind::BitXor => BinOp::BitXor,
1522        hir::BinOpKind::BitAnd => BinOp::BitAnd,
1523        hir::BinOpKind::BitOr => BinOp::BitOr,
1524        hir::BinOpKind::Shl => BinOp::Shl,
1525        hir::BinOpKind::Shr => BinOp::Shr,
1526        hir::BinOpKind::Eq => BinOp::Eq,
1527        hir::BinOpKind::Lt => BinOp::Lt,
1528        hir::BinOpKind::Le => BinOp::Le,
1529        hir::BinOpKind::Ne => BinOp::Ne,
1530        hir::BinOpKind::Ge => BinOp::Ge,
1531        hir::BinOpKind::Gt => BinOp::Gt,
1532        _ => ::rustc_middle::util::bug::bug_fmt(format_args!("no equivalent for ast binop {0:?}",
        op))bug!("no equivalent for ast binop {:?}", op),
1533    }
1534}
1535
1536fn assign_op(op: hir::AssignOpKind) -> AssignOp {
1537    match op {
1538        hir::AssignOpKind::AddAssign => AssignOp::AddAssign,
1539        hir::AssignOpKind::SubAssign => AssignOp::SubAssign,
1540        hir::AssignOpKind::MulAssign => AssignOp::MulAssign,
1541        hir::AssignOpKind::DivAssign => AssignOp::DivAssign,
1542        hir::AssignOpKind::RemAssign => AssignOp::RemAssign,
1543        hir::AssignOpKind::BitXorAssign => AssignOp::BitXorAssign,
1544        hir::AssignOpKind::BitAndAssign => AssignOp::BitAndAssign,
1545        hir::AssignOpKind::BitOrAssign => AssignOp::BitOrAssign,
1546        hir::AssignOpKind::ShlAssign => AssignOp::ShlAssign,
1547        hir::AssignOpKind::ShrAssign => AssignOp::ShrAssign,
1548    }
1549}