From 0c9b749d208ccc75f03ab9f7fce1322aa5dbbfd3 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Fri, 29 Jul 2011 18:38:22 -0700 Subject: [PATCH] Enable kind checking on typarams, fix kind constraints in library and comp. --- src/comp/middle/ast_map.rs | 16 +++++----- src/comp/middle/kind.rs | 31 +++++++++++++++++--- src/comp/syntax/util/interner.rs | 4 +-- src/comp/util/common.rs | 2 +- src/lib/ivec.rs | 50 ++++++++++++++++---------------- src/lib/list.rs | 2 +- src/lib/map.rs | 4 +-- src/lib/option.rs | 18 ++++++------ src/lib/smallintmap.rs | 12 ++++---- src/lib/sort.rs | 2 +- src/test/stdtest/deque.rs | 6 ++-- 11 files changed, 85 insertions(+), 62 deletions(-) diff --git a/src/comp/middle/ast_map.rs b/src/comp/middle/ast_map.rs index 172c9d939e90..336629965300 100644 --- a/src/comp/middle/ast_map.rs +++ b/src/comp/middle/ast_map.rs @@ -47,7 +47,7 @@ fn map_expr(map: &map, ex: &@expr, e: &(), v: &vt[()]) { visit::visit_expr(ex, e, v); } -fn new_smallintmap_int_adapter[V]() -> std::map::hashmap[int, V] { +fn new_smallintmap_int_adapter[@V]() -> std::map::hashmap[int, V] { let key_idx = fn (key: &int) -> uint { key as uint }; let idx_key = fn (idx: &uint) -> int { idx as int }; ret new_smallintmap_adapter(key_idx, idx_key); @@ -58,15 +58,15 @@ fn new_smallintmap_int_adapter[V]() -> std::map::hashmap[int, V] { // the entire codebase adapting all the callsites to the different // interface. // FIXME: hashmap and smallintmap should support the same interface. -fn new_smallintmap_adapter[K, - V](key_idx: fn(&K) -> uint , - idx_key: fn(&uint) -> K ) -> +fn new_smallintmap_adapter[@K, + @V](key_idx: fn(&K) -> uint , + idx_key: fn(&uint) -> K ) -> std::map::hashmap[K, V] { - obj adapter[K, - V](map: smallintmap::smallintmap[V], - key_idx: fn(&K) -> uint , - idx_key: fn(&uint) -> K ) { + obj adapter[@K, + @V](map: smallintmap::smallintmap[V], + key_idx: fn(&K) -> uint , + idx_key: fn(&uint) -> K ) { fn size() -> uint { fail } diff --git a/src/comp/middle/kind.rs b/src/comp/middle/kind.rs index 1590a8fc0956..4ff4e2c846fb 100644 --- a/src/comp/middle/kind.rs +++ b/src/comp/middle/kind.rs @@ -74,6 +74,8 @@ import syntax::ast; import syntax::visit; +import std::ivec; + import ast::kind; import ast::kind_unique; import ast::kind_shared; @@ -138,10 +140,31 @@ fn check_expr(tcx: &ty::ctxt, e: &@ast::expr) { ast::expr_move(a, b) { need_shared_lhs_rhs(tcx, a, b, "<-"); } ast::expr_assign(a, b) { need_shared_lhs_rhs(tcx, a, b, "="); } ast::expr_swap(a, b) { need_shared_lhs_rhs(tcx, a, b, "<->"); } - ast::expr_call(callee, args) { - // FIXME: when ready, start checking param kinds against args. - // This will break stdlib again. - // let tpt = ty::expr_ty_params_and_ty(tcx, callee); + ast::expr_call(callee, _) { + let tpt = ty::expr_ty_params_and_ty(tcx, callee); + // If we have typarams, we're calling an item; we need to check + // that all the types we're supplying as typarams conform to the + // typaram kind constraints on that item. + if ivec::len(tpt.params) != 0u { + let callee_def = ast::def_id_of_def(tcx.def_map.get(callee.id)); + let item_tk = ty::lookup_item_type(tcx, callee_def); + let i = 0; + assert ivec::len(item_tk.kinds) == ivec::len(tpt.params); + for k_need: ast::kind in item_tk.kinds { + let t = tpt.params.(i); + let k = ty::type_kind(tcx, t); + if ! kind_lteq(k_need, k) { + let s = #fmt("mismatched kinds for typaram %d: \ + needed %s type, got %s type %s", + i, + kind_to_str(k_need), + kind_to_str(k), + util::ppaux::ty_to_str(tcx, t)); + tcx.sess.span_err(e.span, s); + } + i += 1; + } + } } _ { } } diff --git a/src/comp/syntax/util/interner.rs b/src/comp/syntax/util/interner.rs index ec4843560897..9474ddd16d2c 100644 --- a/src/comp/syntax/util/interner.rs +++ b/src/comp/syntax/util/interner.rs @@ -16,11 +16,11 @@ type interner[T] = hasher: hashfn[T], eqer: eqfn[T]}; -fn mk[T](hasher: hashfn[T], eqer: eqfn[T]) -> interner[T] { +fn mk[@T](hasher: hashfn[T], eqer: eqfn[T]) -> interner[T] { let m = map::mk_hashmap[T, uint](hasher, eqer); ret {map: m, mutable vect: ~[], hasher: hasher, eqer: eqer}; } -fn intern[T](itr: &interner[T], val: &T) -> uint { +fn intern[@T](itr: &interner[T], val: &T) -> uint { alt itr.map.find(val) { some(idx) { ret idx; } none. { diff --git a/src/comp/util/common.rs b/src/comp/util/common.rs index e3154581b93f..cbca8e905a97 100644 --- a/src/comp/util/common.rs +++ b/src/comp/util/common.rs @@ -41,7 +41,7 @@ fn hash_def(d: &ast::def_id) -> uint { ret h; } -fn new_def_hash[V]() -> std::map::hashmap[ast::def_id, V] { +fn new_def_hash[@V]() -> std::map::hashmap[ast::def_id, V] { let hasher: std::map::hashfn[ast::def_id] = hash_def; let eqer: std::map::eqfn[ast::def_id] = def_eq; ret std::map::mk_hashmap[ast::def_id, V](hasher, eqer); diff --git a/src/lib/ivec.rs b/src/lib/ivec.rs index 6d12d5506251..fb9df536df35 100644 --- a/src/lib/ivec.rs +++ b/src/lib/ivec.rs @@ -19,7 +19,7 @@ native "rust" mod rustrt { count: uint); } -fn from_vec[T](v: &vec[T]) -> T[] { +fn from_vec[@T](v: &vec[T]) -> T[] { let iv: T[] = ~[]; for e in v { iv += ~[e]; @@ -27,7 +27,7 @@ fn from_vec[T](v: &vec[T]) -> T[] { ret iv; } -fn to_vec[T](iv: &T[]) -> vec[T] { +fn to_vec[@T](iv: &T[]) -> vec[T] { let v: vec[T] = []; for e in iv { v += [e]; @@ -36,7 +36,7 @@ fn to_vec[T](iv: &T[]) -> vec[T] { } /// Reserves space for `n` elements in the given vector. -fn reserve[T](v: &mutable T[mutable? ], n: uint) { +fn reserve[@T](v: &mutable T[mutable? ], n: uint) { rustrt::ivec_reserve_shared(v, n); } @@ -48,7 +48,7 @@ fn len[T](v: &T[mutable? ]) -> uint { ret rusti::ivec_len(v); } type init_op[T] = fn(uint) -> T ; -fn init_fn[T](op: &init_op[T], n_elts: uint) -> T[] { +fn init_fn[@T](op: &init_op[T], n_elts: uint) -> T[] { let v = ~[]; reserve(v, n_elts); let i: uint = 0u; @@ -57,7 +57,7 @@ fn init_fn[T](op: &init_op[T], n_elts: uint) -> T[] { } // TODO: Remove me once we have slots. -fn init_fn_mut[T](op: &init_op[T], n_elts: uint) -> T[mutable ] { +fn init_fn_mut[@T](op: &init_op[T], n_elts: uint) -> T[mutable ] { let v = ~[mutable ]; reserve(v, n_elts); let i: uint = 0u; @@ -65,7 +65,7 @@ fn init_fn_mut[T](op: &init_op[T], n_elts: uint) -> T[mutable ] { ret v; } -fn init_elt[T](t: &T, n_elts: uint) -> T[] { +fn init_elt[@T](t: &T, n_elts: uint) -> T[] { let v = ~[]; reserve(v, n_elts); let i: uint = 0u; @@ -74,7 +74,7 @@ fn init_elt[T](t: &T, n_elts: uint) -> T[] { } // TODO: Remove me once we have slots. -fn init_elt_mut[T](t: &T, n_elts: uint) -> T[mutable ] { +fn init_elt_mut[@T](t: &T, n_elts: uint) -> T[mutable ] { let v = ~[mutable ]; reserve(v, n_elts); let i: uint = 0u; @@ -82,13 +82,13 @@ fn init_elt_mut[T](t: &T, n_elts: uint) -> T[mutable ] { ret v; } -fn to_mut[T](v: &T[]) -> T[mutable ] { +fn to_mut[@T](v: &T[]) -> T[mutable ] { let vres = ~[mutable ]; for t: T in v { vres += ~[mutable t]; } ret vres; } -fn from_mut[T](v: &T[mutable ]) -> T[] { +fn from_mut[@T](v: &T[mutable ]) -> T[] { let vres = ~[]; for t: T in v { vres += ~[t]; } ret vres; @@ -106,21 +106,21 @@ pred is_not_empty[T](v: &T[mutable? ]) -> bool { ret !is_empty(v); } // Accessors /// Returns the first element of a vector -fn head[T](v: &T[mutable?]) : is_not_empty(v) -> T { ret v.(0); } +fn head[@T](v: &T[mutable?]) : is_not_empty(v) -> T { ret v.(0); } /// Returns all but the first element of a vector -fn tail[T](v: &T[mutable? ]) : is_not_empty(v) -> T[mutable?] { +fn tail[@T](v: &T[mutable? ]) : is_not_empty(v) -> T[mutable?] { ret slice(v, 1u, len(v)); } /// Returns the last element of `v`. -fn last[T](v: &T[mutable? ]) -> option::t[T] { +fn last[@T](v: &T[mutable? ]) -> option::t[T] { if len(v) == 0u { ret none; } ret some(v.(len(v) - 1u)); } /// Returns a copy of the elements from [`start`..`end`) from `v`. -fn slice[T](v: &T[mutable? ], start: uint, end: uint) -> T[] { +fn slice[@T](v: &T[mutable? ], start: uint, end: uint) -> T[] { assert (start <= end); assert (end <= len(v)); let result = ~[]; @@ -131,7 +131,7 @@ fn slice[T](v: &T[mutable? ], start: uint, end: uint) -> T[] { } // TODO: Remove me once we have slots. -fn slice_mut[T](v: &T[mutable? ], start: uint, end: uint) -> T[mutable ] { +fn slice_mut[@T](v: &T[mutable? ], start: uint, end: uint) -> T[mutable ] { assert (start <= end); assert (end <= len(v)); let result = ~[mutable ]; @@ -145,7 +145,7 @@ fn slice_mut[T](v: &T[mutable? ], start: uint, end: uint) -> T[mutable ] { // Mutators // TODO: Write this, unsafely, in a way that's not O(n). -fn pop[T](v: &mutable T[mutable? ]) -> T { +fn pop[@T](v: &mutable T[mutable? ]) -> T { let ln = len(v); assert (ln > 0u); ln -= 1u; @@ -160,14 +160,14 @@ fn pop[T](v: &mutable T[mutable? ]) -> T { // Appending /// Expands the given vector in-place by appending `n` copies of `initval`. -fn grow[T](v: &mutable T[], n: uint, initval: &T) { +fn grow[@T](v: &mutable T[], n: uint, initval: &T) { reserve(v, next_power_of_two(len(v) + n)); let i: uint = 0u; while i < n { v += ~[initval]; i += 1u; } } // TODO: Remove me once we have slots. -fn grow_mut[T](v: &mutable T[mutable ], n: uint, initval: &T) { +fn grow_mut[@T](v: &mutable T[mutable ], n: uint, initval: &T) { reserve(v, next_power_of_two(len(v) + n)); let i: uint = 0u; while i < n { v += ~[mutable initval]; i += 1u; } @@ -175,7 +175,7 @@ fn grow_mut[T](v: &mutable T[mutable ], n: uint, initval: &T) { /// Calls `f` `n` times and appends the results of these calls to the given /// vector. -fn grow_fn[T](v: &mutable T[], n: uint, init_fn: fn(uint) -> T ) { +fn grow_fn[@T](v: &mutable T[], n: uint, init_fn: fn(uint) -> T ) { reserve(v, next_power_of_two(len(v) + n)); let i: uint = 0u; while i < n { v += ~[init_fn(i)]; i += 1u; } @@ -192,7 +192,7 @@ fn grow_set[@T](v: &mutable T[mutable ], index: uint, initval: &T, val: &T) { // Functional utilities -fn map[T, U](f: fn(&T) -> U , v: &T[mutable? ]) -> U[] { +fn map[@T, @U](f: fn(&T) -> U , v: &T[mutable? ]) -> U[] { let result = ~[]; reserve(result, len(v)); for elem: T in v { @@ -202,7 +202,7 @@ fn map[T, U](f: fn(&T) -> U , v: &T[mutable? ]) -> U[] { ret result; } -fn filter_map[T, U](f: fn(&T) -> option::t[U] , v: &T[mutable? ]) -> U[] { +fn filter_map[@T, @U](f: fn(&T) -> option::t[U] , v: &T[mutable? ]) -> U[] { let result = ~[]; for elem: T in v { let elem2 = elem; // satisfies alias checker @@ -214,7 +214,7 @@ fn filter_map[T, U](f: fn(&T) -> option::t[U] , v: &T[mutable? ]) -> U[] { ret result; } -fn foldl[T, U](p: fn(&U, &T) -> U , z: &U, v: &T[mutable? ]) -> U { +fn foldl[@T, @U](p: fn(&U, &T) -> U , z: &U, v: &T[mutable? ]) -> U { let sz = len(v); if sz == 0u { ret z; } let first = v.(0); @@ -243,12 +243,12 @@ fn count[T](x: &T, v: &T[mutable? ]) -> uint { ret cnt; } -fn find[T](f: fn(&T) -> bool , v: &T[]) -> option::t[T] { +fn find[@T](f: fn(&T) -> bool , v: &T[]) -> option::t[T] { for elt: T in v { if f(elt) { ret some[T](elt); } } ret none[T]; } -fn unzip[T, U](v: &{_0: T, _1: U}[]) -> {_0: T[], _1: U[]} { +fn unzip[@T, @U](v: &{_0: T, _1: U}[]) -> {_0: T[], _1: U[]} { let sz = len(v); if sz == 0u { ret {_0: ~[], _1: ~[]}; @@ -263,7 +263,7 @@ fn unzip[T, U](v: &{_0: T, _1: U}[]) -> {_0: T[], _1: U[]} { // FIXME make the lengths being equal a constraint -fn zip[T, U](v: &T[], u: &U[]) -> {_0: T, _1: U}[] { +fn zip[@T, @U](v: &T[], u: &U[]) -> {_0: T, _1: U}[] { let sz = len(v); assert (sz == len(u)); if sz == 0u { @@ -309,5 +309,5 @@ mod unsafe { // indent-tabs-mode: nil // c-basic-offset: 4 // buffer-file-coding-system: utf-8-unix -// compile-command: "make -k -C .. 2>&1 | sed -e 's/\\/x\\//x:\\//g'"; +// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'"; // End: diff --git a/src/lib/list.rs b/src/lib/list.rs index cd38d0f6cd79..a53ea671e907 100644 --- a/src/lib/list.rs +++ b/src/lib/list.rs @@ -55,7 +55,7 @@ fn has[@T](ls_: &list[T], elt: &T) -> bool { } -fn length[T](ls: &list[T]) -> uint { +fn length[@T](ls: &list[T]) -> uint { fn count[T](t: &T, u: &uint) -> uint { ret u + 1u; } ret foldl[T, uint](ls, 0u, bind count[T](_, _)); } diff --git a/src/lib/map.rs b/src/lib/map.rs index 6ce93d4592f1..3883d0b94e85 100644 --- a/src/lib/map.rs +++ b/src/lib/map.rs @@ -25,8 +25,8 @@ fn mk_hashmap[@K, @V](hasher: &hashfn[K], eqer: &eqfn[K]) -> hashmap[K, V] { let initial_capacity: uint = 32u; // 2^5 let load_factor: util::rational = {num: 3, den: 4}; - tag bucket[K, V] { nil; deleted; some(K, V); } - fn make_buckets[K, V](nbkts: uint) -> (bucket[K, V])[mutable ] { + tag bucket[@K, @V] { nil; deleted; some(K, V); } + fn make_buckets[@K, @V](nbkts: uint) -> (bucket[K, V])[mutable ] { ret ivec::init_elt_mut[bucket[K, V]](nil[K, V], nbkts); } // Derive two hash functions from the one given by taking the upper diff --git a/src/lib/option.rs b/src/lib/option.rs index d08fcfd28ccd..a67408ac1788 100644 --- a/src/lib/option.rs +++ b/src/lib/option.rs @@ -2,34 +2,34 @@ // lib/option::rs -tag t[T] { none; some(T); } +tag t[@T] { none; some(T); } -type operator[T, U] = fn(&T) -> U ; +type operator[@T, @U] = fn(&T) -> U ; -fn get[T](opt: &t[T]) -> T { ret alt opt { some(x) { x } none. { fail } }; } +fn get[@T](opt: &t[T]) -> T { ret alt opt { some(x) { x } none. { fail } }; } -fn map[T, U](f: &operator[T, U], opt: &t[T]) -> t[U] { +fn map[@T, @U](f: &operator[T, U], opt: &t[T]) -> t[U] { ret alt opt { some(x) { some[U](f(x)) } none. { none[U] } }; } -fn is_none[T](opt: &t[T]) -> bool { +fn is_none[@T](opt: &t[T]) -> bool { ret alt opt { none. { true } some(_) { false } }; } -fn is_some[T](opt: &t[T]) -> bool { ret !is_none(opt); } +fn is_some[@T](opt: &t[T]) -> bool { ret !is_none(opt); } -fn from_maybe[T](def: &T, opt: &t[T]) -> T { +fn from_maybe[@T](def: &T, opt: &t[T]) -> T { let f = bind util::id[T](_); ret maybe[T, T](def, f, opt); } -fn maybe[T, U](def: &U, f: fn(&T) -> U , opt: &t[T]) -> U { +fn maybe[@T, @U](def: &U, f: fn(&T) -> U , opt: &t[T]) -> U { ret alt opt { none. { def } some(t) { f(t) } }; } // Can be defined in terms of the above when/if we have const bind. -fn may[T](f: fn(&T) , opt: &t[T]) { +fn may[@T](f: fn(&T) , opt: &t[T]) { alt opt { none. {/* nothing */ } some(t) { f(t); } } } // Local Variables: diff --git a/src/lib/smallintmap.rs b/src/lib/smallintmap.rs index 0c11e69c349f..fdee322d30ee 100644 --- a/src/lib/smallintmap.rs +++ b/src/lib/smallintmap.rs @@ -9,32 +9,32 @@ import option::some; // to be. type smallintmap[T] = @{mutable v: (option::t[T])[mutable ]}; -fn mk[T]() -> smallintmap[T] { +fn mk[@T]() -> smallintmap[T] { let v: (option::t[T])[mutable ] = ~[mutable ]; ret @{mutable v: v}; } -fn insert[T](m: &smallintmap[T], key: uint, val: &T) { +fn insert[@T](m: &smallintmap[T], key: uint, val: &T) { ivec::grow_set[option::t[T]](m.v, key, none[T], some[T](val)); } -fn find[T](m: &smallintmap[T], key: uint) -> option::t[T] { +fn find[@T](m: &smallintmap[T], key: uint) -> option::t[T] { if key < ivec::len[option::t[T]](m.v) { ret m.v.(key); } ret none[T]; } -fn get[T](m: &smallintmap[T], key: uint) -> T { +fn get[@T](m: &smallintmap[T], key: uint) -> T { alt find[T](m, key) { none[T]. { log_err "smallintmap::get(): key not present"; fail; } some[T](v) { ret v; } } } -fn contains_key[T](m: &smallintmap[T], key: uint) -> bool { +fn contains_key[@T](m: &smallintmap[T], key: uint) -> bool { ret !option::is_none(find[T](m, key)); } -fn truncate[T](m: &smallintmap[T], len: uint) { +fn truncate[@T](m: &smallintmap[T], len: uint) { m.v = ivec::slice_mut[option::t[T]](m.v, 0u, len); } diff --git a/src/lib/sort.rs b/src/lib/sort.rs index 909e40c5c6b3..2a7348b354f1 100644 --- a/src/lib/sort.rs +++ b/src/lib/sort.rs @@ -12,7 +12,7 @@ export quick_sort3; type lteq[T] = fn(&T, &T) -> bool ; fn merge_sort[@T](le: lteq[T], v: vec[T]) -> vec[T] { - fn merge[T](le: lteq[T], a: vec[T], b: vec[T]) -> vec[T] { + fn merge[@T](le: lteq[T], a: vec[T], b: vec[T]) -> vec[T] { let rs: vec[T] = []; let a_len: uint = len[T](a); let a_ix: uint = 0u; diff --git a/src/test/stdtest/deque.rs b/src/test/stdtest/deque.rs index 2b4da0cdf6bb..6d405f2eae85 100644 --- a/src/test/stdtest/deque.rs +++ b/src/test/stdtest/deque.rs @@ -81,7 +81,7 @@ fn test_boxes(a: @int, b: @int, c: @int, d: @int) { type eqfn[T] = fn(&T, &T) -> bool ; -fn test_parameterized[T](e: eqfn[T], a: &T, b: &T, c: &T, d: &T) { +fn test_parameterized[@T](e: eqfn[T], a: &T, b: &T, c: &T, d: &T) { let deq: deque::t[T] = deque::create[T](); assert (deq.size() == 0u); deq.add_front(a); @@ -113,7 +113,7 @@ fn test_parameterized[T](e: eqfn[T], a: &T, b: &T, c: &T, d: &T) { tag taggy { one(int); two(int, int); three(int, int, int); } -tag taggypar[T] { onepar(int); twopar(int, int); threepar(int, int, int); } +tag taggypar[@T] { onepar(int); twopar(int, int); threepar(int, int, int); } type reccy = {x: int, y: int, t: taggy}; @@ -138,7 +138,7 @@ fn test() { } } } - fn taggypareq[T](a: &taggypar[T], b: &taggypar[T]) -> bool { + fn taggypareq[@T](a: &taggypar[T], b: &taggypar[T]) -> bool { alt a { onepar[T](a1) { alt b { onepar[T](b1) { ret a1 == b1; } _ { ret false; } }