@@ -89,8 +89,11 @@ fn check_crate(tcx: ty::ctxt,
89
89
tcx.sess.abort_if_errors();
90
90
}
91
91
92
+ // bool flag is only used for checking closures,
93
+ // where it refers to whether a var is 'move' in the
94
+ // capture clause
92
95
type check_fn = fn@(ctx, node_id, Option<@freevar_entry>,
93
- bool, ty::t, sp: span);
96
+ bool, ty::t, sp: span);
94
97
95
98
// Yields the appropriate function to check the kind of closed over
96
99
// variables. `id` is the node_id for some expression that creates the
@@ -111,7 +114,6 @@ fn with_appropriate_checker(cx: ctx, id: node_id, b: fn(check_fn)) {
111
114
"to copy values into a ~fn closure, use a \
112
115
capture clause: `fn~(copy x)` or `|copy x|`") ) ) ;
113
116
}
114
-
115
117
// check that only immutable variables are implicitly copied in
116
118
for fv. each |fv| {
117
119
check_imm_free_var( cx, fv. def, fv. span) ;
@@ -132,7 +134,6 @@ fn with_appropriate_checker(cx: ctx, id: node_id, b: fn(check_fn)) {
132
134
"to copy values into a @fn closure, use a \
133
135
capture clause: `fn~(copy x)` or `|copy x|`") ) ) ;
134
136
}
135
-
136
137
// check that only immutable variables are implicitly copied in
137
138
for fv. each |fv| {
138
139
check_imm_free_var( cx, fv. def, fv. span) ;
@@ -151,7 +152,7 @@ fn with_appropriate_checker(cx: ctx, id: node_id, b: fn(check_fn)) {
151
152
}
152
153
153
154
fn check_for_bare ( cx : ctx , _id : node_id , _fv : Option < @freevar_entry > ,
154
- _is_move : bool , _var_t : ty:: t , sp : span ) {
155
+ _is_move : bool , _var_t : ty:: t , sp : span ) {
155
156
cx. tcx . sess . span_err ( sp, ~"attempted dynamic environment capture") ;
156
157
}
157
158
@@ -189,6 +190,7 @@ fn check_fn(fk: visit::fn_kind, decl: fn_decl, body: blk, sp: span,
189
190
let cap_def = cx. tcx . def_map . get ( cap_item. id ) ;
190
191
let cap_def_id = ast_util:: def_id_of_def ( cap_def) . node ;
191
192
let ty = ty:: node_id_to_type ( cx. tcx , cap_def_id) ;
193
+ // Here's where is_move isn't always false...
192
194
chk ( cx, fn_id, None , cap_item. is_move , ty, cap_item. span ) ;
193
195
cap_def_id
194
196
} ;
@@ -201,17 +203,10 @@ fn check_fn(fk: visit::fn_kind, decl: fn_decl, body: blk, sp: span,
201
203
// skip over free variables that appear in the cap clause
202
204
if captured_vars. contains ( & id) { loop ; }
203
205
204
- // if this is the last use of the variable, then it will be
205
- // a move and not a copy
206
- let is_move = {
207
- match cx. last_use_map . find ( fn_id) {
208
- Some ( vars) => ( * vars) . contains ( & id) ,
209
- None => false
210
- }
211
- } ;
212
-
213
206
let ty = ty:: node_id_to_type ( cx. tcx , id) ;
214
- chk ( cx, fn_id, Some ( * fv) , is_move, ty, fv. span ) ;
207
+ // is_move is always false here. See the let captured_vars...
208
+ // code above for where it's not always false.
209
+ chk ( cx, fn_id, Some ( * fv) , false , ty, fv. span ) ;
215
210
}
216
211
}
217
212
@@ -220,7 +215,9 @@ fn check_fn(fk: visit::fn_kind, decl: fn_decl, body: blk, sp: span,
220
215
221
216
fn check_block ( b : blk , cx : ctx , v : visit:: vt < ctx > ) {
222
217
match b. node . expr {
223
- Some ( ex) => maybe_copy ( cx, ex, None ) ,
218
+ Some ( ex) => maybe_copy ( cx, ex,
219
+ Some ( ( "Tail expressions in blocks must be copyable" ,
220
+ "(Try adding a move)" ) ) ) ,
224
221
_ => ( )
225
222
}
226
223
visit:: visit_block ( b, cx, v) ;
@@ -281,33 +278,45 @@ fn check_expr(e: @expr, cx: ctx, v: visit::vt<ctx>) {
281
278
expr_assign( _, ex) |
282
279
expr_unary( box( _) , ex) | expr_unary( uniq( _) , ex) |
283
280
expr_ret( Some ( ex) ) => {
284
- maybe_copy ( cx, ex, None ) ;
281
+ maybe_copy ( cx, ex, Some ( ( "Returned values must be copyable" ,
282
+ "Try adding a move" ) ) ) ;
285
283
}
286
284
expr_cast( source, _) => {
287
- maybe_copy ( cx, source, None ) ;
285
+ maybe_copy ( cx, source, Some ( ( "Casted values must be copyable" ,
286
+ "Try adding a move" ) ) ) ;
288
287
check_cast_for_escaping_regions ( cx, source, e) ;
289
288
}
290
- expr_copy( expr) => check_copy_ex ( cx, expr, false , None ) ,
289
+ expr_copy( expr) => check_copy_ex ( cx, expr, false ,
290
+ Some ( ( "Explicit copy requires a copyable argument" , "" ) ) ) ,
291
291
// Vector add copies, but not "implicitly"
292
- expr_assign_op( _, _, ex) => check_copy_ex ( cx, ex, false , None ) ,
292
+ expr_assign_op( _, _, ex) => check_copy_ex ( cx, ex, false ,
293
+ Some ( ( "Assignment with operation requires \
294
+ a copyable argument", "" ) ) ) ,
293
295
expr_binary( add, ls, rs) => {
294
- check_copy_ex ( cx, ls, false , None ) ;
295
- check_copy_ex ( cx, rs, false , None ) ;
296
+ let reason = Some ( ( "Binary operators require copyable arguments" ,
297
+ "" ) ) ;
298
+ check_copy_ex ( cx, ls, false , reason) ;
299
+ check_copy_ex ( cx, rs, false , reason) ;
296
300
}
297
- expr_rec( fields, def) => {
298
- for fields. each |field| { maybe_copy( cx, field. node. expr, None ) ; }
301
+ expr_rec( fields, def) | expr_struct( _, fields, def) => {
302
+ for fields. each |field| { maybe_copy( cx, field. node. expr,
303
+ Some ( ( "Record or struct fields require \
304
+ copyable arguments", "" ) ) ) ; }
299
305
match def {
300
306
Some ( ex) => {
301
307
// All noncopyable fields must be overridden
302
308
let t = ty:: expr_ty ( cx. tcx , ex) ;
303
309
let ty_fields = match ty:: get ( t) . sty {
304
310
ty:: ty_rec( f) => f,
305
- _ => cx. tcx . sess . span_bug ( ex. span , ~"bad expr type in record")
311
+ ty:: ty_class( did, substs) =>
312
+ ty:: class_items_as_fields ( cx. tcx , did, & substs) ,
313
+ _ => cx. tcx . sess . span_bug ( ex. span ,
314
+ ~"bad base expr type in record")
306
315
} ;
307
316
for ty_fields. each |tf| {
308
317
if !vec:: any ( fields, |f| f. node . ident == tf. ident ) &&
309
318
!ty:: kind_can_be_copied ( ty:: type_kind ( cx. tcx , tf. mt . ty ) ) {
310
- cx. tcx . sess . span_err ( ex . span ,
319
+ cx. tcx . sess . span_err ( e . span ,
311
320
~"copying a noncopyable value") ;
312
321
}
313
322
}
@@ -316,16 +325,16 @@ fn check_expr(e: @expr, cx: ctx, v: visit::vt<ctx>) {
316
325
}
317
326
}
318
327
expr_tup ( exprs) | expr_vec ( exprs, _) => {
319
- for exprs. each |expr| { maybe_copy ( cx, * expr, None ) ; }
328
+ for exprs. each |expr| { maybe_copy ( cx, * expr,
329
+ Some ( ( "Tuple or vec elements must be copyable" , "" ) ) ) ; }
320
330
}
321
331
expr_call( f, args, _) => {
322
- let mut i = 0 u;
323
- for ty:: ty_fn_args( ty:: expr_ty( cx. tcx, f) ) . each |arg_t| {
332
+ for ty:: ty_fn_args( ty:: expr_ty( cx. tcx, f) ) . eachi |i, arg_t| {
324
333
match ty:: arg_mode ( cx. tcx , * arg_t) {
325
- by_copy => maybe_copy ( cx, args[ i] , None ) ,
334
+ by_copy => maybe_copy ( cx, args[ i] ,
335
+ Some ( ( "Callee takes its argument by copy" , "" ) ) ) ,
326
336
by_ref | by_val | by_move => ( )
327
337
}
328
- i += 1 u;
329
338
}
330
339
}
331
340
expr_field ( lhs, _, _) => {
@@ -334,7 +343,9 @@ fn check_expr(e: @expr, cx: ctx, v: visit::vt<ctx>) {
334
343
match cx. method_map . find ( e. id ) {
335
344
Some ( ref mme) => {
336
345
match ty:: arg_mode ( cx. tcx , mme. self_arg ) {
337
- by_copy => maybe_copy ( cx, lhs, None ) ,
346
+ by_copy => maybe_copy ( cx, lhs,
347
+ Some ( ( "Method call takes its self argument by copy" ,
348
+ "" ) ) ) ,
338
349
by_ref | by_val | by_move => ( )
339
350
}
340
351
}
@@ -344,10 +355,12 @@ fn check_expr(e: @expr, cx: ctx, v: visit::vt<ctx>) {
344
355
expr_repeat ( element, count_expr, _) => {
345
356
let count = ty:: eval_repeat_count ( cx. tcx , count_expr, e. span ) ;
346
357
if count == 1 {
347
- maybe_copy ( cx, element, None ) ;
358
+ maybe_copy ( cx, element, Some ( ( "Trivial repeat takes its element \
359
+ by copy", "" ) ) ) ;
348
360
} else {
349
361
let element_ty = ty:: expr_ty ( cx. tcx , element) ;
350
- check_copy ( cx, element. id , element_ty, element. span , true , None ) ;
362
+ check_copy ( cx, element. id , element_ty, element. span , true ,
363
+ Some ( ( "Repeat takes its elements by copy" , "" ) ) ) ;
351
364
}
352
365
}
353
366
_ => { }
@@ -360,7 +373,9 @@ fn check_stmt(stmt: @stmt, cx: ctx, v: visit::vt<ctx>) {
360
373
stmt_decl( @{ node : decl_local( locals) , _} , _) => {
361
374
for locals. each |local| {
362
375
match local. node . init {
363
- Some ( { op : init_assign, expr} ) => maybe_copy ( cx, expr, None ) ,
376
+ Some ( { op : init_assign, expr} ) =>
377
+ maybe_copy ( cx, expr, Some ( ( "Initializer statement \
378
+ takes its right-hand side by copy", "" ) ) ) ,
364
379
_ => { }
365
380
}
366
381
}
@@ -434,9 +449,6 @@ fn check_copy_ex(cx: ctx, ex: @expr, implicit_copy: bool,
434
449
why : Option < ( & str , & str ) > ) {
435
450
if ty:: expr_is_lval ( cx. tcx , cx. method_map , ex) &&
436
451
437
- // this is a move
438
- !cx. last_use_map . contains_key ( ex. id ) &&
439
-
440
452
// a reference to a constant like `none`... no need to warn
441
453
// about *this* even if the type is Option<~int>
442
454
!is_nullary_variant ( cx, ex) &&
0 commit comments