about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorMarijn Haverbeke <marijnh@gmail.com>2012-03-19 10:45:29 +0100
committerMarijn Haverbeke <marijnh@gmail.com>2012-03-19 10:45:29 +0100
commitcec1a9b8592b573e40d81ba52d658bdcd9acacb3 (patch)
treedf516375ee85683a7af3fb7abef20242a0e64beb /src
parent4c4ac05f02aeba7d0abd421e9a19d1b4083018d6 (diff)
downloadrust-cec1a9b8592b573e40d81ba52d658bdcd9acacb3.tar.gz
rust-cec1a9b8592b573e40d81ba52d658bdcd9acacb3.zip
Properly check kinds when instantiating types
Closes #2011
Diffstat (limited to 'src')
-rw-r--r--src/libstd/smallintmap.rs8
-rw-r--r--src/rustc/middle/kind.rs44
-rw-r--r--src/rustc/middle/typeck.rs10
3 files changed, 41 insertions, 21 deletions
diff --git a/src/libstd/smallintmap.rs b/src/libstd/smallintmap.rs
index e90fb1abd96..d58e0519387 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<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>
 }
diff --git a/src/rustc/middle/kind.rs b/src/rustc/middle/kind.rs
index b85627c6856..9f19c91d92d 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<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);
 }
diff --git a/src/rustc/middle/typeck.rs b/src/rustc/middle/typeck.rs
index cc52283dc07..be2dd9c6954 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 {