• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use crate::build::expr::as_place::PlaceBuilder;
2 use crate::build::scope::DropKind;
3 use rustc_apfloat::ieee::{Double, Single};
4 use rustc_apfloat::Float;
5 use rustc_ast::attr;
6 use rustc_data_structures::fx::FxHashMap;
7 use rustc_data_structures::sorted_map::SortedIndexMultiMap;
8 use rustc_errors::ErrorGuaranteed;
9 use rustc_hir as hir;
10 use rustc_hir::def::DefKind;
11 use rustc_hir::def_id::{DefId, LocalDefId};
12 use rustc_hir::{GeneratorKind, Node};
13 use rustc_index::{Idx, IndexSlice, IndexVec};
14 use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
15 use rustc_middle::hir::place::PlaceBase as HirPlaceBase;
16 use rustc_middle::middle::region;
17 use rustc_middle::mir::interpret::ConstValue;
18 use rustc_middle::mir::interpret::Scalar;
19 use rustc_middle::mir::*;
20 use rustc_middle::thir::{
21     self, BindingMode, Expr, ExprId, LintLevel, LocalVarId, Param, ParamId, PatKind, Thir,
22 };
23 use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
24 use rustc_span::symbol::sym;
25 use rustc_span::Span;
26 use rustc_span::Symbol;
27 use rustc_target::abi::FieldIdx;
28 use rustc_target::spec::abi::Abi;
29 
30 use super::lints;
31 
mir_built( tcx: TyCtxt<'_>, def: LocalDefId, ) -> &rustc_data_structures::steal::Steal<Body<'_>>32 pub(crate) fn mir_built(
33     tcx: TyCtxt<'_>,
34     def: LocalDefId,
35 ) -> &rustc_data_structures::steal::Steal<Body<'_>> {
36     tcx.alloc_steal_mir(mir_build(tcx, def))
37 }
38 
closure_saved_names_of_captured_variables<'tcx>( tcx: TyCtxt<'tcx>, def_id: LocalDefId, ) -> IndexVec<FieldIdx, Symbol>39 pub(crate) fn closure_saved_names_of_captured_variables<'tcx>(
40     tcx: TyCtxt<'tcx>,
41     def_id: LocalDefId,
42 ) -> IndexVec<FieldIdx, Symbol> {
43     tcx.closure_captures(def_id)
44         .iter()
45         .map(|captured_place| {
46             let name = captured_place.to_symbol();
47             match captured_place.info.capture_kind {
48                 ty::UpvarCapture::ByValue => name,
49                 ty::UpvarCapture::ByRef(..) => Symbol::intern(&format!("_ref__{name}")),
50             }
51         })
52         .collect()
53 }
54 
55 /// Construct the MIR for a given `DefId`.
mir_build(tcx: TyCtxt<'_>, def: LocalDefId) -> Body<'_>56 fn mir_build(tcx: TyCtxt<'_>, def: LocalDefId) -> Body<'_> {
57     // Ensure unsafeck and abstract const building is ran before we steal the THIR.
58     tcx.ensure_with_value().thir_check_unsafety(def);
59     tcx.ensure_with_value().thir_abstract_const(def);
60     if let Err(e) = tcx.check_match(def) {
61         return construct_error(tcx, def, e);
62     }
63 
64     let body = match tcx.thir_body(def) {
65         Err(error_reported) => construct_error(tcx, def, error_reported),
66         Ok((thir, expr)) => {
67             // We ran all queries that depended on THIR at the beginning
68             // of `mir_build`, so now we can steal it
69             let thir = thir.steal();
70 
71             tcx.ensure().check_match(def);
72             // this must run before MIR dump, because
73             // "not all control paths return a value" is reported here.
74             //
75             // maybe move the check to a MIR pass?
76             tcx.ensure().check_liveness(def);
77 
78             match thir.body_type {
79                 thir::BodyTy::Fn(fn_sig) => construct_fn(tcx, def, &thir, expr, fn_sig),
80                 thir::BodyTy::Const(ty) => construct_const(tcx, def, &thir, expr, ty),
81             }
82         }
83     };
84 
85     lints::check(tcx, &body);
86 
87     // The borrow checker will replace all the regions here with its own
88     // inference variables. There's no point having non-erased regions here.
89     // The exception is `body.user_type_annotations`, which is used unmodified
90     // by borrow checking.
91     debug_assert!(
92         !(body.local_decls.has_free_regions()
93             || body.basic_blocks.has_free_regions()
94             || body.var_debug_info.has_free_regions()
95             || body.yield_ty().has_free_regions()),
96         "Unexpected free regions in MIR: {:?}",
97         body,
98     );
99 
100     body
101 }
102 
103 ///////////////////////////////////////////////////////////////////////////
104 // BuildMir -- walks a crate, looking for fn items and methods to build MIR from
105 
106 #[derive(Debug, PartialEq, Eq)]
107 enum BlockFrame {
108     /// Evaluation is currently within a statement.
109     ///
110     /// Examples include:
111     /// 1. `EXPR;`
112     /// 2. `let _ = EXPR;`
113     /// 3. `let x = EXPR;`
114     Statement {
115         /// If true, then statement discards result from evaluating
116         /// the expression (such as examples 1 and 2 above).
117         ignores_expr_result: bool,
118     },
119 
120     /// Evaluation is currently within the tail expression of a block.
121     ///
122     /// Example: `{ STMT_1; STMT_2; EXPR }`
123     TailExpr {
124         /// If true, then the surrounding context of the block ignores
125         /// the result of evaluating the block's tail expression.
126         ///
127         /// Example: `let _ = { STMT_1; EXPR };`
128         tail_result_is_ignored: bool,
129 
130         /// `Span` of the tail expression.
131         span: Span,
132     },
133 
134     /// Generic mark meaning that the block occurred as a subexpression
135     /// where the result might be used.
136     ///
137     /// Examples: `foo(EXPR)`, `match EXPR { ... }`
138     SubExpr,
139 }
140 
141 impl BlockFrame {
is_tail_expr(&self) -> bool142     fn is_tail_expr(&self) -> bool {
143         match *self {
144             BlockFrame::TailExpr { .. } => true,
145 
146             BlockFrame::Statement { .. } | BlockFrame::SubExpr => false,
147         }
148     }
is_statement(&self) -> bool149     fn is_statement(&self) -> bool {
150         match *self {
151             BlockFrame::Statement { .. } => true,
152 
153             BlockFrame::TailExpr { .. } | BlockFrame::SubExpr => false,
154         }
155     }
156 }
157 
158 #[derive(Debug)]
159 struct BlockContext(Vec<BlockFrame>);
160 
161 struct Builder<'a, 'tcx> {
162     tcx: TyCtxt<'tcx>,
163     infcx: InferCtxt<'tcx>,
164     region_scope_tree: &'tcx region::ScopeTree,
165     param_env: ty::ParamEnv<'tcx>,
166 
167     thir: &'a Thir<'tcx>,
168     cfg: CFG<'tcx>,
169 
170     def_id: LocalDefId,
171     hir_id: hir::HirId,
172     parent_module: DefId,
173     check_overflow: bool,
174     fn_span: Span,
175     arg_count: usize,
176     generator_kind: Option<GeneratorKind>,
177 
178     /// The current set of scopes, updated as we traverse;
179     /// see the `scope` module for more details.
180     scopes: scope::Scopes<'tcx>,
181 
182     /// The block-context: each time we build the code within an thir::Block,
183     /// we push a frame here tracking whether we are building a statement or
184     /// if we are pushing the tail expression of the block. This is used to
185     /// embed information in generated temps about whether they were created
186     /// for a block tail expression or not.
187     ///
188     /// It would be great if we could fold this into `self.scopes`
189     /// somehow, but right now I think that is very tightly tied to
190     /// the code generation in ways that we cannot (or should not)
191     /// start just throwing new entries onto that vector in order to
192     /// distinguish the context of EXPR1 from the context of EXPR2 in
193     /// `{ STMTS; EXPR1 } + EXPR2`.
194     block_context: BlockContext,
195 
196     /// The current unsafe block in scope
197     in_scope_unsafe: Safety,
198 
199     /// The vector of all scopes that we have created thus far;
200     /// we track this for debuginfo later.
201     source_scopes: IndexVec<SourceScope, SourceScopeData<'tcx>>,
202     source_scope: SourceScope,
203 
204     /// The guard-context: each time we build the guard expression for
205     /// a match arm, we push onto this stack, and then pop when we
206     /// finish building it.
207     guard_context: Vec<GuardFrame>,
208 
209     /// Maps `HirId`s of variable bindings to the `Local`s created for them.
210     /// (A match binding can have two locals; the 2nd is for the arm's guard.)
211     var_indices: FxHashMap<LocalVarId, LocalsForNode>,
212     local_decls: IndexVec<Local, LocalDecl<'tcx>>,
213     canonical_user_type_annotations: ty::CanonicalUserTypeAnnotations<'tcx>,
214     upvars: CaptureMap<'tcx>,
215     unit_temp: Option<Place<'tcx>>,
216 
217     var_debug_info: Vec<VarDebugInfo<'tcx>>,
218 }
219 
220 type CaptureMap<'tcx> = SortedIndexMultiMap<usize, hir::HirId, Capture<'tcx>>;
221 
222 #[derive(Debug)]
223 struct Capture<'tcx> {
224     captured_place: &'tcx ty::CapturedPlace<'tcx>,
225     use_place: Place<'tcx>,
226     mutability: Mutability,
227 }
228 
229 impl<'a, 'tcx> Builder<'a, 'tcx> {
is_bound_var_in_guard(&self, id: LocalVarId) -> bool230     fn is_bound_var_in_guard(&self, id: LocalVarId) -> bool {
231         self.guard_context.iter().any(|frame| frame.locals.iter().any(|local| local.id == id))
232     }
233 
var_local_id(&self, id: LocalVarId, for_guard: ForGuard) -> Local234     fn var_local_id(&self, id: LocalVarId, for_guard: ForGuard) -> Local {
235         self.var_indices[&id].local_id(for_guard)
236     }
237 }
238 
239 impl BlockContext {
new() -> Self240     fn new() -> Self {
241         BlockContext(vec![])
242     }
push(&mut self, bf: BlockFrame)243     fn push(&mut self, bf: BlockFrame) {
244         self.0.push(bf);
245     }
pop(&mut self) -> Option<BlockFrame>246     fn pop(&mut self) -> Option<BlockFrame> {
247         self.0.pop()
248     }
249 
250     /// Traverses the frames on the `BlockContext`, searching for either
251     /// the first block-tail expression frame with no intervening
252     /// statement frame.
253     ///
254     /// Notably, this skips over `SubExpr` frames; this method is
255     /// meant to be used in the context of understanding the
256     /// relationship of a temp (created within some complicated
257     /// expression) with its containing expression, and whether the
258     /// value of that *containing expression* (not the temp!) is
259     /// ignored.
currently_in_block_tail(&self) -> Option<BlockTailInfo>260     fn currently_in_block_tail(&self) -> Option<BlockTailInfo> {
261         for bf in self.0.iter().rev() {
262             match bf {
263                 BlockFrame::SubExpr => continue,
264                 BlockFrame::Statement { .. } => break,
265                 &BlockFrame::TailExpr { tail_result_is_ignored, span } => {
266                     return Some(BlockTailInfo { tail_result_is_ignored, span });
267                 }
268             }
269         }
270 
271         None
272     }
273 
274     /// Looks at the topmost frame on the BlockContext and reports
275     /// whether its one that would discard a block tail result.
276     ///
277     /// Unlike `currently_within_ignored_tail_expression`, this does
278     /// *not* skip over `SubExpr` frames: here, we want to know
279     /// whether the block result itself is discarded.
currently_ignores_tail_results(&self) -> bool280     fn currently_ignores_tail_results(&self) -> bool {
281         match self.0.last() {
282             // no context: conservatively assume result is read
283             None => false,
284 
285             // sub-expression: block result feeds into some computation
286             Some(BlockFrame::SubExpr) => false,
287 
288             // otherwise: use accumulated is_ignored state.
289             Some(
290                 BlockFrame::TailExpr { tail_result_is_ignored: ignored, .. }
291                 | BlockFrame::Statement { ignores_expr_result: ignored },
292             ) => *ignored,
293         }
294     }
295 }
296 
297 #[derive(Debug)]
298 enum LocalsForNode {
299     /// In the usual case, a `HirId` for an identifier maps to at most
300     /// one `Local` declaration.
301     One(Local),
302 
303     /// The exceptional case is identifiers in a match arm's pattern
304     /// that are referenced in a guard of that match arm. For these,
305     /// we have `2` Locals.
306     ///
307     /// * `for_arm_body` is the Local used in the arm body (which is
308     ///   just like the `One` case above),
309     ///
310     /// * `ref_for_guard` is the Local used in the arm's guard (which
311     ///   is a reference to a temp that is an alias of
312     ///   `for_arm_body`).
313     ForGuard { ref_for_guard: Local, for_arm_body: Local },
314 }
315 
316 #[derive(Debug)]
317 struct GuardFrameLocal {
318     id: LocalVarId,
319 }
320 
321 impl GuardFrameLocal {
new(id: LocalVarId, _binding_mode: BindingMode) -> Self322     fn new(id: LocalVarId, _binding_mode: BindingMode) -> Self {
323         GuardFrameLocal { id }
324     }
325 }
326 
327 #[derive(Debug)]
328 struct GuardFrame {
329     /// These are the id's of names that are bound by patterns of the
330     /// arm of *this* guard.
331     ///
332     /// (Frames higher up the stack will have the id's bound in arms
333     /// further out, such as in a case like:
334     ///
335     /// match E1 {
336     ///      P1(id1) if (... (match E2 { P2(id2) if ... => B2 })) => B1,
337     /// }
338     ///
339     /// here, when building for FIXME.
340     locals: Vec<GuardFrameLocal>,
341 }
342 
343 /// `ForGuard` indicates whether we are talking about:
344 ///   1. The variable for use outside of guard expressions, or
345 ///   2. The temp that holds reference to (1.), which is actually what the
346 ///      guard expressions see.
347 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
348 enum ForGuard {
349     RefWithinGuard,
350     OutsideGuard,
351 }
352 
353 impl LocalsForNode {
local_id(&self, for_guard: ForGuard) -> Local354     fn local_id(&self, for_guard: ForGuard) -> Local {
355         match (self, for_guard) {
356             (&LocalsForNode::One(local_id), ForGuard::OutsideGuard)
357             | (
358                 &LocalsForNode::ForGuard { ref_for_guard: local_id, .. },
359                 ForGuard::RefWithinGuard,
360             )
361             | (&LocalsForNode::ForGuard { for_arm_body: local_id, .. }, ForGuard::OutsideGuard) => {
362                 local_id
363             }
364 
365             (&LocalsForNode::One(_), ForGuard::RefWithinGuard) => {
366                 bug!("anything with one local should never be within a guard.")
367             }
368         }
369     }
370 }
371 
372 struct CFG<'tcx> {
373     basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>,
374 }
375 
376 rustc_index::newtype_index! {
377     struct ScopeId {}
378 }
379 
380 #[derive(Debug)]
381 enum NeedsTemporary {
382     /// Use this variant when whatever you are converting with `as_operand`
383     /// is the last thing you are converting. This means that if we introduced
384     /// an intermediate temporary, we'd only read it immediately after, so we can
385     /// also avoid it.
386     No,
387     /// For all cases where you aren't sure or that are too expensive to compute
388     /// for now. It is always safe to fall back to this.
389     Maybe,
390 }
391 
392 ///////////////////////////////////////////////////////////////////////////
393 /// The `BlockAnd` "monad" packages up the new basic block along with a
394 /// produced value (sometimes just unit, of course). The `unpack!`
395 /// macro (and methods below) makes working with `BlockAnd` much more
396 /// convenient.
397 
398 #[must_use = "if you don't use one of these results, you're leaving a dangling edge"]
399 struct BlockAnd<T>(BasicBlock, T);
400 
401 trait BlockAndExtension {
and<T>(self, v: T) -> BlockAnd<T>402     fn and<T>(self, v: T) -> BlockAnd<T>;
unit(self) -> BlockAnd<()>403     fn unit(self) -> BlockAnd<()>;
404 }
405 
406 impl BlockAndExtension for BasicBlock {
and<T>(self, v: T) -> BlockAnd<T>407     fn and<T>(self, v: T) -> BlockAnd<T> {
408         BlockAnd(self, v)
409     }
410 
unit(self) -> BlockAnd<()>411     fn unit(self) -> BlockAnd<()> {
412         BlockAnd(self, ())
413     }
414 }
415 
416 /// Update a block pointer and return the value.
417 /// Use it like `let x = unpack!(block = self.foo(block, foo))`.
418 macro_rules! unpack {
419     ($x:ident = $c:expr) => {{
420         let BlockAnd(b, v) = $c;
421         $x = b;
422         v
423     }};
424 
425     ($c:expr) => {{
426         let BlockAnd(b, ()) = $c;
427         b
428     }};
429 }
430 
431 ///////////////////////////////////////////////////////////////////////////
432 /// the main entry point for building MIR for a function
433 
construct_fn<'tcx>( tcx: TyCtxt<'tcx>, fn_def: LocalDefId, thir: &Thir<'tcx>, expr: ExprId, fn_sig: ty::FnSig<'tcx>, ) -> Body<'tcx>434 fn construct_fn<'tcx>(
435     tcx: TyCtxt<'tcx>,
436     fn_def: LocalDefId,
437     thir: &Thir<'tcx>,
438     expr: ExprId,
439     fn_sig: ty::FnSig<'tcx>,
440 ) -> Body<'tcx> {
441     let span = tcx.def_span(fn_def);
442     let fn_id = tcx.hir().local_def_id_to_hir_id(fn_def);
443     let generator_kind = tcx.generator_kind(fn_def);
444 
445     // The representation of thir for `-Zunpretty=thir-tree` relies on
446     // the entry expression being the last element of `thir.exprs`.
447     assert_eq!(expr.as_usize(), thir.exprs.len() - 1);
448 
449     // Figure out what primary body this item has.
450     let body_id = tcx.hir().body_owned_by(fn_def);
451     let span_with_body = tcx.hir().span_with_body(fn_id);
452     let return_ty_span = tcx
453         .hir()
454         .fn_decl_by_hir_id(fn_id)
455         .unwrap_or_else(|| span_bug!(span, "can't build MIR for {:?}", fn_def))
456         .output
457         .span();
458 
459     let safety = match fn_sig.unsafety {
460         hir::Unsafety::Normal => Safety::Safe,
461         hir::Unsafety::Unsafe => Safety::FnUnsafe,
462     };
463 
464     let mut abi = fn_sig.abi;
465     if let DefKind::Closure = tcx.def_kind(fn_def) {
466         // HACK(eddyb) Avoid having RustCall on closures,
467         // as it adds unnecessary (and wrong) auto-tupling.
468         abi = Abi::Rust;
469     }
470 
471     let arguments = &thir.params;
472 
473     let (yield_ty, return_ty) = if generator_kind.is_some() {
474         let gen_ty = arguments[thir::UPVAR_ENV_PARAM].ty;
475         let gen_sig = match gen_ty.kind() {
476             ty::Generator(_, gen_substs, ..) => gen_substs.as_generator().sig(),
477             _ => {
478                 span_bug!(span, "generator w/o generator type: {:?}", gen_ty)
479             }
480         };
481         (Some(gen_sig.yield_ty), gen_sig.return_ty)
482     } else {
483         (None, fn_sig.output())
484     };
485 
486     if let Some(custom_mir_attr) =
487         tcx.hir().attrs(fn_id).iter().find(|attr| attr.name_or_empty() == sym::custom_mir)
488     {
489         return custom::build_custom_mir(
490             tcx,
491             fn_def.to_def_id(),
492             fn_id,
493             thir,
494             expr,
495             arguments,
496             return_ty,
497             return_ty_span,
498             span_with_body,
499             custom_mir_attr,
500         );
501     }
502 
503     let infcx = tcx.infer_ctxt().build();
504     let mut builder = Builder::new(
505         thir,
506         infcx,
507         fn_def,
508         fn_id,
509         span_with_body,
510         arguments.len(),
511         safety,
512         return_ty,
513         return_ty_span,
514         generator_kind,
515     );
516 
517     let call_site_scope =
518         region::Scope { id: body_id.hir_id.local_id, data: region::ScopeData::CallSite };
519     let arg_scope =
520         region::Scope { id: body_id.hir_id.local_id, data: region::ScopeData::Arguments };
521     let source_info = builder.source_info(span);
522     let call_site_s = (call_site_scope, source_info);
523     unpack!(builder.in_scope(call_site_s, LintLevel::Inherited, |builder| {
524         let arg_scope_s = (arg_scope, source_info);
525         // Attribute epilogue to function's closing brace
526         let fn_end = span_with_body.shrink_to_hi();
527         let return_block =
528             unpack!(builder.in_breakable_scope(None, Place::return_place(), fn_end, |builder| {
529                 Some(builder.in_scope(arg_scope_s, LintLevel::Inherited, |builder| {
530                     builder.args_and_body(START_BLOCK, arguments, arg_scope, &thir[expr])
531                 }))
532             }));
533         let source_info = builder.source_info(fn_end);
534         builder.cfg.terminate(return_block, source_info, TerminatorKind::Return);
535         builder.build_drop_trees();
536         return_block.unit()
537     }));
538 
539     let mut body = builder.finish();
540 
541     body.spread_arg = if abi == Abi::RustCall {
542         // RustCall pseudo-ABI untuples the last argument.
543         Some(Local::new(arguments.len()))
544     } else {
545         None
546     };
547     if yield_ty.is_some() {
548         body.generator.as_mut().unwrap().yield_ty = yield_ty;
549     }
550     body
551 }
552 
construct_const<'a, 'tcx>( tcx: TyCtxt<'tcx>, def: LocalDefId, thir: &'a Thir<'tcx>, expr: ExprId, const_ty: Ty<'tcx>, ) -> Body<'tcx>553 fn construct_const<'a, 'tcx>(
554     tcx: TyCtxt<'tcx>,
555     def: LocalDefId,
556     thir: &'a Thir<'tcx>,
557     expr: ExprId,
558     const_ty: Ty<'tcx>,
559 ) -> Body<'tcx> {
560     let hir_id = tcx.hir().local_def_id_to_hir_id(def);
561 
562     // Figure out what primary body this item has.
563     let (span, const_ty_span) = match tcx.hir().get(hir_id) {
564         Node::Item(hir::Item {
565             kind: hir::ItemKind::Static(ty, _, _) | hir::ItemKind::Const(ty, _),
566             span,
567             ..
568         })
569         | Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Const(ty, _), span, .. })
570         | Node::TraitItem(hir::TraitItem {
571             kind: hir::TraitItemKind::Const(ty, Some(_)),
572             span,
573             ..
574         }) => (*span, ty.span),
575         Node::AnonConst(_) | Node::ConstBlock(_) => {
576             let span = tcx.def_span(def);
577             (span, span)
578         }
579         _ => span_bug!(tcx.def_span(def), "can't build MIR for {:?}", def),
580     };
581 
582     let infcx = tcx.infer_ctxt().build();
583     let mut builder = Builder::new(
584         thir,
585         infcx,
586         def,
587         hir_id,
588         span,
589         0,
590         Safety::Safe,
591         const_ty,
592         const_ty_span,
593         None,
594     );
595 
596     let mut block = START_BLOCK;
597     unpack!(block = builder.expr_into_dest(Place::return_place(), block, &thir[expr]));
598 
599     let source_info = builder.source_info(span);
600     builder.cfg.terminate(block, source_info, TerminatorKind::Return);
601 
602     builder.build_drop_trees();
603 
604     builder.finish()
605 }
606 
607 /// Construct MIR for an item that has had errors in type checking.
608 ///
609 /// This is required because we may still want to run MIR passes on an item
610 /// with type errors, but normal MIR construction can't handle that in general.
construct_error(tcx: TyCtxt<'_>, def: LocalDefId, err: ErrorGuaranteed) -> Body<'_>611 fn construct_error(tcx: TyCtxt<'_>, def: LocalDefId, err: ErrorGuaranteed) -> Body<'_> {
612     let span = tcx.def_span(def);
613     let hir_id = tcx.hir().local_def_id_to_hir_id(def);
614     let generator_kind = tcx.generator_kind(def);
615     let body_owner_kind = tcx.hir().body_owner_kind(def);
616 
617     let ty = Ty::new_error(tcx, err);
618     let num_params = match body_owner_kind {
619         hir::BodyOwnerKind::Fn => tcx.fn_sig(def).skip_binder().inputs().skip_binder().len(),
620         hir::BodyOwnerKind::Closure => {
621             let ty = tcx.type_of(def).subst_identity();
622             match ty.kind() {
623                 ty::Closure(_, substs) => {
624                     1 + substs.as_closure().sig().inputs().skip_binder().len()
625                 }
626                 ty::Generator(..) => 2,
627                 _ => bug!("expected closure or generator, found {ty:?}"),
628             }
629         }
630         hir::BodyOwnerKind::Const => 0,
631         hir::BodyOwnerKind::Static(_) => 0,
632     };
633     let mut cfg = CFG { basic_blocks: IndexVec::new() };
634     let mut source_scopes = IndexVec::new();
635     let mut local_decls = IndexVec::from_elem_n(LocalDecl::new(ty, span), 1);
636 
637     cfg.start_new_block();
638     source_scopes.push(SourceScopeData {
639         span,
640         parent_scope: None,
641         inlined: None,
642         inlined_parent_scope: None,
643         local_data: ClearCrossCrate::Set(SourceScopeLocalData {
644             lint_root: hir_id,
645             safety: Safety::Safe,
646         }),
647     });
648     let source_info = SourceInfo { span, scope: OUTERMOST_SOURCE_SCOPE };
649 
650     // Some MIR passes will expect the number of parameters to match the
651     // function declaration.
652     for _ in 0..num_params {
653         local_decls.push(LocalDecl::with_source_info(ty, source_info));
654     }
655     cfg.terminate(START_BLOCK, source_info, TerminatorKind::Unreachable);
656 
657     let mut body = Body::new(
658         MirSource::item(def.to_def_id()),
659         cfg.basic_blocks,
660         source_scopes,
661         local_decls,
662         IndexVec::new(),
663         num_params,
664         vec![],
665         span,
666         generator_kind,
667         Some(err),
668     );
669     body.generator.as_mut().map(|gen| gen.yield_ty = Some(ty));
670     body
671 }
672 
673 impl<'a, 'tcx> Builder<'a, 'tcx> {
new( thir: &'a Thir<'tcx>, infcx: InferCtxt<'tcx>, def: LocalDefId, hir_id: hir::HirId, span: Span, arg_count: usize, safety: Safety, return_ty: Ty<'tcx>, return_span: Span, generator_kind: Option<GeneratorKind>, ) -> Builder<'a, 'tcx>674     fn new(
675         thir: &'a Thir<'tcx>,
676         infcx: InferCtxt<'tcx>,
677         def: LocalDefId,
678         hir_id: hir::HirId,
679         span: Span,
680         arg_count: usize,
681         safety: Safety,
682         return_ty: Ty<'tcx>,
683         return_span: Span,
684         generator_kind: Option<GeneratorKind>,
685     ) -> Builder<'a, 'tcx> {
686         let tcx = infcx.tcx;
687         let attrs = tcx.hir().attrs(hir_id);
688         // Some functions always have overflow checks enabled,
689         // however, they may not get codegen'd, depending on
690         // the settings for the crate they are codegened in.
691         let mut check_overflow = attr::contains_name(attrs, sym::rustc_inherit_overflow_checks);
692         // Respect -C overflow-checks.
693         check_overflow |= tcx.sess.overflow_checks();
694         // Constants always need overflow checks.
695         check_overflow |= matches!(
696             tcx.hir().body_owner_kind(def),
697             hir::BodyOwnerKind::Const | hir::BodyOwnerKind::Static(_)
698         );
699 
700         let lint_level = LintLevel::Explicit(hir_id);
701         let param_env = tcx.param_env(def);
702         let mut builder = Builder {
703             thir,
704             tcx,
705             infcx,
706             region_scope_tree: tcx.region_scope_tree(def),
707             param_env,
708             def_id: def,
709             hir_id,
710             parent_module: tcx.parent_module(hir_id).to_def_id(),
711             check_overflow,
712             cfg: CFG { basic_blocks: IndexVec::new() },
713             fn_span: span,
714             arg_count,
715             generator_kind,
716             scopes: scope::Scopes::new(),
717             block_context: BlockContext::new(),
718             source_scopes: IndexVec::new(),
719             source_scope: OUTERMOST_SOURCE_SCOPE,
720             guard_context: vec![],
721             in_scope_unsafe: safety,
722             local_decls: IndexVec::from_elem_n(LocalDecl::new(return_ty, return_span), 1),
723             canonical_user_type_annotations: IndexVec::new(),
724             upvars: CaptureMap::new(),
725             var_indices: Default::default(),
726             unit_temp: None,
727             var_debug_info: vec![],
728         };
729 
730         assert_eq!(builder.cfg.start_new_block(), START_BLOCK);
731         assert_eq!(
732             builder.new_source_scope(span, lint_level, Some(safety)),
733             OUTERMOST_SOURCE_SCOPE
734         );
735         builder.source_scopes[OUTERMOST_SOURCE_SCOPE].parent_scope = None;
736 
737         builder
738     }
739 
finish(self) -> Body<'tcx>740     fn finish(self) -> Body<'tcx> {
741         for (index, block) in self.cfg.basic_blocks.iter().enumerate() {
742             if block.terminator.is_none() {
743                 span_bug!(self.fn_span, "no terminator on block {:?}", index);
744             }
745         }
746 
747         Body::new(
748             MirSource::item(self.def_id.to_def_id()),
749             self.cfg.basic_blocks,
750             self.source_scopes,
751             self.local_decls,
752             self.canonical_user_type_annotations,
753             self.arg_count,
754             self.var_debug_info,
755             self.fn_span,
756             self.generator_kind,
757             None,
758         )
759     }
760 
insert_upvar_arg(&mut self)761     fn insert_upvar_arg(&mut self) {
762         let Some(closure_arg) = self.local_decls.get(ty::CAPTURE_STRUCT_LOCAL) else { return };
763 
764         let mut closure_ty = closure_arg.ty;
765         let mut closure_env_projs = vec![];
766         if let ty::Ref(_, ty, _) = closure_ty.kind() {
767             closure_env_projs.push(ProjectionElem::Deref);
768             closure_ty = *ty;
769         }
770 
771         let upvar_substs = match closure_ty.kind() {
772             ty::Closure(_, substs) => ty::UpvarSubsts::Closure(substs),
773             ty::Generator(_, substs, _) => ty::UpvarSubsts::Generator(substs),
774             _ => return,
775         };
776 
777         // In analyze_closure() in upvar.rs we gathered a list of upvars used by an
778         // indexed closure and we stored in a map called closure_min_captures in TypeckResults
779         // with the closure's DefId. Here, we run through that vec of UpvarIds for
780         // the given closure and use the necessary information to create upvar
781         // debuginfo and to fill `self.upvars`.
782         let capture_tys = upvar_substs.upvar_tys();
783 
784         let tcx = self.tcx;
785         self.upvars = tcx
786             .closure_captures(self.def_id)
787             .iter()
788             .zip(capture_tys)
789             .enumerate()
790             .map(|(i, (captured_place, ty))| {
791                 let name = captured_place.to_symbol();
792 
793                 let capture = captured_place.info.capture_kind;
794                 let var_id = match captured_place.place.base {
795                     HirPlaceBase::Upvar(upvar_id) => upvar_id.var_path.hir_id,
796                     _ => bug!("Expected an upvar"),
797                 };
798 
799                 let mutability = captured_place.mutability;
800 
801                 let mut projs = closure_env_projs.clone();
802                 projs.push(ProjectionElem::Field(FieldIdx::new(i), ty));
803                 match capture {
804                     ty::UpvarCapture::ByValue => {}
805                     ty::UpvarCapture::ByRef(..) => {
806                         projs.push(ProjectionElem::Deref);
807                     }
808                 };
809 
810                 let use_place = Place {
811                     local: ty::CAPTURE_STRUCT_LOCAL,
812                     projection: tcx.mk_place_elems(&projs),
813                 };
814                 self.var_debug_info.push(VarDebugInfo {
815                     name,
816                     references: 0,
817                     source_info: SourceInfo::outermost(captured_place.var_ident.span),
818                     value: VarDebugInfoContents::Place(use_place),
819                     argument_index: None,
820                 });
821 
822                 let capture = Capture { captured_place, use_place, mutability };
823                 (var_id, capture)
824             })
825             .collect();
826     }
827 
args_and_body( &mut self, mut block: BasicBlock, arguments: &IndexSlice<ParamId, Param<'tcx>>, argument_scope: region::Scope, expr: &Expr<'tcx>, ) -> BlockAnd<()>828     fn args_and_body(
829         &mut self,
830         mut block: BasicBlock,
831         arguments: &IndexSlice<ParamId, Param<'tcx>>,
832         argument_scope: region::Scope,
833         expr: &Expr<'tcx>,
834     ) -> BlockAnd<()> {
835         // Allocate locals for the function arguments
836         for (argument_index, param) in arguments.iter().enumerate() {
837             let source_info =
838                 SourceInfo::outermost(param.pat.as_ref().map_or(self.fn_span, |pat| pat.span));
839             let arg_local =
840                 self.local_decls.push(LocalDecl::with_source_info(param.ty, source_info));
841 
842             // If this is a simple binding pattern, give debuginfo a nice name.
843             if let Some(ref pat) = param.pat && let Some(name) = pat.simple_ident() {
844                 self.var_debug_info.push(VarDebugInfo {
845                     name,
846                     source_info,
847                     references: 0,
848                     value: VarDebugInfoContents::Place(arg_local.into()),
849                     argument_index: Some(argument_index as u16 + 1),
850                 });
851             }
852         }
853 
854         self.insert_upvar_arg();
855 
856         let mut scope = None;
857         // Bind the argument patterns
858         for (index, param) in arguments.iter().enumerate() {
859             // Function arguments always get the first Local indices after the return place
860             let local = Local::new(index + 1);
861             let place = Place::from(local);
862 
863             // Make sure we drop (parts of) the argument even when not matched on.
864             self.schedule_drop(
865                 param.pat.as_ref().map_or(expr.span, |pat| pat.span),
866                 argument_scope,
867                 local,
868                 DropKind::Value,
869             );
870 
871             let Some(ref pat) = param.pat else {
872                 continue;
873             };
874             let original_source_scope = self.source_scope;
875             let span = pat.span;
876             if let Some(arg_hir_id) = param.hir_id {
877                 self.set_correct_source_scope_for_arg(arg_hir_id, original_source_scope, span);
878             }
879             match pat.kind {
880                 // Don't introduce extra copies for simple bindings
881                 PatKind::Binding {
882                     mutability,
883                     var,
884                     mode: BindingMode::ByValue,
885                     subpattern: None,
886                     ..
887                 } => {
888                     self.local_decls[local].mutability = mutability;
889                     self.local_decls[local].source_info.scope = self.source_scope;
890                     **self.local_decls[local].local_info.as_mut().assert_crate_local() =
891                         if let Some(kind) = param.self_kind {
892                             LocalInfo::User(BindingForm::ImplicitSelf(kind))
893                         } else {
894                             let binding_mode = ty::BindingMode::BindByValue(mutability);
895                             LocalInfo::User(BindingForm::Var(VarBindingForm {
896                                 binding_mode,
897                                 opt_ty_info: param.ty_span,
898                                 opt_match_place: Some((None, span)),
899                                 pat_span: span,
900                             }))
901                         };
902                     self.var_indices.insert(var, LocalsForNode::One(local));
903                 }
904                 _ => {
905                     scope = self.declare_bindings(
906                         scope,
907                         expr.span,
908                         &pat,
909                         None,
910                         Some((Some(&place), span)),
911                     );
912                     let place_builder = PlaceBuilder::from(local);
913                     unpack!(block = self.place_into_pattern(block, &pat, place_builder, false));
914                 }
915             }
916             self.source_scope = original_source_scope;
917         }
918 
919         // Enter the argument pattern bindings source scope, if it exists.
920         if let Some(source_scope) = scope {
921             self.source_scope = source_scope;
922         }
923 
924         self.expr_into_dest(Place::return_place(), block, &expr)
925     }
926 
set_correct_source_scope_for_arg( &mut self, arg_hir_id: hir::HirId, original_source_scope: SourceScope, pattern_span: Span, )927     fn set_correct_source_scope_for_arg(
928         &mut self,
929         arg_hir_id: hir::HirId,
930         original_source_scope: SourceScope,
931         pattern_span: Span,
932     ) {
933         let parent_id = self.source_scopes[original_source_scope]
934             .local_data
935             .as_ref()
936             .assert_crate_local()
937             .lint_root;
938         self.maybe_new_source_scope(pattern_span, None, arg_hir_id, parent_id);
939     }
940 
get_unit_temp(&mut self) -> Place<'tcx>941     fn get_unit_temp(&mut self) -> Place<'tcx> {
942         match self.unit_temp {
943             Some(tmp) => tmp,
944             None => {
945                 let ty = Ty::new_unit(self.tcx);
946                 let fn_span = self.fn_span;
947                 let tmp = self.temp(ty, fn_span);
948                 self.unit_temp = Some(tmp);
949                 tmp
950             }
951         }
952     }
953 }
954 
parse_float_into_constval<'tcx>( num: Symbol, float_ty: ty::FloatTy, neg: bool, ) -> Option<ConstValue<'tcx>>955 fn parse_float_into_constval<'tcx>(
956     num: Symbol,
957     float_ty: ty::FloatTy,
958     neg: bool,
959 ) -> Option<ConstValue<'tcx>> {
960     parse_float_into_scalar(num, float_ty, neg).map(ConstValue::Scalar)
961 }
962 
parse_float_into_scalar( num: Symbol, float_ty: ty::FloatTy, neg: bool, ) -> Option<Scalar>963 pub(crate) fn parse_float_into_scalar(
964     num: Symbol,
965     float_ty: ty::FloatTy,
966     neg: bool,
967 ) -> Option<Scalar> {
968     let num = num.as_str();
969     match float_ty {
970         ty::FloatTy::F32 => {
971             let Ok(rust_f) = num.parse::<f32>() else { return None };
972             let mut f = num.parse::<Single>().unwrap_or_else(|e| {
973                 panic!("apfloat::ieee::Single failed to parse `{}`: {:?}", num, e)
974             });
975 
976             assert!(
977                 u128::from(rust_f.to_bits()) == f.to_bits(),
978                 "apfloat::ieee::Single gave different result for `{}`: \
979                  {}({:#x}) vs Rust's {}({:#x})",
980                 rust_f,
981                 f,
982                 f.to_bits(),
983                 Single::from_bits(rust_f.to_bits().into()),
984                 rust_f.to_bits()
985             );
986 
987             if neg {
988                 f = -f;
989             }
990 
991             Some(Scalar::from_f32(f))
992         }
993         ty::FloatTy::F64 => {
994             let Ok(rust_f) = num.parse::<f64>() else { return None };
995             let mut f = num.parse::<Double>().unwrap_or_else(|e| {
996                 panic!("apfloat::ieee::Double failed to parse `{}`: {:?}", num, e)
997             });
998 
999             assert!(
1000                 u128::from(rust_f.to_bits()) == f.to_bits(),
1001                 "apfloat::ieee::Double gave different result for `{}`: \
1002                  {}({:#x}) vs Rust's {}({:#x})",
1003                 rust_f,
1004                 f,
1005                 f.to_bits(),
1006                 Double::from_bits(rust_f.to_bits().into()),
1007                 rust_f.to_bits()
1008             );
1009 
1010             if neg {
1011                 f = -f;
1012             }
1013 
1014             Some(Scalar::from_f64(f))
1015         }
1016     }
1017 }
1018 
1019 ///////////////////////////////////////////////////////////////////////////
1020 // Builder methods are broken up into modules, depending on what kind
1021 // of thing is being lowered. Note that they use the `unpack` macro
1022 // above extensively.
1023 
1024 mod block;
1025 mod cfg;
1026 mod custom;
1027 mod expr;
1028 mod matches;
1029 mod misc;
1030 mod scope;
1031 
1032 pub(crate) use expr::category::Category as ExprCategory;
1033