about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorMarijn Haverbeke <marijnh@gmail.com>2012-03-16 16:25:36 +0100
committerMarijn Haverbeke <marijnh@gmail.com>2012-03-16 17:05:29 +0100
commit35fc4a4291dfc8d33b3b500ff0f1b2748ddd5ff0 (patch)
tree96bcbca364f4cc4d68610271719017b0841c5f97 /src
parent25c2be0ff477c5bd6c71f4dc598d7a94c08bb724 (diff)
downloadrust-35fc4a4291dfc8d33b3b500ff0f1b2748ddd5ff0.tar.gz
rust-35fc4a4291dfc8d33b3b500ff0f1b2748ddd5ff0.zip
Check kind bounds when calling methods
Closes #1915
Diffstat (limited to 'src')
-rw-r--r--src/libstd/map.rs2
-rw-r--r--src/libstd/serialization.rs7
-rw-r--r--src/rustc/middle/kind.rs30
-rw-r--r--src/rustc/syntax/ext/auto_serialize.rs6
-rw-r--r--src/test/compile-fail/bad-method-typaram-kind.rs11
5 files changed, 43 insertions, 13 deletions
diff --git a/src/libstd/map.rs b/src/libstd/map.rs
index f5302082b8d..760dab76643 100644
--- a/src/libstd/map.rs
+++ b/src/libstd/map.rs
@@ -330,7 +330,7 @@ fn uint_hash<V: copy>() -> hashmap<uint, V> {
 #[doc = "
 Convenience function for adding keys to a hashmap with nil type keys
 "]
-fn set_add<K>(set: set<K>, key: K) -> bool { ret set.insert(key, ()); }
+fn set_add<K: copy>(set: set<K>, key: K) -> bool { ret set.insert(key, ()); }
 
 #[cfg(test)]
 mod tests {
diff --git a/src/libstd/serialization.rs b/src/libstd/serialization.rs
index 3734b8db2c0..43059ca7828 100644
--- a/src/libstd/serialization.rs
+++ b/src/libstd/serialization.rs
@@ -93,7 +93,7 @@ fn emit_from_vec<S: serializer, T>(s: S, v: [T], f: fn(T)) {
     }
 }
 
-fn read_to_vec<D: deserializer, T>(d: D, f: fn() -> T) -> [T] {
+fn read_to_vec<D: deserializer, T: copy>(d: D, f: fn() -> T) -> [T] {
     d.read_vec {|len|
         vec::from_fn(len) {|i|
             d.read_vec_elt(i) {|| f() }
@@ -108,7 +108,7 @@ impl serializer_helpers<S: serializer> for S {
 }
 
 impl deserializer_helpers<D: deserializer> for D {
-    fn read_to_vec<T>(f: fn() -> T) -> [T] {
+    fn read_to_vec<T: copy>(f: fn() -> T) -> [T] {
         read_to_vec(self, f)
     }
 }
@@ -252,7 +252,8 @@ fn serialize_option<S: serializer,T>(s: S, v: option<T>, st: fn(T)) {
     }
 }
 
-fn deserialize_option<D: deserializer,T>(d: D, st: fn() -> T) -> option<T> {
+fn deserialize_option<D: deserializer,T: copy>(d: D, st: fn() -> T)
+    -> option<T> {
     d.read_enum("option") {||
         d.read_enum_variant {|i|
             alt check i {
diff --git a/src/rustc/middle/kind.rs b/src/rustc/middle/kind.rs
index 3f385911980..e33389c29b8 100644
--- a/src/rustc/middle/kind.rs
+++ b/src/rustc/middle/kind.rs
@@ -180,22 +180,38 @@ fn check_expr(e: @expr, cx: ctx, v: visit::vt<ctx>) {
             i += 1u;
         }
       }
-      expr_path(_) {
+      expr_path(_) | expr_field(_, _, _) {
         alt cx.tcx.node_type_substs.find(e.id) {
           some(ts) {
-            let did = ast_util::def_id_of_def(cx.tcx.def_map.get(e.id));
-            let bounds = ty::lookup_item_type(cx.tcx, did).bounds;
-            let i = 0u;
-            for ty in ts {
+            let bounds = alt check e.node {
+              expr_path(_) {
+                let did = ast_util::def_id_of_def(cx.tcx.def_map.get(e.id));
+                ty::lookup_item_type(cx.tcx, did).bounds
+              }
+              expr_field(_, _, _) {
+                alt cx.method_map.get(e.id) {
+                  typeck::method_static(did) {
+                    ty::lookup_item_type(cx.tcx, did).bounds
+                  }
+                  typeck::method_param(ifce_id, n_mth, _, _) |
+                  typeck::method_iface(ifce_id, n_mth) {
+                    let ifce_bounds =
+                        ty::lookup_item_type(cx.tcx, ifce_id).bounds;
+                    let mth = ty::iface_methods(cx.tcx, ifce_id)[n_mth];
+                    @(*ifce_bounds + *mth.tps)
+                  }
+                }
+              }
+            };
+            vec::iter2(ts, *bounds) {|ty, bound|
                 let kind = ty::type_kind(cx.tcx, ty);
-                let p_kind = ty::param_bounds_to_kind(bounds[i]);
+                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");
                 }
-                i += 1u;
             }
           }
           none {}
diff --git a/src/rustc/syntax/ext/auto_serialize.rs b/src/rustc/syntax/ext/auto_serialize.rs
index 9911930184d..3af8992a03f 100644
--- a/src/rustc/syntax/ext/auto_serialize.rs
+++ b/src/rustc/syntax/ext/auto_serialize.rs
@@ -723,8 +723,10 @@ fn mk_deser_fn(cx: ext_ctxt, span: span, name: str, tps: [ast::ty_param],
     let deser_tps: [ast::ty_param] =
         [{ident: "__D",
           id: cx.next_id(),
-          bounds: deser_bnds}] +
-        vec::map(tps) {|tp| cx.clone_ty_param(tp) };
+          bounds: deser_bnds}] + vec::map(tps) {|tp|
+        let cloned = cx.clone_ty_param(tp);
+        {bounds: @(*cloned.bounds + [ast::bound_copy]) with cloned}
+    };
 
     let deser_blk = cx.expr_blk(f(cx, tps_map, #ast(expr){__d}));
 
diff --git a/src/test/compile-fail/bad-method-typaram-kind.rs b/src/test/compile-fail/bad-method-typaram-kind.rs
new file mode 100644
index 00000000000..a5070ac5698
--- /dev/null
+++ b/src/test/compile-fail/bad-method-typaram-kind.rs
@@ -0,0 +1,11 @@
+// error-pattern:instantiating a copyable type parameter with a noncopyable
+fn foo<T>() {
+    1u.bar::<T>();
+}
+
+impl methods for uint {
+    fn bar<T:copy>() {
+    }
+}
+
+fn main() {}