]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_mir_build/src/thir/cx/expr.rs
Rename `thir::Adt` as `thir::AdtExpr`.
[rust.git] / compiler / rustc_mir_build / src / thir / cx / expr.rs
1 use crate::thir::cx::region::Scope;
2 use crate::thir::cx::Cx;
3 use crate::thir::util::UserAnnotatedTyHelpers;
4 use rustc_data_structures::stack::ensure_sufficient_stack;
5 use rustc_hir as hir;
6 use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
7 use rustc_index::vec::Idx;
8 use rustc_middle::hir::place::Place as HirPlace;
9 use rustc_middle::hir::place::PlaceBase as HirPlaceBase;
10 use rustc_middle::hir::place::ProjectionKind as HirProjectionKind;
11 use rustc_middle::middle::region;
12 use rustc_middle::mir::{self, BinOp, BorrowKind, Field, UnOp};
13 use rustc_middle::thir::*;
14 use rustc_middle::ty::adjustment::{
15     Adjust, Adjustment, AutoBorrow, AutoBorrowMutability, PointerCast,
16 };
17 use rustc_middle::ty::subst::{InternalSubsts, SubstsRef};
18 use rustc_middle::ty::{
19     self, AdtKind, InlineConstSubsts, InlineConstSubstsParts, ScalarInt, Ty, UpvarSubsts, UserType,
20 };
21 use rustc_span::def_id::DefId;
22 use rustc_span::Span;
23 use rustc_target::abi::VariantIdx;
24
25 impl<'tcx> Cx<'tcx> {
26     pub(crate) fn mirror_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) -> ExprId {
27         // `mirror_expr` is recursing very deep. Make sure the stack doesn't overflow.
28         ensure_sufficient_stack(|| self.mirror_expr_inner(expr))
29     }
30
31     pub(crate) fn mirror_exprs(&mut self, exprs: &'tcx [hir::Expr<'tcx>]) -> Box<[ExprId]> {
32         exprs.iter().map(|expr| self.mirror_expr_inner(expr)).collect()
33     }
34
35     #[instrument(level = "trace", skip(self, hir_expr))]
36     pub(super) fn mirror_expr_inner(&mut self, hir_expr: &'tcx hir::Expr<'tcx>) -> ExprId {
37         let temp_lifetime =
38             self.rvalue_scopes.temporary_scope(self.region_scope_tree, hir_expr.hir_id.local_id);
39         let expr_scope =
40             region::Scope { id: hir_expr.hir_id.local_id, data: region::ScopeData::Node };
41
42         trace!(?hir_expr.hir_id, ?hir_expr.span);
43
44         let mut expr = self.make_mirror_unadjusted(hir_expr);
45
46         let adjustment_span = match self.adjustment_span {
47             Some((hir_id, span)) if hir_id == hir_expr.hir_id => Some(span),
48             _ => None,
49         };
50
51         // Now apply adjustments, if any.
52         for adjustment in self.typeck_results.expr_adjustments(hir_expr) {
53             trace!(?expr, ?adjustment);
54             let span = expr.span;
55             expr =
56                 self.apply_adjustment(hir_expr, expr, adjustment, adjustment_span.unwrap_or(span));
57         }
58
59         // Next, wrap this up in the expr's scope.
60         expr = Expr {
61             temp_lifetime,
62             ty: expr.ty,
63             span: hir_expr.span,
64             kind: ExprKind::Scope {
65                 region_scope: expr_scope,
66                 value: self.thir.exprs.push(expr),
67                 lint_level: LintLevel::Explicit(hir_expr.hir_id),
68             },
69         };
70
71         // Finally, create a destruction scope, if any.
72         if let Some(region_scope) =
73             self.region_scope_tree.opt_destruction_scope(hir_expr.hir_id.local_id)
74         {
75             expr = Expr {
76                 temp_lifetime,
77                 ty: expr.ty,
78                 span: hir_expr.span,
79                 kind: ExprKind::Scope {
80                     region_scope,
81                     value: self.thir.exprs.push(expr),
82                     lint_level: LintLevel::Inherited,
83                 },
84             };
85         }
86
87         // OK, all done!
88         self.thir.exprs.push(expr)
89     }
90
91     fn apply_adjustment(
92         &mut self,
93         hir_expr: &'tcx hir::Expr<'tcx>,
94         mut expr: Expr<'tcx>,
95         adjustment: &Adjustment<'tcx>,
96         mut span: Span,
97     ) -> Expr<'tcx> {
98         let Expr { temp_lifetime, .. } = expr;
99
100         // Adjust the span from the block, to the last expression of the
101         // block. This is a better span when returning a mutable reference
102         // with too short a lifetime. The error message will use the span
103         // from the assignment to the return place, which should only point
104         // at the returned value, not the entire function body.
105         //
106         // fn return_short_lived<'a>(x: &'a mut i32) -> &'static mut i32 {
107         //      x
108         //   // ^ error message points at this expression.
109         // }
110         let mut adjust_span = |expr: &mut Expr<'tcx>| {
111             if let ExprKind::Block { block } = expr.kind {
112                 if let Some(last_expr) = self.thir[block].expr {
113                     span = self.thir[last_expr].span;
114                     expr.span = span;
115                 }
116             }
117         };
118
119         let kind = match adjustment.kind {
120             Adjust::Pointer(PointerCast::Unsize) => {
121                 adjust_span(&mut expr);
122                 ExprKind::Pointer { cast: PointerCast::Unsize, source: self.thir.exprs.push(expr) }
123             }
124             Adjust::Pointer(cast) => ExprKind::Pointer { cast, source: self.thir.exprs.push(expr) },
125             Adjust::NeverToAny => ExprKind::NeverToAny { source: self.thir.exprs.push(expr) },
126             Adjust::Deref(None) => {
127                 adjust_span(&mut expr);
128                 ExprKind::Deref { arg: self.thir.exprs.push(expr) }
129             }
130             Adjust::Deref(Some(deref)) => {
131                 // We don't need to do call adjust_span here since
132                 // deref coercions always start with a built-in deref.
133                 let call = deref.method_call(self.tcx(), expr.ty);
134
135                 expr = Expr {
136                     temp_lifetime,
137                     ty: self
138                         .tcx
139                         .mk_ref(deref.region, ty::TypeAndMut { ty: expr.ty, mutbl: deref.mutbl }),
140                     span,
141                     kind: ExprKind::Borrow {
142                         borrow_kind: deref.mutbl.to_borrow_kind(),
143                         arg: self.thir.exprs.push(expr),
144                     },
145                 };
146
147                 let expr = Box::new([self.thir.exprs.push(expr)]);
148
149                 self.overloaded_place(hir_expr, adjustment.target, Some(call), expr, deref.span)
150             }
151             Adjust::Borrow(AutoBorrow::Ref(_, m)) => ExprKind::Borrow {
152                 borrow_kind: m.to_borrow_kind(),
153                 arg: self.thir.exprs.push(expr),
154             },
155             Adjust::Borrow(AutoBorrow::RawPtr(mutability)) => {
156                 ExprKind::AddressOf { mutability, arg: self.thir.exprs.push(expr) }
157             }
158         };
159
160         Expr { temp_lifetime, ty: adjustment.target, span, kind }
161     }
162
163     /// Lowers a cast expression.
164     ///
165     /// Dealing with user type annotations is left to the caller.
166     fn mirror_expr_cast(
167         &mut self,
168         source: &'tcx hir::Expr<'tcx>,
169         temp_lifetime: Option<Scope>,
170         span: Span,
171     ) -> ExprKind<'tcx> {
172         let tcx = self.tcx;
173
174         // Check to see if this cast is a "coercion cast", where the cast is actually done
175         // using a coercion (or is a no-op).
176         if self.typeck_results().is_coercion_cast(source.hir_id) {
177             // Convert the lexpr to a vexpr.
178             ExprKind::Use { source: self.mirror_expr(source) }
179         } else if self.typeck_results().expr_ty(source).is_region_ptr() {
180             // Special cased so that we can type check that the element
181             // type of the source matches the pointed to type of the
182             // destination.
183             ExprKind::Pointer {
184                 source: self.mirror_expr(source),
185                 cast: PointerCast::ArrayToPointer,
186             }
187         } else {
188             // check whether this is casting an enum variant discriminant
189             // to prevent cycles, we refer to the discriminant initializer
190             // which is always an integer and thus doesn't need to know the
191             // enum's layout (or its tag type) to compute it during const eval
192             // Example:
193             // enum Foo {
194             //     A,
195             //     B = A as isize + 4,
196             // }
197             // The correct solution would be to add symbolic computations to miri,
198             // so we wouldn't have to compute and store the actual value
199
200             let hir::ExprKind::Path(ref qpath) = source.kind else {
201                 return ExprKind::Cast { source: self.mirror_expr(source)};
202             };
203
204             let res = self.typeck_results().qpath_res(qpath, source.hir_id);
205             let ty = self.typeck_results().node_type(source.hir_id);
206             let ty::Adt(adt_def, substs) = ty.kind() else {
207                 return ExprKind::Cast { source: self.mirror_expr(source)};
208             };
209
210             let Res::Def(DefKind::Ctor(CtorOf::Variant, CtorKind::Const), variant_ctor_id) = res else {
211                 return ExprKind::Cast { source: self.mirror_expr(source)};
212             };
213
214             let idx = adt_def.variant_index_with_ctor_id(variant_ctor_id);
215             let (discr_did, discr_offset) = adt_def.discriminant_def_for_variant(idx);
216
217             use rustc_middle::ty::util::IntTypeExt;
218             let ty = adt_def.repr().discr_type();
219             let discr_ty = ty.to_ty(tcx);
220
221             let param_env_ty = self.param_env.and(discr_ty);
222             let size = tcx
223                 .layout_of(param_env_ty)
224                 .unwrap_or_else(|e| {
225                     panic!("could not compute layout for {:?}: {:?}", param_env_ty, e)
226                 })
227                 .size;
228
229             let lit = ScalarInt::try_from_uint(discr_offset as u128, size).unwrap();
230             let kind = ExprKind::NonHirLiteral { lit, user_ty: None };
231             let offset = self.thir.exprs.push(Expr { temp_lifetime, ty: discr_ty, span, kind });
232
233             let source = match discr_did {
234                 // in case we are offsetting from a computed discriminant
235                 // and not the beginning of discriminants (which is always `0`)
236                 Some(did) => {
237                     let kind = ExprKind::NamedConst { def_id: did, substs, user_ty: None };
238                     let lhs =
239                         self.thir.exprs.push(Expr { temp_lifetime, ty: discr_ty, span, kind });
240                     let bin = ExprKind::Binary { op: BinOp::Add, lhs, rhs: offset };
241                     self.thir.exprs.push(Expr {
242                         temp_lifetime,
243                         ty: discr_ty,
244                         span: span,
245                         kind: bin,
246                     })
247                 }
248                 None => offset,
249             };
250
251             ExprKind::Cast { source }
252         }
253     }
254
255     fn make_mirror_unadjusted(&mut self, expr: &'tcx hir::Expr<'tcx>) -> Expr<'tcx> {
256         let tcx = self.tcx;
257         let expr_ty = self.typeck_results().expr_ty(expr);
258         let expr_span = expr.span;
259         let temp_lifetime =
260             self.rvalue_scopes.temporary_scope(self.region_scope_tree, expr.hir_id.local_id);
261
262         let kind = match expr.kind {
263             // Here comes the interesting stuff:
264             hir::ExprKind::MethodCall(segment, ref args, fn_span) => {
265                 // Rewrite a.b(c) into UFCS form like Trait::b(a, c)
266                 let expr = self.method_callee(expr, segment.ident.span, None);
267                 // When we apply adjustments to the receiver, use the span of
268                 // the overall method call for better diagnostics. args[0]
269                 // is guaranteed to exist, since a method call always has a receiver.
270                 let old_adjustment_span = self.adjustment_span.replace((args[0].hir_id, expr_span));
271                 tracing::info!("Using method span: {:?}", expr.span);
272                 let args = self.mirror_exprs(args);
273                 self.adjustment_span = old_adjustment_span;
274                 ExprKind::Call {
275                     ty: expr.ty,
276                     fun: self.thir.exprs.push(expr),
277                     args,
278                     from_hir_call: true,
279                     fn_span,
280                 }
281             }
282
283             hir::ExprKind::Call(ref fun, ref args) => {
284                 if self.typeck_results().is_method_call(expr) {
285                     // The callee is something implementing Fn, FnMut, or FnOnce.
286                     // Find the actual method implementation being called and
287                     // build the appropriate UFCS call expression with the
288                     // callee-object as expr parameter.
289
290                     // rewrite f(u, v) into FnOnce::call_once(f, (u, v))
291
292                     let method = self.method_callee(expr, fun.span, None);
293
294                     let arg_tys = args.iter().map(|e| self.typeck_results().expr_ty_adjusted(e));
295                     let tupled_args = Expr {
296                         ty: tcx.mk_tup(arg_tys),
297                         temp_lifetime,
298                         span: expr.span,
299                         kind: ExprKind::Tuple { fields: self.mirror_exprs(args) },
300                     };
301                     let tupled_args = self.thir.exprs.push(tupled_args);
302
303                     ExprKind::Call {
304                         ty: method.ty,
305                         fun: self.thir.exprs.push(method),
306                         args: Box::new([self.mirror_expr(fun), tupled_args]),
307                         from_hir_call: true,
308                         fn_span: expr.span,
309                     }
310                 } else {
311                     let adt_data =
312                         if let hir::ExprKind::Path(hir::QPath::Resolved(_, ref path)) = fun.kind {
313                             // Tuple-like ADTs are represented as ExprKind::Call. We convert them here.
314                             expr_ty.ty_adt_def().and_then(|adt_def| match path.res {
315                                 Res::Def(DefKind::Ctor(_, CtorKind::Fn), ctor_id) => {
316                                     Some((adt_def, adt_def.variant_index_with_ctor_id(ctor_id)))
317                                 }
318                                 Res::SelfCtor(..) => Some((adt_def, VariantIdx::new(0))),
319                                 _ => None,
320                             })
321                         } else {
322                             None
323                         };
324                     if let Some((adt_def, index)) = adt_data {
325                         let substs = self.typeck_results().node_substs(fun.hir_id);
326                         let user_provided_types = self.typeck_results().user_provided_types();
327                         let user_ty =
328                             user_provided_types.get(fun.hir_id).copied().map(|mut u_ty| {
329                                 if let UserType::TypeOf(ref mut did, _) = &mut u_ty.value {
330                                     *did = adt_def.did();
331                                 }
332                                 Box::new(u_ty)
333                             });
334                         debug!("make_mirror_unadjusted: (call) user_ty={:?}", user_ty);
335
336                         let field_refs = args
337                             .iter()
338                             .enumerate()
339                             .map(|(idx, e)| FieldExpr {
340                                 name: Field::new(idx),
341                                 expr: self.mirror_expr(e),
342                             })
343                             .collect();
344                         ExprKind::Adt(Box::new(AdtExpr {
345                             adt_def,
346                             substs,
347                             variant_index: index,
348                             fields: field_refs,
349                             user_ty,
350                             base: None,
351                         }))
352                     } else {
353                         ExprKind::Call {
354                             ty: self.typeck_results().node_type(fun.hir_id),
355                             fun: self.mirror_expr(fun),
356                             args: self.mirror_exprs(args),
357                             from_hir_call: true,
358                             fn_span: expr.span,
359                         }
360                     }
361                 }
362             }
363
364             hir::ExprKind::AddrOf(hir::BorrowKind::Ref, mutbl, ref arg) => {
365                 ExprKind::Borrow { borrow_kind: mutbl.to_borrow_kind(), arg: self.mirror_expr(arg) }
366             }
367
368             hir::ExprKind::AddrOf(hir::BorrowKind::Raw, mutability, ref arg) => {
369                 ExprKind::AddressOf { mutability, arg: self.mirror_expr(arg) }
370             }
371
372             hir::ExprKind::Block(ref blk, _) => ExprKind::Block { block: self.mirror_block(blk) },
373
374             hir::ExprKind::Assign(ref lhs, ref rhs, _) => {
375                 ExprKind::Assign { lhs: self.mirror_expr(lhs), rhs: self.mirror_expr(rhs) }
376             }
377
378             hir::ExprKind::AssignOp(op, ref lhs, ref rhs) => {
379                 if self.typeck_results().is_method_call(expr) {
380                     let lhs = self.mirror_expr(lhs);
381                     let rhs = self.mirror_expr(rhs);
382                     self.overloaded_operator(expr, Box::new([lhs, rhs]))
383                 } else {
384                     ExprKind::AssignOp {
385                         op: bin_op(op.node),
386                         lhs: self.mirror_expr(lhs),
387                         rhs: self.mirror_expr(rhs),
388                     }
389                 }
390             }
391
392             hir::ExprKind::Lit(ref lit) => ExprKind::Literal { lit, neg: false },
393
394             hir::ExprKind::Binary(op, ref lhs, ref rhs) => {
395                 if self.typeck_results().is_method_call(expr) {
396                     let lhs = self.mirror_expr(lhs);
397                     let rhs = self.mirror_expr(rhs);
398                     self.overloaded_operator(expr, Box::new([lhs, rhs]))
399                 } else {
400                     // FIXME overflow
401                     match op.node {
402                         hir::BinOpKind::And => ExprKind::LogicalOp {
403                             op: LogicalOp::And,
404                             lhs: self.mirror_expr(lhs),
405                             rhs: self.mirror_expr(rhs),
406                         },
407                         hir::BinOpKind::Or => ExprKind::LogicalOp {
408                             op: LogicalOp::Or,
409                             lhs: self.mirror_expr(lhs),
410                             rhs: self.mirror_expr(rhs),
411                         },
412                         _ => {
413                             let op = bin_op(op.node);
414                             ExprKind::Binary {
415                                 op,
416                                 lhs: self.mirror_expr(lhs),
417                                 rhs: self.mirror_expr(rhs),
418                             }
419                         }
420                     }
421                 }
422             }
423
424             hir::ExprKind::Index(ref lhs, ref index) => {
425                 if self.typeck_results().is_method_call(expr) {
426                     let lhs = self.mirror_expr(lhs);
427                     let index = self.mirror_expr(index);
428                     self.overloaded_place(expr, expr_ty, None, Box::new([lhs, index]), expr.span)
429                 } else {
430                     ExprKind::Index { lhs: self.mirror_expr(lhs), index: self.mirror_expr(index) }
431                 }
432             }
433
434             hir::ExprKind::Unary(hir::UnOp::Deref, ref arg) => {
435                 if self.typeck_results().is_method_call(expr) {
436                     let arg = self.mirror_expr(arg);
437                     self.overloaded_place(expr, expr_ty, None, Box::new([arg]), expr.span)
438                 } else {
439                     ExprKind::Deref { arg: self.mirror_expr(arg) }
440                 }
441             }
442
443             hir::ExprKind::Unary(hir::UnOp::Not, ref arg) => {
444                 if self.typeck_results().is_method_call(expr) {
445                     let arg = self.mirror_expr(arg);
446                     self.overloaded_operator(expr, Box::new([arg]))
447                 } else {
448                     ExprKind::Unary { op: UnOp::Not, arg: self.mirror_expr(arg) }
449                 }
450             }
451
452             hir::ExprKind::Unary(hir::UnOp::Neg, ref arg) => {
453                 if self.typeck_results().is_method_call(expr) {
454                     let arg = self.mirror_expr(arg);
455                     self.overloaded_operator(expr, Box::new([arg]))
456                 } else if let hir::ExprKind::Lit(ref lit) = arg.kind {
457                     ExprKind::Literal { lit, neg: true }
458                 } else {
459                     ExprKind::Unary { op: UnOp::Neg, arg: self.mirror_expr(arg) }
460                 }
461             }
462
463             hir::ExprKind::Struct(ref qpath, ref fields, ref base) => match expr_ty.kind() {
464                 ty::Adt(adt, substs) => match adt.adt_kind() {
465                     AdtKind::Struct | AdtKind::Union => {
466                         let user_provided_types = self.typeck_results().user_provided_types();
467                         let user_ty = user_provided_types.get(expr.hir_id).copied().map(Box::new);
468                         debug!("make_mirror_unadjusted: (struct/union) user_ty={:?}", user_ty);
469                         ExprKind::Adt(Box::new(AdtExpr {
470                             adt_def: *adt,
471                             variant_index: VariantIdx::new(0),
472                             substs,
473                             user_ty,
474                             fields: self.field_refs(fields),
475                             base: base.as_ref().map(|base| FruInfo {
476                                 base: self.mirror_expr(base),
477                                 field_types: self.typeck_results().fru_field_types()[expr.hir_id]
478                                     .iter()
479                                     .copied()
480                                     .collect(),
481                             }),
482                         }))
483                     }
484                     AdtKind::Enum => {
485                         let res = self.typeck_results().qpath_res(qpath, expr.hir_id);
486                         match res {
487                             Res::Def(DefKind::Variant, variant_id) => {
488                                 assert!(base.is_none());
489
490                                 let index = adt.variant_index_with_id(variant_id);
491                                 let user_provided_types =
492                                     self.typeck_results().user_provided_types();
493                                 let user_ty =
494                                     user_provided_types.get(expr.hir_id).copied().map(Box::new);
495                                 debug!("make_mirror_unadjusted: (variant) user_ty={:?}", user_ty);
496                                 ExprKind::Adt(Box::new(AdtExpr {
497                                     adt_def: *adt,
498                                     variant_index: index,
499                                     substs,
500                                     user_ty,
501                                     fields: self.field_refs(fields),
502                                     base: None,
503                                 }))
504                             }
505                             _ => {
506                                 span_bug!(expr.span, "unexpected res: {:?}", res);
507                             }
508                         }
509                     }
510                 },
511                 _ => {
512                     span_bug!(expr.span, "unexpected type for struct literal: {:?}", expr_ty);
513                 }
514             },
515
516             hir::ExprKind::Closure { .. } => {
517                 let closure_ty = self.typeck_results().expr_ty(expr);
518                 let (def_id, substs, movability) = match *closure_ty.kind() {
519                     ty::Closure(def_id, substs) => (def_id, UpvarSubsts::Closure(substs), None),
520                     ty::Generator(def_id, substs, movability) => {
521                         (def_id, UpvarSubsts::Generator(substs), Some(movability))
522                     }
523                     _ => {
524                         span_bug!(expr.span, "closure expr w/o closure type: {:?}", closure_ty);
525                     }
526                 };
527                 let def_id = def_id.expect_local();
528
529                 let upvars = self
530                     .typeck_results
531                     .closure_min_captures_flattened(def_id)
532                     .zip(substs.upvar_tys())
533                     .map(|(captured_place, ty)| {
534                         let upvars = self.capture_upvar(expr, captured_place, ty);
535                         self.thir.exprs.push(upvars)
536                     })
537                     .collect();
538
539                 // Convert the closure fake reads, if any, from hir `Place` to ExprRef
540                 let fake_reads = match self.typeck_results.closure_fake_reads.get(&def_id) {
541                     Some(fake_reads) => fake_reads
542                         .iter()
543                         .map(|(place, cause, hir_id)| {
544                             let expr = self.convert_captured_hir_place(expr, place.clone());
545                             (self.thir.exprs.push(expr), *cause, *hir_id)
546                         })
547                         .collect(),
548                     None => Vec::new(),
549                 };
550
551                 ExprKind::Closure(Box::new(ClosureExpr {
552                     closure_id: def_id,
553                     substs,
554                     upvars,
555                     movability,
556                     fake_reads,
557                 }))
558             }
559
560             hir::ExprKind::Path(ref qpath) => {
561                 let res = self.typeck_results().qpath_res(qpath, expr.hir_id);
562                 self.convert_path_expr(expr, res)
563             }
564
565             hir::ExprKind::InlineAsm(ref asm) => ExprKind::InlineAsm(Box::new(InlineAsmExpr {
566                 template: asm.template,
567                 operands: asm
568                     .operands
569                     .iter()
570                     .map(|(op, _op_sp)| match *op {
571                         hir::InlineAsmOperand::In { reg, ref expr } => {
572                             InlineAsmOperand::In { reg, expr: self.mirror_expr(expr) }
573                         }
574                         hir::InlineAsmOperand::Out { reg, late, ref expr } => {
575                             InlineAsmOperand::Out {
576                                 reg,
577                                 late,
578                                 expr: expr.as_ref().map(|expr| self.mirror_expr(expr)),
579                             }
580                         }
581                         hir::InlineAsmOperand::InOut { reg, late, ref expr } => {
582                             InlineAsmOperand::InOut { reg, late, expr: self.mirror_expr(expr) }
583                         }
584                         hir::InlineAsmOperand::SplitInOut {
585                             reg,
586                             late,
587                             ref in_expr,
588                             ref out_expr,
589                         } => InlineAsmOperand::SplitInOut {
590                             reg,
591                             late,
592                             in_expr: self.mirror_expr(in_expr),
593                             out_expr: out_expr.as_ref().map(|expr| self.mirror_expr(expr)),
594                         },
595                         hir::InlineAsmOperand::Const { ref anon_const } => {
596                             let anon_const_def_id = tcx.hir().local_def_id(anon_const.hir_id);
597                             let value = mir::ConstantKind::from_anon_const(
598                                 tcx,
599                                 anon_const_def_id,
600                                 self.param_env,
601                             );
602                             let span = tcx.hir().span(anon_const.hir_id);
603
604                             InlineAsmOperand::Const { value, span }
605                         }
606                         hir::InlineAsmOperand::SymFn { ref anon_const } => {
607                             let anon_const_def_id = tcx.hir().local_def_id(anon_const.hir_id);
608                             let value = mir::ConstantKind::from_anon_const(
609                                 tcx,
610                                 anon_const_def_id,
611                                 self.param_env,
612                             );
613                             let span = tcx.hir().span(anon_const.hir_id);
614
615                             InlineAsmOperand::SymFn { value, span }
616                         }
617                         hir::InlineAsmOperand::SymStatic { path: _, def_id } => {
618                             InlineAsmOperand::SymStatic { def_id }
619                         }
620                     })
621                     .collect(),
622                 options: asm.options,
623                 line_spans: asm.line_spans,
624             })),
625
626             hir::ExprKind::ConstBlock(ref anon_const) => {
627                 let ty = self.typeck_results().node_type(anon_const.hir_id);
628                 let did = tcx.hir().local_def_id(anon_const.hir_id).to_def_id();
629                 let typeck_root_def_id = tcx.typeck_root_def_id(did);
630                 let parent_substs =
631                     tcx.erase_regions(InternalSubsts::identity_for_item(tcx, typeck_root_def_id));
632                 let substs =
633                     InlineConstSubsts::new(tcx, InlineConstSubstsParts { parent_substs, ty })
634                         .substs;
635
636                 ExprKind::ConstBlock { did, substs }
637             }
638             // Now comes the rote stuff:
639             hir::ExprKind::Repeat(ref v, _) => {
640                 let ty = self.typeck_results().expr_ty(expr);
641                 let ty::Array(_, count) = ty.kind() else {
642                     span_bug!(expr.span, "unexpected repeat expr ty: {:?}", ty);
643                 };
644
645                 ExprKind::Repeat { value: self.mirror_expr(v), count: *count }
646             }
647             hir::ExprKind::Ret(ref v) => {
648                 ExprKind::Return { value: v.as_ref().map(|v| self.mirror_expr(v)) }
649             }
650             hir::ExprKind::Break(dest, ref value) => match dest.target_id {
651                 Ok(target_id) => ExprKind::Break {
652                     label: region::Scope { id: target_id.local_id, data: region::ScopeData::Node },
653                     value: value.as_ref().map(|value| self.mirror_expr(value)),
654                 },
655                 Err(err) => bug!("invalid loop id for break: {}", err),
656             },
657             hir::ExprKind::Continue(dest) => match dest.target_id {
658                 Ok(loop_id) => ExprKind::Continue {
659                     label: region::Scope { id: loop_id.local_id, data: region::ScopeData::Node },
660                 },
661                 Err(err) => bug!("invalid loop id for continue: {}", err),
662             },
663             hir::ExprKind::Let(let_expr) => ExprKind::Let {
664                 expr: self.mirror_expr(let_expr.init),
665                 pat: self.pattern_from_hir(let_expr.pat),
666             },
667             hir::ExprKind::If(cond, then, else_opt) => ExprKind::If {
668                 if_then_scope: region::Scope {
669                     id: then.hir_id.local_id,
670                     data: region::ScopeData::IfThen,
671                 },
672                 cond: self.mirror_expr(cond),
673                 then: self.mirror_expr(then),
674                 else_opt: else_opt.map(|el| self.mirror_expr(el)),
675             },
676             hir::ExprKind::Match(ref discr, ref arms, _) => ExprKind::Match {
677                 scrutinee: self.mirror_expr(discr),
678                 arms: arms.iter().map(|a| self.convert_arm(a)).collect(),
679             },
680             hir::ExprKind::Loop(ref body, ..) => {
681                 let block_ty = self.typeck_results().node_type(body.hir_id);
682                 let temp_lifetime = self
683                     .rvalue_scopes
684                     .temporary_scope(self.region_scope_tree, body.hir_id.local_id);
685                 let block = self.mirror_block(body);
686                 let body = self.thir.exprs.push(Expr {
687                     ty: block_ty,
688                     temp_lifetime,
689                     span: self.thir[block].span,
690                     kind: ExprKind::Block { block },
691                 });
692                 ExprKind::Loop { body }
693             }
694             hir::ExprKind::Field(ref source, ..) => ExprKind::Field {
695                 lhs: self.mirror_expr(source),
696                 variant_index: VariantIdx::new(0),
697                 name: Field::new(tcx.field_index(expr.hir_id, self.typeck_results)),
698             },
699             hir::ExprKind::Cast(ref source, ref cast_ty) => {
700                 // Check for a user-given type annotation on this `cast`
701                 let user_provided_types = self.typeck_results.user_provided_types();
702                 let user_ty = user_provided_types.get(cast_ty.hir_id);
703
704                 debug!(
705                     "cast({:?}) has ty w/ hir_id {:?} and user provided ty {:?}",
706                     expr, cast_ty.hir_id, user_ty,
707                 );
708
709                 let cast = self.mirror_expr_cast(*source, temp_lifetime, expr.span);
710
711                 if let Some(user_ty) = user_ty {
712                     // NOTE: Creating a new Expr and wrapping a Cast inside of it may be
713                     //       inefficient, revisit this when performance becomes an issue.
714                     let cast_expr = self.thir.exprs.push(Expr {
715                         temp_lifetime,
716                         ty: expr_ty,
717                         span: expr.span,
718                         kind: cast,
719                     });
720                     debug!("make_mirror_unadjusted: (cast) user_ty={:?}", user_ty);
721
722                     ExprKind::ValueTypeAscription {
723                         source: cast_expr,
724                         user_ty: Some(Box::new(*user_ty)),
725                     }
726                 } else {
727                     cast
728                 }
729             }
730             hir::ExprKind::Type(ref source, ref ty) => {
731                 let user_provided_types = self.typeck_results.user_provided_types();
732                 let user_ty = user_provided_types.get(ty.hir_id).copied().map(Box::new);
733                 debug!("make_mirror_unadjusted: (type) user_ty={:?}", user_ty);
734                 let mirrored = self.mirror_expr(source);
735                 if source.is_syntactic_place_expr() {
736                     ExprKind::PlaceTypeAscription { source: mirrored, user_ty }
737                 } else {
738                     ExprKind::ValueTypeAscription { source: mirrored, user_ty }
739                 }
740             }
741             hir::ExprKind::DropTemps(ref source) => {
742                 ExprKind::Use { source: self.mirror_expr(source) }
743             }
744             hir::ExprKind::Box(ref value) => ExprKind::Box { value: self.mirror_expr(value) },
745             hir::ExprKind::Array(ref fields) => {
746                 ExprKind::Array { fields: self.mirror_exprs(fields) }
747             }
748             hir::ExprKind::Tup(ref fields) => ExprKind::Tuple { fields: self.mirror_exprs(fields) },
749
750             hir::ExprKind::Yield(ref v, _) => ExprKind::Yield { value: self.mirror_expr(v) },
751             hir::ExprKind::Err => unreachable!(),
752         };
753
754         Expr { temp_lifetime, ty: expr_ty, span: expr.span, kind }
755     }
756
757     fn user_substs_applied_to_res(
758         &mut self,
759         hir_id: hir::HirId,
760         res: Res,
761     ) -> Option<Box<ty::CanonicalUserType<'tcx>>> {
762         debug!("user_substs_applied_to_res: res={:?}", res);
763         let user_provided_type = match res {
764             // A reference to something callable -- e.g., a fn, method, or
765             // a tuple-struct or tuple-variant. This has the type of a
766             // `Fn` but with the user-given substitutions.
767             Res::Def(DefKind::Fn, _)
768             | Res::Def(DefKind::AssocFn, _)
769             | Res::Def(DefKind::Ctor(_, CtorKind::Fn), _)
770             | Res::Def(DefKind::Const, _)
771             | Res::Def(DefKind::AssocConst, _) => {
772                 self.typeck_results().user_provided_types().get(hir_id).copied().map(Box::new)
773             }
774
775             // A unit struct/variant which is used as a value (e.g.,
776             // `None`). This has the type of the enum/struct that defines
777             // this variant -- but with the substitutions given by the
778             // user.
779             Res::Def(DefKind::Ctor(_, CtorKind::Const), _) => {
780                 self.user_substs_applied_to_ty_of_hir_id(hir_id).map(Box::new)
781             }
782
783             // `Self` is used in expression as a tuple struct constructor or a unit struct constructor
784             Res::SelfCtor(_) => self.user_substs_applied_to_ty_of_hir_id(hir_id).map(Box::new),
785
786             _ => bug!("user_substs_applied_to_res: unexpected res {:?} at {:?}", res, hir_id),
787         };
788         debug!("user_substs_applied_to_res: user_provided_type={:?}", user_provided_type);
789         user_provided_type
790     }
791
792     fn method_callee(
793         &mut self,
794         expr: &hir::Expr<'_>,
795         span: Span,
796         overloaded_callee: Option<(DefId, SubstsRef<'tcx>)>,
797     ) -> Expr<'tcx> {
798         let temp_lifetime =
799             self.rvalue_scopes.temporary_scope(self.region_scope_tree, expr.hir_id.local_id);
800         let (def_id, substs, user_ty) = match overloaded_callee {
801             Some((def_id, substs)) => (def_id, substs, None),
802             None => {
803                 let (kind, def_id) =
804                     self.typeck_results().type_dependent_def(expr.hir_id).unwrap_or_else(|| {
805                         span_bug!(expr.span, "no type-dependent def for method callee")
806                     });
807                 let user_ty = self.user_substs_applied_to_res(expr.hir_id, Res::Def(kind, def_id));
808                 debug!("method_callee: user_ty={:?}", user_ty);
809                 (def_id, self.typeck_results().node_substs(expr.hir_id), user_ty)
810             }
811         };
812         let ty = self.tcx().mk_fn_def(def_id, substs);
813         Expr { temp_lifetime, ty, span, kind: ExprKind::ZstLiteral { user_ty } }
814     }
815
816     fn convert_arm(&mut self, arm: &'tcx hir::Arm<'tcx>) -> ArmId {
817         let arm = Arm {
818             pattern: self.pattern_from_hir(&arm.pat),
819             guard: arm.guard.as_ref().map(|g| match g {
820                 hir::Guard::If(ref e) => Guard::If(self.mirror_expr(e)),
821                 hir::Guard::IfLet(ref l) => {
822                     Guard::IfLet(self.pattern_from_hir(l.pat), self.mirror_expr(l.init))
823                 }
824             }),
825             body: self.mirror_expr(arm.body),
826             lint_level: LintLevel::Explicit(arm.hir_id),
827             scope: region::Scope { id: arm.hir_id.local_id, data: region::ScopeData::Node },
828             span: arm.span,
829         };
830         self.thir.arms.push(arm)
831     }
832
833     fn convert_path_expr(&mut self, expr: &'tcx hir::Expr<'tcx>, res: Res) -> ExprKind<'tcx> {
834         let substs = self.typeck_results().node_substs(expr.hir_id);
835         match res {
836             // A regular function, constructor function or a constant.
837             Res::Def(DefKind::Fn, _)
838             | Res::Def(DefKind::AssocFn, _)
839             | Res::Def(DefKind::Ctor(_, CtorKind::Fn), _)
840             | Res::SelfCtor(_) => {
841                 let user_ty = self.user_substs_applied_to_res(expr.hir_id, res);
842                 ExprKind::ZstLiteral { user_ty }
843             }
844
845             Res::Def(DefKind::ConstParam, def_id) => {
846                 let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
847                 let item_id = self.tcx.hir().get_parent_node(hir_id);
848                 let item_def_id = self.tcx.hir().local_def_id(item_id);
849                 let generics = self.tcx.generics_of(item_def_id);
850                 let index = generics.param_def_id_to_index[&def_id];
851                 let name = self.tcx.hir().name(hir_id);
852                 let param = ty::ParamConst::new(index, name);
853
854                 ExprKind::ConstParam { param, def_id }
855             }
856
857             Res::Def(DefKind::Const, def_id) | Res::Def(DefKind::AssocConst, def_id) => {
858                 let user_ty = self.user_substs_applied_to_res(expr.hir_id, res);
859                 ExprKind::NamedConst { def_id, substs, user_ty }
860             }
861
862             Res::Def(DefKind::Ctor(_, CtorKind::Const), def_id) => {
863                 let user_provided_types = self.typeck_results.user_provided_types();
864                 let user_ty = user_provided_types.get(expr.hir_id).copied().map(Box::new);
865                 debug!("convert_path_expr: user_ty={:?}", user_ty);
866                 let ty = self.typeck_results().node_type(expr.hir_id);
867                 match ty.kind() {
868                     // A unit struct/variant which is used as a value.
869                     // We return a completely different ExprKind here to account for this special case.
870                     ty::Adt(adt_def, substs) => ExprKind::Adt(Box::new(AdtExpr {
871                         adt_def: *adt_def,
872                         variant_index: adt_def.variant_index_with_ctor_id(def_id),
873                         substs,
874                         user_ty,
875                         fields: Box::new([]),
876                         base: None,
877                     })),
878                     _ => bug!("unexpected ty: {:?}", ty),
879                 }
880             }
881
882             // We encode uses of statics as a `*&STATIC` where the `&STATIC` part is
883             // a constant reference (or constant raw pointer for `static mut`) in MIR
884             Res::Def(DefKind::Static(_), id) => {
885                 let ty = self.tcx.static_ptr_ty(id);
886                 let temp_lifetime = self
887                     .rvalue_scopes
888                     .temporary_scope(self.region_scope_tree, expr.hir_id.local_id);
889                 let kind = if self.tcx.is_thread_local_static(id) {
890                     ExprKind::ThreadLocalRef(id)
891                 } else {
892                     let alloc_id = self.tcx.create_static_alloc(id);
893                     ExprKind::StaticRef { alloc_id, ty, def_id: id }
894                 };
895                 ExprKind::Deref {
896                     arg: self.thir.exprs.push(Expr { ty, temp_lifetime, span: expr.span, kind }),
897                 }
898             }
899
900             Res::Local(var_hir_id) => self.convert_var(var_hir_id),
901
902             _ => span_bug!(expr.span, "res `{:?}` not yet implemented", res),
903         }
904     }
905
906     fn convert_var(&mut self, var_hir_id: hir::HirId) -> ExprKind<'tcx> {
907         // We want upvars here not captures.
908         // Captures will be handled in MIR.
909         let is_upvar = self
910             .tcx
911             .upvars_mentioned(self.body_owner)
912             .map_or(false, |upvars| upvars.contains_key(&var_hir_id));
913
914         debug!(
915             "convert_var({:?}): is_upvar={}, body_owner={:?}",
916             var_hir_id, is_upvar, self.body_owner
917         );
918
919         if is_upvar {
920             ExprKind::UpvarRef {
921                 closure_def_id: self.body_owner,
922                 var_hir_id: LocalVarId(var_hir_id),
923             }
924         } else {
925             ExprKind::VarRef { id: LocalVarId(var_hir_id) }
926         }
927     }
928
929     fn overloaded_operator(
930         &mut self,
931         expr: &'tcx hir::Expr<'tcx>,
932         args: Box<[ExprId]>,
933     ) -> ExprKind<'tcx> {
934         let fun = self.method_callee(expr, expr.span, None);
935         let fun = self.thir.exprs.push(fun);
936         ExprKind::Call {
937             ty: self.thir[fun].ty,
938             fun,
939             args,
940             from_hir_call: false,
941             fn_span: expr.span,
942         }
943     }
944
945     fn overloaded_place(
946         &mut self,
947         expr: &'tcx hir::Expr<'tcx>,
948         place_ty: Ty<'tcx>,
949         overloaded_callee: Option<(DefId, SubstsRef<'tcx>)>,
950         args: Box<[ExprId]>,
951         span: Span,
952     ) -> ExprKind<'tcx> {
953         // For an overloaded *x or x[y] expression of type T, the method
954         // call returns an &T and we must add the deref so that the types
955         // line up (this is because `*x` and `x[y]` represent places):
956
957         // Reconstruct the output assuming it's a reference with the
958         // same region and mutability as the receiver. This holds for
959         // `Deref(Mut)::Deref(_mut)` and `Index(Mut)::index(_mut)`.
960         let ty::Ref(region, _, mutbl) = *self.thir[args[0]].ty.kind() else {
961             span_bug!(span, "overloaded_place: receiver is not a reference");
962         };
963         let ref_ty = self.tcx.mk_ref(region, ty::TypeAndMut { ty: place_ty, mutbl });
964
965         // construct the complete expression `foo()` for the overloaded call,
966         // which will yield the &T type
967         let temp_lifetime =
968             self.rvalue_scopes.temporary_scope(self.region_scope_tree, expr.hir_id.local_id);
969         let fun = self.method_callee(expr, span, overloaded_callee);
970         let fun = self.thir.exprs.push(fun);
971         let fun_ty = self.thir[fun].ty;
972         let ref_expr = self.thir.exprs.push(Expr {
973             temp_lifetime,
974             ty: ref_ty,
975             span,
976             kind: ExprKind::Call { ty: fun_ty, fun, args, from_hir_call: false, fn_span: span },
977         });
978
979         // construct and return a deref wrapper `*foo()`
980         ExprKind::Deref { arg: ref_expr }
981     }
982
983     fn convert_captured_hir_place(
984         &mut self,
985         closure_expr: &'tcx hir::Expr<'tcx>,
986         place: HirPlace<'tcx>,
987     ) -> Expr<'tcx> {
988         let temp_lifetime = self
989             .rvalue_scopes
990             .temporary_scope(self.region_scope_tree, closure_expr.hir_id.local_id);
991         let var_ty = place.base_ty;
992
993         // The result of capture analysis in `rustc_typeck/check/upvar.rs`represents a captured path
994         // as it's seen for use within the closure and not at the time of closure creation.
995         //
996         // That is we see expect to see it start from a captured upvar and not something that is local
997         // to the closure's parent.
998         let var_hir_id = match place.base {
999             HirPlaceBase::Upvar(upvar_id) => upvar_id.var_path.hir_id,
1000             base => bug!("Expected an upvar, found {:?}", base),
1001         };
1002
1003         let mut captured_place_expr = Expr {
1004             temp_lifetime,
1005             ty: var_ty,
1006             span: closure_expr.span,
1007             kind: self.convert_var(var_hir_id),
1008         };
1009
1010         for proj in place.projections.iter() {
1011             let kind = match proj.kind {
1012                 HirProjectionKind::Deref => {
1013                     ExprKind::Deref { arg: self.thir.exprs.push(captured_place_expr) }
1014                 }
1015                 HirProjectionKind::Field(field, variant_index) => ExprKind::Field {
1016                     lhs: self.thir.exprs.push(captured_place_expr),
1017                     variant_index,
1018                     name: Field::new(field as usize),
1019                 },
1020                 HirProjectionKind::Index | HirProjectionKind::Subslice => {
1021                     // We don't capture these projections, so we can ignore them here
1022                     continue;
1023                 }
1024             };
1025
1026             captured_place_expr =
1027                 Expr { temp_lifetime, ty: proj.ty, span: closure_expr.span, kind };
1028         }
1029
1030         captured_place_expr
1031     }
1032
1033     fn capture_upvar(
1034         &mut self,
1035         closure_expr: &'tcx hir::Expr<'tcx>,
1036         captured_place: &'tcx ty::CapturedPlace<'tcx>,
1037         upvar_ty: Ty<'tcx>,
1038     ) -> Expr<'tcx> {
1039         let upvar_capture = captured_place.info.capture_kind;
1040         let captured_place_expr =
1041             self.convert_captured_hir_place(closure_expr, captured_place.place.clone());
1042         let temp_lifetime = self
1043             .rvalue_scopes
1044             .temporary_scope(self.region_scope_tree, closure_expr.hir_id.local_id);
1045
1046         match upvar_capture {
1047             ty::UpvarCapture::ByValue => captured_place_expr,
1048             ty::UpvarCapture::ByRef(upvar_borrow) => {
1049                 let borrow_kind = match upvar_borrow {
1050                     ty::BorrowKind::ImmBorrow => BorrowKind::Shared,
1051                     ty::BorrowKind::UniqueImmBorrow => BorrowKind::Unique,
1052                     ty::BorrowKind::MutBorrow => BorrowKind::Mut { allow_two_phase_borrow: false },
1053                 };
1054                 Expr {
1055                     temp_lifetime,
1056                     ty: upvar_ty,
1057                     span: closure_expr.span,
1058                     kind: ExprKind::Borrow {
1059                         borrow_kind,
1060                         arg: self.thir.exprs.push(captured_place_expr),
1061                     },
1062                 }
1063             }
1064         }
1065     }
1066
1067     /// Converts a list of named fields (i.e., for struct-like struct/enum ADTs) into FieldExpr.
1068     fn field_refs(&mut self, fields: &'tcx [hir::ExprField<'tcx>]) -> Box<[FieldExpr]> {
1069         fields
1070             .iter()
1071             .map(|field| FieldExpr {
1072                 name: Field::new(self.tcx.field_index(field.hir_id, self.typeck_results)),
1073                 expr: self.mirror_expr(field.expr),
1074             })
1075             .collect()
1076     }
1077 }
1078
1079 trait ToBorrowKind {
1080     fn to_borrow_kind(&self) -> BorrowKind;
1081 }
1082
1083 impl ToBorrowKind for AutoBorrowMutability {
1084     fn to_borrow_kind(&self) -> BorrowKind {
1085         use rustc_middle::ty::adjustment::AllowTwoPhase;
1086         match *self {
1087             AutoBorrowMutability::Mut { allow_two_phase_borrow } => BorrowKind::Mut {
1088                 allow_two_phase_borrow: match allow_two_phase_borrow {
1089                     AllowTwoPhase::Yes => true,
1090                     AllowTwoPhase::No => false,
1091                 },
1092             },
1093             AutoBorrowMutability::Not => BorrowKind::Shared,
1094         }
1095     }
1096 }
1097
1098 impl ToBorrowKind for hir::Mutability {
1099     fn to_borrow_kind(&self) -> BorrowKind {
1100         match *self {
1101             hir::Mutability::Mut => BorrowKind::Mut { allow_two_phase_borrow: false },
1102             hir::Mutability::Not => BorrowKind::Shared,
1103         }
1104     }
1105 }
1106
1107 fn bin_op(op: hir::BinOpKind) -> BinOp {
1108     match op {
1109         hir::BinOpKind::Add => BinOp::Add,
1110         hir::BinOpKind::Sub => BinOp::Sub,
1111         hir::BinOpKind::Mul => BinOp::Mul,
1112         hir::BinOpKind::Div => BinOp::Div,
1113         hir::BinOpKind::Rem => BinOp::Rem,
1114         hir::BinOpKind::BitXor => BinOp::BitXor,
1115         hir::BinOpKind::BitAnd => BinOp::BitAnd,
1116         hir::BinOpKind::BitOr => BinOp::BitOr,
1117         hir::BinOpKind::Shl => BinOp::Shl,
1118         hir::BinOpKind::Shr => BinOp::Shr,
1119         hir::BinOpKind::Eq => BinOp::Eq,
1120         hir::BinOpKind::Lt => BinOp::Lt,
1121         hir::BinOpKind::Le => BinOp::Le,
1122         hir::BinOpKind::Ne => BinOp::Ne,
1123         hir::BinOpKind::Ge => BinOp::Ge,
1124         hir::BinOpKind::Gt => BinOp::Gt,
1125         _ => bug!("no equivalent for ast binop {:?}", op),
1126     }
1127 }