From cec1a9b8592b573e40d81ba52d658bdcd9acacb3 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Mon, 19 Mar 2012 10:45:29 +0100 Subject: [PATCH] Properly check kinds when instantiating types Closes #2011 --- src/libstd/smallintmap.rs | 8 +++---- src/rustc/middle/kind.rs | 44 +++++++++++++++++++++++++++----------- src/rustc/middle/typeck.rs | 10 +++++---- 3 files changed, 41 insertions(+), 21 deletions(-) diff --git a/src/libstd/smallintmap.rs b/src/libstd/smallintmap.rs index e90fb1abd96b..d58e0519387e 100644 --- a/src/libstd/smallintmap.rs +++ b/src/libstd/smallintmap.rs @@ -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 = @{mutable v: [mutable option]}; +type smallintmap = @{mutable v: [mutable option]}; #[doc = "Create a smallintmap"] -fn mk() -> smallintmap { +fn mk() -> smallintmap { let v: [mutable option] = [mutable]; ret @{mutable v: v}; } @@ -59,7 +59,7 @@ fn truncate(m: smallintmap, len: uint) { m.v = vec::to_mut(vec::slice::>(m.v, 0u, len)); } -fn max_key(m: smallintmap) -> uint { +fn max_key(m: smallintmap) -> uint { ret vec::len::>(m.v); } @@ -116,6 +116,6 @@ impl of map::map for smallintmap { } #[doc = "Cast the given smallintmap to a map::map"] -fn as_map(s: smallintmap) -> map::map { +fn as_map(s: smallintmap) -> map::map { s as map::map:: } diff --git a/src/rustc/middle/kind.rs b/src/rustc/middle/kind.rs index b85627c6856e..9f19c91d92d5 100644 --- a/src/rustc/middle/kind.rs +++ b/src/rustc/middle/kind.rs @@ -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) { } } 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) { } }; 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) { visit::visit_stmt(stmt, cx, v); } +fn check_ty(aty: @ty, cx: ctx, v: visit::vt) { + 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); } diff --git a/src/rustc/middle/typeck.rs b/src/rustc/middle/typeck.rs index cc52283dc073..be2dd9c69546 100644 --- a/src/rustc/middle/typeck.rs +++ b/src/rustc/middle/typeck.rs @@ -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 {