Skip to content

Commit 4d5d43b

Browse files
committed
Warn when invoking polymorphic functions with non copyable types. Closes #2466.
1 parent 5a4e534 commit 4d5d43b

File tree

3 files changed

+45
-15
lines changed

3 files changed

+45
-15
lines changed

src/rustc/middle/kind.rs

Lines changed: 35 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import util::ppaux::{ty_to_str, tys_to_str};
99
import syntax::print::pprust::expr_to_str;
1010
import freevars::freevar_entry;
1111
import dvec::extensions;
12+
import lint::non_implicitly_copyable_typarams;
1213

1314
// Kind analysis pass.
1415
//
@@ -56,19 +57,26 @@ type rval_map = std::map::hashmap<node_id, ()>;
5657

5758
type ctx = {tcx: ty::ctxt,
5859
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};
6062

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) {
6367
let ctx = {tcx: tcx,
6468
method_map: method_map,
65-
last_use_map: last_use_map};
69+
last_use_map: last_use_map,
70+
current_item: -1};
6671
let visit = visit::mk_vt(@{
6772
visit_expr: check_expr,
6873
visit_stmt: check_stmt,
6974
visit_block: check_block,
7075
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+
}
7280
with *visit::default_visitor()
7381
});
7482
visit::visit_crate(*crate, ctx, visit);
@@ -280,7 +288,7 @@ fn check_expr(e: @expr, cx: ctx, v: visit::vt<ctx>) {
280288
tys_to_str(cx.tcx, ts), ts.len(), *bounds, (*bounds).len());
281289
}
282290
vec::iter2(ts, *bounds) {|ty, bound|
283-
check_bounds(cx, e.span, ty, bound)
291+
check_bounds(cx, e.id, e.span, ty, bound)
284292
}
285293
}
286294
}
@@ -311,7 +319,7 @@ fn check_ty(aty: @ty, cx: ctx, v: visit::vt<ctx>) {
311319
let did = ast_util::def_id_of_def(cx.tcx.def_map.get(id));
312320
let bounds = ty::lookup_item_type(cx.tcx, did).bounds;
313321
vec::iter2(ts, *bounds) {|ty, bound|
314-
check_bounds(cx, aty.span, ty, bound)
322+
check_bounds(cx, aty.id, aty.span, ty, bound)
315323
}
316324
}
317325
}
@@ -320,15 +328,29 @@ fn check_ty(aty: @ty, cx: ctx, v: visit::vt<ctx>) {
320328
visit::visit_ty(aty, cx, v);
321329
}
322330

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) {
324333
let kind = ty::type_kind(cx.tcx, ty);
325334
let p_kind = ty::param_bounds_to_kind(bounds);
326335
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+
}
332354
}
333355
}
334356

src/rustc/middle/lint.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ enum lint {
4444
path_statement,
4545
old_vecs,
4646
unrecognized_warning,
47+
non_implicitly_copyable_typarams,
4748
}
4849

4950
// This is pretty unfortunate. We really want some sort of "deriving Enum"
@@ -56,6 +57,7 @@ fn int_to_lint(i: int) -> lint {
5657
3 { path_statement }
5758
4 { old_vecs }
5859
5 { unrecognized_warning }
60+
6 { non_implicitly_copyable_typarams }
5961
}
6062
}
6163

@@ -103,6 +105,11 @@ fn get_lint_dict() -> lint_dict {
103105
("unrecognized_warning",
104106
@{lint: unrecognized_warning,
105107
desc: "unrecognized warning attribute",
108+
default: warn}),
109+
110+
("non_implicitly_copyable_typarams",
111+
@{lint: non_implicitly_copyable_typarams,
112+
desc: "passing non implicitly copyable types as copy type params",
106113
default: warn})
107114

108115
];

src/rustc/middle/ty.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,8 @@ export ty_var_id;
112112
export ty_to_def_id;
113113
export ty_fn_args;
114114
export type_constr;
115-
export kind, kind_sendable, kind_copyable, kind_noncopyable, kind_const;
115+
export kind, kind_implicitly_copyable, kind_sendable, kind_copyable;
116+
export kind_noncopyable, kind_const;
116117
export kind_can_be_copied, kind_can_be_sent, kind_can_be_implicitly_copied;
117118
export proto_kind, kind_lteq, type_kind;
118119
export operators;
@@ -455,7 +456,7 @@ fn param_bounds_to_kind(bounds: param_bounds) -> kind {
455456
for vec::each(*bounds) {|bound|
456457
alt bound {
457458
bound_copy {
458-
kind = raise_kind(kind, kind_copyable());
459+
kind = raise_kind(kind, kind_implicitly_copyable());
459460
}
460461
bound_send { kind = raise_kind(kind, kind_send_only()); }
461462
bound_const { kind = raise_kind(kind, kind_const()); }

0 commit comments

Comments
 (0)