@@ -26,6 +26,7 @@ type restrict =
26
26
@{ root_var: option:: t<node_id>,
27
27
node_id: node_id,
28
28
ty: ty:: t,
29
+ span: span,
29
30
local_id: uint,
30
31
bindings: [ node_id] ,
31
32
unsafe_ty: option:: t<ty:: t>,
@@ -169,6 +170,12 @@ fn cant_copy(cx: ctx, r: restrict) -> bool {
169
170
if ty:: type_allows_implicit_copy ( cx. tcx , r. ty ) {
170
171
r. given_up = true ;
171
172
cx. copy_map . insert ( r. node_id , ( ) ) ;
173
+ if copy_is_expensive ( cx. tcx , r. ty ) {
174
+ // FIXME better message
175
+ cx. tcx . sess . span_warn ( r. span ,
176
+ "inserting an implicit copy for type " +
177
+ util:: ppaux:: ty_to_str ( cx. tcx , r. ty ) ) ;
178
+ }
172
179
ret false;
173
180
} else { ret true ; }
174
181
}
@@ -201,6 +208,7 @@ fn check_call(cx: ctx, f: @ast::expr, args: [@ast::expr], sc: scope) ->
201
208
@{ root_var: root_var,
202
209
node_id: arg_t. mode == ast:: by_mut_ref ? 0 : arg. id ,
203
210
ty: arg_t. ty ,
211
+ span: arg. span ,
204
212
local_id: cx. next_local ,
205
213
bindings: [ arg. id ] ,
206
214
unsafe_ty: unsafe_t,
@@ -282,19 +290,17 @@ fn check_alt(cx: ctx, input: @ast::expr, arms: [ast::arm], sc: scope,
282
290
let new_sc = sc;
283
291
if vec:: len ( dnums) > 0 u {
284
292
let root_var = path_def_id ( cx, root. ex ) ;
285
- new_sc =
286
- @( * sc +
287
- [
288
- // FIXME need to use separate restrict for each binding
289
- @{ root_var: root_var,
290
- node_id: 0 ,
291
- ty: ty:: mk_int ( cx. tcx ) ,
292
- local_id: cx. next_local ,
293
- bindings: dnums,
294
- unsafe_ty: inner_mut ( root. ds ) ,
295
- depends_on : deps( sc, root_var) ,
296
- mutable ok: valid,
297
- mutable given_up: false} ] ) ;
293
+ // FIXME need to use separate restrict for each binding
294
+ new_sc = @( * sc + [ @{ root_var: root_var,
295
+ node_id: 0 ,
296
+ ty: ty:: mk_int ( cx. tcx ) ,
297
+ span: a. pats [ 0 ] . span ,
298
+ local_id: cx. next_local ,
299
+ bindings: dnums,
300
+ unsafe_ty: inner_mut ( root. ds ) ,
301
+ depends_on : deps( sc, root_var) ,
302
+ mutable ok: valid,
303
+ mutable given_up: false} ] ) ;
298
304
}
299
305
register_locals ( cx, a. pats [ 0 ] ) ;
300
306
visit:: visit_arm ( a, new_sc, v) ;
@@ -332,10 +338,10 @@ fn check_for(cx: ctx, local: @ast::local, seq: @ast::expr, blk: ast::blk,
332
338
let root_var = path_def_id ( cx, root. ex ) ;
333
339
let new_sc =
334
340
@{ root_var: root_var,
335
-
336
341
// FIXME reenable when trans knows how to copy for vars
337
342
node_id: 0 , // blk.node.id,
338
343
ty: elt_t,
344
+ span: local. node . pat . span ,
339
345
local_id: cx. next_local ,
340
346
bindings: ast_util:: pat_binding_ids ( local. node . pat ) ,
341
347
unsafe_ty: unsafe ,
@@ -516,6 +522,37 @@ fn def_is_local(d: ast::def, objfields_count: bool) -> bool {
516
522
} ;
517
523
}
518
524
525
+ // Heuristic, somewhat random way to decide whether to warn when inserting an
526
+ // implicit copy.
527
+ fn copy_is_expensive ( tcx : ty:: ctxt , ty : ty:: t ) -> bool {
528
+ fn score_ty ( tcx : ty:: ctxt , ty : ty:: t ) -> uint {
529
+ ret alt ty:: struct ( tcx, ty) {
530
+ ty:: ty_nil. | ty:: ty_bot. | ty:: ty_bool. | ty:: ty_int. |
531
+ ty:: ty_uint. | ty:: ty_float. | ty:: ty_machine ( _) |
532
+ ty:: ty_char. | ty:: ty_type. | ty:: ty_native ( _) |
533
+ ty:: ty_ptr ( _) { 1 u }
534
+ ty:: ty_box ( _) { 3 u }
535
+ ty:: ty_constr ( t, _) | ty:: ty_res ( _, t, _) { score_ty ( tcx, t) }
536
+ ty:: ty_fn ( _, _, _, _, _) | ty:: ty_native_fn ( _, _, _) |
537
+ ty:: ty_obj ( _) { 4 u }
538
+ ty:: ty_str. | ty:: ty_vec ( _) { 50 u }
539
+ ty:: ty_uniq ( t) { 1 u + score_ty ( tcx, t) }
540
+ ty:: ty_tag ( _, ts) | ty:: ty_tup ( ts) {
541
+ let sum = 0 u;
542
+ for t in ts { sum += score_ty ( tcx, t) ; }
543
+ sum
544
+ }
545
+ ty:: ty_rec ( fs) {
546
+ let sum = 0 u;
547
+ for f in fs { sum += score_ty ( tcx, f. mt . ty ) ; }
548
+ sum
549
+ }
550
+ ty:: ty_param ( _, _) { 5 u }
551
+ } ;
552
+ }
553
+ ret score_ty( tcx, ty) > 8 u;
554
+ }
555
+
519
556
// Local Variables:
520
557
// mode: rust
521
558
// fill-column: 78;
0 commit comments