@@ -103,7 +103,13 @@ fn with_appropriate_checker(cx: ctx, id: node_id, b: fn(check_fn)) {
103
103
104
104
// copied in data must be copyable, but moved in data can be anything
105
105
let is_implicit = fv.is_some();
106
- if !is_move { check_copy(cx, id, var_t, sp, is_implicit); }
106
+ if !is_move {
107
+ check_copy(cx, id, var_t, sp, is_implicit,
108
+ some((" non-copyable value cannot be copied into a \
109
+ ~fn closure",
110
+ "to copy values into a ~fn closure, use a \
111
+ capture clause: `fn~(copy x)` or `|copy x|`") ) ) ;
112
+ }
107
113
108
114
// check that only immutable variables are implicitly copied in
109
115
for fv. each |fv| {
@@ -118,7 +124,13 @@ fn with_appropriate_checker(cx: ctx, id: node_id, b: fn(check_fn)) {
118
124
119
125
// copied in data must be copyable, but moved in data can be anything
120
126
let is_implicit = fv. is_some ( ) ;
121
- if !is_move { check_copy(cx, id, var_t, sp, is_implicit); }
127
+ if !is_move {
128
+ check_copy ( cx, id, var_t, sp, is_implicit,
129
+ some ( ( "non-copyable value cannot be copied into a \
130
+ @fn closure",
131
+ "to copy values into a @fn closure, use a \
132
+ capture clause: `fn~(copy x)` or `|copy x|`") ) ) ;
133
+ }
122
134
123
135
// check that only immutable variables are implicitly copied in
124
136
for fv. each |fv| {
@@ -207,7 +219,7 @@ fn check_fn(fk: visit::fn_kind, decl: fn_decl, body: blk, sp: span,
207
219
208
220
fn check_block ( b : blk , cx : ctx , v : visit:: vt < ctx > ) {
209
221
match b. node . expr {
210
- some( ex) => maybe_copy ( cx, ex) ,
222
+ some( ex) => maybe_copy ( cx, ex, none ) ,
211
223
_ => ( )
212
224
}
213
225
visit:: visit_block ( b, cx, v) ;
@@ -247,21 +259,21 @@ fn check_expr(e: @expr, cx: ctx, v: visit::vt<ctx>) {
247
259
expr_assign ( _, ex) |
248
260
expr_unary ( box ( _) , ex) | expr_unary ( uniq ( _) , ex) |
249
261
expr_ret ( some ( ex) ) => {
250
- maybe_copy ( cx, ex) ;
262
+ maybe_copy ( cx, ex, none ) ;
251
263
}
252
264
expr_cast ( source, _) => {
253
- maybe_copy ( cx, source) ;
265
+ maybe_copy ( cx, source, none ) ;
254
266
check_cast_for_escaping_regions ( cx, source, e) ;
255
267
}
256
- expr_copy ( expr) => check_copy_ex ( cx, expr, false ) ,
268
+ expr_copy ( expr) => check_copy_ex ( cx, expr, false , none ) ,
257
269
// Vector add copies, but not "implicitly"
258
- expr_assign_op ( _, _, ex) => check_copy_ex ( cx, ex, false ) ,
270
+ expr_assign_op ( _, _, ex) => check_copy_ex ( cx, ex, false , none ) ,
259
271
expr_binary ( add, ls, rs) => {
260
- check_copy_ex ( cx, ls, false ) ;
261
- check_copy_ex ( cx, rs, false ) ;
272
+ check_copy_ex ( cx, ls, false , none ) ;
273
+ check_copy_ex ( cx, rs, false , none ) ;
262
274
}
263
275
expr_rec ( fields, def) => {
264
- for fields. each |field| { maybe_copy ( cx, field. node . expr ) ; }
276
+ for fields. each |field| { maybe_copy ( cx, field. node . expr , none ) ; }
265
277
match def {
266
278
some( ex) => {
267
279
// All noncopyable fields must be overridden
@@ -282,13 +294,13 @@ fn check_expr(e: @expr, cx: ctx, v: visit::vt<ctx>) {
282
294
}
283
295
}
284
296
expr_tup ( exprs) | expr_vec ( exprs, _) => {
285
- for exprs. each |expr| { maybe_copy ( cx, expr) ; }
297
+ for exprs. each |expr| { maybe_copy ( cx, expr, none ) ; }
286
298
}
287
299
expr_call( f, args, _) => {
288
300
let mut i = 0 u;
289
301
for ty:: ty_fn_args( ty:: expr_ty( cx. tcx, f) ) . each |arg_t| {
290
302
match ty:: arg_mode ( cx. tcx , arg_t) {
291
- by_copy => maybe_copy ( cx, args[ i] ) ,
303
+ by_copy => maybe_copy ( cx, args[ i] , none ) ,
292
304
by_ref | by_val | by_mutbl_ref | by_move => ( )
293
305
}
294
306
i += 1 u;
@@ -298,17 +310,17 @@ fn check_expr(e: @expr, cx: ctx, v: visit::vt<ctx>) {
298
310
// If this is a method call with a by-val argument, we need
299
311
// to check the copy
300
312
match cx. method_map . find ( e. id ) {
301
- some ( { self_mode : by_copy, _} ) => maybe_copy ( cx, lhs) ,
313
+ some ( { self_mode : by_copy, _} ) => maybe_copy ( cx, lhs, none ) ,
302
314
_ => ( )
303
315
}
304
316
}
305
317
expr_repeat ( element, count_expr, _) => {
306
318
let count = ty:: eval_repeat_count ( cx. tcx , count_expr, e. span ) ;
307
319
if count == 1 {
308
- maybe_copy ( cx, element) ;
320
+ maybe_copy ( cx, element, none ) ;
309
321
} else {
310
322
let element_ty = ty:: expr_ty ( cx. tcx , element) ;
311
- check_copy ( cx, element. id , element_ty, element. span , true ) ;
323
+ check_copy ( cx, element. id , element_ty, element. span , true , none ) ;
312
324
}
313
325
}
314
326
_ => { }
@@ -321,7 +333,7 @@ fn check_stmt(stmt: @stmt, cx: ctx, v: visit::vt<ctx>) {
321
333
stmt_decl( @{ node : decl_local( locals) , _} , _) => {
322
334
for locals. each |local| {
323
335
match local. node . init {
324
- some ( { op : init_assign, expr} ) => maybe_copy ( cx, expr) ,
336
+ some ( { op : init_assign, expr} ) => maybe_copy ( cx, expr, none ) ,
325
337
_ => { }
326
338
}
327
339
}
@@ -373,8 +385,8 @@ fn check_bounds(cx: ctx, id: node_id, sp: span,
373
385
}
374
386
}
375
387
376
- fn maybe_copy ( cx: ctx, ex: @expr) {
377
- check_copy_ex ( cx, ex, true ) ;
388
+ fn maybe_copy( cx: ctx, ex: @expr, why : option< ( & str , & str ) > ) {
389
+ check_copy_ex ( cx, ex, true , why ) ;
378
390
}
379
391
380
392
fn is_nullary_variant ( cx : ctx , ex: @expr) -> bool {
@@ -391,7 +403,8 @@ fn is_nullary_variant(cx: ctx, ex: @expr) -> bool {
391
403
}
392
404
}
393
405
394
- fn check_copy_ex ( cx : ctx , ex: @expr, implicit_copy : bool ) {
406
+ fn check_copy_ex ( cx : ctx , ex: @expr, implicit_copy : bool ,
407
+ why : option < ( & str , & str ) > ) {
395
408
if ty:: expr_is_lval ( cx. method_map , ex) &&
396
409
397
410
// this is a move
@@ -405,7 +418,7 @@ fn check_copy_ex(cx: ctx, ex: @expr, implicit_copy: bool) {
405
418
!cx. tcx . borrowings . contains_key ( ex. id )
406
419
{
407
420
let ty = ty:: expr_ty ( cx. tcx , ex) ;
408
- check_copy ( cx, ex. id , ty, ex. span , implicit_copy) ;
421
+ check_copy ( cx, ex. id , ty, ex. span , implicit_copy, why ) ;
409
422
}
410
423
}
411
424
@@ -439,15 +452,21 @@ fn check_imm_free_var(cx: ctx, def: def, sp: span) {
439
452
}
440
453
441
454
fn check_copy ( cx : ctx , id : node_id , ty : ty:: t , sp : span ,
442
- implicit_copy : bool ) {
455
+ implicit_copy : bool , why : option < ( & str , & str ) > ) {
443
456
let k = ty:: type_kind ( cx. tcx , ty) ;
444
457
if !ty:: kind_can_be_copied ( k) {
445
458
cx. tcx . sess . span_err ( sp, ~"copying a noncopyable value") ;
459
+ do why. map |reason| {
460
+ cx. tcx . sess . span_note ( sp, fmt ! ( "%s" , reason. first( ) ) ) ;
461
+ } ;
446
462
} else if implicit_copy && !ty:: kind_can_be_implicitly_copied ( k) {
447
463
cx. tcx . sess . span_lint (
448
464
implicit_copies, id, cx. current_item ,
449
465
sp,
450
466
~"implicitly copying a non-implicitly-copyable value") ;
467
+ do why. map |reason| {
468
+ cx. tcx . sess . span_note ( sp, fmt ! ( "%s" , reason. second( ) ) ) ;
469
+ } ;
451
470
}
452
471
}
453
472
0 commit comments