2 use crate::hair
::cx
::Cx
;
3 use crate::hair
::cx
::block
;
4 use crate::hair
::cx
::to_ref
::ToRef
;
5 use crate::hair
::util
::UserAnnotatedTyHelpers
;
6 use rustc_data_structures
::indexed_vec
::Idx
;
7 use rustc
::hir
::def
::{Def, CtorKind}
;
8 use rustc
::mir
::interpret
::{GlobalId, ErrorHandled}
;
9 use rustc
::ty
::{self, AdtKind, Ty}
;
10 use rustc
::ty
::adjustment
::{Adjustment, Adjust, AutoBorrow, AutoBorrowMutability}
;
11 use rustc
::ty
::cast
::CastKind
as TyCastKind
;
13 use rustc
::hir
::def_id
::LocalDefId
;
14 use rustc
::mir
::BorrowKind
;
17 impl<'tcx
> Mirror
<'tcx
> for &'tcx hir
::Expr
{
18 type Output
= Expr
<'tcx
>;
20 fn make_mirror
<'a
, 'gcx
>(self, cx
: &mut Cx
<'a
, 'gcx
, 'tcx
>) -> Expr
<'tcx
> {
21 let temp_lifetime
= cx
.region_scope_tree
.temporary_scope(self.hir_id
.local_id
);
22 let expr_scope
= region
::Scope
{
23 id
: self.hir_id
.local_id
,
24 data
: region
::ScopeData
::Node
27 debug
!("Expr::make_mirror(): id={}, span={:?}", self.id
, self.span
);
29 let mut expr
= make_mirror_unadjusted(cx
, self);
31 // Now apply adjustments, if any.
32 for adjustment
in cx
.tables().expr_adjustments(self) {
33 debug
!("make_mirror: expr={:?} applying adjustment={:?}",
36 expr
= apply_adjustment(cx
, self, expr
, adjustment
);
39 // Next, wrap this up in the expr's scope.
44 kind
: ExprKind
::Scope
{
45 region_scope
: expr_scope
,
47 lint_level
: cx
.lint_level_of(self.id
),
51 // Finally, create a destruction scope, if any.
52 if let Some(region_scope
) =
53 cx
.region_scope_tree
.opt_destruction_scope(self.hir_id
.local_id
) {
58 kind
: ExprKind
::Scope
{
61 lint_level
: LintLevel
::Inherited
,
71 fn apply_adjustment
<'a
, 'gcx
, 'tcx
>(cx
: &mut Cx
<'a
, 'gcx
, 'tcx
>,
72 hir_expr
: &'tcx hir
::Expr
,
74 adjustment
: &Adjustment
<'tcx
>)
76 let Expr { temp_lifetime, mut span, .. }
= expr
;
77 let kind
= match adjustment
.kind
{
78 Adjust
::ReifyFnPointer
=> {
79 ExprKind
::ReifyFnPointer { source: expr.to_ref() }
81 Adjust
::UnsafeFnPointer
=> {
82 ExprKind
::UnsafeFnPointer { source: expr.to_ref() }
84 Adjust
::ClosureFnPointer
=> {
85 ExprKind
::ClosureFnPointer { source: expr.to_ref() }
87 Adjust
::NeverToAny
=> {
88 ExprKind
::NeverToAny { source: expr.to_ref() }
90 Adjust
::MutToConstPointer
=> {
91 ExprKind
::Cast { source: expr.to_ref() }
93 Adjust
::Deref(None
) => {
94 // Adjust the span from the block, to the last expression of the
95 // block. This is a better span when returning a mutable reference
96 // with too short a lifetime. The error message will use the span
97 // from the assignment to the return place, which should only point
98 // at the returned value, not the entire function body.
100 // fn return_short_lived<'a>(x: &'a mut i32) -> &'static mut i32 {
102 // // ^ error message points at this expression.
105 // We don't need to do this adjustment in the next match arm since
106 // deref coercions always start with a built-in deref.
107 if let ExprKind
::Block { body }
= expr
.kind
{
108 if let Some(ref last_expr
) = body
.expr
{
109 span
= last_expr
.span
;
113 ExprKind
::Deref { arg: expr.to_ref() }
115 Adjust
::Deref(Some(deref
)) => {
116 let call
= deref
.method_call(cx
.tcx(), expr
.ty
);
120 ty
: cx
.tcx
.mk_ref(deref
.region
,
126 kind
: ExprKind
::Borrow
{
127 borrow_kind
: deref
.mutbl
.to_borrow_kind(),
132 overloaded_place(cx
, hir_expr
, adjustment
.target
, Some(call
), vec
![expr
.to_ref()])
134 Adjust
::Borrow(AutoBorrow
::Ref(_
, m
)) => {
136 borrow_kind
: m
.to_borrow_kind(),
140 Adjust
::Borrow(AutoBorrow
::RawPtr(m
)) => {
141 // Convert this to a suitable `&foo` and
142 // then an unsafe coercion.
145 ty
: cx
.tcx
.mk_ref(cx
.tcx
.types
.re_erased
,
151 kind
: ExprKind
::Borrow
{
152 borrow_kind
: m
.to_borrow_kind(),
156 let cast_expr
= Expr
{
158 ty
: adjustment
.target
,
160 kind
: ExprKind
::Cast { source: expr.to_ref() }
163 // To ensure that both implicit and explicit coercions are
164 // handled the same way, we insert an extra layer of indirection here.
165 // For explicit casts (e.g., 'foo as *const T'), the source of the 'Use'
166 // will be an ExprKind::Hair with the appropriate cast expression. Here,
167 // we make our Use source the generated Cast from the original coercion.
169 // In both cases, this outer 'Use' ensures that the inner 'Cast' is handled by
170 // as_operand, not by as_rvalue - causing the cast result to be stored in a temporary.
171 // Ordinary, this is identical to using the cast directly as an rvalue. However, if the
172 // source of the cast was previously borrowed as mutable, storing the cast in a
173 // temporary gives the source a chance to expire before the cast is used. For
174 // structs with a self-referential *mut ptr, this allows assignment to work as
177 // For example, consider the type 'struct Foo { field: *mut Foo }',
178 // The method 'fn bar(&mut self) { self.field = self }'
179 // triggers a coercion from '&mut self' to '*mut self'. In order
180 // for the assignment to be valid, the implicit borrow
181 // of 'self' involved in the coercion needs to end before the local
182 // containing the '*mut T' is assigned to 'self.field' - otherwise,
183 // we end up trying to assign to 'self.field' while we have another mutable borrow
186 // We only need to worry about this kind of thing for coercions from refs to ptrs,
187 // since they get rid of a borrow implicitly.
188 ExprKind
::Use { source: cast_expr.to_ref() }
191 // See the above comment for Adjust::Deref
192 if let ExprKind
::Block { body }
= expr
.kind
{
193 if let Some(ref last_expr
) = body
.expr
{
194 span
= last_expr
.span
;
198 ExprKind
::Unsize { source: expr.to_ref() }
204 ty
: adjustment
.target
,
210 fn make_mirror_unadjusted
<'a
, 'gcx
, 'tcx
>(cx
: &mut Cx
<'a
, 'gcx
, 'tcx
>,
211 expr
: &'tcx hir
::Expr
)
213 let expr_ty
= cx
.tables().expr_ty(expr
);
214 let temp_lifetime
= cx
.region_scope_tree
.temporary_scope(expr
.hir_id
.local_id
);
216 let kind
= match expr
.node
{
217 // Here comes the interesting stuff:
218 hir
::ExprKind
::MethodCall(_
, method_span
, ref args
) => {
219 // Rewrite a.b(c) into UFCS form like Trait::b(a, c)
220 let expr
= method_callee(cx
, expr
, method_span
,None
);
221 let args
= args
.iter()
232 hir
::ExprKind
::Call(ref fun
, ref args
) => {
233 if cx
.tables().is_method_call(expr
) {
234 // The callee is something implementing Fn, FnMut, or FnOnce.
235 // Find the actual method implementation being called and
236 // build the appropriate UFCS call expression with the
237 // callee-object as expr parameter.
239 // rewrite f(u, v) into FnOnce::call_once(f, (u, v))
241 let method
= method_callee(cx
, expr
, fun
.span
,None
);
243 let arg_tys
= args
.iter().map(|e
| cx
.tables().expr_ty_adjusted(e
));
244 let tupled_args
= Expr
{
245 ty
: cx
.tcx
.mk_tup(arg_tys
),
248 kind
: ExprKind
::Tuple { fields: args.iter().map(ToRef::to_ref).collect() }
,
253 fun
: method
.to_ref(),
254 args
: vec
![fun
.to_ref(), tupled_args
.to_ref()],
258 let adt_data
= if let hir
::ExprKind
::Path(hir
::QPath
::Resolved(_
, ref path
)) =
261 // Tuple-like ADTs are represented as ExprKind::Call. We convert them here.
262 expr_ty
.ty_adt_def().and_then(|adt_def
| {
264 Def
::VariantCtor(variant_id
, CtorKind
::Fn
) => {
265 Some((adt_def
, adt_def
.variant_index_with_id(variant_id
)))
267 Def
::StructCtor(_
, CtorKind
::Fn
) |
268 Def
::SelfCtor(..) => Some((adt_def
, VariantIdx
::new(0))),
275 if let Some((adt_def
, index
)) = adt_data
{
276 let substs
= cx
.tables().node_substs(fun
.hir_id
);
277 let user_provided_types
= cx
.tables().user_provided_types();
278 let user_ty
= user_provided_types
.get(fun
.hir_id
)
281 if let UserType
::TypeOf(ref mut did
, _
) = &mut u_ty
.value
{
286 debug
!("make_mirror_unadjusted: (call) user_ty={:?}", user_ty
);
288 let field_refs
= args
.iter()
292 name
: Field
::new(idx
),
300 variant_index
: index
,
307 ty
: cx
.tables().node_type(fun
.hir_id
),
316 hir
::ExprKind
::AddrOf(mutbl
, ref expr
) => {
318 borrow_kind
: mutbl
.to_borrow_kind(),
323 hir
::ExprKind
::Block(ref blk
, _
) => ExprKind
::Block { body: &blk }
,
325 hir
::ExprKind
::Assign(ref lhs
, ref rhs
) => {
332 hir
::ExprKind
::AssignOp(op
, ref lhs
, ref rhs
) => {
333 if cx
.tables().is_method_call(expr
) {
334 overloaded_operator(cx
, expr
, vec
![lhs
.to_ref(), rhs
.to_ref()])
344 hir
::ExprKind
::Lit(ref lit
) => ExprKind
::Literal
{
345 literal
: cx
.tcx
.mk_lazy_const(ty
::LazyConst
::Evaluated(
346 cx
.const_eval_literal(&lit
.node
, expr_ty
, lit
.span
, false)
351 hir
::ExprKind
::Binary(op
, ref lhs
, ref rhs
) => {
352 if cx
.tables().is_method_call(expr
) {
353 overloaded_operator(cx
, expr
, vec
![lhs
.to_ref(), rhs
.to_ref()])
356 match (op
.node
, cx
.constness
) {
357 // FIXME(eddyb) use logical ops in constants when
358 // they can handle that kind of control-flow.
359 (hir
::BinOpKind
::And
, hir
::Constness
::Const
) => {
360 cx
.control_flow_destroyed
.push((
362 "`&&` operator".into(),
370 (hir
::BinOpKind
::Or
, hir
::Constness
::Const
) => {
371 cx
.control_flow_destroyed
.push((
373 "`||` operator".into(),
382 (hir
::BinOpKind
::And
, hir
::Constness
::NotConst
) => {
383 ExprKind
::LogicalOp
{
389 (hir
::BinOpKind
::Or
, hir
::Constness
::NotConst
) => {
390 ExprKind
::LogicalOp
{
398 let op
= bin_op(op
.node
);
409 hir
::ExprKind
::Index(ref lhs
, ref index
) => {
410 if cx
.tables().is_method_call(expr
) {
411 overloaded_place(cx
, expr
, expr_ty
, None
, vec
![lhs
.to_ref(), index
.to_ref()])
415 index
: index
.to_ref(),
420 hir
::ExprKind
::Unary(hir
::UnOp
::UnDeref
, ref arg
) => {
421 if cx
.tables().is_method_call(expr
) {
422 overloaded_place(cx
, expr
, expr_ty
, None
, vec
![arg
.to_ref()])
424 ExprKind
::Deref { arg: arg.to_ref() }
428 hir
::ExprKind
::Unary(hir
::UnOp
::UnNot
, ref arg
) => {
429 if cx
.tables().is_method_call(expr
) {
430 overloaded_operator(cx
, expr
, vec
![arg
.to_ref()])
439 hir
::ExprKind
::Unary(hir
::UnOp
::UnNeg
, ref arg
) => {
440 if cx
.tables().is_method_call(expr
) {
441 overloaded_operator(cx
, expr
, vec
![arg
.to_ref()])
443 if let hir
::ExprKind
::Lit(ref lit
) = arg
.node
{
445 literal
: cx
.tcx
.mk_lazy_const(ty
::LazyConst
::Evaluated(
446 cx
.const_eval_literal(&lit
.node
, expr_ty
, lit
.span
, true)
459 hir
::ExprKind
::Struct(ref qpath
, ref fields
, ref base
) => {
461 ty
::Adt(adt
, substs
) => {
462 match adt
.adt_kind() {
463 AdtKind
::Struct
| AdtKind
::Union
=> {
464 let user_provided_types
= cx
.tables().user_provided_types();
465 let user_ty
= user_provided_types
.get(expr
.hir_id
).map(|u_ty
| *u_ty
);
466 debug
!("make_mirror_unadjusted: (struct/union) user_ty={:?}", user_ty
);
469 variant_index
: VariantIdx
::new(0),
472 fields
: field_refs(cx
, fields
),
473 base
: base
.as_ref().map(|base
| {
476 field_types
: cx
.tables()
477 .fru_field_types()[expr
.hir_id
]
484 let def
= cx
.tables().qpath_def(qpath
, expr
.hir_id
);
486 Def
::Variant(variant_id
) => {
487 assert
!(base
.is_none());
489 let index
= adt
.variant_index_with_id(variant_id
);
490 let user_provided_types
= cx
.tables().user_provided_types();
491 let user_ty
= user_provided_types
.get(expr
.hir_id
)
494 "make_mirror_unadjusted: (variant) user_ty={:?}",
499 variant_index
: index
,
502 fields
: field_refs(cx
, fields
),
507 span_bug
!(expr
.span
, "unexpected def: {:?}", def
);
515 "unexpected type for struct literal: {:?}",
521 hir
::ExprKind
::Closure(..) => {
522 let closure_ty
= cx
.tables().expr_ty(expr
);
523 let (def_id
, substs
, movability
) = match closure_ty
.sty
{
524 ty
::Closure(def_id
, substs
) => (def_id
, UpvarSubsts
::Closure(substs
), None
),
525 ty
::Generator(def_id
, substs
, movability
) => {
526 (def_id
, UpvarSubsts
::Generator(substs
), Some(movability
))
529 span_bug
!(expr
.span
, "closure expr w/o closure type: {:?}", closure_ty
);
532 let upvars
= cx
.tcx
.with_freevars(expr
.id
, |freevars
| {
534 .zip(substs
.upvar_tys(def_id
, cx
.tcx
))
535 .map(|(fv
, ty
)| capture_freevar(cx
, expr
, fv
, ty
))
546 hir
::ExprKind
::Path(ref qpath
) => {
547 let def
= cx
.tables().qpath_def(qpath
, expr
.hir_id
);
548 convert_path_expr(cx
, expr
, def
)
551 hir
::ExprKind
::InlineAsm(ref asm
, ref outputs
, ref inputs
) => {
552 ExprKind
::InlineAsm
{
554 outputs
: outputs
.to_ref(),
555 inputs
: inputs
.to_ref(),
559 // Now comes the rote stuff:
560 hir
::ExprKind
::Repeat(ref v
, ref count
) => {
561 let def_id
= cx
.tcx
.hir().local_def_id(count
.id
);
562 let substs
= Substs
::identity_for_item(cx
.tcx
.global_tcx(), def_id
);
563 let instance
= ty
::Instance
::resolve(
569 let global_id
= GlobalId
{
573 let span
= cx
.tcx
.def_span(def_id
);
574 let count
= match cx
.tcx
.at(span
).const_eval(cx
.param_env
.and(global_id
)) {
575 Ok(cv
) => cv
.unwrap_usize(cx
.tcx
),
576 Err(ErrorHandled
::Reported
) => 0,
577 Err(ErrorHandled
::TooGeneric
) => {
578 cx
.tcx
.sess
.span_err(span
, "array lengths can't depend on generic parameters");
588 hir
::ExprKind
::Ret(ref v
) => ExprKind
::Return { value: v.to_ref() }
,
589 hir
::ExprKind
::Break(dest
, ref value
) => {
590 match dest
.target_id
{
591 Ok(target_id
) => ExprKind
::Break
{
592 label
: region
::Scope
{
593 id
: cx
.tcx
.hir().node_to_hir_id(target_id
).local_id
,
594 data
: region
::ScopeData
::Node
596 value
: value
.to_ref(),
598 Err(err
) => bug
!("invalid loop id for break: {}", err
)
601 hir
::ExprKind
::Continue(dest
) => {
602 match dest
.target_id
{
603 Ok(loop_id
) => ExprKind
::Continue
{
604 label
: region
::Scope
{
605 id
: cx
.tcx
.hir().node_to_hir_id(loop_id
).local_id
,
606 data
: region
::ScopeData
::Node
609 Err(err
) => bug
!("invalid loop id for continue: {}", err
)
612 hir
::ExprKind
::Match(ref discr
, ref arms
, _
) => {
614 scrutinee
: discr
.to_ref(),
615 arms
: arms
.iter().map(|a
| convert_arm(cx
, a
)).collect(),
618 hir
::ExprKind
::If(ref cond
, ref then
, ref otherwise
) => {
620 condition
: cond
.to_ref(),
622 otherwise
: otherwise
.to_ref(),
625 hir
::ExprKind
::While(ref cond
, ref body
, _
) => {
627 condition
: Some(cond
.to_ref()),
628 body
: block
::to_expr_ref(cx
, body
),
631 hir
::ExprKind
::Loop(ref body
, _
, _
) => {
634 body
: block
::to_expr_ref(cx
, body
),
637 hir
::ExprKind
::Field(ref source
, ..) => {
639 lhs
: source
.to_ref(),
640 name
: Field
::new(cx
.tcx
.field_index(expr
.id
, cx
.tables
)),
643 hir
::ExprKind
::Cast(ref source
, ref cast_ty
) => {
644 // Check for a user-given type annotation on this `cast`
645 let user_provided_types
= cx
.tables
.user_provided_types();
646 let user_ty
= user_provided_types
.get(cast_ty
.hir_id
);
649 "cast({:?}) has ty w/ hir_id {:?} and user provided ty {:?}",
655 // Check to see if this cast is a "coercion cast", where the cast is actually done
656 // using a coercion (or is a no-op).
657 let cast
= if let Some(&TyCastKind
::CoercionCast
) =
662 // Convert the lexpr to a vexpr.
663 ExprKind
::Use { source: source.to_ref() }
665 // check whether this is casting an enum variant discriminant
666 // to prevent cycles, we refer to the discriminant initializer
667 // which is always an integer and thus doesn't need to know the
668 // enum's layout (or its tag type) to compute it during const eval
672 // B = A as isize + 4,
674 // The correct solution would be to add symbolic computations to miri,
675 // so we wouldn't have to compute and store the actual value
676 let var
= if let hir
::ExprKind
::Path(ref qpath
) = source
.node
{
677 let def
= cx
.tables().qpath_def(qpath
, source
.hir_id
);
680 .node_type(source
.hir_id
)
682 .and_then(|adt_def
| {
684 Def
::VariantCtor(variant_id
, CtorKind
::Const
) => {
685 let idx
= adt_def
.variant_index_with_id(variant_id
);
686 let (d
, o
) = adt_def
.discriminant_def_for_variant(idx
);
687 use rustc
::ty
::util
::IntTypeExt
;
688 let ty
= adt_def
.repr
.discr_type();
689 let ty
= ty
.to_ty(cx
.tcx());
699 let source
= if let Some((did
, offset
, var_ty
)) = var
{
700 let mk_const
= |literal
| Expr
{
704 kind
: ExprKind
::Literal
{
705 literal
: cx
.tcx
.mk_lazy_const(literal
),
709 let offset
= mk_const(ty
::LazyConst
::Evaluated(ty
::Const
::from_bits(
712 cx
.param_env
.and(var_ty
),
716 // in case we are offsetting from a computed discriminant
717 // and not the beginning of discriminants (which is always `0`)
718 let substs
= Substs
::identity_for_item(cx
.tcx(), did
);
719 let lhs
= mk_const(ty
::LazyConst
::Unevaluated(did
, substs
));
720 let bin
= ExprKind
::Binary
{
738 ExprKind
::Cast { source }
741 if let Some(user_ty
) = user_ty
{
742 // NOTE: Creating a new Expr and wrapping a Cast inside of it may be
743 // inefficient, revisit this when performance becomes an issue.
744 let cast_expr
= Expr
{
750 debug
!("make_mirror_unadjusted: (cast) user_ty={:?}", user_ty
);
752 ExprKind
::ValueTypeAscription
{
753 source
: cast_expr
.to_ref(),
754 user_ty
: Some(*user_ty
),
760 hir
::ExprKind
::Type(ref source
, ref ty
) => {
761 let user_provided_types
= cx
.tables
.user_provided_types();
762 let user_ty
= user_provided_types
.get(ty
.hir_id
).map(|u_ty
| *u_ty
);
763 debug
!("make_mirror_unadjusted: (type) user_ty={:?}", user_ty
);
764 if source
.is_place_expr() {
765 ExprKind
::PlaceTypeAscription
{
766 source
: source
.to_ref(),
770 ExprKind
::ValueTypeAscription
{
771 source
: source
.to_ref(),
776 hir
::ExprKind
::Box(ref value
) => {
778 value
: value
.to_ref(),
781 hir
::ExprKind
::Array(ref fields
) => ExprKind
::Array { fields: fields.to_ref() }
,
782 hir
::ExprKind
::Tup(ref fields
) => ExprKind
::Tuple { fields: fields.to_ref() }
,
784 hir
::ExprKind
::Yield(ref v
) => ExprKind
::Yield { value: v.to_ref() }
,
785 hir
::ExprKind
::Err
=> unreachable
!(),
796 fn user_substs_applied_to_def(
797 cx
: &mut Cx
<'a
, 'gcx
, 'tcx
>,
800 ) -> Option
<ty
::CanonicalUserType
<'tcx
>> {
801 debug
!("user_substs_applied_to_def: def={:?}", def
);
802 let user_provided_type
= match def
{
803 // A reference to something callable -- e.g., a fn, method, or
804 // a tuple-struct or tuple-variant. This has the type of a
805 // `Fn` but with the user-given substitutions.
808 Def
::StructCtor(_
, CtorKind
::Fn
) |
809 Def
::VariantCtor(_
, CtorKind
::Fn
) |
811 Def
::AssociatedConst(_
) => cx
.tables().user_provided_types().get(hir_id
).map(|u_ty
| *u_ty
),
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
817 Def
::StructCtor(_def_id
, CtorKind
::Const
) |
818 Def
::VariantCtor(_def_id
, CtorKind
::Const
) =>
819 cx
.user_substs_applied_to_ty_of_hir_id(hir_id
),
821 // `Self` is used in expression as a tuple struct constructor or an unit struct constructor
823 cx
.user_substs_applied_to_ty_of_hir_id(hir_id
),
826 bug
!("user_substs_applied_to_def: unexpected def {:?} at {:?}", def
, hir_id
)
828 debug
!("user_substs_applied_to_def: user_provided_type={:?}", user_provided_type
);
832 fn method_callee
<'a
, 'gcx
, 'tcx
>(
833 cx
: &mut Cx
<'a
, 'gcx
, 'tcx
>,
836 overloaded_callee
: Option
<(DefId
, &'tcx Substs
<'tcx
>)>,
838 let temp_lifetime
= cx
.region_scope_tree
.temporary_scope(expr
.hir_id
.local_id
);
839 let (def_id
, substs
, user_ty
) = match overloaded_callee
{
840 Some((def_id
, substs
)) => (def_id
, substs
, None
),
842 let type_dependent_defs
= cx
.tables().type_dependent_defs();
843 let def
= type_dependent_defs
846 span_bug
!(expr
.span
, "no type-dependent def for method callee")
848 let user_ty
= user_substs_applied_to_def(cx
, expr
.hir_id
, def
);
849 debug
!("method_callee: user_ty={:?}", user_ty
);
850 (def
.def_id(), cx
.tables().node_substs(expr
.hir_id
), user_ty
)
853 let ty
= cx
.tcx().mk_fn_def(def_id
, substs
);
858 kind
: ExprKind
::Literal
{
859 literal
: cx
.tcx().mk_lazy_const(ty
::LazyConst
::Evaluated(
860 ty
::Const
::zero_sized(ty
)
867 trait ToBorrowKind { fn to_borrow_kind(&self) -> BorrowKind; }
869 impl ToBorrowKind
for AutoBorrowMutability
{
870 fn to_borrow_kind(&self) -> BorrowKind
{
871 use rustc
::ty
::adjustment
::AllowTwoPhase
;
873 AutoBorrowMutability
::Mutable { allow_two_phase_borrow }
=>
874 BorrowKind
::Mut
{ allow_two_phase_borrow
: match allow_two_phase_borrow
{
875 AllowTwoPhase
::Yes
=> true,
876 AllowTwoPhase
::No
=> false
878 AutoBorrowMutability
::Immutable
=>
884 impl ToBorrowKind
for hir
::Mutability
{
885 fn to_borrow_kind(&self) -> BorrowKind
{
887 hir
::MutMutable
=> BorrowKind
::Mut { allow_two_phase_borrow: false }
,
888 hir
::MutImmutable
=> BorrowKind
::Shared
,
893 fn convert_arm
<'a
, 'gcx
, 'tcx
>(cx
: &mut Cx
<'a
, 'gcx
, 'tcx
>, arm
: &'tcx hir
::Arm
) -> Arm
<'tcx
> {
895 patterns
: arm
.pats
.iter().map(|p
| cx
.pattern_from_hir(p
)).collect(),
896 guard
: match arm
.guard
{
897 Some(hir
::Guard
::If(ref e
)) => Some(Guard
::If(e
.to_ref())),
900 body
: arm
.body
.to_ref(),
902 lint_level
: LintLevel
::Inherited
,
906 fn convert_path_expr
<'a
, 'gcx
, 'tcx
>(cx
: &mut Cx
<'a
, 'gcx
, 'tcx
>,
907 expr
: &'tcx hir
::Expr
,
910 let substs
= cx
.tables().node_substs(expr
.hir_id
);
912 // A regular function, constructor function or a constant.
915 Def
::StructCtor(_
, CtorKind
::Fn
) |
916 Def
::VariantCtor(_
, CtorKind
::Fn
) |
917 Def
::SelfCtor(..) => {
918 let user_ty
= user_substs_applied_to_def(cx
, expr
.hir_id
, &def
);
919 debug
!("convert_path_expr: user_ty={:?}", user_ty
);
921 literal
: cx
.tcx
.mk_lazy_const(ty
::LazyConst
::Evaluated(ty
::Const
::zero_sized(
922 cx
.tables().node_type(expr
.hir_id
),
929 Def
::AssociatedConst(def_id
) => {
930 let user_ty
= user_substs_applied_to_def(cx
, expr
.hir_id
, &def
);
931 debug
!("convert_path_expr: (const) user_ty={:?}", user_ty
);
933 literal
: cx
.tcx
.mk_lazy_const(ty
::LazyConst
::Unevaluated(def_id
, substs
)),
938 Def
::StructCtor(def_id
, CtorKind
::Const
) |
939 Def
::VariantCtor(def_id
, CtorKind
::Const
) => {
940 let user_provided_types
= cx
.tables
.user_provided_types();
941 let user_provided_type
= user_provided_types
.get(expr
.hir_id
).map(|u_ty
| *u_ty
);
942 debug
!("convert_path_expr: user_provided_type={:?}", user_provided_type
);
943 match cx
.tables().node_type(expr
.hir_id
).sty
{
944 // A unit struct/variant which is used as a value.
945 // We return a completely different ExprKind here to account for this special case.
946 ty
::Adt(adt_def
, substs
) => {
949 variant_index
: adt_def
.variant_index_with_id(def_id
),
951 user_ty
: user_provided_type
,
956 ref sty
=> bug
!("unexpected sty: {:?}", sty
),
960 Def
::Static(node_id
, _
) => ExprKind
::StaticRef { id: node_id }
,
962 Def
::Local(..) | Def
::Upvar(..) => convert_var(cx
, expr
, def
),
964 _
=> span_bug
!(expr
.span
, "def `{:?}` not yet implemented", def
),
968 fn convert_var
<'a
, 'gcx
, 'tcx
>(cx
: &mut Cx
<'a
, 'gcx
, 'tcx
>,
969 expr
: &'tcx hir
::Expr
,
972 let temp_lifetime
= cx
.region_scope_tree
.temporary_scope(expr
.hir_id
.local_id
);
975 Def
::Local(id
) => ExprKind
::VarRef { id }
,
977 Def
::Upvar(var_id
, index
, closure_expr_id
) => {
978 debug
!("convert_var(upvar({:?}, {:?}, {:?}))",
982 let var_hir_id
= cx
.tcx
.hir().node_to_hir_id(var_id
);
983 let var_ty
= cx
.tables().node_type(var_hir_id
);
985 // FIXME free regions in closures are not right
986 let closure_ty
= cx
.tables()
987 .node_type(cx
.tcx
.hir().node_to_hir_id(closure_expr_id
));
989 // FIXME we're just hard-coding the idea that the
990 // signature will be &self or &mut self and hence will
991 // have a bound region with number 0
992 let closure_def_id
= cx
.tcx
.hir().local_def_id(closure_expr_id
);
993 let region
= ty
::ReFree(ty
::FreeRegion
{
994 scope
: closure_def_id
,
995 bound_region
: ty
::BoundRegion
::BrAnon(0),
997 let region
= cx
.tcx
.mk_region(region
);
999 let self_expr
= if let ty
::Closure(_
, closure_substs
) = closure_ty
.sty
{
1000 match cx
.infcx
.closure_kind(closure_def_id
, closure_substs
).unwrap() {
1001 ty
::ClosureKind
::Fn
=> {
1002 let ref_closure_ty
= cx
.tcx
.mk_ref(region
,
1005 mutbl
: hir
::MutImmutable
,
1009 temp_lifetime
: temp_lifetime
,
1011 kind
: ExprKind
::Deref
{
1016 kind
: ExprKind
::SelfRef
,
1022 ty
::ClosureKind
::FnMut
=> {
1023 let ref_closure_ty
= cx
.tcx
.mk_ref(region
,
1026 mutbl
: hir
::MutMutable
,
1032 kind
: ExprKind
::Deref
{
1037 kind
: ExprKind
::SelfRef
,
1042 ty
::ClosureKind
::FnOnce
=> {
1047 kind
: ExprKind
::SelfRef
,
1056 kind
: ExprKind
::SelfRef
,
1060 // at this point we have `self.n`, which loads up the upvar
1061 let field_kind
= ExprKind
::Field
{
1062 lhs
: self_expr
.to_ref(),
1063 name
: Field
::new(index
),
1066 // ...but the upvar might be an `&T` or `&mut T` capture, at which
1067 // point we need an implicit deref
1068 let upvar_id
= ty
::UpvarId
{
1069 var_path
: ty
::UpvarPath {hir_id: var_hir_id}
,
1070 closure_expr_id
: LocalDefId
::from_def_id(closure_def_id
),
1072 match cx
.tables().upvar_capture(upvar_id
) {
1073 ty
::UpvarCapture
::ByValue
=> field_kind
,
1074 ty
::UpvarCapture
::ByRef(borrow
) => {
1078 ty
: cx
.tcx
.mk_ref(borrow
.region
,
1081 mutbl
: borrow
.kind
.to_mutbl_lossy(),
1091 _
=> span_bug
!(expr
.span
, "type of & not region"),
1096 fn bin_op(op
: hir
::BinOpKind
) -> BinOp
{
1098 hir
::BinOpKind
::Add
=> BinOp
::Add
,
1099 hir
::BinOpKind
::Sub
=> BinOp
::Sub
,
1100 hir
::BinOpKind
::Mul
=> BinOp
::Mul
,
1101 hir
::BinOpKind
::Div
=> BinOp
::Div
,
1102 hir
::BinOpKind
::Rem
=> BinOp
::Rem
,
1103 hir
::BinOpKind
::BitXor
=> BinOp
::BitXor
,
1104 hir
::BinOpKind
::BitAnd
=> BinOp
::BitAnd
,
1105 hir
::BinOpKind
::BitOr
=> BinOp
::BitOr
,
1106 hir
::BinOpKind
::Shl
=> BinOp
::Shl
,
1107 hir
::BinOpKind
::Shr
=> BinOp
::Shr
,
1108 hir
::BinOpKind
::Eq
=> BinOp
::Eq
,
1109 hir
::BinOpKind
::Lt
=> BinOp
::Lt
,
1110 hir
::BinOpKind
::Le
=> BinOp
::Le
,
1111 hir
::BinOpKind
::Ne
=> BinOp
::Ne
,
1112 hir
::BinOpKind
::Ge
=> BinOp
::Ge
,
1113 hir
::BinOpKind
::Gt
=> BinOp
::Gt
,
1114 _
=> bug
!("no equivalent for ast binop {:?}", op
),
1118 fn overloaded_operator
<'a
, 'gcx
, 'tcx
>(cx
: &mut Cx
<'a
, 'gcx
, 'tcx
>,
1119 expr
: &'tcx hir
::Expr
,
1120 args
: Vec
<ExprRef
<'tcx
>>)
1122 let fun
= method_callee(cx
, expr
, expr
.span
, None
);
1127 from_hir_call
: false,
1131 fn overloaded_place
<'a
, 'gcx
, 'tcx
>(
1132 cx
: &mut Cx
<'a
, 'gcx
, 'tcx
>,
1133 expr
: &'tcx hir
::Expr
,
1135 overloaded_callee
: Option
<(DefId
, &'tcx Substs
<'tcx
>)>,
1136 args
: Vec
<ExprRef
<'tcx
>>,
1137 ) -> ExprKind
<'tcx
> {
1138 // For an overloaded *x or x[y] expression of type T, the method
1139 // call returns an &T and we must add the deref so that the types
1140 // line up (this is because `*x` and `x[y]` represent places):
1142 let recv_ty
= match args
[0] {
1143 ExprRef
::Hair(e
) => cx
.tables().expr_ty_adjusted(e
),
1144 ExprRef
::Mirror(ref e
) => e
.ty
1147 // Reconstruct the output assuming it's a reference with the
1148 // same region and mutability as the receiver. This holds for
1149 // `Deref(Mut)::Deref(_mut)` and `Index(Mut)::index(_mut)`.
1150 let (region
, mutbl
) = match recv_ty
.sty
{
1151 ty
::Ref(region
, _
, mutbl
) => (region
, mutbl
),
1152 _
=> span_bug
!(expr
.span
, "overloaded_place: receiver is not a reference"),
1154 let ref_ty
= cx
.tcx
.mk_ref(region
, ty
::TypeAndMut
{
1159 // construct the complete expression `foo()` for the overloaded call,
1160 // which will yield the &T type
1161 let temp_lifetime
= cx
.region_scope_tree
.temporary_scope(expr
.hir_id
.local_id
);
1162 let fun
= method_callee(cx
, expr
, expr
.span
, overloaded_callee
);
1163 let ref_expr
= Expr
{
1167 kind
: ExprKind
::Call
{
1171 from_hir_call
: false,
1175 // construct and return a deref wrapper `*foo()`
1176 ExprKind
::Deref { arg: ref_expr.to_ref() }
1179 fn capture_freevar
<'a
, 'gcx
, 'tcx
>(cx
: &mut Cx
<'a
, 'gcx
, 'tcx
>,
1180 closure_expr
: &'tcx hir
::Expr
,
1181 freevar
: &hir
::Freevar
,
1182 freevar_ty
: Ty
<'tcx
>)
1184 let var_hir_id
= cx
.tcx
.hir().node_to_hir_id(freevar
.var_id());
1185 let upvar_id
= ty
::UpvarId
{
1186 var_path
: ty
::UpvarPath { hir_id: var_hir_id }
,
1187 closure_expr_id
: cx
.tcx
.hir().local_def_id(closure_expr
.id
).to_local(),
1189 let upvar_capture
= cx
.tables().upvar_capture(upvar_id
);
1190 let temp_lifetime
= cx
.region_scope_tree
.temporary_scope(closure_expr
.hir_id
.local_id
);
1191 let var_ty
= cx
.tables().node_type(var_hir_id
);
1192 let captured_var
= Expr
{
1195 span
: closure_expr
.span
,
1196 kind
: convert_var(cx
, closure_expr
, freevar
.def
),
1198 match upvar_capture
{
1199 ty
::UpvarCapture
::ByValue
=> captured_var
.to_ref(),
1200 ty
::UpvarCapture
::ByRef(upvar_borrow
) => {
1201 let borrow_kind
= match upvar_borrow
.kind
{
1202 ty
::BorrowKind
::ImmBorrow
=> BorrowKind
::Shared
,
1203 ty
::BorrowKind
::UniqueImmBorrow
=> BorrowKind
::Unique
,
1204 ty
::BorrowKind
::MutBorrow
=> BorrowKind
::Mut { allow_two_phase_borrow: false }
1209 span
: closure_expr
.span
,
1210 kind
: ExprKind
::Borrow
{
1212 arg
: captured_var
.to_ref(),
1219 /// Converts a list of named fields (i.e., for struct-like struct/enum ADTs) into FieldExprRef.
1220 fn field_refs
<'a
, 'gcx
, 'tcx
>(cx
: &mut Cx
<'a
, 'gcx
, 'tcx
>,
1221 fields
: &'tcx
[hir
::Field
])
1222 -> Vec
<FieldExprRef
<'tcx
>> {
1226 name
: Field
::new(cx
.tcx
.field_index(field
.id
, cx
.tables
)),
1227 expr
: field
.expr
.to_ref(),