@@ -9,6 +9,7 @@ import util::ppaux::{ty_to_str, tys_to_str};
9
9
import syntax:: print:: pprust:: expr_to_str;
10
10
import freevars:: freevar_entry;
11
11
import dvec:: extensions;
12
+ import lint:: non_implicitly_copyable_typarams;
12
13
13
14
// Kind analysis pass.
14
15
//
@@ -56,19 +57,26 @@ type rval_map = std::map::hashmap<node_id, ()>;
56
57
57
58
type ctx = { tcx : ty:: ctxt ,
58
59
method_map : typeck:: method_map ,
59
- last_use_map : liveness:: last_use_map } ;
60
+ last_use_map : liveness:: last_use_map ,
61
+ current_item : node_id } ;
60
62
61
- fn check_crate ( tcx : ty:: ctxt , method_map : typeck:: method_map ,
62
- last_use_map : liveness:: last_use_map , crate : @crate ) {
63
+ fn check_crate ( tcx : ty:: ctxt ,
64
+ method_map : typeck:: method_map ,
65
+ last_use_map : liveness:: last_use_map ,
66
+ crate : @crate ) {
63
67
let ctx = { tcx: tcx,
64
68
method_map: method_map,
65
- last_use_map: last_use_map} ;
69
+ last_use_map: last_use_map,
70
+ current_item: -1 } ;
66
71
let visit = visit:: mk_vt ( @{
67
72
visit_expr: check_expr,
68
73
visit_stmt: check_stmt,
69
74
visit_block: check_block,
70
75
visit_fn: check_fn,
71
- visit_ty: check_ty
76
+ visit_ty: check_ty,
77
+ visit_item: fn @( i: @item, cx: ctx, v: visit:: vt<ctx>) {
78
+ visit:: visit_item ( i, { current_item: i. id with cx} , v) ;
79
+ }
72
80
with * visit:: default_visitor ( )
73
81
} ) ;
74
82
visit:: visit_crate ( * crate , ctx, visit) ;
@@ -280,7 +288,7 @@ fn check_expr(e: @expr, cx: ctx, v: visit::vt<ctx>) {
280
288
tys_to_str( cx. tcx, ts) , ts. len( ) , * bounds, ( * bounds) . len( ) ) ;
281
289
}
282
290
vec:: iter2( ts, * bounds) { |ty, bound|
283
- check_bounds( cx, e. span, ty, bound)
291
+ check_bounds( cx, e. id , e . span, ty, bound)
284
292
}
285
293
}
286
294
}
@@ -311,7 +319,7 @@ fn check_ty(aty: @ty, cx: ctx, v: visit::vt<ctx>) {
311
319
let did = ast_util:: def_id_of_def( cx. tcx. def_map. get( id) ) ;
312
320
let bounds = ty:: lookup_item_type( cx. tcx, did) . bounds;
313
321
vec:: iter2( ts, * bounds) { |ty, bound|
314
- check_bounds( cx, aty. span, ty, bound)
322
+ check_bounds( cx, aty. id , aty . span, ty, bound)
315
323
}
316
324
}
317
325
}
@@ -320,15 +328,29 @@ fn check_ty(aty: @ty, cx: ctx, v: visit::vt<ctx>) {
320
328
visit:: visit_ty( aty, cx, v) ;
321
329
}
322
330
323
- fn check_bounds( cx: ctx, sp: span, ty: ty:: t, bounds: ty:: param_bounds) {
331
+ fn check_bounds( cx: ctx, id: node_id, sp: span,
332
+ ty: ty:: t, bounds: ty:: param_bounds) {
324
333
let kind = ty:: type_kind( cx. tcx, ty) ;
325
334
let p_kind = ty:: param_bounds_to_kind( bounds) ;
326
335
if !ty:: kind_lteq( p_kind, kind) {
327
- cx. tcx. sess. span_err(
328
- sp, "instantiating a type parameter with an incompatible type " +
329
- "(needs `" + kind_to_str( p_kind) +
330
- "`, got `" + kind_to_str( kind) +
331
- "`, missing `" + kind_to_str( p_kind - kind) + "`)" ) ;
336
+ // If the only reason the kind check fails is because the
337
+ // argument type isn't implicitly copyable, consult the warning
338
+ // settings to figure out what to do.
339
+ let implicit = ty:: kind_implicitly_copyable( ) - ty:: kind_copyable( ) ;
340
+ if ty:: kind_lteq( p_kind, kind | implicit) {
341
+ cx. tcx. sess. span_lint(
342
+ non_implicitly_copyable_typarams,
343
+ id, cx. current_item, sp,
344
+ "instantiating copy type parameter with a \
345
+ not implicitly copyable type") ;
346
+ } else {
347
+ cx. tcx. sess. span_err(
348
+ sp,
349
+ "instantiating a type parameter with an incompatible type " +
350
+ "(needs `" + kind_to_str( p_kind) +
351
+ "`, got `" + kind_to_str( kind) +
352
+ "`, missing `" + kind_to_str( p_kind - kind) + "`)" ) ;
353
+ }
332
354
}
333
355
}
334
356
0 commit comments