]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_mir_build/src/thir/cx/expr.rs
Auto merge of #101437 - compiler-errors:erase-normalize-ordering, r=tmandry
[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, receiver, 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 =
271                     self.adjustment_span.replace((receiver.hir_id, expr_span));
272                 info!("Using method span: {:?}", expr.span);
273                 let args = std::iter::once(receiver)
274                     .chain(args.iter())
275                     .map(|expr| self.mirror_expr(expr))
276                     .collect();
277                 self.adjustment_span = old_adjustment_span;
278                 ExprKind::Call {
279                     ty: expr.ty,
280                     fun: self.thir.exprs.push(expr),
281                     args,
282                     from_hir_call: true,
283                     fn_span,
284                 }
285             }
286
287             hir::ExprKind::Call(ref fun, ref args) => {
288                 if self.typeck_results().is_method_call(expr) {
289                     // The callee is something implementing Fn, FnMut, or FnOnce.
290                     // Find the actual method implementation being called and
291                     // build the appropriate UFCS call expression with the
292                     // callee-object as expr parameter.
293
294                     // rewrite f(u, v) into FnOnce::call_once(f, (u, v))
295
296                     let method = self.method_callee(expr, fun.span, None);
297
298                     let arg_tys = args.iter().map(|e| self.typeck_results().expr_ty_adjusted(e));
299                     let tupled_args = Expr {
300                         ty: tcx.mk_tup(arg_tys),
301                         temp_lifetime,
302                         span: expr.span,
303                         kind: ExprKind::Tuple { fields: self.mirror_exprs(args) },
304                     };
305                     let tupled_args = self.thir.exprs.push(tupled_args);
306
307                     ExprKind::Call {
308                         ty: method.ty,
309                         fun: self.thir.exprs.push(method),
310                         args: Box::new([self.mirror_expr(fun), tupled_args]),
311                         from_hir_call: true,
312                         fn_span: expr.span,
313                     }
314                 } else {
315                     let adt_data =
316                         if let hir::ExprKind::Path(hir::QPath::Resolved(_, ref path)) = fun.kind {
317                             // Tuple-like ADTs are represented as ExprKind::Call. We convert them here.
318                             expr_ty.ty_adt_def().and_then(|adt_def| match path.res {
319                                 Res::Def(DefKind::Ctor(_, CtorKind::Fn), ctor_id) => {
320                                     Some((adt_def, adt_def.variant_index_with_ctor_id(ctor_id)))
321                                 }
322                                 Res::SelfCtor(..) => Some((adt_def, VariantIdx::new(0))),
323                                 _ => None,
324                             })
325                         } else {
326                             None
327                         };
328                     if let Some((adt_def, index)) = adt_data {
329                         let substs = self.typeck_results().node_substs(fun.hir_id);
330                         let user_provided_types = self.typeck_results().user_provided_types();
331                         let user_ty =
332                             user_provided_types.get(fun.hir_id).copied().map(|mut u_ty| {
333                                 if let UserType::TypeOf(ref mut did, _) = &mut u_ty.value {
334                                     *did = adt_def.did();
335                                 }
336                                 Box::new(u_ty)
337                             });
338                         debug!("make_mirror_unadjusted: (call) user_ty={:?}", user_ty);
339
340                         let field_refs = args
341                             .iter()
342                             .enumerate()
343                             .map(|(idx, e)| FieldExpr {
344                                 name: Field::new(idx),
345                                 expr: self.mirror_expr(e),
346                             })
347                             .collect();
348                         ExprKind::Adt(Box::new(AdtExpr {
349                             adt_def,
350                             substs,
351                             variant_index: index,
352                             fields: field_refs,
353                             user_ty,
354                             base: None,
355                         }))
356                     } else {
357                         ExprKind::Call {
358                             ty: self.typeck_results().node_type(fun.hir_id),
359                             fun: self.mirror_expr(fun),
360                             args: self.mirror_exprs(args),
361                             from_hir_call: true,
362                             fn_span: expr.span,
363                         }
364                     }
365                 }
366             }
367
368             hir::ExprKind::AddrOf(hir::BorrowKind::Ref, mutbl, ref arg) => {
369                 ExprKind::Borrow { borrow_kind: mutbl.to_borrow_kind(), arg: self.mirror_expr(arg) }
370             }
371
372             hir::ExprKind::AddrOf(hir::BorrowKind::Raw, mutability, ref arg) => {
373                 ExprKind::AddressOf { mutability, arg: self.mirror_expr(arg) }
374             }
375
376             hir::ExprKind::Block(ref blk, _) => ExprKind::Block { block: self.mirror_block(blk) },
377
378             hir::ExprKind::Assign(ref lhs, ref rhs, _) => {
379                 ExprKind::Assign { lhs: self.mirror_expr(lhs), rhs: self.mirror_expr(rhs) }
380             }
381
382             hir::ExprKind::AssignOp(op, ref lhs, ref rhs) => {
383                 if self.typeck_results().is_method_call(expr) {
384                     let lhs = self.mirror_expr(lhs);
385                     let rhs = self.mirror_expr(rhs);
386                     self.overloaded_operator(expr, Box::new([lhs, rhs]))
387                 } else {
388                     ExprKind::AssignOp {
389                         op: bin_op(op.node),
390                         lhs: self.mirror_expr(lhs),
391                         rhs: self.mirror_expr(rhs),
392                     }
393                 }
394             }
395
396             hir::ExprKind::Lit(ref lit) => ExprKind::Literal { lit, neg: false },
397
398             hir::ExprKind::Binary(op, ref lhs, ref rhs) => {
399                 if self.typeck_results().is_method_call(expr) {
400                     let lhs = self.mirror_expr(lhs);
401                     let rhs = self.mirror_expr(rhs);
402                     self.overloaded_operator(expr, Box::new([lhs, rhs]))
403                 } else {
404                     // FIXME overflow
405                     match op.node {
406                         hir::BinOpKind::And => ExprKind::LogicalOp {
407                             op: LogicalOp::And,
408                             lhs: self.mirror_expr(lhs),
409                             rhs: self.mirror_expr(rhs),
410                         },
411                         hir::BinOpKind::Or => ExprKind::LogicalOp {
412                             op: LogicalOp::Or,
413                             lhs: self.mirror_expr(lhs),
414                             rhs: self.mirror_expr(rhs),
415                         },
416                         _ => {
417                             let op = bin_op(op.node);
418                             ExprKind::Binary {
419                                 op,
420                                 lhs: self.mirror_expr(lhs),
421                                 rhs: self.mirror_expr(rhs),
422                             }
423                         }
424                     }
425                 }
426             }
427
428             hir::ExprKind::Index(ref lhs, ref index) => {
429                 if self.typeck_results().is_method_call(expr) {
430                     let lhs = self.mirror_expr(lhs);
431                     let index = self.mirror_expr(index);
432                     self.overloaded_place(expr, expr_ty, None, Box::new([lhs, index]), expr.span)
433                 } else {
434                     ExprKind::Index { lhs: self.mirror_expr(lhs), index: self.mirror_expr(index) }
435                 }
436             }
437
438             hir::ExprKind::Unary(hir::UnOp::Deref, ref arg) => {
439                 if self.typeck_results().is_method_call(expr) {
440                     let arg = self.mirror_expr(arg);
441                     self.overloaded_place(expr, expr_ty, None, Box::new([arg]), expr.span)
442                 } else {
443                     ExprKind::Deref { arg: self.mirror_expr(arg) }
444                 }
445             }
446
447             hir::ExprKind::Unary(hir::UnOp::Not, ref arg) => {
448                 if self.typeck_results().is_method_call(expr) {
449                     let arg = self.mirror_expr(arg);
450                     self.overloaded_operator(expr, Box::new([arg]))
451                 } else {
452                     ExprKind::Unary { op: UnOp::Not, arg: self.mirror_expr(arg) }
453                 }
454             }
455
456             hir::ExprKind::Unary(hir::UnOp::Neg, ref arg) => {
457                 if self.typeck_results().is_method_call(expr) {
458                     let arg = self.mirror_expr(arg);
459                     self.overloaded_operator(expr, Box::new([arg]))
460                 } else if let hir::ExprKind::Lit(ref lit) = arg.kind {
461                     ExprKind::Literal { lit, neg: true }
462                 } else {
463                     ExprKind::Unary { op: UnOp::Neg, arg: self.mirror_expr(arg) }
464                 }
465             }
466
467             hir::ExprKind::Struct(ref qpath, ref fields, ref base) => match expr_ty.kind() {
468                 ty::Adt(adt, substs) => match adt.adt_kind() {
469                     AdtKind::Struct | AdtKind::Union => {
470                         let user_provided_types = self.typeck_results().user_provided_types();
471                         let user_ty = user_provided_types.get(expr.hir_id).copied().map(Box::new);
472                         debug!("make_mirror_unadjusted: (struct/union) user_ty={:?}", user_ty);
473                         ExprKind::Adt(Box::new(AdtExpr {
474                             adt_def: *adt,
475                             variant_index: VariantIdx::new(0),
476                             substs,
477                             user_ty,
478                             fields: self.field_refs(fields),
479                             base: base.as_ref().map(|base| FruInfo {
480                                 base: self.mirror_expr(base),
481                                 field_types: self.typeck_results().fru_field_types()[expr.hir_id]
482                                     .iter()
483                                     .copied()
484                                     .collect(),
485                             }),
486                         }))
487                     }
488                     AdtKind::Enum => {
489                         let res = self.typeck_results().qpath_res(qpath, expr.hir_id);
490                         match res {
491                             Res::Def(DefKind::Variant, variant_id) => {
492                                 assert!(base.is_none());
493
494                                 let index = adt.variant_index_with_id(variant_id);
495                                 let user_provided_types =
496                                     self.typeck_results().user_provided_types();
497                                 let user_ty =
498                                     user_provided_types.get(expr.hir_id).copied().map(Box::new);
499                                 debug!("make_mirror_unadjusted: (variant) user_ty={:?}", user_ty);
500                                 ExprKind::Adt(Box::new(AdtExpr {
501                                     adt_def: *adt,
502                                     variant_index: index,
503                                     substs,
504                                     user_ty,
505                                     fields: self.field_refs(fields),
506                                     base: None,
507                                 }))
508                             }
509                             _ => {
510                                 span_bug!(expr.span, "unexpected res: {:?}", res);
511                             }
512                         }
513                     }
514                 },
515                 _ => {
516                     span_bug!(expr.span, "unexpected type for struct literal: {:?}", expr_ty);
517                 }
518             },
519
520             hir::ExprKind::Closure { .. } => {
521                 let closure_ty = self.typeck_results().expr_ty(expr);
522                 let (def_id, substs, movability) = match *closure_ty.kind() {
523                     ty::Closure(def_id, substs) => (def_id, UpvarSubsts::Closure(substs), None),
524                     ty::Generator(def_id, substs, movability) => {
525                         (def_id, UpvarSubsts::Generator(substs), Some(movability))
526                     }
527                     _ => {
528                         span_bug!(expr.span, "closure expr w/o closure type: {:?}", closure_ty);
529                     }
530                 };
531                 let def_id = def_id.expect_local();
532
533                 let upvars = self
534                     .typeck_results
535                     .closure_min_captures_flattened(def_id)
536                     .zip(substs.upvar_tys())
537                     .map(|(captured_place, ty)| {
538                         let upvars = self.capture_upvar(expr, captured_place, ty);
539                         self.thir.exprs.push(upvars)
540                     })
541                     .collect();
542
543                 // Convert the closure fake reads, if any, from hir `Place` to ExprRef
544                 let fake_reads = match self.typeck_results.closure_fake_reads.get(&def_id) {
545                     Some(fake_reads) => fake_reads
546                         .iter()
547                         .map(|(place, cause, hir_id)| {
548                             let expr = self.convert_captured_hir_place(expr, place.clone());
549                             (self.thir.exprs.push(expr), *cause, *hir_id)
550                         })
551                         .collect(),
552                     None => Vec::new(),
553                 };
554
555                 ExprKind::Closure(Box::new(ClosureExpr {
556                     closure_id: def_id,
557                     substs,
558                     upvars,
559                     movability,
560                     fake_reads,
561                 }))
562             }
563
564             hir::ExprKind::Path(ref qpath) => {
565                 let res = self.typeck_results().qpath_res(qpath, expr.hir_id);
566                 self.convert_path_expr(expr, res)
567             }
568
569             hir::ExprKind::InlineAsm(ref asm) => ExprKind::InlineAsm(Box::new(InlineAsmExpr {
570                 template: asm.template,
571                 operands: asm
572                     .operands
573                     .iter()
574                     .map(|(op, _op_sp)| match *op {
575                         hir::InlineAsmOperand::In { reg, ref expr } => {
576                             InlineAsmOperand::In { reg, expr: self.mirror_expr(expr) }
577                         }
578                         hir::InlineAsmOperand::Out { reg, late, ref expr } => {
579                             InlineAsmOperand::Out {
580                                 reg,
581                                 late,
582                                 expr: expr.as_ref().map(|expr| self.mirror_expr(expr)),
583                             }
584                         }
585                         hir::InlineAsmOperand::InOut { reg, late, ref expr } => {
586                             InlineAsmOperand::InOut { reg, late, expr: self.mirror_expr(expr) }
587                         }
588                         hir::InlineAsmOperand::SplitInOut {
589                             reg,
590                             late,
591                             ref in_expr,
592                             ref out_expr,
593                         } => InlineAsmOperand::SplitInOut {
594                             reg,
595                             late,
596                             in_expr: self.mirror_expr(in_expr),
597                             out_expr: out_expr.as_ref().map(|expr| self.mirror_expr(expr)),
598                         },
599                         hir::InlineAsmOperand::Const { ref anon_const } => {
600                             let anon_const_def_id = tcx.hir().local_def_id(anon_const.hir_id);
601                             let value = mir::ConstantKind::from_anon_const(
602                                 tcx,
603                                 anon_const_def_id,
604                                 self.param_env,
605                             );
606                             let span = tcx.hir().span(anon_const.hir_id);
607
608                             InlineAsmOperand::Const { value, span }
609                         }
610                         hir::InlineAsmOperand::SymFn { ref anon_const } => {
611                             let anon_const_def_id = tcx.hir().local_def_id(anon_const.hir_id);
612                             let value = mir::ConstantKind::from_anon_const(
613                                 tcx,
614                                 anon_const_def_id,
615                                 self.param_env,
616                             );
617                             let span = tcx.hir().span(anon_const.hir_id);
618
619                             InlineAsmOperand::SymFn { value, span }
620                         }
621                         hir::InlineAsmOperand::SymStatic { path: _, def_id } => {
622                             InlineAsmOperand::SymStatic { def_id }
623                         }
624                     })
625                     .collect(),
626                 options: asm.options,
627                 line_spans: asm.line_spans,
628             })),
629
630             hir::ExprKind::ConstBlock(ref anon_const) => {
631                 let ty = self.typeck_results().node_type(anon_const.hir_id);
632                 let did = tcx.hir().local_def_id(anon_const.hir_id).to_def_id();
633                 let typeck_root_def_id = tcx.typeck_root_def_id(did);
634                 let parent_substs =
635                     tcx.erase_regions(InternalSubsts::identity_for_item(tcx, typeck_root_def_id));
636                 let substs =
637                     InlineConstSubsts::new(tcx, InlineConstSubstsParts { parent_substs, ty })
638                         .substs;
639
640                 ExprKind::ConstBlock { did, substs }
641             }
642             // Now comes the rote stuff:
643             hir::ExprKind::Repeat(ref v, _) => {
644                 let ty = self.typeck_results().expr_ty(expr);
645                 let ty::Array(_, count) = ty.kind() else {
646                     span_bug!(expr.span, "unexpected repeat expr ty: {:?}", ty);
647                 };
648
649                 ExprKind::Repeat { value: self.mirror_expr(v), count: *count }
650             }
651             hir::ExprKind::Ret(ref v) => {
652                 ExprKind::Return { value: v.as_ref().map(|v| self.mirror_expr(v)) }
653             }
654             hir::ExprKind::Break(dest, ref value) => match dest.target_id {
655                 Ok(target_id) => ExprKind::Break {
656                     label: region::Scope { id: target_id.local_id, data: region::ScopeData::Node },
657                     value: value.as_ref().map(|value| self.mirror_expr(value)),
658                 },
659                 Err(err) => bug!("invalid loop id for break: {}", err),
660             },
661             hir::ExprKind::Continue(dest) => match dest.target_id {
662                 Ok(loop_id) => ExprKind::Continue {
663                     label: region::Scope { id: loop_id.local_id, data: region::ScopeData::Node },
664                 },
665                 Err(err) => bug!("invalid loop id for continue: {}", err),
666             },
667             hir::ExprKind::Let(let_expr) => ExprKind::Let {
668                 expr: self.mirror_expr(let_expr.init),
669                 pat: self.pattern_from_hir(let_expr.pat),
670             },
671             hir::ExprKind::If(cond, then, else_opt) => ExprKind::If {
672                 if_then_scope: region::Scope {
673                     id: then.hir_id.local_id,
674                     data: region::ScopeData::IfThen,
675                 },
676                 cond: self.mirror_expr(cond),
677                 then: self.mirror_expr(then),
678                 else_opt: else_opt.map(|el| self.mirror_expr(el)),
679             },
680             hir::ExprKind::Match(ref discr, ref arms, _) => ExprKind::Match {
681                 scrutinee: self.mirror_expr(discr),
682                 arms: arms.iter().map(|a| self.convert_arm(a)).collect(),
683             },
684             hir::ExprKind::Loop(ref body, ..) => {
685                 let block_ty = self.typeck_results().node_type(body.hir_id);
686                 let temp_lifetime = self
687                     .rvalue_scopes
688                     .temporary_scope(self.region_scope_tree, body.hir_id.local_id);
689                 let block = self.mirror_block(body);
690                 let body = self.thir.exprs.push(Expr {
691                     ty: block_ty,
692                     temp_lifetime,
693                     span: self.thir[block].span,
694                     kind: ExprKind::Block { block },
695                 });
696                 ExprKind::Loop { body }
697             }
698             hir::ExprKind::Field(ref source, ..) => ExprKind::Field {
699                 lhs: self.mirror_expr(source),
700                 variant_index: VariantIdx::new(0),
701                 name: Field::new(tcx.field_index(expr.hir_id, self.typeck_results)),
702             },
703             hir::ExprKind::Cast(ref source, ref cast_ty) => {
704                 // Check for a user-given type annotation on this `cast`
705                 let user_provided_types = self.typeck_results.user_provided_types();
706                 let user_ty = user_provided_types.get(cast_ty.hir_id);
707
708                 debug!(
709                     "cast({:?}) has ty w/ hir_id {:?} and user provided ty {:?}",
710                     expr, cast_ty.hir_id, user_ty,
711                 );
712
713                 let cast = self.mirror_expr_cast(*source, temp_lifetime, expr.span);
714
715                 if let Some(user_ty) = user_ty {
716                     // NOTE: Creating a new Expr and wrapping a Cast inside of it may be
717                     //       inefficient, revisit this when performance becomes an issue.
718                     let cast_expr = self.thir.exprs.push(Expr {
719                         temp_lifetime,
720                         ty: expr_ty,
721                         span: expr.span,
722                         kind: cast,
723                     });
724                     debug!("make_mirror_unadjusted: (cast) user_ty={:?}", user_ty);
725
726                     ExprKind::ValueTypeAscription {
727                         source: cast_expr,
728                         user_ty: Some(Box::new(*user_ty)),
729                     }
730                 } else {
731                     cast
732                 }
733             }
734             hir::ExprKind::Type(ref source, ref ty) => {
735                 let user_provided_types = self.typeck_results.user_provided_types();
736                 let user_ty = user_provided_types.get(ty.hir_id).copied().map(Box::new);
737                 debug!("make_mirror_unadjusted: (type) user_ty={:?}", user_ty);
738                 let mirrored = self.mirror_expr(source);
739                 if source.is_syntactic_place_expr() {
740                     ExprKind::PlaceTypeAscription { source: mirrored, user_ty }
741                 } else {
742                     ExprKind::ValueTypeAscription { source: mirrored, user_ty }
743                 }
744             }
745             hir::ExprKind::DropTemps(ref source) => {
746                 ExprKind::Use { source: self.mirror_expr(source) }
747             }
748             hir::ExprKind::Box(ref value) => ExprKind::Box { value: self.mirror_expr(value) },
749             hir::ExprKind::Array(ref fields) => {
750                 ExprKind::Array { fields: self.mirror_exprs(fields) }
751             }
752             hir::ExprKind::Tup(ref fields) => ExprKind::Tuple { fields: self.mirror_exprs(fields) },
753
754             hir::ExprKind::Yield(ref v, _) => ExprKind::Yield { value: self.mirror_expr(v) },
755             hir::ExprKind::Err => unreachable!(),
756         };
757
758         Expr { temp_lifetime, ty: expr_ty, span: expr.span, kind }
759     }
760
761     fn user_substs_applied_to_res(
762         &mut self,
763         hir_id: hir::HirId,
764         res: Res,
765     ) -> Option<Box<ty::CanonicalUserType<'tcx>>> {
766         debug!("user_substs_applied_to_res: res={:?}", res);
767         let user_provided_type = match res {
768             // A reference to something callable -- e.g., a fn, method, or
769             // a tuple-struct or tuple-variant. This has the type of a
770             // `Fn` but with the user-given substitutions.
771             Res::Def(DefKind::Fn, _)
772             | Res::Def(DefKind::AssocFn, _)
773             | Res::Def(DefKind::Ctor(_, CtorKind::Fn), _)
774             | Res::Def(DefKind::Const, _)
775             | Res::Def(DefKind::AssocConst, _) => {
776                 self.typeck_results().user_provided_types().get(hir_id).copied().map(Box::new)
777             }
778
779             // A unit struct/variant which is used as a value (e.g.,
780             // `None`). This has the type of the enum/struct that defines
781             // this variant -- but with the substitutions given by the
782             // user.
783             Res::Def(DefKind::Ctor(_, CtorKind::Const), _) => {
784                 self.user_substs_applied_to_ty_of_hir_id(hir_id).map(Box::new)
785             }
786
787             // `Self` is used in expression as a tuple struct constructor or a unit struct constructor
788             Res::SelfCtor(_) => self.user_substs_applied_to_ty_of_hir_id(hir_id).map(Box::new),
789
790             _ => bug!("user_substs_applied_to_res: unexpected res {:?} at {:?}", res, hir_id),
791         };
792         debug!("user_substs_applied_to_res: user_provided_type={:?}", user_provided_type);
793         user_provided_type
794     }
795
796     fn method_callee(
797         &mut self,
798         expr: &hir::Expr<'_>,
799         span: Span,
800         overloaded_callee: Option<(DefId, SubstsRef<'tcx>)>,
801     ) -> Expr<'tcx> {
802         let temp_lifetime =
803             self.rvalue_scopes.temporary_scope(self.region_scope_tree, expr.hir_id.local_id);
804         let (def_id, substs, user_ty) = match overloaded_callee {
805             Some((def_id, substs)) => (def_id, substs, None),
806             None => {
807                 let (kind, def_id) =
808                     self.typeck_results().type_dependent_def(expr.hir_id).unwrap_or_else(|| {
809                         span_bug!(expr.span, "no type-dependent def for method callee")
810                     });
811                 let user_ty = self.user_substs_applied_to_res(expr.hir_id, Res::Def(kind, def_id));
812                 debug!("method_callee: user_ty={:?}", user_ty);
813                 (def_id, self.typeck_results().node_substs(expr.hir_id), user_ty)
814             }
815         };
816         let ty = self.tcx().mk_fn_def(def_id, substs);
817         Expr { temp_lifetime, ty, span, kind: ExprKind::ZstLiteral { user_ty } }
818     }
819
820     fn convert_arm(&mut self, arm: &'tcx hir::Arm<'tcx>) -> ArmId {
821         let arm = Arm {
822             pattern: self.pattern_from_hir(&arm.pat),
823             guard: arm.guard.as_ref().map(|g| match g {
824                 hir::Guard::If(ref e) => Guard::If(self.mirror_expr(e)),
825                 hir::Guard::IfLet(ref l) => {
826                     Guard::IfLet(self.pattern_from_hir(l.pat), self.mirror_expr(l.init))
827                 }
828             }),
829             body: self.mirror_expr(arm.body),
830             lint_level: LintLevel::Explicit(arm.hir_id),
831             scope: region::Scope { id: arm.hir_id.local_id, data: region::ScopeData::Node },
832             span: arm.span,
833         };
834         self.thir.arms.push(arm)
835     }
836
837     fn convert_path_expr(&mut self, expr: &'tcx hir::Expr<'tcx>, res: Res) -> ExprKind<'tcx> {
838         let substs = self.typeck_results().node_substs(expr.hir_id);
839         match res {
840             // A regular function, constructor function or a constant.
841             Res::Def(DefKind::Fn, _)
842             | Res::Def(DefKind::AssocFn, _)
843             | Res::Def(DefKind::Ctor(_, CtorKind::Fn), _)
844             | Res::SelfCtor(_) => {
845                 let user_ty = self.user_substs_applied_to_res(expr.hir_id, res);
846                 ExprKind::ZstLiteral { user_ty }
847             }
848
849             Res::Def(DefKind::ConstParam, def_id) => {
850                 let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
851                 let item_id = self.tcx.hir().get_parent_node(hir_id);
852                 let item_def_id = self.tcx.hir().local_def_id(item_id);
853                 let generics = self.tcx.generics_of(item_def_id);
854                 let index = generics.param_def_id_to_index[&def_id];
855                 let name = self.tcx.hir().name(hir_id);
856                 let param = ty::ParamConst::new(index, name);
857
858                 ExprKind::ConstParam { param, def_id }
859             }
860
861             Res::Def(DefKind::Const, def_id) | Res::Def(DefKind::AssocConst, def_id) => {
862                 let user_ty = self.user_substs_applied_to_res(expr.hir_id, res);
863                 ExprKind::NamedConst { def_id, substs, user_ty }
864             }
865
866             Res::Def(DefKind::Ctor(_, CtorKind::Const), def_id) => {
867                 let user_provided_types = self.typeck_results.user_provided_types();
868                 let user_ty = user_provided_types.get(expr.hir_id).copied().map(Box::new);
869                 debug!("convert_path_expr: user_ty={:?}", user_ty);
870                 let ty = self.typeck_results().node_type(expr.hir_id);
871                 match ty.kind() {
872                     // A unit struct/variant which is used as a value.
873                     // We return a completely different ExprKind here to account for this special case.
874                     ty::Adt(adt_def, substs) => ExprKind::Adt(Box::new(AdtExpr {
875                         adt_def: *adt_def,
876                         variant_index: adt_def.variant_index_with_ctor_id(def_id),
877                         substs,
878                         user_ty,
879                         fields: Box::new([]),
880                         base: None,
881                     })),
882                     _ => bug!("unexpected ty: {:?}", ty),
883                 }
884             }
885
886             // We encode uses of statics as a `*&STATIC` where the `&STATIC` part is
887             // a constant reference (or constant raw pointer for `static mut`) in MIR
888             Res::Def(DefKind::Static(_), id) => {
889                 let ty = self.tcx.static_ptr_ty(id);
890                 let temp_lifetime = self
891                     .rvalue_scopes
892                     .temporary_scope(self.region_scope_tree, expr.hir_id.local_id);
893                 let kind = if self.tcx.is_thread_local_static(id) {
894                     ExprKind::ThreadLocalRef(id)
895                 } else {
896                     let alloc_id = self.tcx.create_static_alloc(id);
897                     ExprKind::StaticRef { alloc_id, ty, def_id: id }
898                 };
899                 ExprKind::Deref {
900                     arg: self.thir.exprs.push(Expr { ty, temp_lifetime, span: expr.span, kind }),
901                 }
902             }
903
904             Res::Local(var_hir_id) => self.convert_var(var_hir_id),
905
906             _ => span_bug!(expr.span, "res `{:?}` not yet implemented", res),
907         }
908     }
909
910     fn convert_var(&mut self, var_hir_id: hir::HirId) -> ExprKind<'tcx> {
911         // We want upvars here not captures.
912         // Captures will be handled in MIR.
913         let is_upvar = self
914             .tcx
915             .upvars_mentioned(self.body_owner)
916             .map_or(false, |upvars| upvars.contains_key(&var_hir_id));
917
918         debug!(
919             "convert_var({:?}): is_upvar={}, body_owner={:?}",
920             var_hir_id, is_upvar, self.body_owner
921         );
922
923         if is_upvar {
924             ExprKind::UpvarRef {
925                 closure_def_id: self.body_owner,
926                 var_hir_id: LocalVarId(var_hir_id),
927             }
928         } else {
929             ExprKind::VarRef { id: LocalVarId(var_hir_id) }
930         }
931     }
932
933     fn overloaded_operator(
934         &mut self,
935         expr: &'tcx hir::Expr<'tcx>,
936         args: Box<[ExprId]>,
937     ) -> ExprKind<'tcx> {
938         let fun = self.method_callee(expr, expr.span, None);
939         let fun = self.thir.exprs.push(fun);
940         ExprKind::Call {
941             ty: self.thir[fun].ty,
942             fun,
943             args,
944             from_hir_call: false,
945             fn_span: expr.span,
946         }
947     }
948
949     fn overloaded_place(
950         &mut self,
951         expr: &'tcx hir::Expr<'tcx>,
952         place_ty: Ty<'tcx>,
953         overloaded_callee: Option<(DefId, SubstsRef<'tcx>)>,
954         args: Box<[ExprId]>,
955         span: Span,
956     ) -> ExprKind<'tcx> {
957         // For an overloaded *x or x[y] expression of type T, the method
958         // call returns an &T and we must add the deref so that the types
959         // line up (this is because `*x` and `x[y]` represent places):
960
961         // Reconstruct the output assuming it's a reference with the
962         // same region and mutability as the receiver. This holds for
963         // `Deref(Mut)::Deref(_mut)` and `Index(Mut)::index(_mut)`.
964         let ty::Ref(region, _, mutbl) = *self.thir[args[0]].ty.kind() else {
965             span_bug!(span, "overloaded_place: receiver is not a reference");
966         };
967         let ref_ty = self.tcx.mk_ref(region, ty::TypeAndMut { ty: place_ty, mutbl });
968
969         // construct the complete expression `foo()` for the overloaded call,
970         // which will yield the &T type
971         let temp_lifetime =
972             self.rvalue_scopes.temporary_scope(self.region_scope_tree, expr.hir_id.local_id);
973         let fun = self.method_callee(expr, span, overloaded_callee);
974         let fun = self.thir.exprs.push(fun);
975         let fun_ty = self.thir[fun].ty;
976         let ref_expr = self.thir.exprs.push(Expr {
977             temp_lifetime,
978             ty: ref_ty,
979             span,
980             kind: ExprKind::Call { ty: fun_ty, fun, args, from_hir_call: false, fn_span: span },
981         });
982
983         // construct and return a deref wrapper `*foo()`
984         ExprKind::Deref { arg: ref_expr }
985     }
986
987     fn convert_captured_hir_place(
988         &mut self,
989         closure_expr: &'tcx hir::Expr<'tcx>,
990         place: HirPlace<'tcx>,
991     ) -> Expr<'tcx> {
992         let temp_lifetime = self
993             .rvalue_scopes
994             .temporary_scope(self.region_scope_tree, closure_expr.hir_id.local_id);
995         let var_ty = place.base_ty;
996
997         // The result of capture analysis in `rustc_typeck/check/upvar.rs`represents a captured path
998         // as it's seen for use within the closure and not at the time of closure creation.
999         //
1000         // That is we see expect to see it start from a captured upvar and not something that is local
1001         // to the closure's parent.
1002         let var_hir_id = match place.base {
1003             HirPlaceBase::Upvar(upvar_id) => upvar_id.var_path.hir_id,
1004             base => bug!("Expected an upvar, found {:?}", base),
1005         };
1006
1007         let mut captured_place_expr = Expr {
1008             temp_lifetime,
1009             ty: var_ty,
1010             span: closure_expr.span,
1011             kind: self.convert_var(var_hir_id),
1012         };
1013
1014         for proj in place.projections.iter() {
1015             let kind = match proj.kind {
1016                 HirProjectionKind::Deref => {
1017                     ExprKind::Deref { arg: self.thir.exprs.push(captured_place_expr) }
1018                 }
1019                 HirProjectionKind::Field(field, variant_index) => ExprKind::Field {
1020                     lhs: self.thir.exprs.push(captured_place_expr),
1021                     variant_index,
1022                     name: Field::new(field as usize),
1023                 },
1024                 HirProjectionKind::Index | HirProjectionKind::Subslice => {
1025                     // We don't capture these projections, so we can ignore them here
1026                     continue;
1027                 }
1028             };
1029
1030             captured_place_expr =
1031                 Expr { temp_lifetime, ty: proj.ty, span: closure_expr.span, kind };
1032         }
1033
1034         captured_place_expr
1035     }
1036
1037     fn capture_upvar(
1038         &mut self,
1039         closure_expr: &'tcx hir::Expr<'tcx>,
1040         captured_place: &'tcx ty::CapturedPlace<'tcx>,
1041         upvar_ty: Ty<'tcx>,
1042     ) -> Expr<'tcx> {
1043         let upvar_capture = captured_place.info.capture_kind;
1044         let captured_place_expr =
1045             self.convert_captured_hir_place(closure_expr, captured_place.place.clone());
1046         let temp_lifetime = self
1047             .rvalue_scopes
1048             .temporary_scope(self.region_scope_tree, closure_expr.hir_id.local_id);
1049
1050         match upvar_capture {
1051             ty::UpvarCapture::ByValue => captured_place_expr,
1052             ty::UpvarCapture::ByRef(upvar_borrow) => {
1053                 let borrow_kind = match upvar_borrow {
1054                     ty::BorrowKind::ImmBorrow => BorrowKind::Shared,
1055                     ty::BorrowKind::UniqueImmBorrow => BorrowKind::Unique,
1056                     ty::BorrowKind::MutBorrow => BorrowKind::Mut { allow_two_phase_borrow: false },
1057                 };
1058                 Expr {
1059                     temp_lifetime,
1060                     ty: upvar_ty,
1061                     span: closure_expr.span,
1062                     kind: ExprKind::Borrow {
1063                         borrow_kind,
1064                         arg: self.thir.exprs.push(captured_place_expr),
1065                     },
1066                 }
1067             }
1068         }
1069     }
1070
1071     /// Converts a list of named fields (i.e., for struct-like struct/enum ADTs) into FieldExpr.
1072     fn field_refs(&mut self, fields: &'tcx [hir::ExprField<'tcx>]) -> Box<[FieldExpr]> {
1073         fields
1074             .iter()
1075             .map(|field| FieldExpr {
1076                 name: Field::new(self.tcx.field_index(field.hir_id, self.typeck_results)),
1077                 expr: self.mirror_expr(field.expr),
1078             })
1079             .collect()
1080     }
1081 }
1082
1083 trait ToBorrowKind {
1084     fn to_borrow_kind(&self) -> BorrowKind;
1085 }
1086
1087 impl ToBorrowKind for AutoBorrowMutability {
1088     fn to_borrow_kind(&self) -> BorrowKind {
1089         use rustc_middle::ty::adjustment::AllowTwoPhase;
1090         match *self {
1091             AutoBorrowMutability::Mut { allow_two_phase_borrow } => BorrowKind::Mut {
1092                 allow_two_phase_borrow: match allow_two_phase_borrow {
1093                     AllowTwoPhase::Yes => true,
1094                     AllowTwoPhase::No => false,
1095                 },
1096             },
1097             AutoBorrowMutability::Not => BorrowKind::Shared,
1098         }
1099     }
1100 }
1101
1102 impl ToBorrowKind for hir::Mutability {
1103     fn to_borrow_kind(&self) -> BorrowKind {
1104         match *self {
1105             hir::Mutability::Mut => BorrowKind::Mut { allow_two_phase_borrow: false },
1106             hir::Mutability::Not => BorrowKind::Shared,
1107         }
1108     }
1109 }
1110
1111 fn bin_op(op: hir::BinOpKind) -> BinOp {
1112     match op {
1113         hir::BinOpKind::Add => BinOp::Add,
1114         hir::BinOpKind::Sub => BinOp::Sub,
1115         hir::BinOpKind::Mul => BinOp::Mul,
1116         hir::BinOpKind::Div => BinOp::Div,
1117         hir::BinOpKind::Rem => BinOp::Rem,
1118         hir::BinOpKind::BitXor => BinOp::BitXor,
1119         hir::BinOpKind::BitAnd => BinOp::BitAnd,
1120         hir::BinOpKind::BitOr => BinOp::BitOr,
1121         hir::BinOpKind::Shl => BinOp::Shl,
1122         hir::BinOpKind::Shr => BinOp::Shr,
1123         hir::BinOpKind::Eq => BinOp::Eq,
1124         hir::BinOpKind::Lt => BinOp::Lt,
1125         hir::BinOpKind::Le => BinOp::Le,
1126         hir::BinOpKind::Ne => BinOp::Ne,
1127         hir::BinOpKind::Ge => BinOp::Ge,
1128         hir::BinOpKind::Gt => BinOp::Gt,
1129         _ => bug!("no equivalent for ast binop {:?}", op),
1130     }
1131 }