rustc_mir_build/builder/
mod.rs

1//! This module used to be named `build`, but that was causing GitHub's
2//! "Go to file" feature to silently ignore all files in the module, probably
3//! because it assumes that "build" is a build-output directory.
4//! See <https://github.com/rust-lang/rust/pull/134365>.
5//!
6//! ## The `let this = self;` idiom (LET_THIS_SELF)
7//!
8//! Throughout MIR building there are several places where a `Builder` method
9//! needs to borrow `self`, and then re-expose it to a closure as `|this|`.
10//!
11//! In complex builder methods, potentially with multiple levels of nesting, it
12//! would thus become necessary to mentally keep track of whether the builder
13//! is `self` (at the top level) or `this` (nested in a closure), or to replace
14//! one with the other when moving code in or out of a closure.
15//!
16//! (The borrow checker will prevent incorrect usage, but having to go back and
17//! satisfy the borrow checker still creates contributor friction.)
18//!
19//! To reduce that friction, some builder methods therefore start with
20//! `let this = self;` or similar, allowing subsequent code to uniformly refer
21//! to the builder as `this` (and never `self`), even when not nested.
22
23use itertools::Itertools;
24use rustc_abi::{ExternAbi, FieldIdx};
25use rustc_apfloat::Float;
26use rustc_apfloat::ieee::{Double, Half, Quad, Single};
27use rustc_ast::attr;
28use rustc_data_structures::fx::FxHashMap;
29use rustc_data_structures::sorted_map::SortedIndexMultiMap;
30use rustc_errors::ErrorGuaranteed;
31use rustc_hir::attrs::AttributeKind;
32use rustc_hir::def::DefKind;
33use rustc_hir::def_id::{DefId, LocalDefId};
34use rustc_hir::{self as hir, BindingMode, ByRef, HirId, ItemLocalId, Node, find_attr};
35use rustc_index::bit_set::GrowableBitSet;
36use rustc_index::{Idx, IndexSlice, IndexVec};
37use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
38use rustc_middle::hir::place::PlaceBase as HirPlaceBase;
39use rustc_middle::middle::region;
40use rustc_middle::mir::*;
41use rustc_middle::thir::{self, ExprId, LintLevel, LocalVarId, Param, ParamId, PatKind, Thir};
42use rustc_middle::ty::{self, ScalarInt, Ty, TyCtxt, TypeVisitableExt, TypingMode};
43use rustc_middle::{bug, span_bug};
44use rustc_session::lint;
45use rustc_span::{Span, Symbol, sym};
46
47use crate::builder::expr::as_place::PlaceBuilder;
48use crate::builder::scope::DropKind;
49use crate::errors;
50
51pub(crate) fn closure_saved_names_of_captured_variables<'tcx>(
52    tcx: TyCtxt<'tcx>,
53    def_id: LocalDefId,
54) -> IndexVec<FieldIdx, Symbol> {
55    tcx.closure_captures(def_id)
56        .iter()
57        .map(|captured_place| {
58            let name = captured_place.to_symbol();
59            match captured_place.info.capture_kind {
60                ty::UpvarCapture::ByValue | ty::UpvarCapture::ByUse => name,
61                ty::UpvarCapture::ByRef(..) => Symbol::intern(&format!("_ref__{name}")),
62            }
63        })
64        .collect()
65}
66
67/// Create the MIR for a given `DefId`, including unreachable code.
68///
69/// This is the implementation of hook `build_mir_inner_impl`, which should only
70/// be called by the query `mir_built`.
71pub(crate) fn build_mir_inner_impl<'tcx>(tcx: TyCtxt<'tcx>, def: LocalDefId) -> Body<'tcx> {
72    tcx.ensure_done().thir_abstract_const(def);
73    if let Err(e) = tcx.ensure_ok().check_match(def) {
74        return construct_error(tcx, def, e);
75    }
76
77    if let Err(err) = tcx.ensure_ok().check_tail_calls(def) {
78        return construct_error(tcx, def, err);
79    }
80
81    let body = match tcx.thir_body(def) {
82        Err(error_reported) => construct_error(tcx, def, error_reported),
83        Ok((thir, expr)) => {
84            let build_mir = |thir: &Thir<'tcx>| match thir.body_type {
85                thir::BodyTy::Fn(fn_sig) => construct_fn(tcx, def, thir, expr, fn_sig),
86                thir::BodyTy::Const(ty) | thir::BodyTy::GlobalAsm(ty) => {
87                    construct_const(tcx, def, thir, expr, ty)
88                }
89            };
90
91            // Don't steal here, instead steal in unsafeck. This is so that
92            // pattern inline constants can be evaluated as part of building the
93            // THIR of the parent function without a cycle.
94            build_mir(&thir.borrow())
95        }
96    };
97
98    // The borrow checker will replace all the regions here with its own
99    // inference variables. There's no point having non-erased regions here.
100    // The exception is `body.user_type_annotations`, which is used unmodified
101    // by borrow checking.
102    debug_assert!(
103        !(body.local_decls.has_free_regions()
104            || body.basic_blocks.has_free_regions()
105            || body.var_debug_info.has_free_regions()
106            || body.yield_ty().has_free_regions()),
107        "Unexpected free regions in MIR: {body:?}",
108    );
109
110    body
111}
112
113///////////////////////////////////////////////////////////////////////////
114// BuildMir -- walks a crate, looking for fn items and methods to build MIR from
115
116#[derive(Debug, PartialEq, Eq)]
117enum BlockFrame {
118    /// Evaluation is currently within a statement.
119    ///
120    /// Examples include:
121    /// 1. `EXPR;`
122    /// 2. `let _ = EXPR;`
123    /// 3. `let x = EXPR;`
124    Statement {
125        /// If true, then statement discards result from evaluating
126        /// the expression (such as examples 1 and 2 above).
127        ignores_expr_result: bool,
128    },
129
130    /// Evaluation is currently within the tail expression of a block.
131    ///
132    /// Example: `{ STMT_1; STMT_2; EXPR }`
133    TailExpr { info: BlockTailInfo },
134
135    /// Generic mark meaning that the block occurred as a subexpression
136    /// where the result might be used.
137    ///
138    /// Examples: `foo(EXPR)`, `match EXPR { ... }`
139    SubExpr,
140}
141
142impl BlockFrame {
143    fn is_tail_expr(&self) -> bool {
144        match *self {
145            BlockFrame::TailExpr { .. } => true,
146
147            BlockFrame::Statement { .. } | BlockFrame::SubExpr => false,
148        }
149    }
150    fn is_statement(&self) -> bool {
151        match *self {
152            BlockFrame::Statement { .. } => true,
153
154            BlockFrame::TailExpr { .. } | BlockFrame::SubExpr => false,
155        }
156    }
157}
158
159#[derive(Debug)]
160struct BlockContext(Vec<BlockFrame>);
161
162struct Builder<'a, 'tcx> {
163    tcx: TyCtxt<'tcx>,
164    // FIXME(@lcnr): Why does this use an `infcx`, there should be
165    // no shared type inference going on here. I feel like it would
166    // clearer to manually construct one where necessary or to provide
167    // a nice API for non-type inference trait system checks.
168    infcx: InferCtxt<'tcx>,
169    region_scope_tree: &'tcx region::ScopeTree,
170    param_env: ty::ParamEnv<'tcx>,
171
172    thir: &'a Thir<'tcx>,
173    cfg: CFG<'tcx>,
174
175    def_id: LocalDefId,
176    hir_id: HirId,
177    parent_module: DefId,
178    check_overflow: bool,
179    fn_span: Span,
180    arg_count: usize,
181    coroutine: Option<Box<CoroutineInfo<'tcx>>>,
182
183    /// The current set of scopes, updated as we traverse;
184    /// see the `scope` module for more details.
185    scopes: scope::Scopes<'tcx>,
186
187    /// The block-context: each time we build the code within an thir::Block,
188    /// we push a frame here tracking whether we are building a statement or
189    /// if we are pushing the tail expression of the block. This is used to
190    /// embed information in generated temps about whether they were created
191    /// for a block tail expression or not.
192    ///
193    /// It would be great if we could fold this into `self.scopes`
194    /// somehow, but right now I think that is very tightly tied to
195    /// the code generation in ways that we cannot (or should not)
196    /// start just throwing new entries onto that vector in order to
197    /// distinguish the context of EXPR1 from the context of EXPR2 in
198    /// `{ STMTS; EXPR1 } + EXPR2`.
199    block_context: BlockContext,
200
201    /// The vector of all scopes that we have created thus far;
202    /// we track this for debuginfo later.
203    source_scopes: IndexVec<SourceScope, SourceScopeData<'tcx>>,
204    source_scope: SourceScope,
205
206    /// The guard-context: each time we build the guard expression for
207    /// a match arm, we push onto this stack, and then pop when we
208    /// finish building it.
209    guard_context: Vec<GuardFrame>,
210
211    /// Temporaries with fixed indexes. Used so that if-let guards on arms
212    /// with an or-pattern are only created once.
213    fixed_temps: FxHashMap<ExprId, Local>,
214    /// Scope of temporaries that should be deduplicated using [Self::fixed_temps].
215    fixed_temps_scope: Option<region::Scope>,
216
217    /// Maps `HirId`s of variable bindings to the `Local`s created for them.
218    /// (A match binding can have two locals; the 2nd is for the arm's guard.)
219    var_indices: FxHashMap<LocalVarId, LocalsForNode>,
220    local_decls: IndexVec<Local, LocalDecl<'tcx>>,
221    canonical_user_type_annotations: ty::CanonicalUserTypeAnnotations<'tcx>,
222    upvars: CaptureMap<'tcx>,
223    unit_temp: Option<Place<'tcx>>,
224
225    var_debug_info: Vec<VarDebugInfo<'tcx>>,
226
227    // A cache for `maybe_lint_level_roots_bounded`. That function is called
228    // repeatedly, and each time it effectively traces a path through a tree
229    // structure from a node towards the root, doing an attribute check on each
230    // node along the way. This cache records which nodes trace all the way to
231    // the root (most of them do) and saves us from retracing many sub-paths
232    // many times, and rechecking many nodes.
233    lint_level_roots_cache: GrowableBitSet<hir::ItemLocalId>,
234
235    /// Collects additional coverage information during MIR building.
236    /// Only present if coverage is enabled and this function is eligible.
237    coverage_info: Option<coverageinfo::CoverageInfoBuilder>,
238}
239
240type CaptureMap<'tcx> = SortedIndexMultiMap<usize, ItemLocalId, Capture<'tcx>>;
241
242#[derive(Debug)]
243struct Capture<'tcx> {
244    captured_place: &'tcx ty::CapturedPlace<'tcx>,
245    use_place: Place<'tcx>,
246    mutability: Mutability,
247}
248
249impl<'a, 'tcx> Builder<'a, 'tcx> {
250    fn typing_env(&self) -> ty::TypingEnv<'tcx> {
251        self.infcx.typing_env(self.param_env)
252    }
253
254    fn is_bound_var_in_guard(&self, id: LocalVarId) -> bool {
255        self.guard_context.iter().any(|frame| frame.locals.iter().any(|local| local.id == id))
256    }
257
258    fn var_local_id(&self, id: LocalVarId, for_guard: ForGuard) -> Local {
259        self.var_indices[&id].local_id(for_guard)
260    }
261}
262
263impl BlockContext {
264    fn new() -> Self {
265        BlockContext(vec![])
266    }
267    fn push(&mut self, bf: BlockFrame) {
268        self.0.push(bf);
269    }
270    fn pop(&mut self) -> Option<BlockFrame> {
271        self.0.pop()
272    }
273
274    /// Traverses the frames on the `BlockContext`, searching for either
275    /// the first block-tail expression frame with no intervening
276    /// statement frame.
277    ///
278    /// Notably, this skips over `SubExpr` frames; this method is
279    /// meant to be used in the context of understanding the
280    /// relationship of a temp (created within some complicated
281    /// expression) with its containing expression, and whether the
282    /// value of that *containing expression* (not the temp!) is
283    /// ignored.
284    fn currently_in_block_tail(&self) -> Option<BlockTailInfo> {
285        for bf in self.0.iter().rev() {
286            match bf {
287                BlockFrame::SubExpr => continue,
288                BlockFrame::Statement { .. } => break,
289                &BlockFrame::TailExpr { info } => return Some(info),
290            }
291        }
292
293        None
294    }
295
296    /// Looks at the topmost frame on the BlockContext and reports
297    /// whether its one that would discard a block tail result.
298    ///
299    /// Unlike `currently_within_ignored_tail_expression`, this does
300    /// *not* skip over `SubExpr` frames: here, we want to know
301    /// whether the block result itself is discarded.
302    fn currently_ignores_tail_results(&self) -> bool {
303        match self.0.last() {
304            // no context: conservatively assume result is read
305            None => false,
306
307            // sub-expression: block result feeds into some computation
308            Some(BlockFrame::SubExpr) => false,
309
310            // otherwise: use accumulated is_ignored state.
311            Some(
312                BlockFrame::TailExpr { info: BlockTailInfo { tail_result_is_ignored: ign, .. } }
313                | BlockFrame::Statement { ignores_expr_result: ign },
314            ) => *ign,
315        }
316    }
317}
318
319#[derive(Debug)]
320enum LocalsForNode {
321    /// In the usual case, a `HirId` for an identifier maps to at most
322    /// one `Local` declaration.
323    One(Local),
324
325    /// The exceptional case is identifiers in a match arm's pattern
326    /// that are referenced in a guard of that match arm. For these,
327    /// we have `2` Locals.
328    ///
329    /// * `for_arm_body` is the Local used in the arm body (which is
330    ///   just like the `One` case above),
331    ///
332    /// * `ref_for_guard` is the Local used in the arm's guard (which
333    ///   is a reference to a temp that is an alias of
334    ///   `for_arm_body`).
335    ForGuard { ref_for_guard: Local, for_arm_body: Local },
336}
337
338#[derive(Debug)]
339struct GuardFrameLocal {
340    id: LocalVarId,
341}
342
343impl GuardFrameLocal {
344    fn new(id: LocalVarId) -> Self {
345        GuardFrameLocal { id }
346    }
347}
348
349#[derive(Debug)]
350struct GuardFrame {
351    /// These are the id's of names that are bound by patterns of the
352    /// arm of *this* guard.
353    ///
354    /// (Frames higher up the stack will have the id's bound in arms
355    /// further out, such as in a case like:
356    ///
357    /// match E1 {
358    ///      P1(id1) if (... (match E2 { P2(id2) if ... => B2 })) => B1,
359    /// }
360    ///
361    /// here, when building for FIXME.
362    locals: Vec<GuardFrameLocal>,
363}
364
365/// `ForGuard` indicates whether we are talking about:
366///   1. The variable for use outside of guard expressions, or
367///   2. The temp that holds reference to (1.), which is actually what the
368///      guard expressions see.
369#[derive(Copy, Clone, Debug, PartialEq, Eq)]
370enum ForGuard {
371    RefWithinGuard,
372    OutsideGuard,
373}
374
375impl LocalsForNode {
376    fn local_id(&self, for_guard: ForGuard) -> Local {
377        match (self, for_guard) {
378            (&LocalsForNode::One(local_id), ForGuard::OutsideGuard)
379            | (
380                &LocalsForNode::ForGuard { ref_for_guard: local_id, .. },
381                ForGuard::RefWithinGuard,
382            )
383            | (&LocalsForNode::ForGuard { for_arm_body: local_id, .. }, ForGuard::OutsideGuard) => {
384                local_id
385            }
386
387            (&LocalsForNode::One(_), ForGuard::RefWithinGuard) => {
388                bug!("anything with one local should never be within a guard.")
389            }
390        }
391    }
392}
393
394struct CFG<'tcx> {
395    basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>,
396}
397
398rustc_index::newtype_index! {
399    struct ScopeId {}
400}
401
402#[derive(Debug)]
403enum NeedsTemporary {
404    /// Use this variant when whatever you are converting with `as_operand`
405    /// is the last thing you are converting. This means that if we introduced
406    /// an intermediate temporary, we'd only read it immediately after, so we can
407    /// also avoid it.
408    No,
409    /// For all cases where you aren't sure or that are too expensive to compute
410    /// for now. It is always safe to fall back to this.
411    Maybe,
412}
413
414/// The `BlockAnd` "monad" packages up the new basic block along with a
415/// produced value (sometimes just unit, of course). The `unpack!`
416/// macro (and methods below) makes working with `BlockAnd` much more
417/// convenient.
418#[must_use = "if you don't use one of these results, you're leaving a dangling edge"]
419struct BlockAnd<T>(BasicBlock, T);
420
421impl BlockAnd<()> {
422    /// Unpacks `BlockAnd<()>` into a [`BasicBlock`].
423    #[must_use]
424    fn into_block(self) -> BasicBlock {
425        let Self(block, ()) = self;
426        block
427    }
428}
429
430trait BlockAndExtension {
431    fn and<T>(self, v: T) -> BlockAnd<T>;
432    fn unit(self) -> BlockAnd<()>;
433}
434
435impl BlockAndExtension for BasicBlock {
436    fn and<T>(self, v: T) -> BlockAnd<T> {
437        BlockAnd(self, v)
438    }
439
440    fn unit(self) -> BlockAnd<()> {
441        BlockAnd(self, ())
442    }
443}
444
445/// Update a block pointer and return the value.
446/// Use it like `let x = unpack!(block = self.foo(block, foo))`.
447macro_rules! unpack {
448    ($x:ident = $c:expr) => {{
449        let BlockAnd(b, v) = $c;
450        $x = b;
451        v
452    }};
453}
454
455/// The main entry point for building MIR for a function.
456fn construct_fn<'tcx>(
457    tcx: TyCtxt<'tcx>,
458    fn_def: LocalDefId,
459    thir: &Thir<'tcx>,
460    expr: ExprId,
461    fn_sig: ty::FnSig<'tcx>,
462) -> Body<'tcx> {
463    let span = tcx.def_span(fn_def);
464    let fn_id = tcx.local_def_id_to_hir_id(fn_def);
465
466    // Figure out what primary body this item has.
467    let body = tcx.hir_body_owned_by(fn_def);
468    let span_with_body = tcx.hir_span_with_body(fn_id);
469    let return_ty_span = tcx
470        .hir_fn_decl_by_hir_id(fn_id)
471        .unwrap_or_else(|| span_bug!(span, "can't build MIR for {:?}", fn_def))
472        .output
473        .span();
474
475    let mut abi = fn_sig.abi;
476    if let DefKind::Closure = tcx.def_kind(fn_def) {
477        // HACK(eddyb) Avoid having RustCall on closures,
478        // as it adds unnecessary (and wrong) auto-tupling.
479        abi = ExternAbi::Rust;
480    }
481
482    let arguments = &thir.params;
483
484    let return_ty = fn_sig.output();
485    let coroutine = match tcx.type_of(fn_def).instantiate_identity().kind() {
486        ty::Coroutine(_, args) => Some(Box::new(CoroutineInfo::initial(
487            tcx.coroutine_kind(fn_def).unwrap(),
488            args.as_coroutine().yield_ty(),
489            args.as_coroutine().resume_ty(),
490        ))),
491        ty::Closure(..) | ty::CoroutineClosure(..) | ty::FnDef(..) => None,
492        ty => span_bug!(span_with_body, "unexpected type of body: {ty:?}"),
493    };
494
495    if let Some((dialect, phase)) = find_attr!(tcx.hir_attrs(fn_id), AttributeKind::CustomMir(dialect, phase, _) => (dialect, phase))
496    {
497        return custom::build_custom_mir(
498            tcx,
499            fn_def.to_def_id(),
500            fn_id,
501            thir,
502            expr,
503            arguments,
504            return_ty,
505            return_ty_span,
506            span_with_body,
507            dialect.as_ref().map(|(d, _)| *d),
508            phase.as_ref().map(|(p, _)| *p),
509        );
510    }
511
512    // FIXME(#132279): This should be able to reveal opaque
513    // types defined during HIR typeck.
514    let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
515    let mut builder = Builder::new(
516        thir,
517        infcx,
518        fn_def,
519        fn_id,
520        span_with_body,
521        arguments.len(),
522        return_ty,
523        return_ty_span,
524        coroutine,
525    );
526
527    let call_site_scope =
528        region::Scope { local_id: body.id().hir_id.local_id, data: region::ScopeData::CallSite };
529    let arg_scope =
530        region::Scope { local_id: body.id().hir_id.local_id, data: region::ScopeData::Arguments };
531    let source_info = builder.source_info(span);
532    let call_site_s = (call_site_scope, source_info);
533    let _: BlockAnd<()> = builder.in_scope(call_site_s, LintLevel::Inherited, |builder| {
534        let arg_scope_s = (arg_scope, source_info);
535        // Attribute epilogue to function's closing brace
536        let fn_end = span_with_body.shrink_to_hi();
537        let return_block = builder
538            .in_breakable_scope(None, Place::return_place(), fn_end, |builder| {
539                Some(builder.in_scope(arg_scope_s, LintLevel::Inherited, |builder| {
540                    builder.args_and_body(START_BLOCK, arguments, arg_scope, expr)
541                }))
542            })
543            .into_block();
544        let source_info = builder.source_info(fn_end);
545        builder.cfg.terminate(return_block, source_info, TerminatorKind::Return);
546        builder.build_drop_trees();
547        return_block.unit()
548    });
549
550    builder.lint_and_remove_uninhabited();
551    let mut body = builder.finish();
552
553    body.spread_arg = if abi == ExternAbi::RustCall {
554        // RustCall pseudo-ABI untuples the last argument.
555        Some(Local::new(arguments.len()))
556    } else {
557        None
558    };
559
560    body
561}
562
563fn construct_const<'a, 'tcx>(
564    tcx: TyCtxt<'tcx>,
565    def: LocalDefId,
566    thir: &'a Thir<'tcx>,
567    expr: ExprId,
568    const_ty: Ty<'tcx>,
569) -> Body<'tcx> {
570    let hir_id = tcx.local_def_id_to_hir_id(def);
571
572    // Figure out what primary body this item has.
573    let (span, const_ty_span) = match tcx.hir_node(hir_id) {
574        Node::Item(hir::Item {
575            kind: hir::ItemKind::Static(_, _, ty, _) | hir::ItemKind::Const(_, _, ty, _),
576            span,
577            ..
578        })
579        | Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Const(ty, _), span, .. })
580        | Node::TraitItem(hir::TraitItem {
581            kind: hir::TraitItemKind::Const(ty, Some(_)),
582            span,
583            ..
584        }) => (*span, ty.span),
585        Node::AnonConst(ct) => (ct.span, ct.span),
586        Node::ConstBlock(_) => {
587            let span = tcx.def_span(def);
588            (span, span)
589        }
590        Node::Item(hir::Item { kind: hir::ItemKind::GlobalAsm { .. }, span, .. }) => (*span, *span),
591        _ => span_bug!(tcx.def_span(def), "can't build MIR for {:?}", def),
592    };
593
594    // FIXME(#132279): We likely want to be able to use the hidden types of
595    // opaques used by this function here.
596    let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
597    let mut builder =
598        Builder::new(thir, infcx, def, hir_id, span, 0, const_ty, const_ty_span, None);
599
600    let mut block = START_BLOCK;
601    block = builder.expr_into_dest(Place::return_place(), block, expr).into_block();
602
603    let source_info = builder.source_info(span);
604    builder.cfg.terminate(block, source_info, TerminatorKind::Return);
605
606    builder.build_drop_trees();
607
608    builder.lint_and_remove_uninhabited();
609    builder.finish()
610}
611
612/// Construct MIR for an item that has had errors in type checking.
613///
614/// This is required because we may still want to run MIR passes on an item
615/// with type errors, but normal MIR construction can't handle that in general.
616fn construct_error(tcx: TyCtxt<'_>, def_id: LocalDefId, guar: ErrorGuaranteed) -> Body<'_> {
617    let span = tcx.def_span(def_id);
618    let hir_id = tcx.local_def_id_to_hir_id(def_id);
619
620    let (inputs, output, coroutine) = match tcx.def_kind(def_id) {
621        DefKind::Const
622        | DefKind::AssocConst
623        | DefKind::AnonConst
624        | DefKind::InlineConst
625        | DefKind::Static { .. }
626        | DefKind::GlobalAsm => (vec![], tcx.type_of(def_id).instantiate_identity(), None),
627        DefKind::Ctor(..) | DefKind::Fn | DefKind::AssocFn => {
628            let sig = tcx.liberate_late_bound_regions(
629                def_id.to_def_id(),
630                tcx.fn_sig(def_id).instantiate_identity(),
631            );
632            (sig.inputs().to_vec(), sig.output(), None)
633        }
634        DefKind::Closure => {
635            let closure_ty = tcx.type_of(def_id).instantiate_identity();
636            match closure_ty.kind() {
637                ty::Closure(_, args) => {
638                    let args = args.as_closure();
639                    let sig = tcx.liberate_late_bound_regions(def_id.to_def_id(), args.sig());
640                    let self_ty = match args.kind() {
641                        ty::ClosureKind::Fn => {
642                            Ty::new_imm_ref(tcx, tcx.lifetimes.re_erased, closure_ty)
643                        }
644                        ty::ClosureKind::FnMut => {
645                            Ty::new_mut_ref(tcx, tcx.lifetimes.re_erased, closure_ty)
646                        }
647                        ty::ClosureKind::FnOnce => closure_ty,
648                    };
649                    (
650                        [self_ty].into_iter().chain(sig.inputs()[0].tuple_fields()).collect(),
651                        sig.output(),
652                        None,
653                    )
654                }
655                ty::Coroutine(_, args) => {
656                    let args = args.as_coroutine();
657                    let resume_ty = args.resume_ty();
658                    let yield_ty = args.yield_ty();
659                    let return_ty = args.return_ty();
660                    (
661                        vec![closure_ty, resume_ty],
662                        return_ty,
663                        Some(Box::new(CoroutineInfo::initial(
664                            tcx.coroutine_kind(def_id).unwrap(),
665                            yield_ty,
666                            resume_ty,
667                        ))),
668                    )
669                }
670                ty::CoroutineClosure(did, args) => {
671                    let args = args.as_coroutine_closure();
672                    let sig = tcx.liberate_late_bound_regions(
673                        def_id.to_def_id(),
674                        args.coroutine_closure_sig(),
675                    );
676                    let self_ty = match args.kind() {
677                        ty::ClosureKind::Fn => {
678                            Ty::new_imm_ref(tcx, tcx.lifetimes.re_erased, closure_ty)
679                        }
680                        ty::ClosureKind::FnMut => {
681                            Ty::new_mut_ref(tcx, tcx.lifetimes.re_erased, closure_ty)
682                        }
683                        ty::ClosureKind::FnOnce => closure_ty,
684                    };
685                    (
686                        [self_ty].into_iter().chain(sig.tupled_inputs_ty.tuple_fields()).collect(),
687                        sig.to_coroutine(
688                            tcx,
689                            args.parent_args(),
690                            args.kind_ty(),
691                            tcx.coroutine_for_closure(*did),
692                            Ty::new_error(tcx, guar),
693                        ),
694                        None,
695                    )
696                }
697                ty::Error(_) => (vec![closure_ty, closure_ty], closure_ty, None),
698                kind => {
699                    span_bug!(
700                        span,
701                        "expected type of closure body to be a closure or coroutine, got {kind:?}"
702                    );
703                }
704            }
705        }
706        dk => span_bug!(span, "{:?} is not a body: {:?}", def_id, dk),
707    };
708
709    let source_info = SourceInfo { span, scope: OUTERMOST_SOURCE_SCOPE };
710    let local_decls = IndexVec::from_iter(
711        [output].iter().chain(&inputs).map(|ty| LocalDecl::with_source_info(*ty, source_info)),
712    );
713    let mut cfg = CFG { basic_blocks: IndexVec::new() };
714    let mut source_scopes = IndexVec::new();
715
716    cfg.start_new_block();
717    source_scopes.push(SourceScopeData {
718        span,
719        parent_scope: None,
720        inlined: None,
721        inlined_parent_scope: None,
722        local_data: ClearCrossCrate::Set(SourceScopeLocalData { lint_root: hir_id }),
723    });
724
725    cfg.terminate(START_BLOCK, source_info, TerminatorKind::Unreachable);
726
727    Body::new(
728        MirSource::item(def_id.to_def_id()),
729        cfg.basic_blocks,
730        source_scopes,
731        local_decls,
732        IndexVec::new(),
733        inputs.len(),
734        vec![],
735        span,
736        coroutine,
737        Some(guar),
738    )
739}
740
741impl<'a, 'tcx> Builder<'a, 'tcx> {
742    fn new(
743        thir: &'a Thir<'tcx>,
744        infcx: InferCtxt<'tcx>,
745        def: LocalDefId,
746        hir_id: HirId,
747        span: Span,
748        arg_count: usize,
749        return_ty: Ty<'tcx>,
750        return_span: Span,
751        coroutine: Option<Box<CoroutineInfo<'tcx>>>,
752    ) -> Builder<'a, 'tcx> {
753        let tcx = infcx.tcx;
754        let attrs = tcx.hir_attrs(hir_id);
755        // Some functions always have overflow checks enabled,
756        // however, they may not get codegen'd, depending on
757        // the settings for the crate they are codegened in.
758        let mut check_overflow = attr::contains_name(attrs, sym::rustc_inherit_overflow_checks);
759        // Respect -C overflow-checks.
760        check_overflow |= tcx.sess.overflow_checks();
761        // Constants always need overflow checks.
762        check_overflow |= matches!(
763            tcx.hir_body_owner_kind(def),
764            hir::BodyOwnerKind::Const { .. } | hir::BodyOwnerKind::Static(_)
765        );
766
767        let lint_level = LintLevel::Explicit(hir_id);
768        let param_env = tcx.param_env(def);
769        let mut builder = Builder {
770            thir,
771            tcx,
772            infcx,
773            region_scope_tree: tcx.region_scope_tree(def),
774            param_env,
775            def_id: def,
776            hir_id,
777            parent_module: tcx.parent_module(hir_id).to_def_id(),
778            check_overflow,
779            cfg: CFG { basic_blocks: IndexVec::new() },
780            fn_span: span,
781            arg_count,
782            coroutine,
783            scopes: scope::Scopes::new(),
784            block_context: BlockContext::new(),
785            source_scopes: IndexVec::new(),
786            source_scope: OUTERMOST_SOURCE_SCOPE,
787            guard_context: vec![],
788            fixed_temps: Default::default(),
789            fixed_temps_scope: None,
790            local_decls: IndexVec::from_elem_n(LocalDecl::new(return_ty, return_span), 1),
791            canonical_user_type_annotations: IndexVec::new(),
792            upvars: CaptureMap::new(),
793            var_indices: Default::default(),
794            unit_temp: None,
795            var_debug_info: vec![],
796            lint_level_roots_cache: GrowableBitSet::new_empty(),
797            coverage_info: coverageinfo::CoverageInfoBuilder::new_if_enabled(tcx, def),
798        };
799
800        assert_eq!(builder.cfg.start_new_block(), START_BLOCK);
801        assert_eq!(builder.new_source_scope(span, lint_level), OUTERMOST_SOURCE_SCOPE);
802        builder.source_scopes[OUTERMOST_SOURCE_SCOPE].parent_scope = None;
803
804        builder
805    }
806
807    #[allow(dead_code)]
808    fn dump_for_debugging(&self) {
809        let mut body = Body::new(
810            MirSource::item(self.def_id.to_def_id()),
811            self.cfg.basic_blocks.clone(),
812            self.source_scopes.clone(),
813            self.local_decls.clone(),
814            self.canonical_user_type_annotations.clone(),
815            self.arg_count.clone(),
816            self.var_debug_info.clone(),
817            self.fn_span.clone(),
818            self.coroutine.clone(),
819            None,
820        );
821        body.coverage_info_hi = self.coverage_info.as_ref().map(|b| b.as_done());
822
823        let writer = pretty::MirWriter::new(self.tcx);
824        writer.write_mir_fn(&body, &mut std::io::stdout()).unwrap();
825    }
826
827    fn lint_and_remove_uninhabited(&mut self) {
828        let mut lints = vec![];
829
830        for bbdata in self.cfg.basic_blocks.iter_mut() {
831            let term = bbdata.terminator_mut();
832            let TerminatorKind::Call { ref mut target, destination, .. } = term.kind else {
833                continue;
834            };
835            let Some(target_bb) = *target else { continue };
836
837            let ty = destination.ty(&self.local_decls, self.tcx).ty;
838            let ty_is_inhabited = ty.is_inhabited_from(
839                self.tcx,
840                self.parent_module,
841                self.infcx.typing_env(self.param_env),
842            );
843            if !ty_is_inhabited {
844                // Unreachable code warnings are already emitted during type checking.
845                // However, during type checking, full type information is being
846                // calculated but not yet available, so the check for diverging
847                // expressions due to uninhabited result types is pretty crude and
848                // only checks whether ty.is_never(). Here, we have full type
849                // information available and can issue warnings for less obviously
850                // uninhabited types (e.g. empty enums). The check above is used so
851                // that we do not emit the same warning twice if the uninhabited type
852                // is indeed `!`.
853                if !ty.is_never()
854                    && matches!(self.tcx.def_kind(self.def_id), DefKind::Fn | DefKind::AssocFn)
855                // check if the function's return type is inhabited
856                // this was added here because of this regression
857                // https://github.com/rust-lang/rust/issues/149571
858                    && self
859                        .tcx
860                        .fn_sig(self.def_id)
861                        .instantiate_identity()
862                        .skip_binder()
863                        .output()
864                        .is_inhabited_from(
865                            self.tcx,
866                            self.parent_module,
867                            self.infcx.typing_env(self.param_env),
868                        )
869                {
870                    lints.push((target_bb, ty, term.source_info.span));
871                }
872
873                // The presence or absence of a return edge affects control-flow sensitive
874                // MIR checks and ultimately whether code is accepted or not. We can only
875                // omit the return edge if a return type is visibly uninhabited to a module
876                // that makes the call.
877                *target = None;
878            }
879        }
880
881        /// Starting at a target unreachable block, find some user code to lint as unreachable
882        fn find_unreachable_code_from(
883            bb: BasicBlock,
884            bbs: &IndexVec<BasicBlock, BasicBlockData<'_>>,
885        ) -> Option<(SourceInfo, &'static str)> {
886            let bb = &bbs[bb];
887            for stmt in &bb.statements {
888                match &stmt.kind {
889                    // Ignore the implicit `()` return place assignment for unit functions/blocks
890                    StatementKind::Assign(box (_, Rvalue::Use(Operand::Constant(const_))))
891                        if const_.ty().is_unit() =>
892                    {
893                        continue;
894                    }
895                    StatementKind::StorageLive(_) | StatementKind::StorageDead(_) => {
896                        continue;
897                    }
898                    StatementKind::FakeRead(..) => return Some((stmt.source_info, "definition")),
899                    _ => return Some((stmt.source_info, "expression")),
900                }
901            }
902
903            let term = bb.terminator();
904            match term.kind {
905                // No user code in this bb, and our goto target may be reachable via other paths
906                TerminatorKind::Goto { .. } | TerminatorKind::Return => None,
907                _ => Some((term.source_info, "expression")),
908            }
909        }
910
911        for (target_bb, orig_ty, orig_span) in lints {
912            if orig_span.in_external_macro(self.tcx.sess.source_map()) {
913                continue;
914            }
915
916            let Some((target_loc, descr)) =
917                find_unreachable_code_from(target_bb, &self.cfg.basic_blocks)
918            else {
919                continue;
920            };
921            let lint_root = self.source_scopes[target_loc.scope]
922                .local_data
923                .as_ref()
924                .unwrap_crate_local()
925                .lint_root;
926            self.tcx.emit_node_span_lint(
927                lint::builtin::UNREACHABLE_CODE,
928                lint_root,
929                target_loc.span,
930                errors::UnreachableDueToUninhabited {
931                    expr: target_loc.span,
932                    orig: orig_span,
933                    descr,
934                    ty: orig_ty,
935                },
936            );
937        }
938    }
939
940    fn finish(self) -> Body<'tcx> {
941        let mut body = Body::new(
942            MirSource::item(self.def_id.to_def_id()),
943            self.cfg.basic_blocks,
944            self.source_scopes,
945            self.local_decls,
946            self.canonical_user_type_annotations,
947            self.arg_count,
948            self.var_debug_info,
949            self.fn_span,
950            self.coroutine,
951            None,
952        );
953        body.coverage_info_hi = self.coverage_info.map(|b| b.into_done());
954
955        let writer = pretty::MirWriter::new(self.tcx);
956        for (index, block) in body.basic_blocks.iter().enumerate() {
957            if block.terminator.is_none() {
958                writer.write_mir_fn(&body, &mut std::io::stdout()).unwrap();
959                span_bug!(self.fn_span, "no terminator on block {:?}", index);
960            }
961        }
962
963        body
964    }
965
966    fn insert_upvar_arg(&mut self) {
967        let Some(closure_arg) = self.local_decls.get(ty::CAPTURE_STRUCT_LOCAL) else { return };
968
969        let mut closure_ty = closure_arg.ty;
970        let mut closure_env_projs = vec![];
971        if let ty::Ref(_, ty, _) = closure_ty.kind() {
972            closure_env_projs.push(ProjectionElem::Deref);
973            closure_ty = *ty;
974        }
975
976        let upvar_args = match closure_ty.kind() {
977            ty::Closure(_, args) => ty::UpvarArgs::Closure(args),
978            ty::Coroutine(_, args) => ty::UpvarArgs::Coroutine(args),
979            ty::CoroutineClosure(_, args) => ty::UpvarArgs::CoroutineClosure(args),
980            _ => return,
981        };
982
983        // In analyze_closure() in upvar.rs we gathered a list of upvars used by an
984        // indexed closure and we stored in a map called closure_min_captures in TypeckResults
985        // with the closure's DefId. Here, we run through that vec of UpvarIds for
986        // the given closure and use the necessary information to create upvar
987        // debuginfo and to fill `self.upvars`.
988        let capture_tys = upvar_args.upvar_tys();
989
990        let tcx = self.tcx;
991        let mut upvar_owner = None;
992        self.upvars = tcx
993            .closure_captures(self.def_id)
994            .iter()
995            .zip_eq(capture_tys)
996            .enumerate()
997            .map(|(i, (captured_place, ty))| {
998                let name = captured_place.to_symbol();
999
1000                let capture = captured_place.info.capture_kind;
1001                let var_id = match captured_place.place.base {
1002                    HirPlaceBase::Upvar(upvar_id) => upvar_id.var_path.hir_id,
1003                    _ => bug!("Expected an upvar"),
1004                };
1005                let upvar_base = upvar_owner.get_or_insert(var_id.owner);
1006                assert_eq!(*upvar_base, var_id.owner);
1007                let var_id = var_id.local_id;
1008
1009                let mutability = captured_place.mutability;
1010
1011                let mut projs = closure_env_projs.clone();
1012                projs.push(ProjectionElem::Field(FieldIdx::new(i), ty));
1013                match capture {
1014                    ty::UpvarCapture::ByValue | ty::UpvarCapture::ByUse => {}
1015                    ty::UpvarCapture::ByRef(..) => {
1016                        projs.push(ProjectionElem::Deref);
1017                    }
1018                };
1019
1020                let use_place = Place {
1021                    local: ty::CAPTURE_STRUCT_LOCAL,
1022                    projection: tcx.mk_place_elems(&projs),
1023                };
1024                self.var_debug_info.push(VarDebugInfo {
1025                    name,
1026                    source_info: SourceInfo::outermost(captured_place.var_ident.span),
1027                    value: VarDebugInfoContents::Place(use_place),
1028                    composite: None,
1029                    argument_index: None,
1030                });
1031
1032                let capture = Capture { captured_place, use_place, mutability };
1033                (var_id, capture)
1034            })
1035            .collect();
1036    }
1037
1038    fn args_and_body(
1039        &mut self,
1040        mut block: BasicBlock,
1041        arguments: &IndexSlice<ParamId, Param<'tcx>>,
1042        argument_scope: region::Scope,
1043        expr_id: ExprId,
1044    ) -> BlockAnd<()> {
1045        let expr_span = self.thir[expr_id].span;
1046        // Allocate locals for the function arguments
1047        for (argument_index, param) in arguments.iter().enumerate() {
1048            let source_info =
1049                SourceInfo::outermost(param.pat.as_ref().map_or(self.fn_span, |pat| pat.span));
1050            let arg_local =
1051                self.local_decls.push(LocalDecl::with_source_info(param.ty, source_info));
1052
1053            // If this is a simple binding pattern, give debuginfo a nice name.
1054            if let Some(ref pat) = param.pat
1055                && let Some(name) = pat.simple_ident()
1056            {
1057                self.var_debug_info.push(VarDebugInfo {
1058                    name,
1059                    source_info,
1060                    value: VarDebugInfoContents::Place(arg_local.into()),
1061                    composite: None,
1062                    argument_index: Some(argument_index as u16 + 1),
1063                });
1064            }
1065        }
1066
1067        self.insert_upvar_arg();
1068
1069        let mut scope = None;
1070        // Bind the argument patterns
1071        for (index, param) in arguments.iter().enumerate() {
1072            // Function arguments always get the first Local indices after the return place
1073            let local = Local::new(index + 1);
1074            let place = Place::from(local);
1075
1076            // Make sure we drop (parts of) the argument even when not matched on.
1077            self.schedule_drop(
1078                param.pat.as_ref().map_or(expr_span, |pat| pat.span),
1079                argument_scope,
1080                local,
1081                DropKind::Value,
1082            );
1083
1084            let Some(ref pat) = param.pat else {
1085                continue;
1086            };
1087            let original_source_scope = self.source_scope;
1088            let span = pat.span;
1089            if let Some(arg_hir_id) = param.hir_id {
1090                self.set_correct_source_scope_for_arg(arg_hir_id, original_source_scope, span);
1091            }
1092            match pat.kind {
1093                // Don't introduce extra copies for simple bindings
1094                PatKind::Binding {
1095                    var,
1096                    mode: BindingMode(ByRef::No, mutability),
1097                    subpattern: None,
1098                    ..
1099                } => {
1100                    self.local_decls[local].mutability = mutability;
1101                    self.local_decls[local].source_info.scope = self.source_scope;
1102                    **self.local_decls[local].local_info.as_mut().unwrap_crate_local() =
1103                        if let Some(kind) = param.self_kind {
1104                            LocalInfo::User(BindingForm::ImplicitSelf(kind))
1105                        } else {
1106                            let binding_mode = BindingMode(ByRef::No, mutability);
1107                            LocalInfo::User(BindingForm::Var(VarBindingForm {
1108                                binding_mode,
1109                                opt_ty_info: param.ty_span,
1110                                opt_match_place: Some((None, span)),
1111                                pat_span: span,
1112                                introductions: vec![VarBindingIntroduction {
1113                                    span,
1114                                    is_shorthand: false,
1115                                }],
1116                            }))
1117                        };
1118                    self.var_indices.insert(var, LocalsForNode::One(local));
1119                }
1120                _ => {
1121                    scope = self.declare_bindings(
1122                        scope,
1123                        expr_span,
1124                        &pat,
1125                        None,
1126                        Some((Some(&place), span)),
1127                    );
1128                    let place_builder = PlaceBuilder::from(local);
1129                    block = self.place_into_pattern(block, pat, place_builder, false).into_block();
1130                }
1131            }
1132            self.source_scope = original_source_scope;
1133        }
1134
1135        // Enter the argument pattern bindings source scope, if it exists.
1136        if let Some(source_scope) = scope {
1137            self.source_scope = source_scope;
1138        }
1139
1140        if self.tcx.intrinsic(self.def_id).is_some_and(|i| i.must_be_overridden)
1141            || self.tcx.is_sdylib_interface_build()
1142        {
1143            let source_info = self.source_info(rustc_span::DUMMY_SP);
1144            self.cfg.terminate(block, source_info, TerminatorKind::Unreachable);
1145            self.cfg.start_new_block().unit()
1146        } else {
1147            // Ensure we don't silently codegen functions with fake bodies.
1148            match self.tcx.hir_node(self.hir_id) {
1149                hir::Node::Item(hir::Item {
1150                    kind: hir::ItemKind::Fn { has_body: false, .. },
1151                    ..
1152                }) => {
1153                    self.tcx.dcx().span_delayed_bug(
1154                        expr_span,
1155                        format!("fn item without body has reached MIR building: {:?}", self.def_id),
1156                    );
1157                }
1158                _ => {}
1159            }
1160            self.expr_into_dest(Place::return_place(), block, expr_id)
1161        }
1162    }
1163
1164    fn set_correct_source_scope_for_arg(
1165        &mut self,
1166        arg_hir_id: HirId,
1167        original_source_scope: SourceScope,
1168        pattern_span: Span,
1169    ) {
1170        let parent_id = self.source_scopes[original_source_scope]
1171            .local_data
1172            .as_ref()
1173            .unwrap_crate_local()
1174            .lint_root;
1175        self.maybe_new_source_scope(pattern_span, arg_hir_id, parent_id);
1176    }
1177
1178    fn get_unit_temp(&mut self) -> Place<'tcx> {
1179        match self.unit_temp {
1180            Some(tmp) => tmp,
1181            None => {
1182                let ty = self.tcx.types.unit;
1183                let fn_span = self.fn_span;
1184                let tmp = self.temp(ty, fn_span);
1185                self.unit_temp = Some(tmp);
1186                tmp
1187            }
1188        }
1189    }
1190}
1191
1192fn parse_float_into_constval(num: Symbol, float_ty: ty::FloatTy, neg: bool) -> Option<ConstValue> {
1193    parse_float_into_scalar(num, float_ty, neg).map(|s| ConstValue::Scalar(s.into()))
1194}
1195
1196pub(crate) fn parse_float_into_scalar(
1197    num: Symbol,
1198    float_ty: ty::FloatTy,
1199    neg: bool,
1200) -> Option<ScalarInt> {
1201    let num = num.as_str();
1202    match float_ty {
1203        // FIXME(f16_f128): When available, compare to the library parser as with `f32` and `f64`
1204        ty::FloatTy::F16 => {
1205            let mut f = num.parse::<Half>().ok()?;
1206            if neg {
1207                f = -f;
1208            }
1209            Some(ScalarInt::from(f))
1210        }
1211        ty::FloatTy::F32 => {
1212            let Ok(rust_f) = num.parse::<f32>() else { return None };
1213            let mut f = num
1214                .parse::<Single>()
1215                .unwrap_or_else(|e| panic!("apfloat::ieee::Single failed to parse `{num}`: {e:?}"));
1216
1217            assert!(
1218                u128::from(rust_f.to_bits()) == f.to_bits(),
1219                "apfloat::ieee::Single gave different result for `{}`: \
1220                 {}({:#x}) vs Rust's {}({:#x})",
1221                rust_f,
1222                f,
1223                f.to_bits(),
1224                Single::from_bits(rust_f.to_bits().into()),
1225                rust_f.to_bits()
1226            );
1227
1228            if neg {
1229                f = -f;
1230            }
1231
1232            Some(ScalarInt::from(f))
1233        }
1234        ty::FloatTy::F64 => {
1235            let Ok(rust_f) = num.parse::<f64>() else { return None };
1236            let mut f = num
1237                .parse::<Double>()
1238                .unwrap_or_else(|e| panic!("apfloat::ieee::Double failed to parse `{num}`: {e:?}"));
1239
1240            assert!(
1241                u128::from(rust_f.to_bits()) == f.to_bits(),
1242                "apfloat::ieee::Double gave different result for `{}`: \
1243                 {}({:#x}) vs Rust's {}({:#x})",
1244                rust_f,
1245                f,
1246                f.to_bits(),
1247                Double::from_bits(rust_f.to_bits().into()),
1248                rust_f.to_bits()
1249            );
1250
1251            if neg {
1252                f = -f;
1253            }
1254
1255            Some(ScalarInt::from(f))
1256        }
1257        // FIXME(f16_f128): When available, compare to the library parser as with `f32` and `f64`
1258        ty::FloatTy::F128 => {
1259            let mut f = num.parse::<Quad>().ok()?;
1260            if neg {
1261                f = -f;
1262            }
1263            Some(ScalarInt::from(f))
1264        }
1265    }
1266}
1267
1268///////////////////////////////////////////////////////////////////////////
1269// Builder methods are broken up into modules, depending on what kind
1270// of thing is being lowered. Note that they use the `unpack` macro
1271// above extensively.
1272
1273mod block;
1274mod cfg;
1275mod coverageinfo;
1276mod custom;
1277mod expr;
1278mod matches;
1279mod misc;
1280mod scope;
1281
1282pub(crate) use expr::category::Category as ExprCategory;