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