10
10
11
11
use rustc:: hir;
12
12
use rustc:: mir:: * ;
13
- use rustc:: ty:: { self , TyCtxt } ;
13
+ use rustc:: ty;
14
+ use rustc_data_structures:: indexed_vec:: Idx ;
14
15
use rustc_errors:: DiagnosticBuilder ;
15
16
use syntax_pos:: Span ;
16
17
17
- use dataflow:: move_paths:: { IllegalMoveOrigin , IllegalMoveOriginKind , MoveData } ;
18
+ use borrow_check:: MirBorrowckCtxt ;
19
+ use dataflow:: move_paths:: { IllegalMoveOrigin , IllegalMoveOriginKind } ;
18
20
use dataflow:: move_paths:: { LookupResult , MoveError , MovePathIndex } ;
19
21
use util:: borrowck_errors:: { BorrowckErrors , Origin } ;
20
22
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
-
41
23
// Often when desugaring a pattern match we may have many individual moves in
42
24
// MIR that are all part of one operation from the user's point-of-view. For
43
25
// example:
@@ -76,15 +58,15 @@ enum GroupedMoveError<'tcx> {
76
58
} ,
77
59
}
78
60
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 > > ) {
81
63
let grouped_errors = self . group_move_errors ( move_errors) ;
82
64
for error in grouped_errors {
83
65
self . report ( error) ;
84
66
}
85
67
}
86
68
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 > > {
88
70
let mut grouped_errors = Vec :: new ( ) ;
89
71
for error in errors {
90
72
self . append_to_grouped_errors ( & mut grouped_errors, error) ;
@@ -93,7 +75,7 @@ impl<'a, 'gcx, 'tcx> MoveErrorCtxt<'a, 'gcx, 'tcx> {
93
75
}
94
76
95
77
fn append_to_grouped_errors (
96
- self ,
78
+ & self ,
97
79
grouped_errors : & mut Vec < GroupedMoveError < ' tcx > > ,
98
80
error : MoveError < ' tcx > ,
99
81
) {
@@ -114,19 +96,19 @@ impl<'a, 'gcx, 'tcx> MoveErrorCtxt<'a, 'gcx, 'tcx> {
114
96
. map ( |stmt| & stmt. kind )
115
97
{
116
98
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
117
106
if let Some ( ClearCrossCrate :: Set ( BindingForm :: Var ( VarBindingForm {
118
107
opt_match_place : Some ( ( ref opt_match_place, match_span) ) ,
119
108
binding_mode : _,
120
109
opt_ty_info : _,
121
110
} ) ) ) = local_decl. is_user_variable
122
111
{
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
-
130
112
// HACK use scopes to determine if this assignment is
131
113
// the initialization of a variable.
132
114
// FIXME(matthewjasper) This would probably be more
@@ -145,8 +127,8 @@ impl<'a, 'gcx, 'tcx> MoveErrorCtxt<'a, 'gcx, 'tcx> {
145
127
opt_match_place,
146
128
match_span,
147
129
) ;
130
+ return ;
148
131
}
149
- return ;
150
132
}
151
133
}
152
134
grouped_errors. push ( GroupedMoveError :: OtherIllegalMove {
@@ -158,7 +140,7 @@ impl<'a, 'gcx, 'tcx> MoveErrorCtxt<'a, 'gcx, 'tcx> {
158
140
}
159
141
160
142
fn append_binding_error (
161
- self ,
143
+ & self ,
162
144
grouped_errors : & mut Vec < GroupedMoveError < ' tcx > > ,
163
145
kind : IllegalMoveOriginKind < ' tcx > ,
164
146
move_from : & Place < ' tcx > ,
@@ -236,7 +218,7 @@ impl<'a, 'gcx, 'tcx> MoveErrorCtxt<'a, 'gcx, 'tcx> {
236
218
} ;
237
219
}
238
220
239
- fn report ( self , error : GroupedMoveError < ' tcx > ) {
221
+ fn report ( & self , error : GroupedMoveError < ' tcx > ) {
240
222
let ( mut err, err_span) = {
241
223
let ( span, kind) : ( Span , & IllegalMoveOriginKind ) = match error {
242
224
GroupedMoveError :: MovesFromMatchPlace { span, ref kind, .. }
@@ -249,14 +231,43 @@ impl<'a, 'gcx, 'tcx> MoveErrorCtxt<'a, 'gcx, 'tcx> {
249
231
IllegalMoveOriginKind :: Static => {
250
232
self . tcx . cannot_move_out_of ( span, "static item" , origin)
251
233
}
252
- IllegalMoveOriginKind :: BorrowedContent { target_ty : ty } => {
234
+ IllegalMoveOriginKind :: BorrowedContent { target_place : place } => {
253
235
// Inspect the type of the content behind the
254
236
// borrow to provide feedback about why this
255
237
// was a move rather than a copy.
238
+ let ty = place. ty ( self . mir , self . tcx ) . to_ty ( self . tcx ) ;
256
239
match ty. sty {
257
240
ty:: TyArray ( ..) | ty:: TySlice ( ..) => self
258
241
. tcx
259
242
. 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
+ }
260
271
_ => self
261
272
. tcx
262
273
. cannot_move_out_of ( span, "borrowed content" , origin) ,
@@ -279,7 +290,7 @@ impl<'a, 'gcx, 'tcx> MoveErrorCtxt<'a, 'gcx, 'tcx> {
279
290
}
280
291
281
292
fn add_move_hints (
282
- self ,
293
+ & self ,
283
294
error : GroupedMoveError < ' tcx > ,
284
295
err : & mut DiagnosticBuilder < ' a > ,
285
296
span : Span ,
@@ -365,7 +376,7 @@ impl<'a, 'gcx, 'tcx> MoveErrorCtxt<'a, 'gcx, 'tcx> {
365
376
}
366
377
}
367
378
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 {
369
380
let is_shared_ref = |ty : ty:: Ty | match ty. sty {
370
381
ty:: TypeVariants :: TyRef ( .., hir:: Mutability :: MutImmutable ) => true ,
371
382
_ => false ,
0 commit comments