@@ -15,9 +15,9 @@ use rustc::hir::def_id::{DefId};
1515use rustc:: infer:: { InferCtxt } ;
1616use rustc:: ty:: { self , TyCtxt , ParamEnv } ;
1717use 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 } ;
1919use 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 } ;
2121use transform:: nll;
2222
2323use rustc_data_structures:: fx:: FxHashSet ;
@@ -1581,6 +1581,31 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
15811581 buf
15821582 }
15831583
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+
15841609 // Appends end-user visible description of `lvalue` to `buf`.
15851610 fn append_lvalue_to_string ( & self ,
15861611 lvalue : & Lvalue < ' tcx > ,
@@ -1596,25 +1621,35 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
15961621 Lvalue :: Projection ( ref proj) => {
15971622 match proj. elem {
15981623 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+ }
16011632 } 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+ }
16041639 }
16051640 } ,
16061641 ProjectionElem :: Downcast ( ..) => {
16071642 self . append_lvalue_to_string ( & proj. base , buf, autoderef) ;
16081643 } ,
16091644 ProjectionElem :: Field ( field, _ty) => {
16101645 autoderef = true ;
1611- let is_projection_from_ty_closure = proj. base . ty ( self . mir , self . tcx )
1612- . to_ty ( self . tcx ) . is_closure ( ) ;
16131646
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) ;
16171651 } else {
1652+ let field_name = self . describe_field ( & proj. base , field) ;
16181653 self . append_lvalue_to_string ( & proj. base , buf, autoderef) ;
16191654 buf. push_str ( & format ! ( ".{}" , field_name) ) ;
16201655 }
0 commit comments