Update stdlib, compiler, and tests to new kind system

This involved adding 'copy' to more generics than I hoped, but an
experiment with making it implicit showed that that way lies madness --
unless enforced, you will not remember to mark functions that don't
copy as not requiring copyable kind.

Issue #1177
This commit is contained in:
Marijn Haverbeke 2011-11-18 12:39:20 +01:00
parent 8f8ebb550c
commit f6491bb426
94 changed files with 327 additions and 489 deletions

View File

@ -199,7 +199,7 @@ fn require_unique_names(sess: session::session, metas: [@ast::meta_item]) {
}
}
fn span<T>(item: T) -> ast::spanned<T> {
fn span<copy T>(item: T) -> ast::spanned<T> {
ret {node: item, span: ast_util::dummy_sp()};
}

View File

@ -196,7 +196,9 @@ fn mk_test_module(cx: test_ctxt) -> @ast::item {
ret @item;
}
fn nospan<T>(t: T) -> ast::spanned<T> { ret {node: t, span: dummy_sp()}; }
fn nospan<copy T>(t: T) -> ast::spanned<T> {
ret {node: t, span: dummy_sp()};
}
fn mk_tests(cx: test_ctxt) -> @ast::item {
let ret_ty = mk_test_desc_vec_ty(cx);

View File

@ -389,7 +389,7 @@ fn encode_info_for_items(ecx: @encode_ctxt, ebml_w: ebml::writer) ->
// Path and definition ID indexing
fn create_index<T>(index: [entry<T>], hash_fn: fn(T) -> uint) ->
fn create_index<copy T>(index: [entry<T>], hash_fn: fn(T) -> uint) ->
[@[entry<T>]] {
let buckets: [@mutable [entry<T>]] = [];
uint::range(0u, 256u) {|_i| buckets += [@mutable []]; };

View File

@ -150,7 +150,7 @@ fn parse_ty_constr_arg(st: @pstate, sd: str_def) ->
}
}
fn parse_constr<T>(st: @pstate, sd: str_def, pser: arg_parser<T>) ->
fn parse_constr<copy T>(st: @pstate, sd: str_def, pser: arg_parser<T>) ->
@ty::constr_general<T> {
let sp = ast_util::dummy_sp(); // FIXME: use a real span
let args: [@sp_constr_arg<T>] = [];

View File

@ -74,7 +74,7 @@ fn map_expr(cx: ctx, ex: @expr) {
cx.map.insert(ex.id, node_expr(ex));
}
fn new_smallintmap_int_adapter<V>() -> std::map::hashmap<int, V> {
fn new_smallintmap_int_adapter<copy 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);
@ -85,11 +85,11 @@ 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<copy K, copy V>(key_idx: fn(K) -> uint,
idx_key: fn(uint) -> K)
-> std::map::hashmap<K, V> {
obj adapter<shar K, shar V>(map: smallintmap::smallintmap<V>,
obj adapter<copy K, copy V>(map: smallintmap::smallintmap<V>,
key_idx: fn(K) -> uint,
idx_key: fn(uint) -> K) {

View File

@ -23,9 +23,7 @@ type def_id = {crate: crate_num, node: node_id};
const local_crate: crate_num = 0;
tag plicit<T> { explicit(T); implicit(T); }
type ty_param = {ident: ident, kind: plicit<kind>};
type ty_param = {ident: ident, kind: kind};
tag def {
def_fn(def_id, purity);

View File

@ -2,7 +2,9 @@ import std::{str, option};
import codemap::span;
import ast::*;
fn respan<T>(sp: span, t: T) -> spanned<T> { ret {node: t, span: sp}; }
fn respan<copy T>(sp: span, t: T) -> spanned<T> {
ret {node: t, span: sp};
}
/* assuming that we're not in macro expansion */
fn mk_sp(lo: uint, hi: uint) -> span {
@ -186,7 +188,7 @@ fn eq_def_id(&&a: def_id, &&b: def_id) -> bool {
a == b
}
fn new_def_id_hash<T>() -> std::map::hashmap<def_id, T> {
fn new_def_id_hash<copy T>() -> std::map::hashmap<def_id, T> {
std::map::mk_hashmap(hash_def_id, eq_def_id)
}
@ -228,9 +230,7 @@ fn ret_by_ref(style: ret_style) -> bool {
}
}
fn ty_param_kind(tp: ty_param) -> kind {
alt tp.kind { ast::implicit(x) | ast::explicit(x) { x } }
}
fn ty_param_kind(tp: ty_param) -> kind { tp.kind }
// Local Variables:
// mode: rust

View File

@ -103,7 +103,7 @@ fn elts_to_ell(cx: ext_ctxt, elts: [@expr]) ->
}
}
fn option_flatten_map<T, U>(f: fn@(T) -> option::t<U>, v: [T]) ->
fn option_flatten_map<copy T, copy U>(f: fn@(T) -> option::t<U>, v: [T]) ->
option::t<[U]> {
let res = [];
for elem: T in v {

View File

@ -219,7 +219,7 @@ fn expect_gt(p: parser) {
}
}
fn spanned<T>(lo: uint, hi: uint, node: T) -> spanned<T> {
fn spanned<copy T>(lo: uint, hi: uint, node: T) -> spanned<T> {
ret {node: node, span: ast_util::mk_sp(lo, hi)};
}
@ -394,8 +394,8 @@ fn parse_constr_in_type(p: parser) -> @ast::ty_constr {
}
fn parse_constrs<T>(pser: block(parser) -> @ast::constr_general<T>,
p: parser) ->
fn parse_constrs<copy T>(pser: block(parser) -> @ast::constr_general<T>,
p: parser) ->
[@ast::constr_general<T>] {
let constrs: [@ast::constr_general<T>] = [];
while true {
@ -595,9 +595,9 @@ fn parse_fn_block_arg(p: parser) -> ast::arg {
ret {mode: m, ty: t, ident: i, id: p.get_id()};
}
fn parse_seq_to_before_gt<T>(sep: option::t<token::token>,
f: block(parser) -> T,
p: parser) -> [T] {
fn parse_seq_to_before_gt<copy T>(sep: option::t<token::token>,
f: block(parser) -> T,
p: parser) -> [T] {
let first = true;
let v = [];
while p.peek() != token::GT && p.peek() != token::BINOP(token::LSR) &&
@ -612,16 +612,17 @@ fn parse_seq_to_before_gt<T>(sep: option::t<token::token>,
ret v;
}
fn parse_seq_to_gt<T>(sep: option::t<token::token>, f: block(parser) -> T,
p: parser) -> [T] {
fn parse_seq_to_gt<copy T>(sep: option::t<token::token>,
f: block(parser) -> T, p: parser) -> [T] {
let v = parse_seq_to_before_gt(sep, f, p);
expect_gt(p);
ret v;
}
fn parse_seq_lt_gt<T>(sep: option::t<token::token>, f: block(parser) -> T,
p: parser) -> spanned<[T]> {
fn parse_seq_lt_gt<copy T>(sep: option::t<token::token>,
f: block(parser) -> T,
p: parser) -> spanned<[T]> {
let lo = p.get_lo_pos();
expect(p, token::LT);
let result = parse_seq_to_before_gt::<T>(sep, f, p);
@ -630,16 +631,16 @@ fn parse_seq_lt_gt<T>(sep: option::t<token::token>, f: block(parser) -> T,
ret spanned(lo, hi, result);
}
fn parse_seq_to_end<T>(ket: token::token, sep: option::t<token::token>,
f: block(parser) -> T, p: parser) -> [T] {
fn parse_seq_to_end<copy T>(ket: token::token, sep: option::t<token::token>,
f: block(parser) -> T, p: parser) -> [T] {
let val = parse_seq_to_before_end(ket, sep, f, p);
p.bump();
ret val;
}
fn parse_seq_to_before_end<T>(ket: token::token,
sep: option::t<token::token>,
f: block(parser) -> T, p: parser) -> [T] {
fn parse_seq_to_before_end<copy T>(ket: token::token,
sep: option::t<token::token>,
f: block(parser) -> T, p: parser) -> [T] {
let first: bool = true;
let v: [T] = [];
while p.peek() != ket {
@ -653,9 +654,9 @@ fn parse_seq_to_before_end<T>(ket: token::token,
}
fn parse_seq<T>(bra: token::token, ket: token::token,
sep: option::t<token::token>, f: block(parser) -> T,
p: parser) -> spanned<[T]> {
fn parse_seq<copy T>(bra: token::token, ket: token::token,
sep: option::t<token::token>, f: block(parser) -> T,
p: parser) -> spanned<[T]> {
let lo = p.get_lo_pos();
expect(p, bra);
let result = parse_seq_to_before_end::<T>(ket, sep, f, p);
@ -1741,24 +1742,18 @@ fn parse_block_tail(p: parser, lo: uint, s: ast::blk_check_mode) -> ast::blk {
ret spanned(lo, hi, bloc);
}
fn parse_ty_param(p: parser, def: ast::kind) -> ast::ty_param {
// Accept both old and new kind names for now. FIXME remove this
let k = if eat_word(p, "send") | eat_word(p, "uniq")
{ ast::explicit(ast::kind_sendable) }
else if eat_word(p, "copy") | eat_word(p, "shar")
{ ast::explicit(ast::kind_copyable) }
else if eat_word(p, "nocopy") | eat_word(p, "pin")
{ ast::explicit(ast::kind_noncopyable) }
else { ast::implicit(def) };
fn parse_ty_param(p: parser) -> ast::ty_param {
let k = if eat_word(p, "send") { ast::kind_sendable }
else if eat_word(p, "copy") { ast::kind_copyable }
else { ast::kind_noncopyable };
ret {ident: parse_ident(p), kind: k};
}
fn parse_ty_params(p: parser, def: ast::kind) -> [ast::ty_param] {
fn parse_ty_params(p: parser) -> [ast::ty_param] {
let ty_params: [ast::ty_param] = [];
if p.peek() == token::LT {
p.bump();
ty_params = parse_seq_to_gt(some(token::COMMA),
{|p| parse_ty_param(p, def)}, p);
ty_params = parse_seq_to_gt(some(token::COMMA), parse_ty_param, p);
}
ret ty_params;
}
@ -1811,7 +1806,7 @@ fn parse_fn(p: parser, proto: ast::proto, purity: ast::purity,
fn parse_fn_header(p: parser) -> {ident: ast::ident, tps: [ast::ty_param]} {
let id = parse_value_ident(p);
let ty_params = parse_ty_params(p, ast::kind_copyable);
let ty_params = parse_ty_params(p);
ret {ident: id, tps: ty_params};
}
@ -1864,7 +1859,7 @@ fn parse_method(p: parser) -> @ast::method {
fn parse_item_obj(p: parser, attrs: [ast::attribute]) -> @ast::item {
let lo = p.get_last_lo_pos();
let ident = parse_value_ident(p);
let ty_params = parse_ty_params(p, ast::kind_copyable);
let ty_params = parse_ty_params(p);
let fields: ast::spanned<[ast::obj_field]> =
parse_seq(token::LPAREN, token::RPAREN, some(token::COMMA),
parse_obj_field, p);
@ -1881,7 +1876,7 @@ fn parse_item_obj(p: parser, attrs: [ast::attribute]) -> @ast::item {
fn parse_item_res(p: parser, attrs: [ast::attribute]) -> @ast::item {
let lo = p.get_last_lo_pos();
let ident = parse_value_ident(p);
let ty_params = parse_ty_params(p, ast::kind_noncopyable);
let ty_params = parse_ty_params(p);
expect(p, token::LPAREN);
let arg_ident = parse_value_ident(p);
expect(p, token::COLON);
@ -2045,7 +2040,7 @@ fn parse_type_decl(p: parser) -> {lo: uint, ident: ast::ident} {
fn parse_item_type(p: parser, attrs: [ast::attribute]) -> @ast::item {
let t = parse_type_decl(p);
let tps = parse_ty_params(p, ast::kind_noncopyable);
let tps = parse_ty_params(p);
expect(p, token::EQ);
let ty = parse_ty(p, false);
let hi = p.get_hi_pos();
@ -2056,7 +2051,7 @@ fn parse_item_type(p: parser, attrs: [ast::attribute]) -> @ast::item {
fn parse_item_tag(p: parser, attrs: [ast::attribute]) -> @ast::item {
let lo = p.get_last_lo_pos();
let id = parse_ident(p);
let ty_params = parse_ty_params(p, ast::kind_noncopyable);
let ty_params = parse_ty_params(p);
let variants: [ast::variant] = [];
// Newtype syntax
if p.peek() == token::EQ {

View File

@ -1167,12 +1167,11 @@ fn print_arg_mode(s: ps, m: ast::mode) {
}
}
fn print_kind(s: ps, kind: ast::plicit<ast::kind>) {
fn print_kind(s: ps, kind: ast::kind) {
alt kind {
ast::explicit(ast::kind_sendable.) { word_nbsp(s, "send"); }
ast::explicit(ast::kind_copyable.) { word_nbsp(s, "copy"); }
ast::explicit(ast::kind_noncopyable.) { word_nbsp(s, "nocopy"); }
ast::implicit(_) {}
ast::kind_sendable. { word_nbsp(s, "send"); }
ast::kind_copyable. { word_nbsp(s, "copy"); }
ast::kind_noncopyable. {}
}
}

View File

@ -11,12 +11,12 @@ type interner<T> =
hasher: hashfn<T>,
eqer: eqfn<T>};
fn mk<T>(hasher: hashfn<T>, eqer: eqfn<T>) -> interner<T> {
fn mk<copy 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<copy T>(itr: interner<T>, val: T) -> uint {
alt itr.map.find(val) {
some(idx) { ret idx; }
none. {
@ -31,7 +31,7 @@ fn intern<T>(itr: interner<T>, val: T) -> uint {
// |get| isn't "pure" in the traditional sense, because it can go from
// failing to returning a value as items are interned. But for typestate,
// where we first check a pred and then rely on it, ceasing to fail is ok.
pure fn get<T>(itr: interner<T>, idx: uint) -> T {
pure fn get<copy T>(itr: interner<T>, idx: uint) -> T {
unchecked {
itr.vect[idx]
}

View File

@ -21,7 +21,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<copy 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);
@ -162,7 +162,7 @@ fn lit_in_range(l: @ast::lit, m1: @ast::lit, m2: @ast::lit) -> bool {
}
}
fn ranges_overlap<T>(a1: T, a2: T, b1: T, b2: T) -> bool {
fn ranges_overlap<copy T>(a1: T, a2: T, b1: T, b2: T) -> bool {
let min1 = min(a1, a2);
let max1 = max(a1, a2);
let min2 = min(b1, b2);

View File

@ -55,7 +55,7 @@ fn mk_filesearch(maybe_sysroot: option::t<fs::path>,
}
// FIXME #1001: This can't be an obj method
fn search<T>(filesearch: filesearch, pick: pick<T>) -> option::t<T> {
fn search<copy T>(filesearch: filesearch, pick: pick<T>) -> option::t<T> {
for lib_search_path in filesearch.lib_search_paths() {
log #fmt["searching %s", lib_search_path];
for path in fs::list_dir(lib_search_path) {

View File

@ -224,7 +224,7 @@ fn check_variants_of_ast(crate: ast::crate, codemap: codemap::codemap,
check_variants_T(crate, codemap, filename, "ty", stolen.tys, pprust::ty_to_str, replace_ty_in_crate, cx);
}
fn check_variants_T<T>(
fn check_variants_T<copy T>(
crate: ast::crate,
codemap: codemap::codemap,
filename: str,

View File

@ -39,7 +39,7 @@ native mod rustrt {
type void;
type rust_port;
fn chan_id_send<uniq T>(t: *sys::type_desc,
fn chan_id_send<send T>(t: *sys::type_desc,
target_task: task::task, target_port: port_id,
data: T) -> ctypes::uintptr_t;
@ -52,7 +52,7 @@ native mod rustrt {
#[abi = "rust-intrinsic"]
native mod rusti {
fn recv<uniq T>(port: *rustrt::rust_port) -> T;
fn recv<send T>(port: *rustrt::rust_port) -> T;
}
type port_id = int;
@ -75,11 +75,11 @@ dropped.
Channels may be duplicated and themselves transmitted over other channels.
*/
tag chan<uniq T> {
tag chan<send T> {
chan_t(task::task, port_id);
}
resource port_ptr<uniq T>(po: *rustrt::rust_port) {
resource port_ptr<send T>(po: *rustrt::rust_port) {
// Once the port is detached it's guaranteed not to receive further
// messages
rustrt::rust_port_detach(po);
@ -103,7 +103,7 @@ transmitted. If a port value is copied, both copies refer to the same port.
Ports may be associated with multiple <chan>s.
*/
tag port<uniq T> { port_t(@port_ptr<T>); }
tag port<send T> { port_t(@port_ptr<T>); }
/*
Function: send
@ -113,7 +113,7 @@ Sends data over a channel.
The sent data is moved into the channel, whereupon the caller loses access
to it.
*/
fn send<uniq T>(ch: chan<T>, -data: T) {
fn send<send T>(ch: chan<T>, -data: T) {
let chan_t(t, p) = ch;
let res = rustrt::chan_id_send(sys::get_type_desc::<T>(), t, p, data);
if res != 0u unsafe {
@ -128,7 +128,7 @@ Function: port
Constructs a port.
*/
fn port<uniq T>() -> port<T> {
fn port<send T>() -> port<T> {
port_t(@port_ptr(rustrt::new_port(sys::size_of::<T>())))
}
@ -140,7 +140,7 @@ Receive from a port.
If no data is available on the port then the task will block until data
becomes available.
*/
fn recv<uniq T>(p: port<T>) -> T { ret rusti::recv(***p) }
fn recv<send T>(p: port<T>) -> T { ret rusti::recv(***p) }
/*
Function: chan
@ -149,6 +149,6 @@ Constructs a channel.
The channel is bound to the port used to construct it.
*/
fn chan<uniq T>(p: port<T>) -> chan<T> {
fn chan<send T>(p: port<T>) -> chan<T> {
chan_t(task::get_task(), rustrt::get_port_id(***p))
}

View File

@ -33,7 +33,7 @@ Section: Functions
/*
Function: create
*/
fn create<T>() -> t<T> {
fn create<copy T>() -> t<T> {
type cell<T> = option::t<T>;
let initial_capacity: uint = 32u; // 2^5
@ -41,7 +41,7 @@ fn create<T>() -> t<T> {
* Grow is only called on full elts, so nelts is also len(elts), unlike
* elsewhere.
*/
fn grow<T>(nelts: uint, lo: uint, elts: [mutable cell<T>]) ->
fn grow<copy T>(nelts: uint, lo: uint, elts: [mutable cell<T>]) ->
[mutable cell<T>] {
assert (nelts == vec::len(elts));
let rv = [mutable];
@ -60,7 +60,7 @@ fn create<T>() -> t<T> {
fn get<T>(elts: [mutable cell<T>], i: uint) -> T {
ret alt elts[i] { option::some(t) { t } _ { fail } };
}
obj deque<shar T>(mutable nelts: uint,
obj deque<copy T>(mutable nelts: uint,
mutable lo: uint,
mutable hi: uint,
mutable elts: [mutable cell<T>]) {

View File

@ -39,7 +39,7 @@ Function: lefts
Extracts from a vector of either all the left values.
*/
fn lefts<T, U>(eithers: [t<T, U>]) -> [T] {
fn lefts<copy T, U>(eithers: [t<T, U>]) -> [T] {
let result: [T] = [];
for elt: t<T, U> in eithers {
alt elt { left(l) { result += [l]; } _ {/* fallthrough */ } }
@ -52,7 +52,7 @@ Function: rights
Extracts from a vector of either all the right values
*/
fn rights<T, U>(eithers: [t<T, U>]) -> [U] {
fn rights<T, copy U>(eithers: [t<T, U>]) -> [U] {
let result: [U] = [];
for elt: t<T, U> in eithers {
alt elt { right(r) { result += [r]; } _ {/* fallthrough */ } }
@ -68,7 +68,8 @@ Extracts from a vector of either all the left values and right values
Returns a structure containing a vector of left values and a vector of
right values.
*/
fn partition<T, U>(eithers: [t<T, U>]) -> {lefts: [T], rights: [U]} {
fn partition<copy T, copy U>(eithers: [t<T, U>])
-> {lefts: [T], rights: [U]} {
let lefts: [T] = [];
let rights: [U] = [];
for elt: t<T, U> in eithers {

View File

@ -50,7 +50,7 @@ Function: insert
Insert a value into the map
*/
fn insert<K, V>(m: treemap<K, V>, k: K, v: V) -> treemap<K, V> {
fn insert<copy K, copy V>(m: treemap<K, V>, k: K, v: V) -> treemap<K, V> {
@alt m {
@empty. { node(@k, @v, @empty, @empty) }
@node(@kk, vv, left, right) {
@ -68,7 +68,7 @@ Function: find
Find a value based on the key
*/
fn find<K, V>(m: treemap<K, V>, k: K) -> option<V> {
fn find<K, copy V>(m: treemap<K, V>, k: K) -> option<V> {
alt *m {
empty. { none }
node(@kk, @v, left, right) {
@ -84,7 +84,7 @@ Function: traverse
Visit all pairs in the map in order.
*/
fn traverse<K, V>(m: treemap<K, V>, f: block(K, V)) {
fn traverse<K, copy V>(m: treemap<K, V>, f: block(K, V)) {
alt *m {
empty. { }
node(@k, @v, _, _) {

View File

@ -25,7 +25,7 @@ Function: from_vec
Create a list from a vector
*/
fn from_vec<T>(v: [const T]) -> list<T> {
fn from_vec<copy T>(v: [const T]) -> list<T> {
*vec::foldr({ |h, t| @cons(h, t) }, @nil::<T>, v)
}
@ -44,7 +44,7 @@ ls - The list to fold
z - The initial value
f - The function to apply
*/
fn foldl<T, U>(ls: list<U>, z: T, f: block(T, U) -> T) -> T {
fn foldl<copy T, copy U>(ls: list<U>, z: T, f: block(T, U) -> T) -> T {
let accum: T = z;
let ls = ls;
while true {
@ -65,7 +65,8 @@ Apply function `f` to each element of `v`, starting from the first.
When function `f` returns true then an option containing the element
is returned. If `f` matches no elements then none is returned.
*/
fn find<T, U>(ls: list<T>, f: block(T) -> option::t<U>) -> option::t<U> {
fn find<copy T, copy U>(ls: list<T>, f: block(T) -> option::t<U>)
-> option::t<U> {
let ls = ls;
while true {
alt ls {
@ -83,7 +84,7 @@ Function: has
Returns true if a list contains an element with the given value
*/
fn has<T>(ls: list<T>, elt: T) -> bool {
fn has<copy T>(ls: list<T>, elt: T) -> bool {
let ls = ls;
while true {
alt ls {
@ -99,7 +100,7 @@ Function: len
Returns the length of a list
*/
fn len<T>(ls: list<T>) -> uint {
fn len<copy T>(ls: list<T>) -> uint {
fn count<T>(&&u: uint, _t: T) -> uint { ret u + 1u; }
ret foldl(ls, 0u, bind count(_, _));
}
@ -109,7 +110,7 @@ Function: tail
Returns all but the first element of a list
*/
fn tail<T>(ls: list<T>) -> list<T> {
fn tail<copy T>(ls: list<T>) -> list<T> {
alt ls { cons(_, tl) { ret *tl; } nil. { fail "list empty" } }
}
@ -118,7 +119,7 @@ Function: head
Returns the first element of a list
*/
fn head<T>(ls: list<T>) -> T {
fn head<copy T>(ls: list<T>) -> T {
alt ls { cons(hd, _) { ret hd; } nil. { fail "list empty" } }
}
@ -127,7 +128,7 @@ Function: append
Appends one list to another
*/
fn append<T>(l: list<T>, m: list<T>) -> list<T> {
fn append<copy T>(l: list<T>, m: list<T>) -> list<T> {
alt l {
nil. { ret m; }
cons(x, xs) { let rest = append(*xs, m); ret cons(x, @rest); }

View File

@ -114,12 +114,13 @@ Parameters:
hasher - The hash function for key type K
eqer - The equality function for key type K
*/
fn mk_hashmap<K, V>(hasher: hashfn<K>, eqer: eqfn<K>) -> hashmap<K, V> {
fn mk_hashmap<copy K, copy 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) -> [mutable bucket<K, V>] {
tag bucket<copy K, copy V> { nil; deleted; some(K, V); }
fn make_buckets<copy K, copy V>(nbkts: uint) -> [mutable bucket<K, V>] {
ret vec::init_elt_mut::<bucket<K, V>>(nil::<K, V>, nbkts);
}
// Derive two hash functions from the one given by taking the upper
@ -146,9 +147,9 @@ fn mk_hashmap<K, V>(hasher: hashfn<K>, eqer: eqfn<K>) -> hashmap<K, V> {
* will fail.
*/
fn insert_common<K, V>(hasher: hashfn<K>, eqer: eqfn<K>,
bkts: [mutable bucket<K, V>], nbkts: uint, key: K,
val: V) -> bool {
fn insert_common<copy K, copy V>(hasher: hashfn<K>, eqer: eqfn<K>,
bkts: [mutable bucket<K, V>],
nbkts: uint, key: K, val: V) -> bool {
let i: uint = 0u;
let h: uint = hasher(key);
while i < nbkts {
@ -166,9 +167,9 @@ fn mk_hashmap<K, V>(hasher: hashfn<K>, eqer: eqfn<K>) -> hashmap<K, V> {
}
fail; // full table
}
fn find_common<K, V>(hasher: hashfn<K>, eqer: eqfn<K>,
bkts: [mutable bucket<K, V>], nbkts: uint, key: K) ->
option::t<V> {
fn find_common<copy K, copy V>(hasher: hashfn<K>, eqer: eqfn<K>,
bkts: [mutable bucket<K, V>],
nbkts: uint, key: K) -> option::t<V> {
let i: uint = 0u;
let h: uint = hasher(key);
while i < nbkts {
@ -187,9 +188,11 @@ fn mk_hashmap<K, V>(hasher: hashfn<K>, eqer: eqfn<K>) -> hashmap<K, V> {
}
ret option::none;
}
fn rehash<K, V>(hasher: hashfn<K>, eqer: eqfn<K>,
oldbkts: [mutable bucket<K, V>], _noldbkts: uint,
newbkts: [mutable bucket<K, V>], nnewbkts: uint) {
fn rehash<copy K, copy V>(hasher: hashfn<K>, eqer: eqfn<K>,
oldbkts: [mutable bucket<K, V>],
_noldbkts: uint,
newbkts: [mutable bucket<K, V>],
nnewbkts: uint) {
for b: bucket<K, V> in oldbkts {
alt b {
some(k_, v_) {
@ -201,7 +204,7 @@ fn mk_hashmap<K, V>(hasher: hashfn<K>, eqer: eqfn<K>) -> hashmap<K, V> {
}
}
}
obj hashmap<shar K, shar V>(hasher: hashfn<K>,
obj hashmap<copy K, copy V>(hasher: hashfn<K>,
eqer: eqfn<K>,
mutable bkts: [mutable bucket<K, V>],
mutable nbkts: uint,
@ -291,7 +294,7 @@ Function: new_str_hash
Construct a hashmap for string keys
*/
fn new_str_hash<V>() -> hashmap<str, V> {
fn new_str_hash<copy V>() -> hashmap<str, V> {
ret mk_hashmap(str::hash, str::eq);
}
@ -300,7 +303,7 @@ Function: new_int_hash
Construct a hashmap for int keys
*/
fn new_int_hash<V>() -> hashmap<int, V> {
fn new_int_hash<copy V>() -> hashmap<int, V> {
fn hash_int(&&x: int) -> uint { ret x as uint; }
fn eq_int(&&a: int, &&b: int) -> bool { ret a == b; }
ret mk_hashmap(hash_int, eq_int);
@ -311,7 +314,7 @@ Function: new_uint_hash
Construct a hashmap for uint keys
*/
fn new_uint_hash<V>() -> hashmap<uint, V> {
fn new_uint_hash<copy V>() -> hashmap<uint, V> {
fn hash_uint(&&x: uint) -> uint { ret x; }
fn eq_uint(&&a: uint, &&b: uint) -> bool { ret a == b; }
ret mk_hashmap(hash_uint, eq_uint);

View File

@ -73,11 +73,11 @@ Function: min
Returns the minimum of two values
*/
fn min<T>(x: T, y: T) -> T { x < y ? x : y }
fn min<copy T>(x: T, y: T) -> T { x < y ? x : y }
/*
Function: max
Returns the maximum of two values
*/
fn max<T>(x: T, y: T) -> T { x < y ? y : x }
fn max<copy T>(x: T, y: T) -> T { x < y ? y : x }

View File

@ -103,7 +103,8 @@ Example:
> })
*/
fn chain<T, U, V>(res: t<T, V>, op: block(T) -> t<U, V>) -> t<U, V> {
fn chain<T, copy U, copy V>(res: t<T, V>, op: block(T) -> t<U, V>)
-> t<U, V> {
alt res {
ok(t) { op(t) }
err(e) { err(e) }

View File

@ -29,7 +29,7 @@ Function: insert
Add a value to the map. If the map already contains a value for
the specified key then the original value is replaced.
*/
fn insert<T>(m: smallintmap<T>, key: uint, val: T) {
fn insert<copy T>(m: smallintmap<T>, key: uint, val: T) {
vec::grow_set::<option::t<T>>(m.v, key, none::<T>, some::<T>(val));
}
@ -39,7 +39,7 @@ Function: find
Get the value for the specified key. If the key does not exist
in the map then returns none.
*/
fn find<T>(m: smallintmap<T>, key: uint) -> option::t<T> {
fn find<copy T>(m: smallintmap<T>, key: uint) -> option::t<T> {
if key < vec::len::<option::t<T>>(m.v) { ret m.v[key]; }
ret none::<T>;
}
@ -53,10 +53,10 @@ Failure:
If the key does not exist in the map
*/
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 get<copy T>(m: smallintmap<T>, key: uint) -> T {
alt find(m, key) {
none. { log_err "smallintmap::get(): key not present"; fail; }
some(v) { ret v; }
}
}
@ -65,13 +65,13 @@ Method: contains_key
Returns true if the map contains a value for the specified key
*/
fn contains_key<T>(m: smallintmap<T>, key: uint) -> bool {
fn contains_key<copy T>(m: smallintmap<T>, key: uint) -> bool {
ret !option::is_none(find::<T>(m, key));
}
// FIXME: Are these really useful?
fn truncate<T>(m: smallintmap<T>, len: uint) {
fn truncate<copy T>(m: smallintmap<T>, len: uint) {
m.v = vec::slice_mut::<option::t<T>>(m.v, 0u, len);
}

View File

@ -20,8 +20,8 @@ Merge sort. Returns a new vector containing the sorted list.
Has worst case O(n log n) performance, best case O(n), but
is not space efficient. This is a stable sort.
*/
fn merge_sort<T>(le: lteq<T>, v: [const T]) -> [T] {
fn merge<T>(le: lteq<T>, a: [T], b: [T]) -> [T] {
fn merge_sort<copy T>(le: lteq<T>, v: [const T]) -> [T] {
fn merge<copy T>(le: lteq<T>, a: [T], b: [T]) -> [T] {
let rs: [T] = [];
let a_len: uint = len::<T>(a);
let a_ix: uint = 0u;
@ -46,30 +46,24 @@ fn merge_sort<T>(le: lteq<T>, v: [const T]) -> [T] {
ret merge::<T>(le, merge_sort::<T>(le, a), merge_sort::<T>(le, b));
}
fn swap<T>(arr: [mutable T], x: uint, y: uint) {
let a = arr[x];
arr[x] = arr[y];
arr[y] = a;
}
fn part<T>(compare_func: lteq<T>, arr: [mutable T], left: uint, right: uint,
pivot: uint) -> uint {
fn part<copy T>(compare_func: lteq<T>, arr: [mutable T], left: uint,
right: uint, pivot: uint) -> uint {
let pivot_value = arr[pivot];
swap::<T>(arr, pivot, right);
arr[pivot] <-> arr[right];
let storage_index: uint = left;
let i: uint = left;
while i < right {
if compare_func({ arr[i] }, pivot_value) {
swap::<T>(arr, i, storage_index);
if compare_func(copy arr[i], pivot_value) {
arr[i] <-> arr[storage_index];
storage_index += 1u;
}
i += 1u;
}
swap::<T>(arr, storage_index, right);
arr[storage_index] <-> arr[right];
ret storage_index;
}
fn qsort<T>(compare_func: lteq<T>, arr: [mutable T], left: uint,
fn qsort<copy T>(compare_func: lteq<T>, arr: [mutable T], left: uint,
right: uint) {
if right > left {
let pivot = (left + right) / 2u;
@ -90,13 +84,13 @@ Quicksort. Sorts a mutable vector in place.
Has worst case O(n^2) performance, average case O(n log n).
This is an unstable sort.
*/
fn quick_sort<T>(compare_func: lteq<T>, arr: [mutable T]) {
fn quick_sort<copy T>(compare_func: lteq<T>, arr: [mutable T]) {
if len::<T>(arr) == 0u { ret; }
qsort::<T>(compare_func, arr, 0u, len::<T>(arr) - 1u);
}
fn qsort3<T>(compare_func_lt: lteq<T>, compare_func_eq: lteq<T>,
arr: [mutable T], left: int, right: int) {
fn qsort3<copy T>(compare_func_lt: lteq<T>, compare_func_eq: lteq<T>,
arr: [mutable T], left: int, right: int) {
if right <= left { ret; }
let v: T = arr[right];
let i: int = left - 1;
@ -105,36 +99,36 @@ fn qsort3<T>(compare_func_lt: lteq<T>, compare_func_eq: lteq<T>,
let q: int = j;
while true {
i += 1;
while compare_func_lt({ arr[i] }, v) { i += 1; }
while compare_func_lt(copy arr[i], v) { i += 1; }
j -= 1;
while compare_func_lt(v, { arr[j] }) {
while compare_func_lt(v, copy arr[j]) {
if j == left { break; }
j -= 1;
}
if i >= j { break; }
swap::<T>(arr, i as uint, j as uint);
if compare_func_eq({ arr[i] }, v) {
arr[i] <-> arr[j];
if compare_func_eq(copy arr[i], v) {
p += 1;
swap::<T>(arr, p as uint, i as uint);
arr[p] <-> arr[i];
}
if compare_func_eq(v, { arr[j] }) {
if compare_func_eq(v, copy arr[j]) {
q -= 1;
swap::<T>(arr, j as uint, q as uint);
arr[j] <-> arr[q];
}
}
swap::<T>(arr, i as uint, right as uint);
arr[i] <-> arr[right];
j = i - 1;
i += 1;
let k: int = left;
while k < p {
swap::<T>(arr, k as uint, j as uint);
arr[k] <-> arr[j];
k += 1;
j -= 1;
if k == len::<T>(arr) as int { break; }
}
k = right - 1;
while k > q {
swap::<T>(arr, i as uint, k as uint);
arr[i] <-> arr[k];
k -= 1;
i += 1;
if k == 0 { break; }
@ -156,8 +150,8 @@ According to these slides this is the algorithm of choice for
This is an unstable sort.
*/
fn quick_sort3<T>(compare_func_lt: lteq<T>, compare_func_eq: lteq<T>,
arr: [mutable T]) {
fn quick_sort3<copy T>(compare_func_lt: lteq<T>, compare_func_eq: lteq<T>,
arr: [mutable T]) {
if len::<T>(arr) == 0u { ret; }
qsort3::<T>(compare_func_lt, compare_func_eq, arr, 0,
(len::<T>(arr) as int) - 1);

View File

@ -232,7 +232,7 @@ Returns:
A handle to the new task
*/
fn spawn<uniq T>(-data: T, f: fn(T)) -> task {
fn spawn<send T>(-data: T, f: fn(T)) -> task {
spawn_inner(data, f, none)
}
@ -245,7 +245,7 @@ termination
Immediately before termination, either on success or failure, the spawned
task will send a <task_notification> message on the provided channel.
*/
fn spawn_notify<uniq T>(-data: T, f: fn(T),
fn spawn_notify<send T>(-data: T, f: fn(T),
notify: comm::chan<task_notification>) -> task {
spawn_inner(data, f, some(notify))
}
@ -259,7 +259,7 @@ This is a convenience wrapper around spawn_notify which, when paired
with <join> can be easily used to spawn a task then wait for it to
complete.
*/
fn spawn_joinable<uniq T>(-data: T, f: fn(T)) -> joinable_task {
fn spawn_joinable<send T>(-data: T, f: fn(T)) -> joinable_task {
let p = comm::port::<task_notification>();
let id = spawn_notify(data, f, comm::chan::<task_notification>(p));
ret (id, p);
@ -275,11 +275,11 @@ fn spawn_joinable<uniq T>(-data: T, f: fn(T)) -> joinable_task {
//
// After the transition this should all be rewritten.
fn spawn_inner<uniq T>(-data: T, f: fn(T),
fn spawn_inner<send T>(-data: T, f: fn(T),
notify: option<comm::chan<task_notification>>)
-> task unsafe {
fn wrapper<uniq T>(-data: *u8, f: fn(T)) unsafe {
fn wrapper<send T>(-data: *u8, f: fn(T)) unsafe {
let data: ~T = unsafe::reinterpret_cast(data);
f(*data);
}

View File

@ -109,8 +109,8 @@ fn run_tests_console(opts: test_opts,
run_tests_console_(opts, tests, default_test_to_task)
}
fn run_tests_console_<T>(opts: test_opts, tests: [test_desc<T>],
to_task: test_to_task<T>) -> bool {
fn run_tests_console_<copy T>(opts: test_opts, tests: [test_desc<T>],
to_task: test_to_task<T>) -> bool {
type test_state =
@{out: io::writer,
@ -121,7 +121,7 @@ fn run_tests_console_<T>(opts: test_opts, tests: [test_desc<T>],
mutable ignored: uint,
mutable failures: [test_desc<T>]};
fn callback<T>(event: testevent<T>, st: test_state) {
fn callback<copy T>(event: testevent<T>, st: test_state) {
alt event {
te_filtered(filtered_tests) {
st.total = vec::len(filtered_tests);
@ -214,9 +214,9 @@ tag testevent<T> {
te_result(test_desc<T>, test_result);
}
fn run_tests<T>(opts: test_opts, tests: [test_desc<T>],
to_task: test_to_task<T>,
callback: fn@(testevent<T>)) {
fn run_tests<copy T>(opts: test_opts, tests: [test_desc<T>],
to_task: test_to_task<T>,
callback: fn@(testevent<T>)) {
let filtered_tests = filter_tests(opts, tests);
callback(te_filtered(filtered_tests));
@ -248,8 +248,8 @@ fn run_tests<T>(opts: test_opts, tests: [test_desc<T>],
fn get_concurrency() -> uint { rustrt::sched_threads() }
fn filter_tests<T>(opts: test_opts,
tests: [test_desc<T>]) -> [test_desc<T>] {
fn filter_tests<copy T>(opts: test_opts,
tests: [test_desc<T>]) -> [test_desc<T>] {
let filtered = tests;
// Remove tests that don't match the test filter
@ -262,7 +262,7 @@ fn filter_tests<T>(opts: test_opts,
option::none. { "" }
};
fn filter_fn<T>(test: test_desc<T>, filter_str: str) ->
fn filter_fn<copy T>(test: test_desc<T>, filter_str: str) ->
option::t<test_desc<T>> {
if str::find(test.name, filter_str) >= 0 {
ret option::some(test);
@ -278,7 +278,7 @@ fn filter_tests<T>(opts: test_opts,
filtered = if !opts.run_ignored {
filtered
} else {
fn filter<T>(test: test_desc<T>) -> option::t<test_desc<T>> {
fn filter<copy T>(test: test_desc<T>) -> option::t<test_desc<T>> {
if test.ignore {
ret option::some({name: test.name,
fn: test.fn,
@ -304,8 +304,8 @@ fn filter_tests<T>(opts: test_opts,
type test_future<T> = {test: test_desc<T>, wait: fn@() -> test_result};
fn run_test<T>(test: test_desc<T>,
to_task: test_to_task<T>) -> test_future<T> {
fn run_test<copy T>(test: test_desc<T>,
to_task: test_to_task<T>) -> test_future<T> {
if test.ignore {
ret {test: test, wait: fn () -> test_result { tr_ignored }};
}

View File

@ -44,7 +44,7 @@ Function: insert
Insert a value into the map
*/
fn insert<K, V>(m: treemap<K, V>, k: K, v: V) {
fn insert<copy K, copy V>(m: treemap<K, V>, k: K, v: V) {
alt m {
@empty. { *m = node(@k, @v, @mutable empty, @mutable empty); }
@node(@kk, _, _, _) {
@ -63,7 +63,7 @@ Function: find
Find a value based on the key
*/
fn find<K, V>(m: treemap<K, V>, k: K) -> option<V> {
fn find<copy K, copy V>(m: treemap<K, V>, k: K) -> option<V> {
alt *m {
empty. { none }
node(@kk, @v, _, _) {

View File

@ -121,7 +121,7 @@ Creates and initializes an immutable vector.
Creates an immutable vector of size `n_elts` and initializes the elements
to the value `t`.
*/
fn init_elt<T>(t: T, n_elts: uint) -> [T] {
fn init_elt<copy T>(t: T, n_elts: uint) -> [T] {
let v = [];
reserve(v, n_elts);
let i: uint = 0u;
@ -138,7 +138,7 @@ Creates and initializes a mutable vector.
Creates a mutable vector of size `n_elts` and initializes the elements
to the value `t`.
*/
fn init_elt_mut<T>(t: T, n_elts: uint) -> [mutable T] {
fn init_elt_mut<copy T>(t: T, n_elts: uint) -> [mutable T] {
let v = [mutable];
reserve(v, n_elts);
let i: uint = 0u;
@ -153,7 +153,7 @@ Function: to_mut
Produces a mutable vector from an immutable vector.
*/
fn to_mut<T>(v: [T]) -> [mutable T] {
fn to_mut<copy T>(v: [T]) -> [mutable T] {
let vres = [mutable];
for t: T in v { vres += [mutable t]; }
ret vres;
@ -165,7 +165,7 @@ Function: from_mut
Produces an immutable vector from a mutable vector.
*/
fn from_mut<T>(v: [mutable T]) -> [T] {
fn from_mut<copy T>(v: [mutable T]) -> [T] {
let vres = [];
for t: T in v { vres += [t]; }
ret vres;
@ -181,7 +181,7 @@ Returns the first element of a vector
Predicates:
<is_not_empty> (v)
*/
fn head<T>(v: [const T]) : is_not_empty(v) -> T { ret v[0]; }
fn head<copy T>(v: [const T]) : is_not_empty(v) -> T { ret v[0]; }
/*
Function: tail
@ -191,7 +191,7 @@ Returns all but the first element of a vector
Predicates:
<is_not_empty> (v)
*/
fn tail<T>(v: [const T]) : is_not_empty(v) -> [T] {
fn tail<copy T>(v: [const T]) : is_not_empty(v) -> [T] {
ret slice(v, 1u, len(v));
}
@ -206,7 +206,7 @@ Returns all but the last elemnt of a vector
Preconditions:
`v` is not empty
*/
fn init<T>(v: [const T]) -> [T] {
fn init<copy T>(v: [const T]) -> [T] {
assert len(v) != 0u;
slice(v, 0u, len(v) - 1u)
}
@ -221,7 +221,7 @@ Returns:
An option containing the last element of `v` if `v` is not empty, or
none if `v` is empty.
*/
fn last<T>(v: [const T]) -> option::t<T> {
fn last<copy T>(v: [const T]) -> option::t<T> {
if len(v) == 0u { ret none; }
ret some(v[len(v) - 1u]);
}
@ -234,7 +234,7 @@ Returns the last element of a non-empty vector `v`
Predicates:
<is_not_empty> (v)
*/
fn last_total<T>(v: [const T]) : is_not_empty(v) -> T {
fn last_total<copy T>(v: [const T]) : is_not_empty(v) -> T {
ret v[len(v) - 1u];
}
@ -243,7 +243,7 @@ Function: slice
Returns a copy of the elements from [`start`..`end`) from `v`.
*/
fn slice<T>(v: [const T], start: uint, end: uint) -> [T] {
fn slice<copy T>(v: [const T], start: uint, end: uint) -> [T] {
assert (start <= end);
assert (end <= len(v));
let result = [];
@ -259,7 +259,7 @@ Function: slice_mut
Returns a copy of the elements from [`start`..`end`) from `v`.
*/
fn slice_mut<T>(v: [const T], start: uint, end: uint) -> [mutable T] {
fn slice_mut<copy T>(v: [const T], start: uint, end: uint) -> [mutable T] {
assert (start <= end);
assert (end <= len(v));
let result = [mutable];
@ -277,7 +277,7 @@ Function: shift
Removes the first element from a vector and return it
*/
fn shift<T>(&v: [const T]) -> T {
fn shift<copy T>(&v: [const T]) -> T {
let ln = len::<T>(v);
assert (ln > 0u);
let e = v[0];
@ -291,7 +291,7 @@ Function: pop
Remove the last element from a vector and return it
*/
fn pop<T>(&v: [const T]) -> T {
fn pop<copy T>(&v: [const T]) -> T {
let ln = len(v);
assert (ln > 0u);
ln -= 1u;
@ -316,7 +316,7 @@ v - The vector to grow
n - The number of elements to add
initval - The value for the new elements
*/
fn grow<T>(&v: [T], n: uint, initval: T) {
fn grow<copy T>(&v: [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; }
@ -335,7 +335,7 @@ v - The vector to grow
n - The number of elements to add
initval - The value for the new elements
*/
fn grow_mut<T>(&v: [mutable T], n: uint, initval: T) {
fn grow_mut<copy 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 += [mutable initval]; i += 1u; }
@ -371,7 +371,7 @@ Sets the element at position `index` to `val`. If `index` is past the end
of the vector, expands the vector by replicating `initval` to fill the
intervening space.
*/
fn grow_set<T>(&v: [mutable T], index: uint, initval: T, val: T) {
fn grow_set<copy T>(&v: [mutable T], index: uint, initval: T, val: T) {
if index >= len(v) { grow_mut(v, index - len(v) + 1u, initval); }
v[index] = val;
}
@ -384,12 +384,12 @@ Function: map
Apply a function to each element of a vector and return the results
*/
fn map<T, U>(f: block(T) -> U, v: [const T]) -> [U] {
fn map<copy T, U>(f: block(T) -> U, v: [const T]) -> [U] {
let result = [];
reserve(result, len(v));
for elem: T in v {
let elem2 = elem; // satisfies alias checker
result += [f(elem2)];
// copy satisfies alias checker
result += [f(copy elem)];
}
ret result;
}
@ -399,12 +399,12 @@ Function: map2
Apply a function to each pair of elements and return the results
*/
fn map2<T, U, V>(f: block(T, U) -> V, v0: [T], v1: [U]) -> [V] {
let v0_len = len::<T>(v0);
if v0_len != len::<U>(v1) { fail; }
fn map2<copy T, copy U, V>(f: block(T, U) -> V, v0: [T], v1: [U]) -> [V] {
let v0_len = len(v0);
if v0_len != len(v1) { fail; }
let u: [V] = [];
let i = 0u;
while i < v0_len { u += [f({ v0[i] }, { v1[i] })]; i += 1u; }
while i < v0_len { u += [f(copy v0[i], copy v1[i])]; i += 1u; }
ret u;
}
@ -416,11 +416,11 @@ Apply a function to each element of a vector and return the results
If function `f` returns `none` then that element is excluded from
the resulting vector.
*/
fn filter_map<T, U>(f: block(T) -> option::t<U>, v: [const T]) -> [U] {
fn filter_map<copy T, copy U>(f: block(T) -> option::t<U>, v: [const T])
-> [U] {
let result = [];
for elem: T in v {
let elem2 = elem; // satisfies alias checker
alt f(elem2) {
alt f(copy elem) {
none. {/* no-op */ }
some(result_elem) { result += [result_elem]; }
}
@ -437,13 +437,10 @@ holds.
Apply function `f` to each element of `v` and return a vector containing
only those elements for which `f` returned true.
*/
fn filter<T>(f: block(T) -> bool, v: [const T]) -> [T] {
fn filter<copy T>(f: block(T) -> bool, v: [T]) -> [T] {
let result = [];
for elem: T in v {
let elem2 = elem; // satisfies alias checker
if f(elem2) {
result += [elem2];
}
if f(elem) { result += [elem]; }
}
ret result;
}
@ -454,8 +451,7 @@ Function: concat
Concatenate a vector of vectors. Flattens a vector of vectors of T into
a single vector of T.
*/
fn concat<T>(v: [const [const T]]) -> [T] {
// FIXME: So much copying
fn concat<copy T>(v: [const [const T]]) -> [T] {
let new: [T] = [];
for inner: [T] in v { new += inner; }
ret new;
@ -466,7 +462,7 @@ Function: foldl
Reduce a vector from left to right
*/
fn foldl<T, U>(p: block(T, U) -> T, z: T, v: [const U]) -> T {
fn foldl<copy T, U>(p: block(T, U) -> T, z: T, v: [const U]) -> T {
let accum = z;
iter(v) { |elt|
accum = p(accum, elt);
@ -479,7 +475,7 @@ Function: foldr
Reduce a vector from right to left
*/
fn foldr<T, U>(p: block(T, U) -> U, z: U, v: [const T]) -> U {
fn foldr<T, copy U>(p: block(T, U) -> U, z: U, v: [const T]) -> U {
let accum = z;
riter(v) { |elt|
accum = p(elt, accum);
@ -541,7 +537,7 @@ Apply function `f` to each element of `v`, starting from the first.
When function `f` returns true then an option containing the element
is returned. If `f` matches no elements then none is returned.
*/
fn find<T>(f: block(T) -> bool, v: [T]) -> option::t<T> {
fn find<copy T>(f: block(T) -> bool, v: [T]) -> option::t<T> {
for elt: T in v { if f(elt) { ret some(elt); } }
ret none;
}
@ -587,7 +583,7 @@ vector contains the first element of the i-th tuple of the input vector,
and the i-th element of the second vector contains the second element
of the i-th tuple of the input vector.
*/
fn unzip<T, U>(v: [(T, U)]) -> ([T], [U]) {
fn unzip<copy T, copy U>(v: [(T, U)]) -> ([T], [U]) {
let as = [], bs = [];
for (a, b) in v { as += [a]; bs += [b]; }
ret (as, bs);
@ -605,7 +601,7 @@ Preconditions:
<same_length> (v, u)
*/
fn zip<T, U>(v: [T], u: [U]) : same_length(v, u) -> [(T, U)] {
fn zip<copy T, copy U>(v: [T], u: [U]) : same_length(v, u) -> [(T, U)] {
let zipped = [];
let sz = len(v), i = 0u;
assert (sz == len(u));
@ -624,9 +620,7 @@ a - The index of the first element
b - The index of the second element
*/
fn swap<T>(v: [mutable T], a: uint, b: uint) {
let t: T = v[a];
v[a] = v[b];
v[b] = t;
v[a] <-> v[b];
}
/*
@ -637,7 +631,7 @@ Reverse the order of elements in a vector, in place
fn reverse<T>(v: [mutable T]) {
let i: uint = 0u;
let ln = len::<T>(v);
while i < ln / 2u { swap(v, i, ln - i - 1u); i += 1u; }
while i < ln / 2u { v[i] <-> v[ln - i - 1u]; i += 1u; }
}
@ -646,7 +640,7 @@ Function: reversed
Returns a vector with the order of elements reversed
*/
fn reversed<T>(v: [const T]) -> [T] {
fn reversed<copy T>(v: [const T]) -> [T] {
let rs: [T] = [];
let i = len::<T>(v);
if i == 0u { ret rs; } else { i -= 1u; }
@ -746,7 +740,7 @@ is sorted then the permutations are lexicographically sorted).
The total number of permutations produced is `len(v)!`. If `v` contains
repeated elements, then some permutations are repeated.
*/
fn permute<T>(v: [const T], put: block([T])) {
fn permute<copy T>(v: [const T], put: block([T])) {
let ln = len(v);
if ln == 0u {
put([]);

View File

@ -55,25 +55,25 @@ mod map_reduce {
export reducer;
export map_reduce;
type putter<uniq K, uniq V> = fn(K, V);
type putter<send K, send V> = fn(K, V);
// FIXME: the first K1 parameter should probably be a -, but that
// doesn't parse at the moment.
type mapper<uniq K1, uniq K2, uniq V> = fn(K1, putter<K2, V>);
type mapper<send K1, send K2, send V> = fn(K1, putter<K2, V>);
type getter<uniq V> = fn() -> option<V>;
type getter<send V> = fn() -> option<V>;
type reducer<uniq K, uniq V> = fn(K, getter<V>);
type reducer<send K, send V> = fn(K, getter<V>);
tag ctrl_proto<uniq K, uniq V> {
tag ctrl_proto<send K, send V> {
find_reducer(K, chan<chan<reduce_proto<V>>>);
mapper_done;
}
tag reduce_proto<uniq V> { emit_val(V); done; ref; release; }
tag reduce_proto<send V> { emit_val(V); done; ref; release; }
fn start_mappers<uniq K1, uniq K2,
uniq V>(map: mapper<K1, K2, V>,
fn start_mappers<send K1, send K2,
send V>(map: mapper<K1, K2, V>,
ctrl: chan<ctrl_proto<K2, V>>, inputs: [K1]) ->
[joinable_task] {
let tasks = [];
@ -84,15 +84,15 @@ mod map_reduce {
ret tasks;
}
fn map_task<uniq K1, uniq K2,
uniq V>(-map: mapper<K1, K2, V>,
fn map_task<send K1, send K2,
send V>(-map: mapper<K1, K2, V>,
-ctrl: chan<ctrl_proto<K2, V>>,
-input: K1) {
// log_err "map_task " + input;
let intermediates = treemap::init();
fn emit<uniq K2,
uniq V>(im: treemap::treemap<K2, chan<reduce_proto<V>>>,
fn emit<send K2,
send V>(im: treemap::treemap<K2, chan<reduce_proto<V>>>,
ctrl: chan<ctrl_proto<K2, V>>, key: K2, val: V) {
let c;
alt treemap::find(im, key) {
@ -110,15 +110,15 @@ mod map_reduce {
map(input, bind emit(intermediates, ctrl, _, _));
fn finish<uniq K, uniq V>(_k: K, v: chan<reduce_proto<V>>) {
fn finish<send K, send V>(_k: K, v: chan<reduce_proto<V>>) {
send(v, release);
}
treemap::traverse(intermediates, finish);
send(ctrl, mapper_done);
}
fn reduce_task<uniq K,
uniq V>(-reduce: reducer<K, V>, -key: K,
fn reduce_task<send K,
send V>(-reduce: reducer<K, V>, -key: K,
-out: chan<chan<reduce_proto<V>>>) {
let p = port();
@ -127,7 +127,7 @@ mod map_reduce {
let ref_count = 0;
let is_done = false;
fn get<uniq V>(p: port<reduce_proto<V>>,
fn get<send V>(p: port<reduce_proto<V>>,
&ref_count: int, &is_done: bool)
-> option<V> {
while !is_done || ref_count > 0 {
@ -150,8 +150,8 @@ mod map_reduce {
reduce(key, bind get(p, ref_count, is_done));
}
fn map_reduce<uniq K1, uniq K2,
uniq V>(map: mapper<K1, K2, V>, reduce: reducer<K2, V>,
fn map_reduce<send K1, send K2,
send V>(map: mapper<K1, K2, V>, reduce: reducer<K2, V>,
inputs: [K1]) {
let ctrl = port();
@ -194,7 +194,7 @@ mod map_reduce {
}
}
fn finish<uniq K, uniq V>(_k: K, v: chan<reduce_proto<V>>) {
fn finish<send K, send V>(_k: K, v: chan<reduce_proto<V>>) {
send(v, done);
}
treemap::traverse(reducers, finish);

View File

@ -1,5 +1,4 @@
// error-pattern: needed shared type, got pinned type block
// xfail-test
// error-pattern: copying a noncopyable value
fn lol(f: block()) -> block() { ret f; }
fn main() { let i = 8; let f = lol(block () { log_err i; }); f(); }

View File

@ -1,6 +1,5 @@
// error-pattern:cannot copy pinned type foo
// xfail-test
// error-pattern: copying a noncopyable value
resource foo(i: int) { }
fn main() { let x <- foo(10); let y = x; }
fn main() { let x <- foo(10); let y = x; log_err x; }

View File

@ -1,16 +0,0 @@
// error-pattern:mismatched kinds for '@' operand
// xfail-test
resource r(i: @mutable int) {
*i = *i + 1;
}
fn main() {
let i = @mutable 0;
{
let j <- r(i);
// No no no no no
let k <- @j;
}
log_err *i;
assert *i == 2;
}

View File

@ -1,16 +0,0 @@
// error-pattern:mismatched kinds for record field
// xfail-test
resource r(i: @mutable int) {
*i = *i + 1;
}
fn main() {
let i = @mutable 0;
{
let j <- r(i);
// No no no no no
let k <- {x: j};
}
log_err *i;
assert *i == 2;
}

View File

@ -1,16 +0,0 @@
// error-pattern:mismatched kinds for tuple parameter
// xfail-test
resource r(i: @mutable int) {
*i = *i + 1;
}
fn main() {
let i = @mutable 0;
{
let j <- r(i);
// No no no no no
let k <- (j, 0);
}
log_err *i;
assert *i == 2;
}

View File

@ -1,16 +0,0 @@
// error-pattern:mismatched kinds for '~' operand
// xfail-test
resource r(i: @mutable int) {
*i = *i + 1;
}
fn main() {
let i = @mutable 0;
{
let j <- r(i);
// No no no no no
let k <- ~j;
}
log_err *i;
assert *i == 2;
}

View File

@ -1,4 +1,4 @@
// error-pattern:expected fn() but found fn(+int)
// error-pattern:expected fn() but found fn(++int)
fn main() {
fn f() { }

View File

@ -1,4 +1,4 @@
// error-pattern:can not pass a dynamically-sized type by value
fn f<T>(+_x: T) {}
fn f<T>(++_x: T) {}
fn main() {}

View File

@ -1,5 +1,4 @@
// error-pattern: cannot copy pinned type ~~~{y: r}
// xfail-test
// error-pattern: copying a noncopyable value
resource r(i: @mutable int) {
*i = *i + 1;
@ -11,6 +10,7 @@ fn main() {
// Can't do this copy
let x = ~~~{y: r(i)};
let z = x;
log x;
}
log_err *i;
}

View File

@ -1,10 +0,0 @@
// error-pattern: mismatched kind
// xfail-test
resource r(b: bool) {
}
fn main() {
let i <- r(true);
let j = i;
}

View File

@ -1,11 +1,10 @@
// error-pattern: mismatched kind
// xfail-test
// error-pattern: copying a noncopyable value
resource r(b: bool) {
}
fn main() {
let i <- ~r(true);
let j;
j = i;
let j = i;
log i;
}

View File

@ -1,37 +0,0 @@
// error-pattern:needed shared type, got pinned type ~r
// xfail-test
resource r(i: @mutable int) {
*i += 1;
}
fn test1() {
let i = @mutable 100;
let j = @mutable 200;
{
let x <- ~r(i);
let y <- ~r(j);
// This is currently not allowed because ~resource is pinned.
// Note that ~resource is supposed to be shared.
x <-> y;
assert ***x == 200;
assert ***y == 100;
}
assert *i == 101;
assert *j == 201;
}
fn test2() {
let i = @mutable 0;
{
let x <- ~r(i);
let y <- ~r(i);
x <-> y;
}
assert *i == 2;
}
fn main() {
test1();
test2();
}

View File

@ -1,7 +1,6 @@
// error-pattern: needed unique type
// xfail-test
// error-pattern: instantiating a sendable type parameter with a copyable type
fn f<uniq T>(i: T) {
fn f<send T>(i: T) {
}
fn main() {

View File

@ -1,12 +1,10 @@
// error-pattern: needed shared type, got pinned type ~r
// xfail-test
// error-pattern: copying a noncopyable value
resource r(i: @mutable int) {
*i = *i + 1;
}
fn f<T>(i: [T], j: [T]) {
// Shouldn't be able to do this copy of j
fn f<T>(+i: [T], +j: [T]) {
let k = i + j;
}
@ -16,6 +14,6 @@ fn main() {
let r1 <- [~r(i1)];
let r2 <- [~r(i2)];
f(r1, r2);
log_err *i1;
log_err *i2;
log (r2, *i1);
log (r1, *i2);
}

View File

@ -1,5 +1,5 @@
// error-pattern: Unsatisfied precondition constraint
fn send<uniq T>(ch: _chan<T>, -data: T) { log ch; log data; fail; }
fn send<send T>(ch: _chan<T>, -data: T) { log ch; log data; fail; }
type _chan<T> = int;
// Tests that "log message;" is flagged as using

View File

@ -1,10 +0,0 @@
// error-pattern: mismatched kind
// xfail-test
resource r(b: bool) {
}
fn main() {
let i <- [r(true)];
i += [r(true)];
}

View File

@ -1,11 +0,0 @@
// error-pattern: mismatched kind
// xfail-test
resource r(b: bool) {
}
fn main() {
let i <- [r(true)];
let j;
j <- copy [r(true)];
}

View File

@ -1,11 +0,0 @@
// error-pattern: mismatched kind
// xfail-test
resource r(b: bool) {
}
fn main() {
let i <- [r(true)];
let j;
j = i;
}

View File

@ -1,12 +1,11 @@
// error-pattern:mismatched kinds
// xfail-test
// error-pattern: copying a noncopyable value
resource r(i: int) {
}
resource r(_i: int) { }
fn main() {
// This can't make sense as it would copy the resources
let i <- [r(0)];
let j <- [r(1)];
let k = i + j;
}
log j;
}

View File

@ -4,8 +4,8 @@ fn test00_start(ch: chan_t<int>, message: int) { send(ch, copy message); }
type task_id = int;
type port_id = int;
type chan_t<uniq T> = {task: task_id, port: port_id};
type chan_t<send T> = {task: task_id, port: port_id};
fn send<uniq T>(ch: chan_t<T>, -data: T) { fail; }
fn send<send T>(ch: chan_t<T>, -data: T) { fail; }
fn main() { fail "quux"; }

View File

@ -5,7 +5,7 @@ import std::comm::port;
import std::comm::send;
import std::comm::recv;
fn echo<uniq T>(c: chan<T>, oc: chan<chan<T>>) {
fn echo<send T>(c: chan<T>, oc: chan<chan<T>>) {
// Tests that the type argument in port gets
// visited
let p = port::<T>();

View File

@ -2,6 +2,6 @@
// -*- rust -*-
fn f<T, U>(x: T, y: U) -> {a: T, b: U} { ret {a: x, b: y}; }
fn f<copy T, copy U>(x: T, y: U) -> {a: T, b: U} { ret {a: x, b: y}; }
fn main() { log f({x: 3, y: 4, z: 5}, 4).a.x; log f(5, 6).a; }

View File

@ -1,4 +1,4 @@
fn wrapper3<T>(i: T, j: int) {
fn wrapper3<copy T>(i: T, j: int) {
log i;
log j;
// This is a regression test that the spawn3 thunk to wrapper3
@ -6,7 +6,7 @@ fn wrapper3<T>(i: T, j: int) {
assert j == 123456789;
}
fn spawn3<T>(i: T, j: int) {
fn spawn3<copy T>(i: T, j: int) {
let wrapped = bind wrapper3(i, j);
wrapped();
}

View File

@ -1,8 +1,8 @@
type box<T> = {c: @T};
type box<copy T> = {c: @T};
fn unbox<T>(b: box<T>) -> T { ret *b.c; }
fn unbox<copy T>(b: box<T>) -> T { ret *b.c; }
fn main() {
let foo: int = 17;

View File

@ -4,7 +4,7 @@
// -*- rust -*-
type compare<T> = fn@(T, T) -> bool;
fn test_generic<T>(expected: T, eq: compare<T>) {
fn test_generic<copy T>(expected: T, eq: compare<T>) {
let actual: T = { expected };
assert (eq(expected, actual));
}

View File

@ -3,7 +3,7 @@
// -*- rust -*-
type compare<T> = fn@(~T, ~T) -> bool;
fn test_generic<T>(expected: ~T, eq: compare<T>) {
fn test_generic<copy T>(expected: ~T, eq: compare<T>) {
let actual: ~T = { expected };
assert (eq(expected, actual));
}

View File

@ -4,7 +4,7 @@
// -*- rust -*-
type compare<T> = fn@(T, T) -> bool;
fn test_generic<T>(expected: T, eq: compare<T>) {
fn test_generic<copy T>(expected: T, eq: compare<T>) {
let actual: T = { expected };
assert (eq(expected, actual));
}

View File

@ -6,7 +6,7 @@
// Tests for standalone blocks as expressions with dynamic type sizes
type compare<T> = fn@(T, T) -> bool;
fn test_generic<T>(expected: T, eq: compare<T>) {
fn test_generic<copy T>(expected: T, eq: compare<T>) {
let actual: T = { expected };
assert (eq(expected, actual));
}

View File

@ -4,7 +4,7 @@
// -*- rust -*-
type compare<T> = fn@(T, T) -> bool;
fn test_generic<T>(expected: T, not_expected: T, eq: compare<T>) {
fn test_generic<copy T>(expected: T, not_expected: T, eq: compare<T>) {
let actual: T = if true { expected } else { not_expected };
assert (eq(expected, actual));
}

View File

@ -6,7 +6,7 @@
// Tests for if as expressions with dynamic type sizes
type compare<T> = fn@(T, T) -> bool;
fn test_generic<T>(expected: T, not_expected: T, eq: compare<T>) {
fn test_generic<copy T>(expected: T, not_expected: T, eq: compare<T>) {
let actual: T = if true { expected } else { not_expected };
assert (eq(expected, actual));
}

View File

@ -1,8 +1,8 @@
fn fix_help<A, uniq B>(f: fn(fn@(A) -> B, A) -> B, x: A) -> B {
fn fix_help<A, send B>(f: fn(fn@(A) -> B, A) -> B, x: A) -> B {
ret f(bind fix_help(f, _), x);
}
fn fix<A, uniq B>(f: fn(fn@(A) -> B, A) -> B) -> fn@(A) -> B {
fn fix<A, send B>(f: fn(fn@(A) -> B, A) -> B) -> fn@(A) -> B {
ret bind fix_help(f, _);
}

View File

@ -1,6 +1,6 @@
// This is what the signature to spawn should look like with bare functions
fn spawn<uniq T>(val: T, f: fn(T)) {
fn spawn<send T>(val: T, f: fn(T)) {
f(val);
}

View File

@ -1,5 +1,5 @@
obj ob<shar K>(k: K) {
obj ob<copy K>(k: K) {
fn foo(it: block(~{a: K})) { it(~{a: k}); }
}

View File

@ -1,6 +1,6 @@
fn id<T>(t: T) -> T { ret t; }
fn id<copy T>(t: T) -> T { ret t; }
fn main() {
let expected = @100;

View File

@ -1,6 +1,6 @@
fn id<uniq T>(t: T) -> T { ret t; }
fn id<send T>(t: T) -> T { ret t; }
fn main() {
let expected = ~100;

View File

@ -1,6 +1,6 @@
fn id<T>(t: T) -> T { ret t; }
fn id<copy T>(t: T) -> T { ret t; }
fn main() {
let t = {a: 1, b: 2, c: 3, d: 4, e: 5, f: 6, g: 7};

View File

@ -1,6 +1,6 @@
fn id<T>(t: T) -> T { ret t; }
fn id<copy T>(t: T) -> T { ret t; }
fn main() {
let t = {_0: 1, _1: 2, _2: 3, _3: 4, _4: 5, _5: 6, _6: 7};

View File

@ -1,6 +1,6 @@
fn box<T>(x: {x: T, y: T, z: T}) -> @{x: T, y: T, z: T} { ret @x; }
fn box<copy T>(x: {x: T, y: T, z: T}) -> @{x: T, y: T, z: T} { ret @x; }
fn main() {
let x: @{x: int, y: int, z: int} = box::<int>({x: 1, y: 2, z: 3});

View File

@ -1,8 +1,8 @@
fn g<X>(x: X) -> X { ret x; }
fn g<copy X>(x: X) -> X { ret x; }
fn f<T>(t: T) -> {a: T, b: T} {
fn f<copy T>(t: T) -> {a: T, b: T} {
type pair = {a: T, b: T};
let x: pair = {a: t, b: t};

View File

@ -1,5 +1,5 @@
fn f<T>(t: T) { let t1: T = t; }
fn f<copy T>(t: T) { let t1: T = t; }
fn main() { let x = {x: @10, y: @12}; f(x); }

View File

@ -1,8 +1,8 @@
type recbox<T> = {x: @T};
type recbox<copy T> = {x: @T};
fn reclift<T>(t: T) -> recbox<T> { ret {x: @t}; }
fn reclift<copy T>(t: T) -> recbox<T> { ret {x: @t}; }
fn main() {
let foo: int = 17;

View File

@ -1,6 +1,6 @@
type recbox<T> = {x: ~T};
type recbox<copy T> = {x: ~T};
fn reclift<T>(t: T) -> recbox<T> { ret {x: ~t}; }
fn reclift<copy T>(t: T) -> recbox<T> { ret {x: ~t}; }
fn main() {
let foo: int = 17;

View File

@ -4,6 +4,6 @@
// -*- rust -*-
// Issue #45: infer type parameters in function applications
fn id<T>(x: T) -> T { ret x; }
fn id<copy T>(x: T) -> T { ret x; }
fn main() { let x: int = 42; let y: int = id(x); assert (x == y); }

View File

@ -1,4 +1,4 @@
fn f<T>(x: ~T) -> ~T { ret x; }
fn f<copy T>(x: ~T) -> ~T { ret x; }
fn main() { let x = f(~3); log *x; }

View File

@ -2,7 +2,7 @@
// -*- rust -*-
fn id<T>(x: T) -> T { ret x; }
fn id<copy T>(x: T) -> T { ret x; }
type triple = {x: int, y: int, z: int};

View File

@ -1,6 +1,6 @@
obj handle<shar T>(data: T) {
obj handle<copy T>(data: T) {
fn get() -> T { ret data; }
}

View File

@ -1,6 +1,6 @@
obj buf<shar T>(data: {_0: T, _1: T, _2: T}) {
obj buf<copy T>(data: {_0: T, _1: T, _2: T}) {
fn get(i: int) -> T {
if i == 0 {
ret data._0;

View File

@ -1,4 +1,4 @@
fn get_third<T>(t: (T, T, T)) -> T { let (_, _, x) = t; ret x; }
fn get_third<copy T>(t: (T, T, T)) -> T { let (_, _, x) = t; ret x; }
fn main() {
log get_third((1, 2, 3));

View File

@ -1,5 +1,5 @@
fn box<T>(x: {x: T, y: T, z: T}) -> ~{x: T, y: T, z: T} { ret ~x; }
fn box<copy T>(x: {x: T, y: T, z: T}) -> ~{x: T, y: T, z: T} { ret ~x; }
fn main() {
let x: ~{x: int, y: int, z: int} = box::<int>({x: 1, y: 2, z: 3});

View File

@ -1,5 +1,5 @@
fn quux<T>(x: T) -> T { let f = bind id::<T>(_); ret f(x); }
fn quux<copy T>(x: T) -> T { let f = bind id::<T>(_); ret f(x); }
fn id<T>(x: T) -> T { ret x; }
fn id<copy T>(x: T) -> T { ret x; }
fn main() { assert (quux(10) == 10); }

View File

@ -1,4 +1,4 @@
fn double<T>(a: T) -> [T] { ret [a] + [a]; }
fn double<copy T>(a: T) -> [T] { ret [a] + [a]; }
fn double_int(a: int) -> [int] { ret [a] + [a]; }

View File

@ -1,8 +1,8 @@
tag myvec<X> = [X];
fn myvec_deref<X>(mv: myvec<X>) -> [X] { ret *mv; }
fn myvec_deref<copy X>(mv: myvec<X>) -> [X] { ret *mv; }
fn myvec_elt<X>(mv: myvec<X>) -> X { ret mv[0]; }
fn myvec_elt<copy X>(mv: myvec<X>) -> X { ret mv[0]; }
fn main() {
let mv = myvec([1, 2, 3]);

View File

@ -2,19 +2,19 @@ use std;
import std::list::*;
pure fn pure_length_go<T>(ls: list<T>, acc: uint) -> uint {
pure fn pure_length_go<copy T>(ls: list<T>, acc: uint) -> uint {
alt ls { nil. { acc } cons(_, tl) { pure_length_go(*tl, acc + 1u) } }
}
pure fn pure_length<T>(ls: list<T>) -> uint { pure_length_go(ls, 0u) }
pure fn pure_length<copy T>(ls: list<T>) -> uint { pure_length_go(ls, 0u) }
pure fn nonempty_list<T>(ls: list<T>) -> bool { pure_length(ls) > 0u }
pure fn nonempty_list<copy T>(ls: list<T>) -> bool { pure_length(ls) > 0u }
// Of course, the compiler can't take advantage of the
// knowledge that ls is a cons node. Future work.
// Also, this is pretty contrived since nonempty_list
// could be a "tag refinement", if we implement those.
fn safe_head<T>(ls: list<T>) : nonempty_list(ls) -> T { head(ls) }
fn safe_head<copy T>(ls: list<T>) : nonempty_list(ls) -> T { head(ls) }
fn main() {
let mylist = cons(@1u, @nil);

View File

@ -6,7 +6,7 @@ tag clam<T> { signed(int); unsigned(uint); }
fn getclam<T>() -> clam<T> { ret signed::<T>(42); }
obj impatience<shar T>() {
obj impatience<copy T>() {
fn moreclam() -> clam<T> { be getclam::<T>(); }
}

View File

@ -5,7 +5,7 @@ type closable = @mutable bool;
resource close_res(i: closable) { *i = false; }
tag option<pin T> { none; some(T); }
tag option<T> { none; some(T); }
fn sink(res: option<close_res>) { }

View File

@ -2,6 +2,6 @@
tag option<T> { none; some(T); }
fn f<T>() -> option<T> { ret none; }
fn f<copy T>() -> option<T> { ret none; }
fn main() { f::<int>(); }

View File

@ -4,9 +4,9 @@ import std::comm::send;
import std::comm::port;
// tests that ctrl's type gets inferred properly
type command<uniq K, uniq V> = {key: K, val: V};
type command<send K, send V> = {key: K, val: V};
fn cache_server<uniq K, uniq V>(c: chan<chan<command<K, V>>>) {
fn cache_server<send K, send V>(c: chan<chan<command<K, V>>>) {
let ctrl = port();
send(c, chan(ctrl));
}

View File

@ -1,6 +1,6 @@
fn p_foo<pin T>(pinned: T) { }
fn s_foo<T>(shared: T) { }
fn u_foo<uniq T>(unique: T) { }
fn p_foo<T>(pinned: T) { }
fn s_foo<copy T>(shared: T) { }
fn u_foo<send T>(unique: T) { }
resource r(i: int) { }

View File

@ -5,24 +5,24 @@ import std::list::*;
// Can't easily be written as a "pure fn" because there's
// no syntax for specifying that f is pure.
fn pure_foldl<T, U>(ls: list<T>, u: U, f: block(T, U) -> U) -> U {
fn pure_foldl<copy T, copy U>(ls: list<T>, u: U, f: block(T, U) -> U) -> U {
alt ls { nil. { u } cons(hd, tl) { f(hd, pure_foldl(*tl, f(hd, u), f)) } }
}
// Shows how to use an "unchecked" block to call a general
// fn from a pure fn
pure fn pure_length<T>(ls: list<T>) -> uint {
pure fn pure_length<copy T>(ls: list<T>) -> uint {
fn count<T>(_t: T, &&u: uint) -> uint { u + 1u }
unchecked{ pure_foldl(ls, 0u, bind count(_, _)) }
}
pure fn nonempty_list<T>(ls: list<T>) -> bool { pure_length(ls) > 0u }
pure fn nonempty_list<copy T>(ls: list<T>) -> bool { pure_length(ls) > 0u }
// Of course, the compiler can't take advantage of the
// knowledge that ls is a cons node. Future work.
// Also, this is pretty contrived since nonempty_list
// could be a "tag refinement", if we implement those.
fn safe_head<T>(ls: list<T>) : nonempty_list(ls) -> T { head(ls) }
fn safe_head<copy T>(ls: list<T>) : nonempty_list(ls) -> T { head(ls) }
fn main() {
let mylist = cons(@1u, @nil);

View File

@ -1,4 +1,4 @@
fn f<T>(t: T) -> T {
fn f<copy T>(t: T) -> T {
let t1 = t;
t1
}

View File

@ -1,6 +1,6 @@
// Issue #976
fn f<T>(x: ~T) {
fn f<copy T>(x: ~T) {
let _x2 = x;
}
fn main() { }

View File

@ -1,10 +1,10 @@
fn unique() {
fn sendable() {
fn f<uniq T>(i: T, j: T) {
fn f<send T>(i: T, j: T) {
assert i == j;
}
fn g<uniq T>(i: T, j: T) {
fn g<send T>(i: T, j: T) {
assert i != j;
}
@ -16,7 +16,25 @@ fn unique() {
g(i, j);
}
fn shared() {
fn copyable() {
fn f<copy T>(i: T, j: T) {
assert i == j;
}
fn g<copy T>(i: T, j: T) {
assert i != j;
}
let i = ~100;
let j = ~100;
f(i, j);
let i = ~100;
let j = ~101;
g(i, j);
}
fn noncopyable() {
fn f<T>(i: T, j: T) {
assert i == j;
@ -34,26 +52,8 @@ fn shared() {
g(i, j);
}
fn pinned() {
fn f<pin T>(i: T, j: T) {
assert i == j;
}
fn g<pin T>(i: T, j: T) {
assert i != j;
}
let i = ~100;
let j = ~100;
f(i, j);
let i = ~100;
let j = ~101;
g(i, j);
}
fn main() {
unique();
shared();
pinned();
}
sendable();
copyable();
noncopyable();
}

View File

@ -1,5 +1,5 @@
fn push<T>(&v: [const T], t: T) { v += [t]; }
fn push<copy T>(&v: [const T], t: T) { v += [t]; }
fn main() { let v = [1, 2, 3]; push(v, 1); }

View File

@ -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<copy 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);

View File

@ -68,7 +68,7 @@ fn test_join_convenient() {
#[ignore]
fn spawn_polymorphic() {
// FIXME #1038: Can't spawn palymorphic functions
/*fn foo<uniq T>(x: T) { log_err x; }
/*fn foo<send T>(x: T) { log_err x; }
task::spawn(true, foo);
task::spawn(42, foo);*/