Properly check kinds when instantiating types

Closes #2011
This commit is contained in:
Marijn Haverbeke 2012-03-19 10:45:29 +01:00
parent 4c4ac05f02
commit cec1a9b859
3 changed files with 41 additions and 21 deletions

View file

@ -7,10 +7,10 @@ import core::option::{some, none};
// FIXME: Should not be @; there's a bug somewhere in rustc that requires this
// to be.
type smallintmap<T> = @{mutable v: [mutable option<T>]};
type smallintmap<T: copy> = @{mutable v: [mutable option<T>]};
#[doc = "Create a smallintmap"]
fn mk<T>() -> smallintmap<T> {
fn mk<T: copy>() -> smallintmap<T> {
let v: [mutable option<T>] = [mutable];
ret @{mutable v: v};
}
@ -59,7 +59,7 @@ fn truncate<T: copy>(m: smallintmap<T>, len: uint) {
m.v = vec::to_mut(vec::slice::<option<T>>(m.v, 0u, len));
}
fn max_key<T>(m: smallintmap<T>) -> uint {
fn max_key<T: copy>(m: smallintmap<T>) -> uint {
ret vec::len::<option<T>>(m.v);
}
@ -116,6 +116,6 @@ impl <V: copy> of map::map<uint, V> for smallintmap<V> {
}
#[doc = "Cast the given smallintmap to a map::map"]
fn as_map<V>(s: smallintmap<V>) -> map::map<uint, V> {
fn as_map<V: copy>(s: smallintmap<V>) -> map::map<uint, V> {
s as map::map::<uint, V>
}

View file

@ -46,7 +46,8 @@ fn check_crate(tcx: ty::ctxt, method_map: typeck::method_map,
visit_expr: check_expr,
visit_stmt: check_stmt,
visit_block: check_block,
visit_fn: check_fn
visit_fn: check_fn,
visit_ty: check_ty
with *visit::default_visitor()
});
visit::visit_crate(*crate, ctx, visit);
@ -182,8 +183,7 @@ fn check_expr(e: @expr, cx: ctx, v: visit::vt<ctx>) {
}
}
expr_path(_) | expr_field(_, _, _) {
alt cx.tcx.node_type_substs.find(e.id) {
some(ts) {
option::may(cx.tcx.node_type_substs.find(e.id)) {|ts|
let bounds = alt check e.node {
expr_path(_) {
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>) {
}
};
vec::iter2(ts, *bounds) {|ty, bound|
let kind = ty::type_kind(cx.tcx, ty);
let p_kind = ty::param_bounds_to_kind(bound);
if !ty::kind_lteq(p_kind, kind) {
cx.tcx.sess.span_err(e.span, "instantiating a " +
kind_to_str(p_kind) +
" type parameter with a "
+ kind_to_str(kind) + " type");
}
check_bounds(cx, e.span, ty, bound)
}
}
none {}
}
}
expr_fn(_, _, _, cap_clause) {
@ -241,6 +232,33 @@ fn check_stmt(stmt: @stmt, cx: ctx, v: visit::vt<ctx>) {
visit::visit_stmt(stmt, cx, v);
}
fn check_ty(aty: @ty, cx: ctx, v: visit::vt<ctx>) {
alt aty.node {
ty_path(_, id) {
option::may(cx.tcx.node_type_substs.find(id)) {|ts|
let did = ast_util::def_id_of_def(cx.tcx.def_map.get(id));
let bounds = ty::lookup_item_type(cx.tcx, did).bounds;
vec::iter2(ts, *bounds) {|ty, bound|
check_bounds(cx, aty.span, ty, bound)
}
}
}
_ {}
}
visit::visit_ty(aty, cx, v);
}
fn check_bounds(cx: ctx, sp: span, ty: ty::t, bounds: ty::param_bounds) {
let kind = ty::type_kind(cx.tcx, ty);
let p_kind = ty::param_bounds_to_kind(bounds);
if !ty::kind_lteq(p_kind, kind) {
cx.tcx.sess.span_err(sp, "instantiating a " +
kind_to_str(p_kind) +
" type parameter with a "
+ kind_to_str(kind) + " type");
}
}
fn maybe_copy(cx: ctx, ex: @expr) {
check_copy_ex(cx, ex, true);
}

View file

@ -297,7 +297,8 @@ fn ast_ty_to_ty(tcx: ty::ctxt, mode: mode, &&ast_ty: @ast::ty) -> ty::t {
mutbl: mt.mutbl};
}
fn instantiate(tcx: ty::ctxt, use_site: ast::node_id, sp: span,
mode: mode, id: ast::def_id, args: [@ast::ty]) -> ty::t {
mode: mode, id: ast::def_id, path_id: ast::node_id,
args: [@ast::ty]) -> ty::t {
let ty_param_bounds_and_ty = getter(tcx, use_site, mode, id);
if vec::len(*ty_param_bounds_and_ty.bounds) == 0u {
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 {
let typ =
ty::substitute_type_params(tcx, param_bindings,
ty_param_bounds_and_ty.ty);
write_substs(tcx, path_id, param_bindings);
ret typ;
}
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 {
path_to_str(path))); }
some(d) { d }};
alt a_def {
ast::def_ty(id) {
instantiate(tcx, use_site, ast_ty.span, mode, id,
path.node.types)
ast::def_ty(did) {
instantiate(tcx, use_site, ast_ty.span, mode, did,
id, path.node.types)
}
ast::def_prim_ty(nty) {
alt nty {