1111use rustc:: hir;
1212use rustc:: mir:: * ;
1313use rustc:: ty;
14- use rustc_data_structures:: indexed_vec:: Idx ;
1514use rustc_errors:: DiagnosticBuilder ;
15+ use rustc_data_structures:: indexed_vec:: Idx ;
1616use syntax_pos:: Span ;
1717
1818use borrow_check:: MirBorrowckCtxt ;
19+ use borrow_check:: prefixes:: PrefixSet ;
1920use dataflow:: move_paths:: { IllegalMoveOrigin , IllegalMoveOriginKind } ;
2021use dataflow:: move_paths:: { LookupResult , MoveError , MovePathIndex } ;
2122use util:: borrowck_errors:: { BorrowckErrors , Origin } ;
@@ -38,6 +39,7 @@ enum GroupedMoveError<'tcx> {
3839 // Match place can't be moved from
3940 // e.g. match x[0] { s => (), } where x: &[String]
4041 MovesFromMatchPlace {
42+ original_path : Place < ' tcx > ,
4143 span : Span ,
4244 move_from : Place < ' tcx > ,
4345 kind : IllegalMoveOriginKind < ' tcx > ,
@@ -46,37 +48,43 @@ enum GroupedMoveError<'tcx> {
4648 // Part of a pattern can't be moved from,
4749 // e.g. match &String::new() { &x => (), }
4850 MovesFromPattern {
51+ original_path : Place < ' tcx > ,
4952 span : Span ,
5053 move_from : MovePathIndex ,
5154 kind : IllegalMoveOriginKind < ' tcx > ,
5255 binds_to : Vec < Local > ,
5356 } ,
5457 // Everything that isn't from pattern matching.
5558 OtherIllegalMove {
59+ original_path : Place < ' tcx > ,
5660 span : Span ,
5761 kind : IllegalMoveOriginKind < ' tcx > ,
5862 } ,
5963}
6064
6165impl < ' a , ' gcx , ' tcx > MirBorrowckCtxt < ' a , ' gcx , ' tcx > {
62- pub ( crate ) fn report_move_errors ( & mut self , move_errors : Vec < MoveError < ' tcx > > ) {
66+ pub ( crate ) fn report_move_errors ( & mut self , move_errors : Vec < ( Place < ' tcx > , MoveError < ' tcx > ) > ) {
6367 let grouped_errors = self . group_move_errors ( move_errors) ;
6468 for error in grouped_errors {
6569 self . report ( error) ;
6670 }
6771 }
6872
69- fn group_move_errors ( & self , errors : Vec < MoveError < ' tcx > > ) -> Vec < GroupedMoveError < ' tcx > > {
73+ fn group_move_errors (
74+ & self ,
75+ errors : Vec < ( Place < ' tcx > , MoveError < ' tcx > ) >
76+ ) -> Vec < GroupedMoveError < ' tcx > > {
7077 let mut grouped_errors = Vec :: new ( ) ;
71- for error in errors {
72- self . append_to_grouped_errors ( & mut grouped_errors, error) ;
78+ for ( original_path , error) in errors {
79+ self . append_to_grouped_errors ( & mut grouped_errors, original_path , error) ;
7380 }
7481 grouped_errors
7582 }
7683
7784 fn append_to_grouped_errors (
7885 & self ,
7986 grouped_errors : & mut Vec < GroupedMoveError < ' tcx > > ,
87+ original_path : Place < ' tcx > ,
8088 error : MoveError < ' tcx > ,
8189 ) {
8290 match error {
@@ -116,6 +124,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
116124 self . append_binding_error (
117125 grouped_errors,
118126 kind,
127+ original_path,
119128 move_from,
120129 * local,
121130 opt_match_place,
@@ -127,6 +136,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
127136 }
128137 grouped_errors. push ( GroupedMoveError :: OtherIllegalMove {
129138 span : stmt_source_info. span ,
139+ original_path,
130140 kind,
131141 } ) ;
132142 }
@@ -137,6 +147,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
137147 & self ,
138148 grouped_errors : & mut Vec < GroupedMoveError < ' tcx > > ,
139149 kind : IllegalMoveOriginKind < ' tcx > ,
150+ original_path : Place < ' tcx > ,
140151 move_from : & Place < ' tcx > ,
141152 bind_to : Local ,
142153 match_place : & Option < Place < ' tcx > > ,
@@ -176,6 +187,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
176187 grouped_errors. push ( GroupedMoveError :: MovesFromMatchPlace {
177188 span,
178189 move_from : match_place. clone ( ) ,
190+ original_path,
179191 kind,
180192 binds_to,
181193 } ) ;
@@ -206,6 +218,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
206218 grouped_errors. push ( GroupedMoveError :: MovesFromPattern {
207219 span : match_span,
208220 move_from : mpi,
221+ original_path,
209222 kind,
210223 binds_to : vec ! [ bind_to] ,
211224 } ) ;
@@ -215,12 +228,23 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
215228
216229 fn report ( & mut self , error : GroupedMoveError < ' tcx > ) {
217230 let ( mut err, err_span) = {
218- let ( span, kind) : ( Span , & IllegalMoveOriginKind ) = match error {
219- GroupedMoveError :: MovesFromMatchPlace { span, ref kind, .. }
220- | GroupedMoveError :: MovesFromPattern { span, ref kind, .. }
221- | GroupedMoveError :: OtherIllegalMove { span, ref kind } => ( span, kind) ,
222- } ;
231+ let ( span, original_path, kind) : ( Span , & Place < ' tcx > , & IllegalMoveOriginKind ) =
232+ match error {
233+ GroupedMoveError :: MovesFromMatchPlace {
234+ span,
235+ ref original_path,
236+ ref kind,
237+ ..
238+ } |
239+ GroupedMoveError :: MovesFromPattern { span, ref original_path, ref kind, .. } |
240+ GroupedMoveError :: OtherIllegalMove { span, ref original_path, ref kind } => {
241+ ( span, original_path, kind)
242+ } ,
243+ } ;
223244 let origin = Origin :: Mir ;
245+ debug ! ( "report: original_path={:?} span={:?}, kind={:?} \
246+ original_path.is_upvar_field_projection={:?}", original_path, span, kind,
247+ original_path. is_upvar_field_projection( self . mir, & self . tcx) ) ;
224248 (
225249 match kind {
226250 IllegalMoveOriginKind :: Static => {
@@ -231,22 +255,17 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
231255 // borrow to provide feedback about why this
232256 // was a move rather than a copy.
233257 let ty = place. ty ( self . mir , self . tcx ) . to_ty ( self . tcx ) ;
258+ let is_upvar_field_projection =
259+ self . prefixes ( & original_path, PrefixSet :: All )
260+ . any ( |p| p. is_upvar_field_projection ( self . mir , & self . tcx )
261+ . is_some ( ) ) ;
234262 match ty. sty {
235263 ty:: TyArray ( ..) | ty:: TySlice ( ..) => self
236264 . tcx
237265 . cannot_move_out_of_interior_noncopy ( span, ty, None , origin) ,
238266 ty:: TyClosure ( def_id, closure_substs)
239- if !self . mir . upvar_decls . is_empty ( )
240- && {
241- match place {
242- Place :: Projection ( ref proj) => {
243- proj. base == Place :: Local ( Local :: new ( 1 ) )
244- }
245- Place :: Promoted ( _) |
246- Place :: Local ( _) | Place :: Static ( _) => unreachable ! ( ) ,
247- }
248- } =>
249- {
267+ if !self . mir . upvar_decls . is_empty ( ) && is_upvar_field_projection
268+ => {
250269 let closure_kind_ty =
251270 closure_substs. closure_kind_ty ( def_id, self . tcx ) ;
252271 let closure_kind = closure_kind_ty. to_opt_closure_kind ( ) ;
@@ -262,7 +281,28 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
262281 }
263282 None => bug ! ( "closure kind not inferred by borrowck" ) ,
264283 } ;
265- self . tcx . cannot_move_out_of ( span, place_description, origin)
284+ debug ! ( "report: closure_kind_ty={:?} closure_kind={:?} \
285+ place_description={:?}", closure_kind_ty, closure_kind,
286+ place_description) ;
287+
288+ let mut diag = self . tcx . cannot_move_out_of (
289+ span, place_description, origin) ;
290+
291+ for prefix in self . prefixes ( & original_path, PrefixSet :: All ) {
292+ if let Some ( field) = prefix. is_upvar_field_projection (
293+ self . mir , & self . tcx ) {
294+ let upvar_decl = & self . mir . upvar_decls [ field. index ( ) ] ;
295+ let upvar_hir_id =
296+ upvar_decl. var_hir_id . assert_crate_local ( ) ;
297+ let upvar_node_id =
298+ self . tcx . hir . hir_to_node_id ( upvar_hir_id) ;
299+ let upvar_span = self . tcx . hir . span ( upvar_node_id) ;
300+ diag. span_label ( upvar_span, "captured outer variable" ) ;
301+ break ;
302+ }
303+ }
304+
305+ diag
266306 }
267307 _ => self
268308 . tcx
0 commit comments