1010
1111use rustc:: hir;
1212use rustc:: mir:: * ;
13- use rustc:: ty:: { self , TyCtxt } ;
13+ use rustc:: ty;
14+ use rustc_data_structures:: indexed_vec:: Idx ;
1415use rustc_errors:: DiagnosticBuilder ;
1516use syntax_pos:: Span ;
1617
17- use dataflow:: move_paths:: { IllegalMoveOrigin , IllegalMoveOriginKind , MoveData } ;
18+ use borrow_check:: MirBorrowckCtxt ;
19+ use dataflow:: move_paths:: { IllegalMoveOrigin , IllegalMoveOriginKind } ;
1820use dataflow:: move_paths:: { LookupResult , MoveError , MovePathIndex } ;
1921use util:: borrowck_errors:: { BorrowckErrors , Origin } ;
2022
21- pub ( crate ) fn report_move_errors < ' gcx , ' tcx > (
22- mir : & Mir < ' tcx > ,
23- tcx : TyCtxt < ' _ , ' gcx , ' tcx > ,
24- move_errors : Vec < MoveError < ' tcx > > ,
25- move_data : & MoveData < ' tcx > ,
26- ) {
27- MoveErrorCtxt {
28- mir,
29- tcx,
30- move_data,
31- } . report_errors ( move_errors) ;
32- }
33-
34- #[ derive( Copy , Clone ) ]
35- struct MoveErrorCtxt < ' a , ' gcx : ' tcx , ' tcx : ' a > {
36- mir : & ' a Mir < ' tcx > ,
37- tcx : TyCtxt < ' a , ' gcx , ' tcx > ,
38- move_data : & ' a MoveData < ' tcx > ,
39- }
40-
4123// Often when desugaring a pattern match we may have many individual moves in
4224// MIR that are all part of one operation from the user's point-of-view. For
4325// example:
@@ -76,15 +58,15 @@ enum GroupedMoveError<'tcx> {
7658 } ,
7759}
7860
79- impl < ' a , ' gcx , ' tcx > MoveErrorCtxt < ' a , ' gcx , ' tcx > {
80- fn report_errors ( self , move_errors : Vec < MoveError < ' tcx > > ) {
61+ impl < ' a , ' gcx , ' tcx > MirBorrowckCtxt < ' a , ' gcx , ' tcx > {
62+ pub ( crate ) fn report_move_errors ( & self , move_errors : Vec < MoveError < ' tcx > > ) {
8163 let grouped_errors = self . group_move_errors ( move_errors) ;
8264 for error in grouped_errors {
8365 self . report ( error) ;
8466 }
8567 }
8668
87- fn group_move_errors ( self , errors : Vec < MoveError < ' tcx > > ) -> Vec < GroupedMoveError < ' tcx > > {
69+ fn group_move_errors ( & self , errors : Vec < MoveError < ' tcx > > ) -> Vec < GroupedMoveError < ' tcx > > {
8870 let mut grouped_errors = Vec :: new ( ) ;
8971 for error in errors {
9072 self . append_to_grouped_errors ( & mut grouped_errors, error) ;
@@ -93,7 +75,7 @@ impl<'a, 'gcx, 'tcx> MoveErrorCtxt<'a, 'gcx, 'tcx> {
9375 }
9476
9577 fn append_to_grouped_errors (
96- self ,
78+ & self ,
9779 grouped_errors : & mut Vec < GroupedMoveError < ' tcx > > ,
9880 error : MoveError < ' tcx > ,
9981 ) {
@@ -114,19 +96,19 @@ impl<'a, 'gcx, 'tcx> MoveErrorCtxt<'a, 'gcx, 'tcx> {
11496 . map ( |stmt| & stmt. kind )
11597 {
11698 let local_decl = & self . mir . local_decls [ * local] ;
99+ // opt_match_place is the
100+ // match_span is the span of the expression being matched on
101+ // match *x.y { ... } match_place is Some(*x.y)
102+ // ^^^^ match_span is the span of *x.y
103+ //
104+ // opt_match_place is None for let [mut] x = ... statements,
105+ // whether or not the right-hand side is a place expression
117106 if let Some ( ClearCrossCrate :: Set ( BindingForm :: Var ( VarBindingForm {
118107 opt_match_place : Some ( ( ref opt_match_place, match_span) ) ,
119108 binding_mode : _,
120109 opt_ty_info : _,
121110 } ) ) ) = local_decl. is_user_variable
122111 {
123- // opt_match_place is the
124- // match_span is the span of the expression being matched on
125- // match *x.y { ... } match_place is Some(*x.y)
126- // ^^^^ match_span is the span of *x.y
127- // opt_match_place is None for let [mut] x = ... statements,
128- // whether or not the right-hand side is a place expression
129-
130112 // HACK use scopes to determine if this assignment is
131113 // the initialization of a variable.
132114 // FIXME(matthewjasper) This would probably be more
@@ -145,8 +127,8 @@ impl<'a, 'gcx, 'tcx> MoveErrorCtxt<'a, 'gcx, 'tcx> {
145127 opt_match_place,
146128 match_span,
147129 ) ;
130+ return ;
148131 }
149- return ;
150132 }
151133 }
152134 grouped_errors. push ( GroupedMoveError :: OtherIllegalMove {
@@ -158,7 +140,7 @@ impl<'a, 'gcx, 'tcx> MoveErrorCtxt<'a, 'gcx, 'tcx> {
158140 }
159141
160142 fn append_binding_error (
161- self ,
143+ & self ,
162144 grouped_errors : & mut Vec < GroupedMoveError < ' tcx > > ,
163145 kind : IllegalMoveOriginKind < ' tcx > ,
164146 move_from : & Place < ' tcx > ,
@@ -236,7 +218,7 @@ impl<'a, 'gcx, 'tcx> MoveErrorCtxt<'a, 'gcx, 'tcx> {
236218 } ;
237219 }
238220
239- fn report ( self , error : GroupedMoveError < ' tcx > ) {
221+ fn report ( & self , error : GroupedMoveError < ' tcx > ) {
240222 let ( mut err, err_span) = {
241223 let ( span, kind) : ( Span , & IllegalMoveOriginKind ) = match error {
242224 GroupedMoveError :: MovesFromMatchPlace { span, ref kind, .. }
@@ -249,14 +231,43 @@ impl<'a, 'gcx, 'tcx> MoveErrorCtxt<'a, 'gcx, 'tcx> {
249231 IllegalMoveOriginKind :: Static => {
250232 self . tcx . cannot_move_out_of ( span, "static item" , origin)
251233 }
252- IllegalMoveOriginKind :: BorrowedContent { target_ty : ty } => {
234+ IllegalMoveOriginKind :: BorrowedContent { target_place : place } => {
253235 // Inspect the type of the content behind the
254236 // borrow to provide feedback about why this
255237 // was a move rather than a copy.
238+ let ty = place. ty ( self . mir , self . tcx ) . to_ty ( self . tcx ) ;
256239 match ty. sty {
257240 ty:: TyArray ( ..) | ty:: TySlice ( ..) => self
258241 . tcx
259242 . cannot_move_out_of_interior_noncopy ( span, ty, None , origin) ,
243+ ty:: TyClosure ( def_id, closure_substs)
244+ if !self . mir . upvar_decls . is_empty ( )
245+ && {
246+ match place {
247+ Place :: Projection ( ref proj) => {
248+ proj. base == Place :: Local ( Local :: new ( 1 ) )
249+ }
250+ Place :: Local ( _) | Place :: Static ( _) => unreachable ! ( ) ,
251+ }
252+ } =>
253+ {
254+ let closure_kind_ty =
255+ closure_substs. closure_kind_ty ( def_id, self . tcx ) ;
256+ let closure_kind = closure_kind_ty. to_opt_closure_kind ( ) ;
257+ let place_description = match closure_kind {
258+ Some ( ty:: ClosureKind :: Fn ) => {
259+ "captured variable in an `Fn` closure"
260+ }
261+ Some ( ty:: ClosureKind :: FnMut ) => {
262+ "captured variable in an `FnMut` closure"
263+ }
264+ Some ( ty:: ClosureKind :: FnOnce ) => {
265+ bug ! ( "closure kind does not match first argument type" )
266+ }
267+ None => bug ! ( "closure kind not inferred by borrowck" ) ,
268+ } ;
269+ self . tcx . cannot_move_out_of ( span, place_description, origin)
270+ }
260271 _ => self
261272 . tcx
262273 . cannot_move_out_of ( span, "borrowed content" , origin) ,
@@ -279,7 +290,7 @@ impl<'a, 'gcx, 'tcx> MoveErrorCtxt<'a, 'gcx, 'tcx> {
279290 }
280291
281292 fn add_move_hints (
282- self ,
293+ & self ,
283294 error : GroupedMoveError < ' tcx > ,
284295 err : & mut DiagnosticBuilder < ' a > ,
285296 span : Span ,
@@ -365,7 +376,7 @@ impl<'a, 'gcx, 'tcx> MoveErrorCtxt<'a, 'gcx, 'tcx> {
365376 }
366377 }
367378
368- fn suitable_to_remove_deref ( self , proj : & PlaceProjection < ' tcx > , snippet : & str ) -> bool {
379+ fn suitable_to_remove_deref ( & self , proj : & PlaceProjection < ' tcx > , snippet : & str ) -> bool {
369380 let is_shared_ref = |ty : ty:: Ty | match ty. sty {
370381 ty:: TypeVariants :: TyRef ( .., hir:: Mutability :: MutImmutable ) => true ,
371382 _ => false ,
0 commit comments