Skip to main content

rustc_mir_build/thir/cx/
expr.rs

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