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 ;
@@ -38,6 +38,7 @@ enum GroupedMoveError<'tcx> {
3838 // Match place can't be moved from
3939 // e.g. match x[0] { s => (), } where x: &[String]
4040 MovesFromMatchPlace {
41+ original_path : Place < ' tcx > ,
4142 span : Span ,
4243 move_from : Place < ' tcx > ,
4344 kind : IllegalMoveOriginKind < ' tcx > ,
@@ -46,37 +47,43 @@ enum GroupedMoveError<'tcx> {
4647 // Part of a pattern can't be moved from,
4748 // e.g. match &String::new() { &x => (), }
4849 MovesFromPattern {
50+ original_path : Place < ' tcx > ,
4951 span : Span ,
5052 move_from : MovePathIndex ,
5153 kind : IllegalMoveOriginKind < ' tcx > ,
5254 binds_to : Vec < Local > ,
5355 } ,
5456 // Everything that isn't from pattern matching.
5557 OtherIllegalMove {
58+ original_path : Place < ' tcx > ,
5659 span : Span ,
5760 kind : IllegalMoveOriginKind < ' tcx > ,
5861 } ,
5962}
6063
6164impl < ' a , ' gcx , ' tcx > MirBorrowckCtxt < ' a , ' gcx , ' tcx > {
62- pub ( crate ) fn report_move_errors ( & mut self , move_errors : Vec < MoveError < ' tcx > > ) {
65+ pub ( crate ) fn report_move_errors ( & mut self , move_errors : Vec < ( Place < ' tcx > , MoveError < ' tcx > ) > ) {
6366 let grouped_errors = self . group_move_errors ( move_errors) ;
6467 for error in grouped_errors {
6568 self . report ( error) ;
6669 }
6770 }
6871
69- fn group_move_errors ( & self , errors : Vec < MoveError < ' tcx > > ) -> Vec < GroupedMoveError < ' tcx > > {
72+ fn group_move_errors (
73+ & self ,
74+ errors : Vec < ( Place < ' tcx > , MoveError < ' tcx > ) >
75+ ) -> Vec < GroupedMoveError < ' tcx > > {
7076 let mut grouped_errors = Vec :: new ( ) ;
71- for error in errors {
72- self . append_to_grouped_errors ( & mut grouped_errors, error) ;
77+ for ( original_path , error) in errors {
78+ self . append_to_grouped_errors ( & mut grouped_errors, original_path , error) ;
7379 }
7480 grouped_errors
7581 }
7682
7783 fn append_to_grouped_errors (
7884 & self ,
7985 grouped_errors : & mut Vec < GroupedMoveError < ' tcx > > ,
86+ original_path : Place < ' tcx > ,
8087 error : MoveError < ' tcx > ,
8188 ) {
8289 match error {
@@ -116,6 +123,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
116123 self . append_binding_error (
117124 grouped_errors,
118125 kind,
126+ original_path,
119127 move_from,
120128 * local,
121129 opt_match_place,
@@ -127,6 +135,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
127135 }
128136 grouped_errors. push ( GroupedMoveError :: OtherIllegalMove {
129137 span : stmt_source_info. span ,
138+ original_path,
130139 kind,
131140 } ) ;
132141 }
@@ -137,6 +146,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
137146 & self ,
138147 grouped_errors : & mut Vec < GroupedMoveError < ' tcx > > ,
139148 kind : IllegalMoveOriginKind < ' tcx > ,
149+ original_path : Place < ' tcx > ,
140150 move_from : & Place < ' tcx > ,
141151 bind_to : Local ,
142152 match_place : & Option < Place < ' tcx > > ,
@@ -176,6 +186,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
176186 grouped_errors. push ( GroupedMoveError :: MovesFromMatchPlace {
177187 span,
178188 move_from : match_place. clone ( ) ,
189+ original_path,
179190 kind,
180191 binds_to,
181192 } ) ;
@@ -206,6 +217,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
206217 grouped_errors. push ( GroupedMoveError :: MovesFromPattern {
207218 span : match_span,
208219 move_from : mpi,
220+ original_path,
209221 kind,
210222 binds_to : vec ! [ bind_to] ,
211223 } ) ;
@@ -215,13 +227,23 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
215227
216228 fn report ( & mut self , error : GroupedMoveError < ' tcx > ) {
217229 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- } ;
230+ let ( span, original_path, kind) : ( Span , & Place < ' tcx > , & IllegalMoveOriginKind ) =
231+ match error {
232+ GroupedMoveError :: MovesFromMatchPlace {
233+ span,
234+ ref original_path,
235+ ref kind,
236+ ..
237+ } |
238+ GroupedMoveError :: MovesFromPattern { span, ref original_path, ref kind, .. } |
239+ GroupedMoveError :: OtherIllegalMove { span, ref original_path, ref kind } => {
240+ ( span, original_path, kind)
241+ } ,
242+ } ;
223243 let origin = Origin :: Mir ;
224- debug ! ( "report: span={:?}, kind={:?}" , span, kind) ;
244+ debug ! ( "report: original_path={:?} span={:?}, kind={:?} \
245+ original_path.is_upvar_field_projection={:?}", original_path, span, kind,
246+ original_path. is_upvar_field_projection( self . mir, & self . tcx) ) ;
225247 (
226248 match kind {
227249 IllegalMoveOriginKind :: Static => {
@@ -237,17 +259,11 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
237259 . tcx
238260 . cannot_move_out_of_interior_noncopy ( span, ty, None , origin) ,
239261 ty:: TyClosure ( def_id, closure_substs)
240- if !self . mir . upvar_decls . is_empty ( )
241- && {
242- match place {
243- Place :: Projection ( ref proj) => {
244- proj. base == Place :: Local ( Local :: new ( 1 ) )
245- }
246- Place :: Promoted ( _) |
247- Place :: Local ( _) | Place :: Static ( _) => unreachable ! ( ) ,
248- }
249- } =>
250- {
262+ if !self . mir . upvar_decls . is_empty ( ) &&
263+ original_path. strip_deref_projections ( )
264+ . is_upvar_field_projection ( self . mir , & self . tcx )
265+ . is_some ( )
266+ => {
251267 let closure_kind_ty =
252268 closure_substs. closure_kind_ty ( def_id, self . tcx ) ;
253269 let closure_kind = closure_kind_ty. to_opt_closure_kind ( ) ;
@@ -267,7 +283,19 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
267283 place_description={:?}", closure_kind_ty, closure_kind,
268284 place_description) ;
269285
270- self . tcx . cannot_move_out_of ( span, place_description, origin)
286+ let mut diag = self . tcx . cannot_move_out_of (
287+ span, place_description, origin) ;
288+
289+ if let Some ( field) = original_path. is_upvar_field_projection (
290+ self . mir , & self . tcx ) {
291+ let upvar_decl = & self . mir . upvar_decls [ field. index ( ) ] ;
292+ let upvar_hir_id = upvar_decl. var_hir_id . assert_crate_local ( ) ;
293+ let upvar_node_id = self . tcx . hir . hir_to_node_id ( upvar_hir_id) ;
294+ let upvar_span = self . tcx . hir . span ( upvar_node_id) ;
295+ diag. span_label ( upvar_span, "captured outer variable" ) ;
296+ }
297+
298+ diag
271299 }
272300 _ => self
273301 . tcx
0 commit comments