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