From 35fc4a4291dfc8d33b3b500ff0f1b2748ddd5ff0 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Fri, 16 Mar 2012 16:25:36 +0100 Subject: [PATCH] Check kind bounds when calling methods Closes #1915 --- src/libstd/map.rs | 2 +- src/libstd/serialization.rs | 7 +++-- src/rustc/middle/kind.rs | 30 ++++++++++++++----- src/rustc/syntax/ext/auto_serialize.rs | 6 ++-- .../compile-fail/bad-method-typaram-kind.rs | 11 +++++++ 5 files changed, 43 insertions(+), 13 deletions(-) create mode 100644 src/test/compile-fail/bad-method-typaram-kind.rs 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() -> hashmap { #[doc = " Convenience function for adding keys to a hashmap with nil type keys "] -fn set_add(set: set, key: K) -> bool { ret set.insert(key, ()); } +fn set_add(set: set, 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: S, v: [T], f: fn(T)) { } } -fn read_to_vec(d: D, f: fn() -> T) -> [T] { +fn read_to_vec(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 for S { } impl deserializer_helpers for D { - fn read_to_vec(f: fn() -> T) -> [T] { + fn read_to_vec(f: fn() -> T) -> [T] { read_to_vec(self, f) } } @@ -252,7 +252,8 @@ fn serialize_option(s: S, v: option, st: fn(T)) { } } -fn deserialize_option(d: D, st: fn() -> T) -> option { +fn deserialize_option(d: D, st: fn() -> T) + -> option { 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) { 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() { + 1u.bar::(); +} + +impl methods for uint { + fn bar() { + } +} + +fn main() {}