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