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