1 use crate::hair
::cx
::block
;
2 use crate::hair
::cx
::to_ref
::ToRef
;
3 use crate::hair
::cx
::Cx
;
4 use crate::hair
::util
::UserAnnotatedTyHelpers
;
7 use rustc_hir
::def
::{CtorKind, CtorOf, DefKind, Res}
;
8 use rustc_index
::vec
::Idx
;
9 use rustc_middle
::mir
::interpret
::Scalar
;
10 use rustc_middle
::mir
::BorrowKind
;
11 use rustc_middle
::ty
::adjustment
::{
12 Adjust
, Adjustment
, AutoBorrow
, AutoBorrowMutability
, PointerCast
,
14 use rustc_middle
::ty
::subst
::{InternalSubsts, SubstsRef}
;
15 use rustc_middle
::ty
::{self, AdtKind, Ty}
;
18 impl<'tcx
> Mirror
<'tcx
> for &'tcx hir
::Expr
<'tcx
> {
19 type Output
= Expr
<'tcx
>;
21 fn make_mirror(self, cx
: &mut Cx
<'_
, 'tcx
>) -> Expr
<'tcx
> {
22 let temp_lifetime
= cx
.region_scope_tree
.temporary_scope(self.hir_id
.local_id
);
23 let expr_scope
= region
::Scope { id: self.hir_id.local_id, data: region::ScopeData::Node }
;
25 debug
!("Expr::make_mirror(): id={}, span={:?}", self.hir_id
, self.span
);
27 let mut expr
= make_mirror_unadjusted(cx
, self);
29 // Now apply adjustments, if any.
30 for adjustment
in cx
.tables().expr_adjustments(self) {
31 debug
!("make_mirror: expr={:?} applying adjustment={:?}", expr
, adjustment
);
32 expr
= apply_adjustment(cx
, self, expr
, adjustment
);
35 // Next, wrap this up in the expr's scope.
40 kind
: ExprKind
::Scope
{
41 region_scope
: expr_scope
,
43 lint_level
: LintLevel
::Explicit(self.hir_id
),
47 // Finally, create a destruction scope, if any.
48 if let Some(region_scope
) = cx
.region_scope_tree
.opt_destruction_scope(self.hir_id
.local_id
)
54 kind
: ExprKind
::Scope
{
57 lint_level
: LintLevel
::Inherited
,
67 fn apply_adjustment
<'a
, 'tcx
>(
68 cx
: &mut Cx
<'a
, 'tcx
>,
69 hir_expr
: &'tcx hir
::Expr
<'tcx
>,
71 adjustment
: &Adjustment
<'tcx
>,
73 let Expr { temp_lifetime, mut span, .. }
= expr
;
75 // Adjust the span from the block, to the last expression of the
76 // block. This is a better span when returning a mutable reference
77 // with too short a lifetime. The error message will use the span
78 // from the assignment to the return place, which should only point
79 // at the returned value, not the entire function body.
81 // fn return_short_lived<'a>(x: &'a mut i32) -> &'static mut i32 {
83 // // ^ error message points at this expression.
85 let mut adjust_span
= |expr
: &mut Expr
<'tcx
>| {
86 if let ExprKind
::Block { body }
= expr
.kind
{
87 if let Some(ref last_expr
) = body
.expr
{
88 span
= last_expr
.span
;
94 let kind
= match adjustment
.kind
{
95 Adjust
::Pointer(PointerCast
::Unsize
) => {
96 adjust_span(&mut expr
);
97 ExprKind
::Pointer { cast: PointerCast::Unsize, source: expr.to_ref() }
99 Adjust
::Pointer(cast
) => ExprKind
::Pointer { cast, source: expr.to_ref() }
,
100 Adjust
::NeverToAny
=> ExprKind
::NeverToAny { source: expr.to_ref() }
,
101 Adjust
::Deref(None
) => {
102 adjust_span(&mut expr
);
103 ExprKind
::Deref { arg: expr.to_ref() }
105 Adjust
::Deref(Some(deref
)) => {
106 // We don't need to do call adjust_span here since
107 // deref coercions always start with a built-in deref.
108 let call
= deref
.method_call(cx
.tcx(), expr
.ty
);
112 ty
: cx
.tcx
.mk_ref(deref
.region
, ty
::TypeAndMut { ty: expr.ty, mutbl: deref.mutbl }
),
114 kind
: ExprKind
::Borrow
{
115 borrow_kind
: deref
.mutbl
.to_borrow_kind(),
120 overloaded_place(cx
, hir_expr
, adjustment
.target
, Some(call
), vec
![expr
.to_ref()])
122 Adjust
::Borrow(AutoBorrow
::Ref(_
, m
)) => {
123 ExprKind
::Borrow { borrow_kind: m.to_borrow_kind(), arg: expr.to_ref() }
125 Adjust
::Borrow(AutoBorrow
::RawPtr(mutability
)) => {
126 ExprKind
::AddressOf { mutability, arg: expr.to_ref() }
130 Expr { temp_lifetime, ty: adjustment.target, span, kind }
133 fn make_mirror_unadjusted
<'a
, 'tcx
>(
134 cx
: &mut Cx
<'a
, 'tcx
>,
135 expr
: &'tcx hir
::Expr
<'tcx
>,
137 let expr_ty
= cx
.tables().expr_ty(expr
);
138 let temp_lifetime
= cx
.region_scope_tree
.temporary_scope(expr
.hir_id
.local_id
);
140 let kind
= match expr
.kind
{
141 // Here comes the interesting stuff:
142 hir
::ExprKind
::MethodCall(_
, method_span
, ref args
) => {
143 // Rewrite a.b(c) into UFCS form like Trait::b(a, c)
144 let expr
= method_callee(cx
, expr
, method_span
, None
);
145 let args
= args
.iter().map(|e
| e
.to_ref()).collect();
146 ExprKind
::Call { ty: expr.ty, fun: expr.to_ref(), args, from_hir_call: true }
149 hir
::ExprKind
::Call(ref fun
, ref args
) => {
150 if cx
.tables().is_method_call(expr
) {
151 // The callee is something implementing Fn, FnMut, or FnOnce.
152 // Find the actual method implementation being called and
153 // build the appropriate UFCS call expression with the
154 // callee-object as expr parameter.
156 // rewrite f(u, v) into FnOnce::call_once(f, (u, v))
158 let method
= method_callee(cx
, expr
, fun
.span
, None
);
160 let arg_tys
= args
.iter().map(|e
| cx
.tables().expr_ty_adjusted(e
));
161 let tupled_args
= Expr
{
162 ty
: cx
.tcx
.mk_tup(arg_tys
),
165 kind
: ExprKind
::Tuple { fields: args.iter().map(ToRef::to_ref).collect() }
,
170 fun
: method
.to_ref(),
171 args
: vec
![fun
.to_ref(), tupled_args
.to_ref()],
176 if let hir
::ExprKind
::Path(hir
::QPath
::Resolved(_
, ref path
)) = fun
.kind
{
177 // Tuple-like ADTs are represented as ExprKind::Call. We convert them here.
178 expr_ty
.ty_adt_def().and_then(|adt_def
| match path
.res
{
179 Res
::Def(DefKind
::Ctor(_
, CtorKind
::Fn
), ctor_id
) => {
180 Some((adt_def
, adt_def
.variant_index_with_ctor_id(ctor_id
)))
182 Res
::SelfCtor(..) => Some((adt_def
, VariantIdx
::new(0))),
188 if let Some((adt_def
, index
)) = adt_data
{
189 let substs
= cx
.tables().node_substs(fun
.hir_id
);
190 let user_provided_types
= cx
.tables().user_provided_types();
191 let user_ty
= user_provided_types
.get(fun
.hir_id
).copied().map(|mut u_ty
| {
192 if let UserType
::TypeOf(ref mut did
, _
) = &mut u_ty
.value
{
197 debug
!("make_mirror_unadjusted: (call) user_ty={:?}", user_ty
);
199 let field_refs
= args
202 .map(|(idx
, e
)| FieldExprRef { name: Field::new(idx), expr: e.to_ref() }
)
207 variant_index
: index
,
214 ty
: cx
.tables().node_type(fun
.hir_id
),
223 hir
::ExprKind
::AddrOf(hir
::BorrowKind
::Ref
, mutbl
, ref arg
) => {
224 ExprKind
::Borrow { borrow_kind: mutbl.to_borrow_kind(), arg: arg.to_ref() }
227 hir
::ExprKind
::AddrOf(hir
::BorrowKind
::Raw
, mutability
, ref arg
) => {
228 ExprKind
::AddressOf { mutability, arg: arg.to_ref() }
231 hir
::ExprKind
::Block(ref blk
, _
) => ExprKind
::Block { body: &blk }
,
233 hir
::ExprKind
::Assign(ref lhs
, ref rhs
, _
) => {
234 ExprKind
::Assign { lhs: lhs.to_ref(), rhs: rhs.to_ref() }
237 hir
::ExprKind
::AssignOp(op
, ref lhs
, ref rhs
) => {
238 if cx
.tables().is_method_call(expr
) {
239 overloaded_operator(cx
, expr
, vec
![lhs
.to_ref(), rhs
.to_ref()])
241 ExprKind
::AssignOp { op: bin_op(op.node), lhs: lhs.to_ref(), rhs: rhs.to_ref() }
245 hir
::ExprKind
::Lit(ref lit
) => ExprKind
::Literal
{
246 literal
: cx
.const_eval_literal(&lit
.node
, expr_ty
, lit
.span
, false),
250 hir
::ExprKind
::Binary(op
, ref lhs
, ref rhs
) => {
251 if cx
.tables().is_method_call(expr
) {
252 overloaded_operator(cx
, expr
, vec
![lhs
.to_ref(), rhs
.to_ref()])
255 match (op
.node
, cx
.constness
) {
256 // Destroy control flow if `#![feature(const_if_match)]` is not enabled.
257 (hir
::BinOpKind
::And
, hir
::Constness
::Const
)
258 if !cx
.tcx
.features().const_if_match
=>
260 cx
.control_flow_destroyed
.push((op
.span
, "`&&` operator".into()));
261 ExprKind
::Binary { op: BinOp::BitAnd, lhs: lhs.to_ref(), rhs: rhs.to_ref() }
263 (hir
::BinOpKind
::Or
, hir
::Constness
::Const
)
264 if !cx
.tcx
.features().const_if_match
=>
266 cx
.control_flow_destroyed
.push((op
.span
, "`||` operator".into()));
267 ExprKind
::Binary { op: BinOp::BitOr, lhs: lhs.to_ref(), rhs: rhs.to_ref() }
270 (hir
::BinOpKind
::And
, _
) => ExprKind
::LogicalOp
{
275 (hir
::BinOpKind
::Or
, _
) => ExprKind
::LogicalOp
{
282 let op
= bin_op(op
.node
);
283 ExprKind
::Binary { op, lhs: lhs.to_ref(), rhs: rhs.to_ref() }
289 hir
::ExprKind
::Index(ref lhs
, ref index
) => {
290 if cx
.tables().is_method_call(expr
) {
291 overloaded_place(cx
, expr
, expr_ty
, None
, vec
![lhs
.to_ref(), index
.to_ref()])
293 ExprKind
::Index { lhs: lhs.to_ref(), index: index.to_ref() }
297 hir
::ExprKind
::Unary(hir
::UnOp
::UnDeref
, ref arg
) => {
298 if cx
.tables().is_method_call(expr
) {
299 overloaded_place(cx
, expr
, expr_ty
, None
, vec
![arg
.to_ref()])
301 ExprKind
::Deref { arg: arg.to_ref() }
305 hir
::ExprKind
::Unary(hir
::UnOp
::UnNot
, ref arg
) => {
306 if cx
.tables().is_method_call(expr
) {
307 overloaded_operator(cx
, expr
, vec
![arg
.to_ref()])
309 ExprKind
::Unary { op: UnOp::Not, arg: arg.to_ref() }
313 hir
::ExprKind
::Unary(hir
::UnOp
::UnNeg
, ref arg
) => {
314 if cx
.tables().is_method_call(expr
) {
315 overloaded_operator(cx
, expr
, vec
![arg
.to_ref()])
317 if let hir
::ExprKind
::Lit(ref lit
) = arg
.kind
{
319 literal
: cx
.const_eval_literal(&lit
.node
, expr_ty
, lit
.span
, true),
323 ExprKind
::Unary { op: UnOp::Neg, arg: arg.to_ref() }
328 hir
::ExprKind
::Struct(ref qpath
, ref fields
, ref base
) => match expr_ty
.kind
{
329 ty
::Adt(adt
, substs
) => match adt
.adt_kind() {
330 AdtKind
::Struct
| AdtKind
::Union
=> {
331 let user_provided_types
= cx
.tables().user_provided_types();
332 let user_ty
= user_provided_types
.get(expr
.hir_id
).copied();
333 debug
!("make_mirror_unadjusted: (struct/union) user_ty={:?}", user_ty
);
336 variant_index
: VariantIdx
::new(0),
339 fields
: field_refs(cx
, fields
),
340 base
: base
.as_ref().map(|base
| FruInfo
{
342 field_types
: cx
.tables().fru_field_types()[expr
.hir_id
].clone(),
347 let res
= cx
.tables().qpath_res(qpath
, expr
.hir_id
);
349 Res
::Def(DefKind
::Variant
, variant_id
) => {
350 assert
!(base
.is_none());
352 let index
= adt
.variant_index_with_id(variant_id
);
353 let user_provided_types
= cx
.tables().user_provided_types();
354 let user_ty
= user_provided_types
.get(expr
.hir_id
).copied();
355 debug
!("make_mirror_unadjusted: (variant) user_ty={:?}", user_ty
);
358 variant_index
: index
,
361 fields
: field_refs(cx
, fields
),
366 span_bug
!(expr
.span
, "unexpected res: {:?}", res
);
372 span_bug
!(expr
.span
, "unexpected type for struct literal: {:?}", expr_ty
);
376 hir
::ExprKind
::Closure(..) => {
377 let closure_ty
= cx
.tables().expr_ty(expr
);
378 let (def_id
, substs
, movability
) = match closure_ty
.kind
{
379 ty
::Closure(def_id
, substs
) => (def_id
, UpvarSubsts
::Closure(substs
), None
),
380 ty
::Generator(def_id
, substs
, movability
) => {
381 (def_id
, UpvarSubsts
::Generator(substs
), Some(movability
))
384 span_bug
!(expr
.span
, "closure expr w/o closure type: {:?}", closure_ty
);
391 .flat_map(|upvars
| upvars
.iter())
392 .zip(substs
.upvar_tys())
393 .map(|((&var_hir_id
, _
), ty
)| capture_upvar(cx
, expr
, var_hir_id
, ty
))
395 ExprKind
::Closure { closure_id: def_id, substs, upvars, movability }
398 hir
::ExprKind
::Path(ref qpath
) => {
399 let res
= cx
.tables().qpath_res(qpath
, expr
.hir_id
);
400 convert_path_expr(cx
, expr
, res
)
403 hir
::ExprKind
::LlvmInlineAsm(ref asm
) => ExprKind
::LlvmInlineAsm
{
405 outputs
: asm
.outputs_exprs
.to_ref(),
406 inputs
: asm
.inputs_exprs
.to_ref(),
409 // Now comes the rote stuff:
410 hir
::ExprKind
::Repeat(ref v
, ref count
) => {
411 let count_def_id
= cx
.tcx
.hir().local_def_id(count
.hir_id
).expect_local();
412 let count
= ty
::Const
::from_anon_const(cx
.tcx
, count_def_id
);
414 ExprKind
::Repeat { value: v.to_ref(), count }
416 hir
::ExprKind
::Ret(ref v
) => ExprKind
::Return { value: v.to_ref() }
,
417 hir
::ExprKind
::Break(dest
, ref value
) => match dest
.target_id
{
418 Ok(target_id
) => ExprKind
::Break
{
419 label
: region
::Scope { id: target_id.local_id, data: region::ScopeData::Node }
,
420 value
: value
.to_ref(),
422 Err(err
) => bug
!("invalid loop id for break: {}", err
),
424 hir
::ExprKind
::Continue(dest
) => match dest
.target_id
{
425 Ok(loop_id
) => ExprKind
::Continue
{
426 label
: region
::Scope { id: loop_id.local_id, data: region::ScopeData::Node }
,
428 Err(err
) => bug
!("invalid loop id for continue: {}", err
),
430 hir
::ExprKind
::Match(ref discr
, ref arms
, _
) => ExprKind
::Match
{
431 scrutinee
: discr
.to_ref(),
432 arms
: arms
.iter().map(|a
| convert_arm(cx
, a
)).collect(),
434 hir
::ExprKind
::Loop(ref body
, _
, _
) => {
435 ExprKind
::Loop { body: block::to_expr_ref(cx, body) }
437 hir
::ExprKind
::Field(ref source
, ..) => ExprKind
::Field
{
438 lhs
: source
.to_ref(),
439 name
: Field
::new(cx
.tcx
.field_index(expr
.hir_id
, cx
.tables
)),
441 hir
::ExprKind
::Cast(ref source
, ref cast_ty
) => {
442 // Check for a user-given type annotation on this `cast`
443 let user_provided_types
= cx
.tables
.user_provided_types();
444 let user_ty
= user_provided_types
.get(cast_ty
.hir_id
);
447 "cast({:?}) has ty w/ hir_id {:?} and user provided ty {:?}",
448 expr
, cast_ty
.hir_id
, user_ty
,
451 // Check to see if this cast is a "coercion cast", where the cast is actually done
452 // using a coercion (or is a no-op).
453 let cast
= if cx
.tables().is_coercion_cast(source
.hir_id
) {
454 // Convert the lexpr to a vexpr.
455 ExprKind
::Use { source: source.to_ref() }
456 } else if cx
.tables().expr_ty(source
).is_region_ptr() {
457 // Special cased so that we can type check that the element
458 // type of the source matches the pointed to type of the
460 ExprKind
::Pointer { source: source.to_ref(), cast: PointerCast::ArrayToPointer }
462 // check whether this is casting an enum variant discriminant
463 // to prevent cycles, we refer to the discriminant initializer
464 // which is always an integer and thus doesn't need to know the
465 // enum's layout (or its tag type) to compute it during const eval
469 // B = A as isize + 4,
471 // The correct solution would be to add symbolic computations to miri,
472 // so we wouldn't have to compute and store the actual value
473 let var
= if let hir
::ExprKind
::Path(ref qpath
) = source
.kind
{
474 let res
= cx
.tables().qpath_res(qpath
, source
.hir_id
);
475 cx
.tables().node_type(source
.hir_id
).ty_adt_def().and_then(
476 |adt_def
| match res
{
478 DefKind
::Ctor(CtorOf
::Variant
, CtorKind
::Const
),
481 let idx
= adt_def
.variant_index_with_ctor_id(variant_ctor_id
);
482 let (d
, o
) = adt_def
.discriminant_def_for_variant(idx
);
483 use rustc_middle
::ty
::util
::IntTypeExt
;
484 let ty
= adt_def
.repr
.discr_type();
485 let ty
= ty
.to_ty(cx
.tcx());
495 let source
= if let Some((did
, offset
, var_ty
)) = var
{
496 let mk_const
= |literal
| {
501 kind
: ExprKind
::Literal { literal, user_ty: None }
,
505 let offset
= mk_const(ty
::Const
::from_bits(
508 cx
.param_env
.and(var_ty
),
512 // in case we are offsetting from a computed discriminant
513 // and not the beginning of discriminants (which is always `0`)
514 let substs
= InternalSubsts
::identity_for_item(cx
.tcx(), did
);
515 let lhs
= mk_const(cx
.tcx().mk_const(ty
::Const
{
516 val
: ty
::ConstKind
::Unevaluated(did
, substs
, None
),
519 let bin
= ExprKind
::Binary { op: BinOp::Add, lhs, rhs: offset }
;
520 Expr { temp_lifetime, ty: var_ty, span: expr.span, kind: bin }
.to_ref()
528 ExprKind
::Cast { source }
531 if let Some(user_ty
) = user_ty
{
532 // NOTE: Creating a new Expr and wrapping a Cast inside of it may be
533 // inefficient, revisit this when performance becomes an issue.
534 let cast_expr
= Expr { temp_lifetime, ty: expr_ty, span: expr.span, kind: cast }
;
535 debug
!("make_mirror_unadjusted: (cast) user_ty={:?}", user_ty
);
537 ExprKind
::ValueTypeAscription
{
538 source
: cast_expr
.to_ref(),
539 user_ty
: Some(*user_ty
),
545 hir
::ExprKind
::Type(ref source
, ref ty
) => {
546 let user_provided_types
= cx
.tables
.user_provided_types();
547 let user_ty
= user_provided_types
.get(ty
.hir_id
).copied();
548 debug
!("make_mirror_unadjusted: (type) user_ty={:?}", user_ty
);
549 if source
.is_syntactic_place_expr() {
550 ExprKind
::PlaceTypeAscription { source: source.to_ref(), user_ty }
552 ExprKind
::ValueTypeAscription { source: source.to_ref(), user_ty }
555 hir
::ExprKind
::DropTemps(ref source
) => ExprKind
::Use { source: source.to_ref() }
,
556 hir
::ExprKind
::Box(ref value
) => ExprKind
::Box { value: value.to_ref() }
,
557 hir
::ExprKind
::Array(ref fields
) => ExprKind
::Array { fields: fields.to_ref() }
,
558 hir
::ExprKind
::Tup(ref fields
) => ExprKind
::Tuple { fields: fields.to_ref() }
,
560 hir
::ExprKind
::Yield(ref v
, _
) => ExprKind
::Yield { value: v.to_ref() }
,
561 hir
::ExprKind
::Err
=> unreachable
!(),
564 Expr { temp_lifetime, ty: expr_ty, span: expr.span, kind }
567 fn user_substs_applied_to_res
<'tcx
>(
568 cx
: &mut Cx
<'_
, 'tcx
>,
571 ) -> Option
<ty
::CanonicalUserType
<'tcx
>> {
572 debug
!("user_substs_applied_to_res: res={:?}", res
);
573 let user_provided_type
= match res
{
574 // A reference to something callable -- e.g., a fn, method, or
575 // a tuple-struct or tuple-variant. This has the type of a
576 // `Fn` but with the user-given substitutions.
577 Res
::Def(DefKind
::Fn
, _
)
578 | Res
::Def(DefKind
::AssocFn
, _
)
579 | Res
::Def(DefKind
::Ctor(_
, CtorKind
::Fn
), _
)
580 | Res
::Def(DefKind
::Const
, _
)
581 | Res
::Def(DefKind
::AssocConst
, _
) => {
582 cx
.tables().user_provided_types().get(hir_id
).copied()
585 // A unit struct/variant which is used as a value (e.g.,
586 // `None`). This has the type of the enum/struct that defines
587 // this variant -- but with the substitutions given by the
589 Res
::Def(DefKind
::Ctor(_
, CtorKind
::Const
), _
) => {
590 cx
.user_substs_applied_to_ty_of_hir_id(hir_id
)
593 // `Self` is used in expression as a tuple struct constructor or an unit struct constructor
594 Res
::SelfCtor(_
) => cx
.user_substs_applied_to_ty_of_hir_id(hir_id
),
596 _
=> bug
!("user_substs_applied_to_res: unexpected res {:?} at {:?}", res
, hir_id
),
598 debug
!("user_substs_applied_to_res: user_provided_type={:?}", user_provided_type
);
602 fn method_callee
<'a
, 'tcx
>(
603 cx
: &mut Cx
<'a
, 'tcx
>,
604 expr
: &hir
::Expr
<'_
>,
606 overloaded_callee
: Option
<(DefId
, SubstsRef
<'tcx
>)>,
608 let temp_lifetime
= cx
.region_scope_tree
.temporary_scope(expr
.hir_id
.local_id
);
609 let (def_id
, substs
, user_ty
) = match overloaded_callee
{
610 Some((def_id
, substs
)) => (def_id
, substs
, None
),
612 let (kind
, def_id
) = cx
614 .type_dependent_def(expr
.hir_id
)
615 .unwrap_or_else(|| span_bug
!(expr
.span
, "no type-dependent def for method callee"));
616 let user_ty
= user_substs_applied_to_res(cx
, expr
.hir_id
, Res
::Def(kind
, def_id
));
617 debug
!("method_callee: user_ty={:?}", user_ty
);
618 (def_id
, cx
.tables().node_substs(expr
.hir_id
), user_ty
)
621 let ty
= cx
.tcx().mk_fn_def(def_id
, substs
);
626 kind
: ExprKind
::Literal { literal: ty::Const::zero_sized(cx.tcx(), ty), user_ty }
,
631 fn to_borrow_kind(&self) -> BorrowKind
;
634 impl ToBorrowKind
for AutoBorrowMutability
{
635 fn to_borrow_kind(&self) -> BorrowKind
{
636 use rustc_middle
::ty
::adjustment
::AllowTwoPhase
;
638 AutoBorrowMutability
::Mut { allow_two_phase_borrow }
=> BorrowKind
::Mut
{
639 allow_two_phase_borrow
: match allow_two_phase_borrow
{
640 AllowTwoPhase
::Yes
=> true,
641 AllowTwoPhase
::No
=> false,
644 AutoBorrowMutability
::Not
=> BorrowKind
::Shared
,
649 impl ToBorrowKind
for hir
::Mutability
{
650 fn to_borrow_kind(&self) -> BorrowKind
{
652 hir
::Mutability
::Mut
=> BorrowKind
::Mut { allow_two_phase_borrow: false }
,
653 hir
::Mutability
::Not
=> BorrowKind
::Shared
,
658 fn convert_arm
<'tcx
>(cx
: &mut Cx
<'_
, 'tcx
>, arm
: &'tcx hir
::Arm
<'tcx
>) -> Arm
<'tcx
> {
660 pattern
: cx
.pattern_from_hir(&arm
.pat
),
661 guard
: match arm
.guard
{
662 Some(hir
::Guard
::If(ref e
)) => Some(Guard
::If(e
.to_ref())),
665 body
: arm
.body
.to_ref(),
666 lint_level
: LintLevel
::Explicit(arm
.hir_id
),
667 scope
: region
::Scope { id: arm.hir_id.local_id, data: region::ScopeData::Node }
,
672 fn convert_path_expr
<'a
, 'tcx
>(
673 cx
: &mut Cx
<'a
, 'tcx
>,
674 expr
: &'tcx hir
::Expr
<'tcx
>,
676 ) -> ExprKind
<'tcx
> {
677 let substs
= cx
.tables().node_substs(expr
.hir_id
);
679 // A regular function, constructor function or a constant.
680 Res
::Def(DefKind
::Fn
, _
)
681 | Res
::Def(DefKind
::AssocFn
, _
)
682 | Res
::Def(DefKind
::Ctor(_
, CtorKind
::Fn
), _
)
683 | Res
::SelfCtor(..) => {
684 let user_ty
= user_substs_applied_to_res(cx
, expr
.hir_id
, res
);
685 debug
!("convert_path_expr: user_ty={:?}", user_ty
);
687 literal
: ty
::Const
::zero_sized(cx
.tcx
, cx
.tables().node_type(expr
.hir_id
)),
692 Res
::Def(DefKind
::ConstParam
, def_id
) => {
693 let hir_id
= cx
.tcx
.hir().as_local_hir_id(def_id
).unwrap();
694 let item_id
= cx
.tcx
.hir().get_parent_node(hir_id
);
695 let item_def_id
= cx
.tcx
.hir().local_def_id(item_id
);
696 let generics
= cx
.tcx
.generics_of(item_def_id
);
697 let local_def_id
= cx
.tcx
.hir().local_def_id(hir_id
);
698 let index
= generics
.param_def_id_to_index
[&local_def_id
];
699 let name
= cx
.tcx
.hir().name(hir_id
);
700 let val
= ty
::ConstKind
::Param(ty
::ParamConst
::new(index
, name
));
702 literal
: cx
.tcx
.mk_const(ty
::Const { val, ty: cx.tables().node_type(expr.hir_id) }
),
707 Res
::Def(DefKind
::Const
, def_id
) | Res
::Def(DefKind
::AssocConst
, def_id
) => {
708 let user_ty
= user_substs_applied_to_res(cx
, expr
.hir_id
, res
);
709 debug
!("convert_path_expr: (const) user_ty={:?}", user_ty
);
711 literal
: cx
.tcx
.mk_const(ty
::Const
{
712 val
: ty
::ConstKind
::Unevaluated(def_id
, substs
, None
),
713 ty
: cx
.tables().node_type(expr
.hir_id
),
719 Res
::Def(DefKind
::Ctor(_
, CtorKind
::Const
), def_id
) => {
720 let user_provided_types
= cx
.tables
.user_provided_types();
721 let user_provided_type
= user_provided_types
.get(expr
.hir_id
).copied();
722 debug
!("convert_path_expr: user_provided_type={:?}", user_provided_type
);
723 let ty
= cx
.tables().node_type(expr
.hir_id
);
725 // A unit struct/variant which is used as a value.
726 // We return a completely different ExprKind here to account for this special case.
727 ty
::Adt(adt_def
, substs
) => ExprKind
::Adt
{
729 variant_index
: adt_def
.variant_index_with_ctor_id(def_id
),
731 user_ty
: user_provided_type
,
735 _
=> bug
!("unexpected ty: {:?}", ty
),
739 // We encode uses of statics as a `*&STATIC` where the `&STATIC` part is
740 // a constant reference (or constant raw pointer for `static mut`) in MIR
741 Res
::Def(DefKind
::Static
, id
) => {
742 let ty
= cx
.tcx
.static_ptr_ty(id
);
743 let ptr
= cx
.tcx
.alloc_map
.lock().create_static_alloc(id
);
744 let temp_lifetime
= cx
.region_scope_tree
.temporary_scope(expr
.hir_id
.local_id
);
750 kind
: ExprKind
::StaticRef
{
751 literal
: ty
::Const
::from_scalar(cx
.tcx
, Scalar
::Ptr(ptr
.into()), ty
),
759 Res
::Local(var_hir_id
) => convert_var(cx
, expr
, var_hir_id
),
761 _
=> span_bug
!(expr
.span
, "res `{:?}` not yet implemented", res
),
765 fn convert_var
<'tcx
>(
766 cx
: &mut Cx
<'_
, 'tcx
>,
767 expr
: &'tcx hir
::Expr
<'tcx
>,
768 var_hir_id
: hir
::HirId
,
769 ) -> ExprKind
<'tcx
> {
774 .and_then(|upvars
| upvars
.get_full(&var_hir_id
).map(|(i
, _
, _
)| i
));
777 "convert_var({:?}): upvar_index={:?}, body_owner={:?}",
778 var_hir_id
, upvar_index
, cx
.body_owner
781 let temp_lifetime
= cx
.region_scope_tree
.temporary_scope(expr
.hir_id
.local_id
);
784 None
=> ExprKind
::VarRef { id: var_hir_id }
,
786 Some(upvar_index
) => {
787 let closure_def_id
= cx
.body_owner
;
788 let upvar_id
= ty
::UpvarId
{
789 var_path
: ty
::UpvarPath { hir_id: var_hir_id }
,
790 closure_expr_id
: closure_def_id
.expect_local(),
792 let var_ty
= cx
.tables().node_type(var_hir_id
);
794 // FIXME free regions in closures are not right
797 .node_type(cx
.tcx
.hir().local_def_id_to_hir_id(upvar_id
.closure_expr_id
));
799 // FIXME we're just hard-coding the idea that the
800 // signature will be &self or &mut self and hence will
801 // have a bound region with number 0
802 let region
= ty
::ReFree(ty
::FreeRegion
{
803 scope
: closure_def_id
,
804 bound_region
: ty
::BoundRegion
::BrAnon(0),
806 let region
= cx
.tcx
.mk_region(region
);
808 let self_expr
= if let ty
::Closure(_
, closure_substs
) = closure_ty
.kind
{
809 match cx
.infcx
.closure_kind(closure_substs
).unwrap() {
810 ty
::ClosureKind
::Fn
=> {
811 let ref_closure_ty
= cx
.tcx
.mk_ref(
813 ty
::TypeAndMut { ty: closure_ty, mutbl: hir::Mutability::Not }
,
819 kind
: ExprKind
::Deref
{
824 kind
: ExprKind
::SelfRef
,
830 ty
::ClosureKind
::FnMut
=> {
831 let ref_closure_ty
= cx
.tcx
.mk_ref(
833 ty
::TypeAndMut { ty: closure_ty, mutbl: hir::Mutability::Mut }
,
839 kind
: ExprKind
::Deref
{
844 kind
: ExprKind
::SelfRef
,
850 ty
::ClosureKind
::FnOnce
=> Expr
{
854 kind
: ExprKind
::SelfRef
,
858 Expr { ty: closure_ty, temp_lifetime, span: expr.span, kind: ExprKind::SelfRef }
861 // at this point we have `self.n`, which loads up the upvar
863 ExprKind
::Field { lhs: self_expr.to_ref(), name: Field::new(upvar_index) }
;
865 // ...but the upvar might be an `&T` or `&mut T` capture, at which
866 // point we need an implicit deref
867 match cx
.tables().upvar_capture(upvar_id
) {
868 ty
::UpvarCapture
::ByValue
=> field_kind
,
869 ty
::UpvarCapture
::ByRef(borrow
) => ExprKind
::Deref
{
874 ty
::TypeAndMut { ty: var_ty, mutbl: borrow.kind.to_mutbl_lossy() }
,
886 fn bin_op(op
: hir
::BinOpKind
) -> BinOp
{
888 hir
::BinOpKind
::Add
=> BinOp
::Add
,
889 hir
::BinOpKind
::Sub
=> BinOp
::Sub
,
890 hir
::BinOpKind
::Mul
=> BinOp
::Mul
,
891 hir
::BinOpKind
::Div
=> BinOp
::Div
,
892 hir
::BinOpKind
::Rem
=> BinOp
::Rem
,
893 hir
::BinOpKind
::BitXor
=> BinOp
::BitXor
,
894 hir
::BinOpKind
::BitAnd
=> BinOp
::BitAnd
,
895 hir
::BinOpKind
::BitOr
=> BinOp
::BitOr
,
896 hir
::BinOpKind
::Shl
=> BinOp
::Shl
,
897 hir
::BinOpKind
::Shr
=> BinOp
::Shr
,
898 hir
::BinOpKind
::Eq
=> BinOp
::Eq
,
899 hir
::BinOpKind
::Lt
=> BinOp
::Lt
,
900 hir
::BinOpKind
::Le
=> BinOp
::Le
,
901 hir
::BinOpKind
::Ne
=> BinOp
::Ne
,
902 hir
::BinOpKind
::Ge
=> BinOp
::Ge
,
903 hir
::BinOpKind
::Gt
=> BinOp
::Gt
,
904 _
=> bug
!("no equivalent for ast binop {:?}", op
),
908 fn overloaded_operator
<'a
, 'tcx
>(
909 cx
: &mut Cx
<'a
, 'tcx
>,
910 expr
: &'tcx hir
::Expr
<'tcx
>,
911 args
: Vec
<ExprRef
<'tcx
>>,
912 ) -> ExprKind
<'tcx
> {
913 let fun
= method_callee(cx
, expr
, expr
.span
, None
);
914 ExprKind
::Call { ty: fun.ty, fun: fun.to_ref(), args, from_hir_call: false }
917 fn overloaded_place
<'a
, 'tcx
>(
918 cx
: &mut Cx
<'a
, 'tcx
>,
919 expr
: &'tcx hir
::Expr
<'tcx
>,
921 overloaded_callee
: Option
<(DefId
, SubstsRef
<'tcx
>)>,
922 args
: Vec
<ExprRef
<'tcx
>>,
923 ) -> ExprKind
<'tcx
> {
924 // For an overloaded *x or x[y] expression of type T, the method
925 // call returns an &T and we must add the deref so that the types
926 // line up (this is because `*x` and `x[y]` represent places):
928 let recv_ty
= match args
[0] {
929 ExprRef
::Hair(e
) => cx
.tables().expr_ty_adjusted(e
),
930 ExprRef
::Mirror(ref e
) => e
.ty
,
933 // Reconstruct the output assuming it's a reference with the
934 // same region and mutability as the receiver. This holds for
935 // `Deref(Mut)::Deref(_mut)` and `Index(Mut)::index(_mut)`.
936 let (region
, mutbl
) = match recv_ty
.kind
{
937 ty
::Ref(region
, _
, mutbl
) => (region
, mutbl
),
938 _
=> span_bug
!(expr
.span
, "overloaded_place: receiver is not a reference"),
940 let ref_ty
= cx
.tcx
.mk_ref(region
, ty
::TypeAndMut { ty: place_ty, mutbl }
);
942 // construct the complete expression `foo()` for the overloaded call,
943 // which will yield the &T type
944 let temp_lifetime
= cx
.region_scope_tree
.temporary_scope(expr
.hir_id
.local_id
);
945 let fun
= method_callee(cx
, expr
, expr
.span
, overloaded_callee
);
946 let ref_expr
= Expr
{
950 kind
: ExprKind
::Call { ty: fun.ty, fun: fun.to_ref(), args, from_hir_call: false }
,
953 // construct and return a deref wrapper `*foo()`
954 ExprKind
::Deref { arg: ref_expr.to_ref() }
957 fn capture_upvar
<'tcx
>(
958 cx
: &mut Cx
<'_
, 'tcx
>,
959 closure_expr
: &'tcx hir
::Expr
<'tcx
>,
960 var_hir_id
: hir
::HirId
,
963 let upvar_id
= ty
::UpvarId
{
964 var_path
: ty
::UpvarPath { hir_id: var_hir_id }
,
965 closure_expr_id
: cx
.tcx
.hir().local_def_id(closure_expr
.hir_id
).expect_local(),
967 let upvar_capture
= cx
.tables().upvar_capture(upvar_id
);
968 let temp_lifetime
= cx
.region_scope_tree
.temporary_scope(closure_expr
.hir_id
.local_id
);
969 let var_ty
= cx
.tables().node_type(var_hir_id
);
970 let captured_var
= Expr
{
973 span
: closure_expr
.span
,
974 kind
: convert_var(cx
, closure_expr
, var_hir_id
),
976 match upvar_capture
{
977 ty
::UpvarCapture
::ByValue
=> captured_var
.to_ref(),
978 ty
::UpvarCapture
::ByRef(upvar_borrow
) => {
979 let borrow_kind
= match upvar_borrow
.kind
{
980 ty
::BorrowKind
::ImmBorrow
=> BorrowKind
::Shared
,
981 ty
::BorrowKind
::UniqueImmBorrow
=> BorrowKind
::Unique
,
982 ty
::BorrowKind
::MutBorrow
=> BorrowKind
::Mut { allow_two_phase_borrow: false }
,
987 span
: closure_expr
.span
,
988 kind
: ExprKind
::Borrow { borrow_kind, arg: captured_var.to_ref() }
,
995 /// Converts a list of named fields (i.e., for struct-like struct/enum ADTs) into FieldExprRef.
996 fn field_refs
<'a
, 'tcx
>(
997 cx
: &mut Cx
<'a
, 'tcx
>,
998 fields
: &'tcx
[hir
::Field
<'tcx
>],
999 ) -> Vec
<FieldExprRef
<'tcx
>> {
1002 .map(|field
| FieldExprRef
{
1003 name
: Field
::new(cx
.tcx
.field_index(field
.hir_id
, cx
.tables
)),
1004 expr
: field
.expr
.to_ref(),