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