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