Enable kind checking on typarams, fix kind constraints in library and comp.
This commit is contained in:
parent
6ba4e34959
commit
0c9b749d20
@ -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 }
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
_ { }
|
||||
}
|
||||
|
@ -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. {
|
||||
|
@ -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);
|
||||
|
@ -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:
|
||||
|
@ -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](_, _));
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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; } }
|
||||
|
Loading…
x
Reference in New Issue
Block a user