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