@@ -15,9 +15,9 @@ use rustc::hir::def_id::{DefId};
15
15
use rustc:: infer:: { InferCtxt } ;
16
16
use rustc:: ty:: { self , TyCtxt , ParamEnv } ;
17
17
use rustc:: ty:: maps:: Providers ;
18
- use rustc:: mir:: { AssertMessage , BasicBlock , BorrowKind , Field , Location , Lvalue , Local } ;
18
+ use rustc:: mir:: { AssertMessage , BasicBlock , BorrowKind , Location , Lvalue , Local } ;
19
19
use rustc:: mir:: { Mir , Mutability , Operand , Projection , ProjectionElem , Rvalue } ;
20
- use rustc:: mir:: { Statement , StatementKind , Terminator , TerminatorKind } ;
20
+ use rustc:: mir:: { Field , Statement , StatementKind , Terminator , TerminatorKind } ;
21
21
use transform:: nll;
22
22
23
23
use rustc_data_structures:: fx:: FxHashSet ;
@@ -1581,6 +1581,31 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
1581
1581
buf
1582
1582
}
1583
1583
1584
+ /// If this is a field projection, and the field is being projected from a closure type,
1585
+ /// then returns the index of the field being projected. Note that this closure will always
1586
+ /// be `self` in the current MIR, because that is the only time we directly access the fields
1587
+ /// of a closure type.
1588
+ fn is_upvar_field_projection ( & self , lvalue : & Lvalue < ' tcx > ) -> Option < Field > {
1589
+ match * lvalue {
1590
+ Lvalue :: Projection ( ref proj) => {
1591
+ match proj. elem {
1592
+ ProjectionElem :: Field ( field, _ty) => {
1593
+ let is_projection_from_ty_closure = proj. base . ty ( self . mir , self . tcx )
1594
+ . to_ty ( self . tcx ) . is_closure ( ) ;
1595
+
1596
+ if is_projection_from_ty_closure {
1597
+ Some ( field)
1598
+ } else {
1599
+ None
1600
+ }
1601
+ } ,
1602
+ _ => None
1603
+ }
1604
+ } ,
1605
+ _ => None
1606
+ }
1607
+ }
1608
+
1584
1609
// Appends end-user visible description of `lvalue` to `buf`.
1585
1610
fn append_lvalue_to_string ( & self ,
1586
1611
lvalue : & Lvalue < ' tcx > ,
@@ -1596,25 +1621,35 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
1596
1621
Lvalue :: Projection ( ref proj) => {
1597
1622
match proj. elem {
1598
1623
ProjectionElem :: Deref => {
1599
- if autoderef {
1600
- self . append_lvalue_to_string ( & proj. base , buf, autoderef) ;
1624
+ if let Some ( field) = self . is_upvar_field_projection ( & proj. base ) {
1625
+ let var_index = field. index ( ) ;
1626
+ let name = self . mir . upvar_decls [ var_index] . debug_name . to_string ( ) ;
1627
+ if self . mir . upvar_decls [ var_index] . by_ref {
1628
+ buf. push_str ( & name) ;
1629
+ } else {
1630
+ buf. push_str ( & format ! ( "*{}" , & name) ) ;
1631
+ }
1601
1632
} else {
1602
- buf. push_str ( & "*" ) ;
1603
- self . append_lvalue_to_string ( & proj. base , buf, autoderef) ;
1633
+ if autoderef {
1634
+ self . append_lvalue_to_string ( & proj. base , buf, autoderef) ;
1635
+ } else {
1636
+ buf. push_str ( & "*" ) ;
1637
+ self . append_lvalue_to_string ( & proj. base , buf, autoderef) ;
1638
+ }
1604
1639
}
1605
1640
} ,
1606
1641
ProjectionElem :: Downcast ( ..) => {
1607
1642
self . append_lvalue_to_string ( & proj. base , buf, autoderef) ;
1608
1643
} ,
1609
1644
ProjectionElem :: Field ( field, _ty) => {
1610
1645
autoderef = true ;
1611
- let is_projection_from_ty_closure = proj. base . ty ( self . mir , self . tcx )
1612
- . to_ty ( self . tcx ) . is_closure ( ) ;
1613
1646
1614
- let field_name = self . describe_field ( & proj. base , field) ;
1615
- if is_projection_from_ty_closure {
1616
- buf. push_str ( & format ! ( "{}" , field_name) ) ;
1647
+ if let Some ( field) = self . is_upvar_field_projection ( lvalue) {
1648
+ let var_index = field. index ( ) ;
1649
+ let name = self . mir . upvar_decls [ var_index] . debug_name . to_string ( ) ;
1650
+ buf. push_str ( & name) ;
1617
1651
} else {
1652
+ let field_name = self . describe_field ( & proj. base , field) ;
1618
1653
self . append_lvalue_to_string ( & proj. base , buf, autoderef) ;
1619
1654
buf. push_str ( & format ! ( ".{}" , field_name) ) ;
1620
1655
}
0 commit comments