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