Skip to content

Commit cec1a9b

Browse files
committed
Properly check kinds when instantiating types
Closes #2011
1 parent 4c4ac05 commit cec1a9b

File tree

3 files changed

+41
-21
lines changed

3 files changed

+41
-21
lines changed

src/libstd/smallintmap.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@ import core::option::{some, none};
77

88
// FIXME: Should not be @; there's a bug somewhere in rustc that requires this
99
// to be.
10-
type smallintmap<T> = @{mutable v: [mutable option<T>]};
10+
type smallintmap<T: copy> = @{mutable v: [mutable option<T>]};
1111

1212
#[doc = "Create a smallintmap"]
13-
fn mk<T>() -> smallintmap<T> {
13+
fn mk<T: copy>() -> smallintmap<T> {
1414
let v: [mutable option<T>] = [mutable];
1515
ret @{mutable v: v};
1616
}
@@ -59,7 +59,7 @@ fn truncate<T: copy>(m: smallintmap<T>, len: uint) {
5959
m.v = vec::to_mut(vec::slice::<option<T>>(m.v, 0u, len));
6060
}
6161

62-
fn max_key<T>(m: smallintmap<T>) -> uint {
62+
fn max_key<T: copy>(m: smallintmap<T>) -> uint {
6363
ret vec::len::<option<T>>(m.v);
6464
}
6565

@@ -116,6 +116,6 @@ impl <V: copy> of map::map<uint, V> for smallintmap<V> {
116116
}
117117

118118
#[doc = "Cast the given smallintmap to a map::map"]
119-
fn as_map<V>(s: smallintmap<V>) -> map::map<uint, V> {
119+
fn as_map<V: copy>(s: smallintmap<V>) -> map::map<uint, V> {
120120
s as map::map::<uint, V>
121121
}

src/rustc/middle/kind.rs

Lines changed: 31 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,8 @@ fn check_crate(tcx: ty::ctxt, method_map: typeck::method_map,
4646
visit_expr: check_expr,
4747
visit_stmt: check_stmt,
4848
visit_block: check_block,
49-
visit_fn: check_fn
49+
visit_fn: check_fn,
50+
visit_ty: check_ty
5051
with *visit::default_visitor()
5152
});
5253
visit::visit_crate(*crate, ctx, visit);
@@ -182,8 +183,7 @@ fn check_expr(e: @expr, cx: ctx, v: visit::vt<ctx>) {
182183
}
183184
}
184185
expr_path(_) | expr_field(_, _, _) {
185-
alt cx.tcx.node_type_substs.find(e.id) {
186-
some(ts) {
186+
option::may(cx.tcx.node_type_substs.find(e.id)) {|ts|
187187
let bounds = alt check e.node {
188188
expr_path(_) {
189189
let did = ast_util::def_id_of_def(cx.tcx.def_map.get(e.id));
@@ -205,17 +205,8 @@ fn check_expr(e: @expr, cx: ctx, v: visit::vt<ctx>) {
205205
}
206206
};
207207
vec::iter2(ts, *bounds) {|ty, bound|
208-
let kind = ty::type_kind(cx.tcx, ty);
209-
let p_kind = ty::param_bounds_to_kind(bound);
210-
if !ty::kind_lteq(p_kind, kind) {
211-
cx.tcx.sess.span_err(e.span, "instantiating a " +
212-
kind_to_str(p_kind) +
213-
" type parameter with a "
214-
+ kind_to_str(kind) + " type");
215-
}
208+
check_bounds(cx, e.span, ty, bound)
216209
}
217-
}
218-
none {}
219210
}
220211
}
221212
expr_fn(_, _, _, cap_clause) {
@@ -241,6 +232,33 @@ fn check_stmt(stmt: @stmt, cx: ctx, v: visit::vt<ctx>) {
241232
visit::visit_stmt(stmt, cx, v);
242233
}
243234

235+
fn check_ty(aty: @ty, cx: ctx, v: visit::vt<ctx>) {
236+
alt aty.node {
237+
ty_path(_, id) {
238+
option::may(cx.tcx.node_type_substs.find(id)) {|ts|
239+
let did = ast_util::def_id_of_def(cx.tcx.def_map.get(id));
240+
let bounds = ty::lookup_item_type(cx.tcx, did).bounds;
241+
vec::iter2(ts, *bounds) {|ty, bound|
242+
check_bounds(cx, aty.span, ty, bound)
243+
}
244+
}
245+
}
246+
_ {}
247+
}
248+
visit::visit_ty(aty, cx, v);
249+
}
250+
251+
fn check_bounds(cx: ctx, sp: span, ty: ty::t, bounds: ty::param_bounds) {
252+
let kind = ty::type_kind(cx.tcx, ty);
253+
let p_kind = ty::param_bounds_to_kind(bounds);
254+
if !ty::kind_lteq(p_kind, kind) {
255+
cx.tcx.sess.span_err(sp, "instantiating a " +
256+
kind_to_str(p_kind) +
257+
" type parameter with a "
258+
+ kind_to_str(kind) + " type");
259+
}
260+
}
261+
244262
fn maybe_copy(cx: ctx, ex: @expr) {
245263
check_copy_ex(cx, ex, true);
246264
}

src/rustc/middle/typeck.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -297,7 +297,8 @@ fn ast_ty_to_ty(tcx: ty::ctxt, mode: mode, &&ast_ty: @ast::ty) -> ty::t {
297297
mutbl: mt.mutbl};
298298
}
299299
fn instantiate(tcx: ty::ctxt, use_site: ast::node_id, sp: span,
300-
mode: mode, id: ast::def_id, args: [@ast::ty]) -> ty::t {
300+
mode: mode, id: ast::def_id, path_id: ast::node_id,
301+
args: [@ast::ty]) -> ty::t {
301302
let ty_param_bounds_and_ty = getter(tcx, use_site, mode, id);
302303
if vec::len(*ty_param_bounds_and_ty.bounds) == 0u {
303304
ret ty_param_bounds_and_ty.ty;
@@ -318,6 +319,7 @@ fn ast_ty_to_ty(tcx: ty::ctxt, mode: mode, &&ast_ty: @ast::ty) -> ty::t {
318319
let typ =
319320
ty::substitute_type_params(tcx, param_bindings,
320321
ty_param_bounds_and_ty.ty);
322+
write_substs(tcx, path_id, param_bindings);
321323
ret typ;
322324
}
323325
fn do_ast_ty_to_ty(tcx: ty::ctxt, use_site: ast::node_id, mode: mode,
@@ -385,9 +387,9 @@ fn ast_ty_to_ty(tcx: ty::ctxt, mode: mode, &&ast_ty: @ast::ty) -> ty::t {
385387
path_to_str(path))); }
386388
some(d) { d }};
387389
alt a_def {
388-
ast::def_ty(id) {
389-
instantiate(tcx, use_site, ast_ty.span, mode, id,
390-
path.node.types)
390+
ast::def_ty(did) {
391+
instantiate(tcx, use_site, ast_ty.span, mode, did,
392+
id, path.node.types)
391393
}
392394
ast::def_prim_ty(nty) {
393395
alt nty {

0 commit comments

Comments
 (0)