@@ -89,8 +89,11 @@ fn check_crate(tcx: ty::ctxt,
8989 tcx.sess.abort_if_errors();
9090}
9191
92+ // bool flag is only used for checking closures,
93+ // where it refers to whether a var is 'move' in the
94+ // capture clause
9295type check_fn = fn@(ctx, node_id, Option<@freevar_entry>,
93- bool, ty::t, sp: span);
96+ bool, ty::t, sp: span);
9497
9598// Yields the appropriate function to check the kind of closed over
9699// 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)) {
111114 "to copy values into a ~fn closure, use a \
112115 capture clause: `fn~(copy x)` or `|copy x|`") ) ) ;
113116 }
114-
115117 // check that only immutable variables are implicitly copied in
116118 for fv. each |fv| {
117119 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)) {
132134 "to copy values into a @fn closure, use a \
133135 capture clause: `fn~(copy x)` or `|copy x|`") ) ) ;
134136 }
135-
136137 // check that only immutable variables are implicitly copied in
137138 for fv. each |fv| {
138139 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)) {
151152 }
152153
153154 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 ) {
155156 cx. tcx . sess . span_err ( sp, ~"attempted dynamic environment capture") ;
156157 }
157158
@@ -189,6 +190,7 @@ fn check_fn(fk: visit::fn_kind, decl: fn_decl, body: blk, sp: span,
189190 let cap_def = cx. tcx . def_map . get ( cap_item. id ) ;
190191 let cap_def_id = ast_util:: def_id_of_def ( cap_def) . node ;
191192 let ty = ty:: node_id_to_type ( cx. tcx , cap_def_id) ;
193+ // Here's where is_move isn't always false...
192194 chk ( cx, fn_id, None , cap_item. is_move , ty, cap_item. span ) ;
193195 cap_def_id
194196 } ;
@@ -201,17 +203,10 @@ fn check_fn(fk: visit::fn_kind, decl: fn_decl, body: blk, sp: span,
201203 // skip over free variables that appear in the cap clause
202204 if captured_vars. contains ( & id) { loop ; }
203205
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-
213206 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 ) ;
215210 }
216211 }
217212
@@ -220,7 +215,9 @@ fn check_fn(fk: visit::fn_kind, decl: fn_decl, body: blk, sp: span,
220215
221216fn check_block ( b : blk , cx : ctx , v : visit:: vt < ctx > ) {
222217 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)" ) ) ) ,
224221 _ => ( )
225222 }
226223 visit:: visit_block ( b, cx, v) ;
@@ -281,33 +278,45 @@ fn check_expr(e: @expr, cx: ctx, v: visit::vt<ctx>) {
281278 expr_assign( _, ex) |
282279 expr_unary( box( _) , ex) | expr_unary( uniq( _) , ex) |
283280 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" ) ) ) ;
285283 }
286284 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" ) ) ) ;
288287 check_cast_for_escaping_regions ( cx, source, e) ;
289288 }
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" , "" ) ) ) ,
291291 // 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", "" ) ) ) ,
293295 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) ;
296300 }
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", "" ) ) ) ; }
299305 match def {
300306 Some ( ex) => {
301307 // All noncopyable fields must be overridden
302308 let t = ty:: expr_ty ( cx. tcx , ex) ;
303309 let ty_fields = match ty:: get ( t) . sty {
304310 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")
306315 } ;
307316 for ty_fields. each |tf| {
308317 if !vec:: any ( fields, |f| f. node . ident == tf. ident ) &&
309318 !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 ,
311320 ~"copying a noncopyable value") ;
312321 }
313322 }
@@ -316,16 +325,16 @@ fn check_expr(e: @expr, cx: ctx, v: visit::vt<ctx>) {
316325 }
317326 }
318327 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" , "" ) ) ) ; }
320330 }
321331 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| {
324333 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" , "" ) ) ) ,
326336 by_ref | by_val | by_move => ( )
327337 }
328- i += 1 u;
329338 }
330339 }
331340 expr_field ( lhs, _, _) => {
@@ -334,7 +343,9 @@ fn check_expr(e: @expr, cx: ctx, v: visit::vt<ctx>) {
334343 match cx. method_map . find ( e. id ) {
335344 Some ( ref mme) => {
336345 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+ "" ) ) ) ,
338349 by_ref | by_val | by_move => ( )
339350 }
340351 }
@@ -344,10 +355,12 @@ fn check_expr(e: @expr, cx: ctx, v: visit::vt<ctx>) {
344355 expr_repeat ( element, count_expr, _) => {
345356 let count = ty:: eval_repeat_count ( cx. tcx , count_expr, e. span ) ;
346357 if count == 1 {
347- maybe_copy ( cx, element, None ) ;
358+ maybe_copy ( cx, element, Some ( ( "Trivial repeat takes its element \
359+ by copy", "" ) ) ) ;
348360 } else {
349361 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" , "" ) ) ) ;
351364 }
352365 }
353366 _ => { }
@@ -360,7 +373,9 @@ fn check_stmt(stmt: @stmt, cx: ctx, v: visit::vt<ctx>) {
360373 stmt_decl( @{ node : decl_local( locals) , _} , _) => {
361374 for locals. each |local| {
362375 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", "" ) ) ) ,
364379 _ => { }
365380 }
366381 }
@@ -434,9 +449,6 @@ fn check_copy_ex(cx: ctx, ex: @expr, implicit_copy: bool,
434449 why : Option < ( & str , & str ) > ) {
435450 if ty:: expr_is_lval ( cx. tcx , cx. method_map , ex) &&
436451
437- // this is a move
438- !cx. last_use_map . contains_key ( ex. id ) &&
439-
440452 // a reference to a constant like `none`... no need to warn
441453 // about *this* even if the type is Option<~int>
442454 !is_nullary_variant ( cx, ex) &&
0 commit comments