1 // Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
12 use rustc_data_structures
::fnv
::FnvHashMap
;
15 use hair
::cx
::to_ref
::ToRef
;
16 use rustc
::front
::map
;
17 use rustc
::middle
::def
;
18 use rustc
::middle
::region
::CodeExtent
;
19 use rustc
::middle
::pat_util
;
20 use rustc
::middle
::ty
::{self, VariantDef, Ty}
;
21 use rustc
::mir
::repr
::*;
23 use rustc_front
::util
as hir_util
;
24 use syntax
::parse
::token
;
27 impl<'tcx
> Mirror
<'tcx
> for &'tcx hir
::Expr
{
28 type Output
= Expr
<'tcx
>;
30 fn make_mirror
<'a
>(self, cx
: &mut Cx
<'a
, 'tcx
>) -> Expr
<'tcx
> {
31 debug
!("Expr::make_mirror(): id={}, span={:?}", self.id
, self.span
);
33 let expr_ty
= cx
.tcx
.expr_ty(self); // note: no adjustments (yet)!
35 let kind
= match self.node
{
36 // Here comes the interesting stuff:
37 hir
::ExprMethodCall(_
, _
, ref args
) => {
38 // Rewrite a.b(c) into UFCS form like Trait::b(a, c)
39 let expr
= method_callee(cx
, self, ty
::MethodCall
::expr(self.id
));
40 let args
= args
.iter()
49 hir
::ExprAddrOf(mutbl
, ref expr
) => {
50 let region
= match expr_ty
.sty
{
52 _
=> cx
.tcx
.sess
.span_bug(expr
.span
, "type of & not region"),
56 borrow_kind
: to_borrow_kind(mutbl
),
61 hir
::ExprBlock(ref blk
) => {
62 ExprKind
::Block { body: &**blk }
65 hir
::ExprAssign(ref lhs
, ref rhs
) => {
72 hir
::ExprAssignOp(op
, ref lhs
, ref rhs
) => {
73 let op
= bin_op(op
.node
);
81 hir
::ExprLit(..) => ExprKind
::Literal
{
82 literal
: cx
.const_eval_literal(self)
85 hir
::ExprBinary(op
, ref lhs
, ref rhs
) => {
86 if cx
.tcx
.is_method_call(self.id
) {
87 let pass_args
= if hir_util
::is_by_value_binop(op
.node
) {
92 overloaded_operator(cx
, self, ty
::MethodCall
::expr(self.id
),
93 pass_args
, lhs
.to_ref(), vec
![rhs
])
97 hir
::BinOp_
::BiAnd
=> {
104 hir
::BinOp_
::BiOr
=> {
105 ExprKind
::LogicalOp
{
112 let op
= bin_op(op
.node
);
123 hir
::ExprIndex(ref lhs
, ref index
) => {
124 if cx
.tcx
.is_method_call(self.id
) {
125 overloaded_lvalue(cx
, self, ty
::MethodCall
::expr(self.id
),
126 PassArgs
::ByValue
, lhs
.to_ref(), vec
![index
])
130 index
: index
.to_ref(),
135 hir
::ExprUnary(hir
::UnOp
::UnDeref
, ref arg
) => {
136 if cx
.tcx
.is_method_call(self.id
) {
137 overloaded_lvalue(cx
, self, ty
::MethodCall
::expr(self.id
),
138 PassArgs
::ByValue
, arg
.to_ref(), vec
![])
140 ExprKind
::Deref { arg: arg.to_ref() }
144 hir
::ExprUnary(op
, ref arg
) => {
145 if cx
.tcx
.is_method_call(self.id
) {
146 overloaded_operator(cx
, self, ty
::MethodCall
::expr(self.id
),
147 PassArgs
::ByValue
, arg
.to_ref(), vec
![])
151 hir
::UnOp
::UnNot
=> UnOp
::Not
,
152 hir
::UnOp
::UnNeg
=> UnOp
::Neg
,
153 hir
::UnOp
::UnDeref
=> {
154 cx
.tcx
.sess
.span_bug(
156 "UnDeref should have been handled elsewhere");
166 hir
::ExprStruct(_
, ref fields
, ref base
) => {
168 ty
::TyStruct(adt
, substs
) => {
169 let field_refs
= field_refs(&adt
.variants
[0], fields
);
178 ty
::TyEnum(adt
, substs
) => {
179 match cx
.tcx
.def_map
.borrow()[&self.id
].full_def() {
180 def
::DefVariant(enum_id
, variant_id
, _
) => {
181 debug_assert
!(adt
.did
== enum_id
);
182 let index
= adt
.variant_index_with_id(variant_id
);
183 let field_refs
= field_refs(&adt
.variants
[index
], fields
);
186 variant_index
: index
,
193 cx
.tcx
.sess
.span_bug(
195 &format
!("unexpected def: {:?}", def
));
200 cx
.tcx
.sess
.span_bug(
202 &format
!("unexpected type for struct literal: {:?}", expr_ty
));
207 hir
::ExprClosure(..) => {
208 let closure_ty
= cx
.tcx
.expr_ty(self);
209 let (def_id
, substs
) = match closure_ty
.sty
{
210 ty
::TyClosure(def_id
, ref substs
) => (def_id
, substs
),
212 cx
.tcx
.sess
.span_bug(self.span
,
213 &format
!("closure expr w/o closure type: {:?}",
217 let upvars
= cx
.tcx
.with_freevars(self.id
, |freevars
| {
220 .map(|(i
, fv
)| capture_freevar(cx
, self, fv
, substs
.upvar_tys
[i
]))
230 hir
::ExprRange(ref start
, ref end
) => {
231 let range_ty
= cx
.tcx
.expr_ty(self);
232 let (adt_def
, substs
) = match range_ty
.sty
{
233 ty
::TyStruct(adt_def
, substs
) => (adt_def
, substs
),
235 cx
.tcx
.sess
.span_bug(self.span
, "unexpanded ast");
239 let field_expr_ref
= |s
: &'tcx P
<hir
::Expr
>, name
: &str| {
240 let name
= token
::intern(name
);
241 let index
= adt_def
.variants
[0].index_of_field_named(name
).unwrap();
242 FieldExprRef { name: Field::new(index), expr: s.to_ref() }
245 let start_field
= start
.as_ref()
247 .map(|s
| field_expr_ref(s
, "start"));
249 let end_field
= end
.as_ref()
251 .map(|e
| field_expr_ref(e
, "end"));
257 fields
: start_field
.chain(end_field
).collect(),
262 hir
::ExprPath(..) => {
263 convert_path_expr(cx
, self)
266 hir
::ExprInlineAsm(ref asm
) => {
267 ExprKind
::InlineAsm { asm: asm }
270 // Now comes the rote stuff:
272 hir
::ExprRepeat(ref v
, ref c
) => ExprKind
::Repeat
{
275 ty
: cx
.tcx
.expr_ty(c
),
278 kind
: ExprKind
::Literal
{
279 literal
: cx
.const_eval_literal(c
)
283 hir
::ExprRet(ref v
) =>
284 ExprKind
::Return { value: v.to_ref() }
,
285 hir
::ExprBreak(label
) =>
286 ExprKind
::Break { label: label.map(|_| loop_label(cx, self)) }
,
287 hir
::ExprAgain(label
) =>
288 ExprKind
::Continue { label: label.map(|_| loop_label(cx, self)) }
,
289 hir
::ExprMatch(ref discr
, ref arms
, _
) =>
290 ExprKind
::Match
{ discriminant
: discr
.to_ref(),
291 arms
: arms
.iter().map(|a
| convert_arm(cx
, a
)).collect() },
292 hir
::ExprIf(ref cond
, ref then
, ref otherwise
) =>
293 ExprKind
::If
{ condition
: cond
.to_ref(),
294 then
: block
::to_expr_ref(cx
, then
),
295 otherwise
: otherwise
.to_ref() },
296 hir
::ExprWhile(ref cond
, ref body
, _
) =>
297 ExprKind
::Loop
{ condition
: Some(cond
.to_ref()),
298 body
: block
::to_expr_ref(cx
, body
) },
299 hir
::ExprLoop(ref body
, _
) =>
300 ExprKind
::Loop
{ condition
: None
,
301 body
: block
::to_expr_ref(cx
, body
) },
302 hir
::ExprField(ref source
, name
) => {
303 let index
= match cx
.tcx
.expr_ty_adjusted(source
).sty
{
304 ty
::TyStruct(adt_def
, _
) =>
305 adt_def
.variants
[0].index_of_field_named(name
.node
),
307 cx
.tcx
.sess
.span_bug(
309 &format
!("field of non-struct: {:?}", ty
)),
311 let index
= index
.unwrap_or_else(|| {
312 cx
.tcx
.sess
.span_bug(
314 &format
!("no index found for field `{}`", name
.node
));
316 ExprKind
::Field { lhs: source.to_ref(), name: Field::new(index) }
318 hir
::ExprTupField(ref source
, index
) =>
319 ExprKind
::Field
{ lhs
: source
.to_ref(),
320 name
: Field
::new(index
.node
as usize) },
321 hir
::ExprCast(ref source
, _
) =>
322 ExprKind
::Cast { source: source.to_ref() }
,
323 hir
::ExprBox(ref value
) =>
324 ExprKind
::Box { value: value.to_ref() }
,
325 hir
::ExprVec(ref fields
) =>
326 ExprKind
::Vec { fields: fields.to_ref() }
,
327 hir
::ExprTup(ref fields
) =>
328 ExprKind
::Tuple { fields: fields.to_ref() }
,
329 hir
::ExprCall(ref fun
, ref args
) =>
330 ExprKind
::Call { fun: fun.to_ref(), args: args.to_ref() }
,
333 let temp_lifetime
= cx
.tcx
.region_maps
.temporary_scope(self.id
);
334 let expr_extent
= cx
.tcx
.region_maps
.node_extent(self.id
);
336 let mut expr
= Expr
{
337 temp_lifetime
: temp_lifetime
,
343 // Now apply adjustments, if any.
344 match cx
.tcx
.tables
.borrow().adjustments
.get(&self.id
) {
346 Some(&ty
::adjustment
::AdjustReifyFnPointer
) => {
347 let adjusted_ty
= cx
.tcx
.expr_ty_adjusted(self);
349 temp_lifetime
: temp_lifetime
,
352 kind
: ExprKind
::ReifyFnPointer { source: expr.to_ref() }
,
355 Some(&ty
::adjustment
::AdjustUnsafeFnPointer
) => {
356 let adjusted_ty
= cx
.tcx
.expr_ty_adjusted(self);
358 temp_lifetime
: temp_lifetime
,
361 kind
: ExprKind
::UnsafeFnPointer { source: expr.to_ref() }
,
364 Some(&ty
::adjustment
::AdjustDerefRef(ref adj
)) => {
365 for i
in 0..adj
.autoderefs
{
368 expr
.ty
.adjust_for_autoderef(
373 |mc
| cx
.tcx
.tables
.borrow().method_map
.get(&mc
).map(|m
| m
.ty
));
374 let kind
= if cx
.tcx
.is_overloaded_autoderef(self.id
, i
) {
375 overloaded_lvalue(cx
, self, ty
::MethodCall
::autoderef(self.id
, i
),
376 PassArgs
::ByValue
, expr
.to_ref(), vec
![])
378 ExprKind
::Deref { arg: expr.to_ref() }
381 temp_lifetime
: temp_lifetime
,
388 if let Some(autoref
) = adj
.autoref
{
389 let adjusted_ty
= expr
.ty
.adjust_for_autoref(cx
.tcx
, Some(autoref
));
391 ty
::adjustment
::AutoPtr(r
, m
) => {
393 temp_lifetime
: temp_lifetime
,
396 kind
: ExprKind
::Borrow
{
398 borrow_kind
: to_borrow_kind(m
),
403 ty
::adjustment
::AutoUnsafe(m
) => {
404 // Convert this to a suitable `&foo` and
405 // then an unsafe coercion. Limit the region to be just this
407 let region
= ty
::ReScope(expr_extent
);
408 let region
= cx
.tcx
.mk_region(region
);
410 temp_lifetime
: temp_lifetime
,
411 ty
: cx
.tcx
.mk_ref(region
, ty
::TypeAndMut { ty: expr.ty, mutbl: m }
),
413 kind
: ExprKind
::Borrow
{
415 borrow_kind
: to_borrow_kind(m
),
420 temp_lifetime
: temp_lifetime
,
423 kind
: ExprKind
::Cast { source: expr.to_ref() }
,
429 if let Some(target
) = adj
.unsize
{
431 temp_lifetime
: temp_lifetime
,
434 kind
: ExprKind
::Unsize { source: expr.to_ref() }
,
440 // Next, wrap this up in the expr's scope.
442 temp_lifetime
: temp_lifetime
,
445 kind
: ExprKind
::Scope
{
447 value
: expr
.to_ref(),
451 // Finally, create a destruction scope, if any.
452 if let Some(extent
) = cx
.tcx
.region_maps
.opt_destruction_extent(self.id
) {
454 temp_lifetime
: temp_lifetime
,
457 kind
: ExprKind
::Scope
{
459 value
: expr
.to_ref(),
469 fn method_callee
<'a
, 'tcx
: 'a
>(cx
: &mut Cx
<'a
, 'tcx
>,
471 method_call
: ty
::MethodCall
)
473 let tables
= cx
.tcx
.tables
.borrow();
474 let callee
= &tables
.method_map
[&method_call
];
475 let temp_lifetime
= cx
.tcx
.region_maps
.temporary_scope(expr
.id
);
477 temp_lifetime
: temp_lifetime
,
480 kind
: ExprKind
::Literal
{
481 literal
: Literal
::Item
{
482 def_id
: callee
.def_id
,
483 substs
: callee
.substs
,
489 fn to_borrow_kind(m
: hir
::Mutability
) -> BorrowKind
{
491 hir
::MutMutable
=> BorrowKind
::Mut
,
492 hir
::MutImmutable
=> BorrowKind
::Shared
,
496 fn convert_arm
<'a
, 'tcx
: 'a
>(cx
: &mut Cx
<'a
, 'tcx
>, arm
: &'tcx hir
::Arm
) -> Arm
<'tcx
> {
498 let opt_map
= if arm
.pats
.len() == 1 {
502 pat_util
::pat_bindings(&cx
.tcx
.def_map
, &arm
.pats
[0], |_
, p_id
, _
, path
| {
503 map
.insert(path
.node
, p_id
);
509 patterns
: arm
.pats
.iter().map(|p
| cx
.refutable_pat(opt_map
, p
)).collect(),
510 guard
: arm
.guard
.to_ref(),
511 body
: arm
.body
.to_ref(),
515 fn convert_path_expr
<'a
, 'tcx
: 'a
>(cx
: &mut Cx
<'a
, 'tcx
>, expr
: &'tcx hir
::Expr
) -> ExprKind
<'tcx
> {
516 let substs
= cx
.tcx
.mk_substs(cx
.tcx
.node_id_item_substs(expr
.id
).substs
);
517 match cx
.tcx
.def_map
.borrow()[&expr
.id
].full_def() {
518 def
::DefVariant(_
, def_id
, false) |
519 def
::DefStruct(def_id
) |
520 def
::DefFn(def_id
, _
) |
521 def
::DefConst(def_id
) |
522 def
::DefMethod(def_id
) |
523 def
::DefAssociatedConst(def_id
) =>
525 literal
: Literal
::Item { def_id: def_id, substs: substs }
528 def
::DefStatic(node_id
, _
) =>
529 ExprKind
::StaticRef
{
533 def @ def
::DefLocal(..) |
534 def @ def
::DefUpvar(..) =>
535 convert_var(cx
, expr
, def
),
538 cx
.tcx
.sess
.span_bug(
540 &format
!("def `{:?}` not yet implemented", def
)),
544 fn convert_var
<'a
, 'tcx
: 'a
>(cx
: &mut Cx
<'a
, 'tcx
>,
545 expr
: &'tcx hir
::Expr
,
548 let temp_lifetime
= cx
.tcx
.region_maps
.temporary_scope(expr
.id
);
551 def
::DefLocal(_
, node_id
) => {
557 def
::DefUpvar(_
, id_var
, index
, closure_expr_id
) => {
558 debug
!("convert_var(upvar({:?}, {:?}, {:?}))", id_var
, index
, closure_expr_id
);
559 let var_ty
= cx
.tcx
.node_id_to_type(id_var
);
561 let body_id
= match cx
.tcx
.map
.find(closure_expr_id
) {
562 Some(map
::NodeExpr(expr
)) => {
564 hir
::ExprClosure(_
, _
, ref body
) => body
.id
,
566 cx
.tcx
.sess
.span_bug(expr
.span
, "closure expr is not a closure expr");
571 cx
.tcx
.sess
.span_bug(expr
.span
, "ast-map has garbage for closure expr");
575 // FIXME free regions in closures are not right
576 let closure_ty
= cx
.tcx
.node_id_to_type(closure_expr_id
);
578 // FIXME we're just hard-coding the idea that the
579 // signature will be &self or &mut self and hence will
580 // have a bound region with number 0
581 let region
= ty
::Region
::ReFree(ty
::FreeRegion
{
582 scope
: cx
.tcx
.region_maps
.node_extent(body_id
),
583 bound_region
: ty
::BoundRegion
::BrAnon(0),
585 let region
= cx
.tcx
.mk_region(region
);
587 let self_expr
= match cx
.tcx
.closure_kind(cx
.tcx
.map
.local_def_id(closure_expr_id
)) {
588 ty
::ClosureKind
::FnClosureKind
=> {
590 cx
.tcx
.mk_ref(region
,
591 ty
::TypeAndMut
{ ty
: closure_ty
,
592 mutbl
: hir
::MutImmutable
});
595 temp_lifetime
: temp_lifetime
,
597 kind
: ExprKind
::Deref
{
600 temp_lifetime
: temp_lifetime
,
602 kind
: ExprKind
::SelfRef
607 ty
::ClosureKind
::FnMutClosureKind
=> {
609 cx
.tcx
.mk_ref(region
,
610 ty
::TypeAndMut
{ ty
: closure_ty
,
611 mutbl
: hir
::MutMutable
});
614 temp_lifetime
: temp_lifetime
,
616 kind
: ExprKind
::Deref
{
619 temp_lifetime
: temp_lifetime
,
621 kind
: ExprKind
::SelfRef
626 ty
::ClosureKind
::FnOnceClosureKind
=> {
629 temp_lifetime
: temp_lifetime
,
631 kind
: ExprKind
::SelfRef
,
636 // at this point we have `self.n`, which loads up the upvar
637 let field_kind
= ExprKind
::Field
{
638 lhs
: self_expr
.to_ref(),
639 name
: Field
::new(index
),
642 // ...but the upvar might be an `&T` or `&mut T` capture, at which
643 // point we need an implicit deref
644 let upvar_id
= ty
::UpvarId
{
646 closure_expr_id
: closure_expr_id
,
648 let upvar_capture
= match cx
.tcx
.upvar_capture(upvar_id
) {
651 cx
.tcx
.sess
.span_bug(
653 &format
!("no upvar_capture for {:?}", upvar_id
));
656 match upvar_capture
{
657 ty
::UpvarCapture
::ByValue
=> field_kind
,
658 ty
::UpvarCapture
::ByRef(_
) => {
661 temp_lifetime
: temp_lifetime
,
671 _
=> cx
.tcx
.sess
.span_bug(expr
.span
, "type of & not region"),
676 fn bin_op(op
: hir
::BinOp_
) -> BinOp
{
678 hir
::BinOp_
::BiAdd
=> BinOp
::Add
,
679 hir
::BinOp_
::BiSub
=> BinOp
::Sub
,
680 hir
::BinOp_
::BiMul
=> BinOp
::Mul
,
681 hir
::BinOp_
::BiDiv
=> BinOp
::Div
,
682 hir
::BinOp_
::BiRem
=> BinOp
::Rem
,
683 hir
::BinOp_
::BiBitXor
=> BinOp
::BitXor
,
684 hir
::BinOp_
::BiBitAnd
=> BinOp
::BitAnd
,
685 hir
::BinOp_
::BiBitOr
=> BinOp
::BitOr
,
686 hir
::BinOp_
::BiShl
=> BinOp
::Shl
,
687 hir
::BinOp_
::BiShr
=> BinOp
::Shr
,
688 hir
::BinOp_
::BiEq
=> BinOp
::Eq
,
689 hir
::BinOp_
::BiLt
=> BinOp
::Lt
,
690 hir
::BinOp_
::BiLe
=> BinOp
::Le
,
691 hir
::BinOp_
::BiNe
=> BinOp
::Ne
,
692 hir
::BinOp_
::BiGe
=> BinOp
::Ge
,
693 hir
::BinOp_
::BiGt
=> BinOp
::Gt
,
694 _
=> panic
!("no equivalent for ast binop {:?}", op
),
703 fn overloaded_operator
<'a
, 'tcx
: 'a
>(cx
: &mut Cx
<'a
, 'tcx
>,
704 expr
: &'tcx hir
::Expr
,
705 method_call
: ty
::MethodCall
,
707 receiver
: ExprRef
<'tcx
>,
708 args
: Vec
<&'tcx P
<hir
::Expr
>>)
710 // the receiver has all the adjustments that are needed, so we can
711 // just push a reference to it
712 let mut argrefs
= vec
![receiver
];
714 // the arguments, unfortunately, do not, so if this is a ByRef
715 // operator, we have to gin up the autorefs (but by value is easy)
717 PassArgs
::ByValue
=> {
718 argrefs
.extend(args
.iter().map(|arg
| arg
.to_ref()))
722 let scope
= cx
.tcx
.region_maps
.node_extent(expr
.id
);
723 let region
= cx
.tcx
.mk_region(ty
::ReScope(scope
));
724 let temp_lifetime
= cx
.tcx
.region_maps
.temporary_scope(expr
.id
);
728 let arg_ty
= cx
.tcx
.expr_ty_adjusted(arg
);
730 cx
.tcx
.mk_ref(region
,
731 ty
::TypeAndMut
{ ty
: arg_ty
,
732 mutbl
: hir
::MutImmutable
});
734 temp_lifetime
: temp_lifetime
,
737 kind
: ExprKind
::Borrow
{ region
: *region
,
738 borrow_kind
: BorrowKind
::Shared
,
745 // now create the call itself
746 let fun
= method_callee(cx
, expr
, method_call
);
753 fn overloaded_lvalue
<'a
, 'tcx
: 'a
>(cx
: &mut Cx
<'a
, 'tcx
>,
754 expr
: &'tcx hir
::Expr
,
755 method_call
: ty
::MethodCall
,
757 receiver
: ExprRef
<'tcx
>,
758 args
: Vec
<&'tcx P
<hir
::Expr
>>)
760 // For an overloaded *x or x[y] expression of type T, the method
761 // call returns an &T and we must add the deref so that the types
762 // line up (this is because `*x` and `x[y]` represent lvalues):
764 // to find the type &T of the content returned by the method;
765 let tables
= cx
.tcx
.tables
.borrow();
766 let callee
= &tables
.method_map
[&method_call
];
767 let ref_ty
= callee
.ty
.fn_ret();
768 let ref_ty
= cx
.tcx
.no_late_bound_regions(&ref_ty
).unwrap().unwrap();
770 // (1) callees always have all late-bound regions fully instantiated,
771 // (2) overloaded methods don't return `!`
773 // construct the complete expression `foo()` for the overloaded call,
774 // which will yield the &T type
775 let temp_lifetime
= cx
.tcx
.region_maps
.temporary_scope(expr
.id
);
776 let ref_kind
= overloaded_operator(cx
, expr
, method_call
, pass_args
, receiver
, args
);
777 let ref_expr
= Expr
{
778 temp_lifetime
: temp_lifetime
,
784 // construct and return a deref wrapper `*foo()`
785 ExprKind
::Deref { arg: ref_expr.to_ref() }
788 fn capture_freevar
<'a
, 'tcx
: 'a
>(cx
: &mut Cx
<'a
, 'tcx
>,
789 closure_expr
: &'tcx hir
::Expr
,
790 freevar
: &ty
::Freevar
,
791 freevar_ty
: Ty
<'tcx
>)
793 let id_var
= freevar
.def
.var_id();
794 let upvar_id
= ty
::UpvarId
{
796 closure_expr_id
: closure_expr
.id
,
798 let upvar_capture
= cx
.tcx
.upvar_capture(upvar_id
).unwrap();
799 let temp_lifetime
= cx
.tcx
.region_maps
.temporary_scope(closure_expr
.id
);
800 let var_ty
= cx
.tcx
.node_id_to_type(id_var
);
801 let captured_var
= Expr
{
802 temp_lifetime
: temp_lifetime
,
804 span
: closure_expr
.span
,
805 kind
: convert_var(cx
, closure_expr
, freevar
.def
),
807 match upvar_capture
{
808 ty
::UpvarCapture
::ByValue
=> {
809 captured_var
.to_ref()
811 ty
::UpvarCapture
::ByRef(upvar_borrow
) => {
812 let borrow_kind
= match upvar_borrow
.kind
{
813 ty
::BorrowKind
::ImmBorrow
=> BorrowKind
::Shared
,
814 ty
::BorrowKind
::UniqueImmBorrow
=> BorrowKind
::Unique
,
815 ty
::BorrowKind
::MutBorrow
=> BorrowKind
::Mut
,
818 temp_lifetime
: temp_lifetime
,
820 span
: closure_expr
.span
,
821 kind
: ExprKind
::Borrow
{ region
: upvar_borrow
.region
,
822 borrow_kind
: borrow_kind
,
823 arg
: captured_var
.to_ref() }
829 fn loop_label
<'a
, 'tcx
: 'a
>(cx
: &mut Cx
<'a
, 'tcx
>, expr
: &'tcx hir
::Expr
) -> CodeExtent
{
830 match cx
.tcx
.def_map
.borrow().get(&expr
.id
).map(|d
| d
.full_def()) {
831 Some(def
::DefLabel(loop_id
)) => cx
.tcx
.region_maps
.node_extent(loop_id
),
833 cx
.tcx
.sess
.span_bug(expr
.span
, &format
!("loop scope resolved to {:?}", d
));
838 fn field_refs
<'tcx
>(variant
: VariantDef
<'tcx
>,
839 fields
: &'tcx
[hir
::Field
])
840 -> Vec
<FieldExprRef
<'tcx
>>
843 .map(|field
| FieldExprRef
{
844 name
: Field
::new(variant
.index_of_field_named(field
.name
.node
).unwrap()),
845 expr
: field
.expr
.to_ref(),