Merge branch 'master' into kmath

Conflicts:
	src/libcore/float.rs
This commit is contained in:
Stefan Plantikow 2012-01-05 17:18:40 +01:00
commit c8467977c4
93 changed files with 401 additions and 445 deletions

View File

@ -114,7 +114,7 @@ fn time<T>(do_it: bool, what: str, thunk: fn@() -> T) -> T {
fn inject_libcore_reference(sess: session::session, fn inject_libcore_reference(sess: session::session,
crate: @ast::crate) -> @ast::crate { crate: @ast::crate) -> @ast::crate {
fn spanned<copy T>(x: T) -> @ast::spanned<T> { fn spanned<T: copy>(x: T) -> @ast::spanned<T> {
ret @{node: x, ret @{node: x,
span: {lo: 0u, hi: 0u, span: {lo: 0u, hi: 0u,
expanded_from: codemap::os_none}}; expanded_from: codemap::os_none}};

View File

@ -221,7 +221,7 @@ fn native_abi(attrs: [ast::attribute]) -> either::t<str, ast::native_abi> {
}; };
} }
fn span<copy T>(item: T) -> ast::spanned<T> { fn span<T: copy>(item: T) -> ast::spanned<T> {
ret {node: item, span: ast_util::dummy_sp()}; ret {node: item, span: ast_util::dummy_sp()};
} }

View File

@ -182,7 +182,7 @@ fn mk_test_module(cx: test_ctxt) -> @ast::item {
ret @item; ret @item;
} }
fn nospan<copy T>(t: T) -> ast::spanned<T> { fn nospan<T: copy>(t: T) -> ast::spanned<T> {
ret {node: t, span: dummy_sp()}; ret {node: t, span: dummy_sp()};
} }

View File

@ -260,7 +260,8 @@ fn resolve_crate(e: env, ident: ast::ident, metas: [@ast::meta_item],
// Now resolve the crates referenced by this crate // Now resolve the crates referenced by this crate
let cnum_map = resolve_crate_deps(e, cdata); let cnum_map = resolve_crate_deps(e, cdata);
let cmeta = {name: ident, data: cdata, cnum_map: cnum_map}; let cmeta = @{name: ident, data: cdata,
cnum_map: cnum_map, cnum: cnum};
let cstore = e.sess.get_cstore(); let cstore = e.sess.get_cstore();
cstore::set_crate_data(cstore, cnum, cmeta); cstore::set_crate_data(cstore, cnum, cmeta);

View File

@ -58,32 +58,27 @@ fn resolve_path(cstore: cstore::cstore, cnum: ast::crate_num,
fn get_tag_variants(tcx: ty::ctxt, def: ast::def_id) -> [ty::variant_info] { fn get_tag_variants(tcx: ty::ctxt, def: ast::def_id) -> [ty::variant_info] {
let cstore = tcx.sess.get_cstore(); let cstore = tcx.sess.get_cstore();
let cnum = def.crate; let cdata = cstore::get_crate_data(cstore, def.crate);
let cdata = cstore::get_crate_data(cstore, cnum).data; ret decoder::get_tag_variants(cdata, def.node, tcx)
let resolver = bind translate_def_id(cstore, cnum, _);
ret decoder::get_tag_variants(cdata, def, tcx, resolver)
} }
fn get_impls_for_mod(cstore: cstore::cstore, def: ast::def_id, fn get_impls_for_mod(cstore: cstore::cstore, def: ast::def_id,
name: option::t<ast::ident>) name: option::t<ast::ident>)
-> @[@middle::resolve::_impl] { -> @[@middle::resolve::_impl] {
let cdata = cstore::get_crate_data(cstore, def.crate).data; let cdata = cstore::get_crate_data(cstore, def.crate);
let resolver = bind translate_def_id(cstore, def.crate, _); decoder::get_impls_for_mod(cdata, def.node, name)
decoder::get_impls_for_mod(cdata, def, name, resolver)
} }
fn get_iface_methods(tcx: ty::ctxt, def: ast::def_id) -> @[ty::method] { fn get_iface_methods(tcx: ty::ctxt, def: ast::def_id) -> @[ty::method] {
let cstore = tcx.sess.get_cstore(); let cstore = tcx.sess.get_cstore();
let cdata = cstore::get_crate_data(cstore, def.crate).data; let cdata = cstore::get_crate_data(cstore, def.crate);
let resolver = bind translate_def_id(cstore, def.crate, _); decoder::get_iface_methods(cdata, def.node, tcx)
decoder::get_iface_methods(cdata, def, tcx, resolver)
} }
fn get_type(tcx: ty::ctxt, def: ast::def_id) -> ty::ty_param_bounds_and_ty { fn get_type(tcx: ty::ctxt, def: ast::def_id) -> ty::ty_param_bounds_and_ty {
let cstore = tcx.sess.get_cstore(); let cstore = tcx.sess.get_cstore();
let cdata = cstore::get_crate_data(cstore, def.crate).data; let cdata = cstore::get_crate_data(cstore, def.crate);
let resolver = bind translate_def_id(cstore, def.crate, _); decoder::get_type(cdata, def.node, tcx)
decoder::get_type(cdata, def, tcx, resolver)
} }
fn get_item_name(cstore: cstore::cstore, cnum: int, id: int) -> ast::ident { fn get_item_name(cstore: cstore::cstore, cnum: int, id: int) -> ast::ident {
@ -94,34 +89,8 @@ fn get_item_name(cstore: cstore::cstore, cnum: int, id: int) -> ast::ident {
fn get_impl_iface(tcx: ty::ctxt, def: ast::def_id) fn get_impl_iface(tcx: ty::ctxt, def: ast::def_id)
-> option::t<ty::t> { -> option::t<ty::t> {
let cstore = tcx.sess.get_cstore(); let cstore = tcx.sess.get_cstore();
let cdata = cstore::get_crate_data(cstore, def.crate).data; let cdata = cstore::get_crate_data(cstore, def.crate);
let resolver = bind translate_def_id(cstore, def.crate, _); decoder::get_impl_iface(cdata, def.node, tcx)
decoder::get_impl_iface(cdata, def, tcx, resolver)
}
// Translates a def_id from an external crate to a def_id for the current
// compilation environment. We use this when trying to load types from
// external crates - if those types further refer to types in other crates
// then we must translate the crate number from that encoded in the external
// crate to the correct local crate number.
fn translate_def_id(cstore: cstore::cstore, searched_crate: ast::crate_num,
def_id: ast::def_id) -> ast::def_id {
let ext_cnum = def_id.crate;
let node_id = def_id.node;
assert (searched_crate != ast::local_crate);
assert (ext_cnum != ast::local_crate);
let cmeta = cstore::get_crate_data(cstore, searched_crate);
let local_cnum =
alt cmeta.cnum_map.find(ext_cnum) {
option::some(n) { n }
option::none. { fail "didn't find a crate in the cnum_map"; }
};
ret {crate: local_cnum, node: node_id};
} }
// Local Variables: // Local Variables:

View File

@ -30,7 +30,10 @@ export get_dep_hashes;
// own crate numbers. // own crate numbers.
type cnum_map = map::hashmap<ast::crate_num, ast::crate_num>; type cnum_map = map::hashmap<ast::crate_num, ast::crate_num>;
type crate_metadata = {name: str, data: @[u8], cnum_map: cnum_map}; type crate_metadata = @{name: str,
data: @[u8],
cnum_map: cnum_map,
cnum: ast::crate_num};
// This is a bit of an experiment at encapsulating the data in cstore. By // This is a bit of an experiment at encapsulating the data in cstore. By
// keeping all the data in a non-exported tag variant, it's impossible for // keeping all the data in a non-exported tag variant, it's impossible for

View File

@ -1,14 +1,13 @@
// Decoding metadata from a single crate's metadata // Decoding metadata from a single crate's metadata
import core::{vec, option, str};
import std::{ebml, io}; import std::{ebml, io};
import syntax::{ast, ast_util}; import syntax::{ast, ast_util};
import front::attr; import front::attr;
import middle::ty; import middle::ty;
import common::*; import common::*;
import tydecode::{parse_def_id, parse_ty_data}; import tydecode::{parse_ty_data, parse_def_id, parse_bounds_data};
import syntax::print::pprust; import syntax::print::pprust;
import cstore; import cmd=cstore::crate_metadata;
export get_symbol; export get_symbol;
export get_tag_variants; export get_tag_variants;
@ -24,7 +23,6 @@ export list_crate_metadata;
export crate_dep; export crate_dep;
export get_crate_deps; export get_crate_deps;
export get_crate_hash; export get_crate_hash;
export external_resolver;
export get_impls_for_mod; export get_impls_for_mod;
export get_iface_methods; export get_iface_methods;
// A function that takes a def_id relative to the crate being searched and // A function that takes a def_id relative to the crate being searched and
@ -32,7 +30,6 @@ export get_iface_methods;
// def_id for an item defined in another crate, somebody needs to figure out // def_id for an item defined in another crate, somebody needs to figure out
// what crate that's in and give us a def_id that makes sense for the current // what crate that's in and give us a def_id that makes sense for the current
// build. // build.
type external_resolver = fn@(ast::def_id) -> ast::def_id;
fn lookup_hash(d: ebml::doc, eq_fn: fn@([u8]) -> bool, hash: uint) -> fn lookup_hash(d: ebml::doc, eq_fn: fn@([u8]) -> bool, hash: uint) ->
[ebml::doc] { [ebml::doc] {
@ -91,66 +88,50 @@ fn variant_tag_id(d: ebml::doc) -> ast::def_id {
ret parse_def_id(ebml::doc_data(tagdoc)); ret parse_def_id(ebml::doc_data(tagdoc));
} }
fn parse_external_def_id(this_cnum: ast::crate_num, fn doc_type(doc: ebml::doc, tcx: ty::ctxt, cdata: cmd) -> ty::t {
extres: external_resolver, s: str) ->
ast::def_id {
let buf = str::bytes(s);
let external_def_id = parse_def_id(buf);
// This item was defined in the crate we're searching if it's has the
// local crate number, otherwise we need to search a different crate
if external_def_id.crate == ast::local_crate {
ret {crate: this_cnum, node: external_def_id.node};
} else { ret extres(external_def_id); }
}
fn doc_type(doc: ebml::doc, this_cnum: ast::crate_num, tcx: ty::ctxt,
extres: external_resolver) -> ty::t {
let tp = ebml::get_doc(doc, tag_items_data_item_type); let tp = ebml::get_doc(doc, tag_items_data_item_type);
let def_parser = bind parse_external_def_id(this_cnum, extres, _); parse_ty_data(tp.data, cdata.cnum, tp.start, tcx, {|did|
parse_ty_data(tp.data, this_cnum, tp.start, def_parser, tcx) translate_def_id(cdata, did)
})
} }
fn item_type(item: ebml::doc, this_cnum: ast::crate_num, tcx: ty::ctxt, fn item_type(item: ebml::doc, tcx: ty::ctxt, cdata: cmd) -> ty::t {
extres: external_resolver) -> ty::t { let t = doc_type(item, tcx, cdata);
let t = doc_type(item, this_cnum, tcx, extres);
if family_names_type(item_family(item)) { if family_names_type(item_family(item)) {
ty::mk_named(tcx, t, @item_name(item)) ty::mk_named(tcx, t, @item_name(item))
} else { t } } else { t }
} }
fn item_impl_iface(item: ebml::doc, this_cnum: ast::crate_num, tcx: ty::ctxt, fn item_impl_iface(item: ebml::doc, tcx: ty::ctxt, cdata: cmd)
extres: external_resolver) -> option::t<ty::t> { -> option::t<ty::t> {
let result = none; let result = none;
ebml::tagged_docs(item, tag_impl_iface) {|ity| ebml::tagged_docs(item, tag_impl_iface) {|ity|
let def_parser = bind parse_external_def_id(this_cnum, extres, _); let t = parse_ty_data(ity.data, cdata.cnum, ity.start, tcx, {|did|
let t = parse_ty_data(ity.data, this_cnum, ity.start, def_parser, translate_def_id(cdata, did)
tcx); });
result = some(t); result = some(t);
} }
result result
} }
fn item_impl_iface_did(item: ebml::doc, this_cnum: ast::crate_num, fn item_impl_iface_did(item: ebml::doc, cdata: cmd)
extres: external_resolver)
-> option::t<ast::def_id> { -> option::t<ast::def_id> {
let result = none; let result = none;
ebml::tagged_docs(item, tag_impl_iface_did) {|doc| ebml::tagged_docs(item, tag_impl_iface_did) {|doc|
let s = str::unsafe_from_bytes(ebml::doc_data(doc)); let did = translate_def_id(cdata, parse_def_id(ebml::doc_data(doc)));
result = some(parse_external_def_id(this_cnum, extres, s)); result = some(did);
} }
result result
} }
fn item_ty_param_bounds(item: ebml::doc, this_cnum: ast::crate_num, fn item_ty_param_bounds(item: ebml::doc, tcx: ty::ctxt, cdata: cmd)
tcx: ty::ctxt, extres: external_resolver)
-> @[ty::param_bounds] { -> @[ty::param_bounds] {
let bounds = []; let bounds = [];
let def_parser = bind parse_external_def_id(this_cnum, extres, _);
ebml::tagged_docs(item, tag_items_data_item_ty_param_bounds) {|p| ebml::tagged_docs(item, tag_items_data_item_ty_param_bounds) {|p|
bounds += [tydecode::parse_bounds_data(p.data, p.start, let bd = parse_bounds_data(p.data, p.start, cdata.cnum, tcx, {|did|
this_cnum, def_parser, tcx)]; translate_def_id(cdata, did)
});
bounds += [bd];
} }
@bounds @bounds
} }
@ -162,13 +143,12 @@ fn item_ty_param_count(item: ebml::doc) -> uint {
n n
} }
fn tag_variant_ids(item: ebml::doc, this_cnum: ast::crate_num) -> fn tag_variant_ids(item: ebml::doc, cdata: cmd) -> [ast::def_id] {
[ast::def_id] {
let ids: [ast::def_id] = []; let ids: [ast::def_id] = [];
let v = tag_items_data_item_variant; let v = tag_items_data_item_variant;
ebml::tagged_docs(item, v) {|p| ebml::tagged_docs(item, v) {|p|
let ext = parse_def_id(ebml::doc_data(p)); let ext = parse_def_id(ebml::doc_data(p));
ids += [{crate: this_cnum, node: ext.node}]; ids += [{crate: cdata.cnum, node: ext.node}];
}; };
ret ids; ret ids;
} }
@ -230,12 +210,12 @@ fn lookup_def(cnum: ast::crate_num, data: @[u8], did_: ast::def_id) ->
ret def; ret def;
} }
fn get_type(data: @[u8], def: ast::def_id, tcx: ty::ctxt, fn get_type(cdata: cmd, id: ast::node_id, tcx: ty::ctxt)
extres: external_resolver) -> ty::ty_param_bounds_and_ty { -> ty::ty_param_bounds_and_ty {
let item = lookup_item(def.node, data); let item = lookup_item(id, cdata.data);
let t = item_type(item, def.crate, tcx, extres); let t = item_type(item, tcx, cdata);
let tp_bounds = if family_has_type_params(item_family(item)) { let tp_bounds = if family_has_type_params(item_family(item)) {
item_ty_param_bounds(item, def.crate, tcx, extres) item_ty_param_bounds(item, tcx, cdata)
} else { @[] }; } else { @[] };
ret {bounds: tp_bounds, ty: t}; ret {bounds: tp_bounds, ty: t};
} }
@ -244,27 +224,25 @@ fn get_type_param_count(data: @[u8], id: ast::node_id) -> uint {
item_ty_param_count(lookup_item(id, data)) item_ty_param_count(lookup_item(id, data))
} }
fn get_impl_iface(data: @[u8], def: ast::def_id, tcx: ty::ctxt, fn get_impl_iface(cdata: cmd, id: ast::node_id, tcx: ty::ctxt)
extres: external_resolver) -> option::t<ty::t> { -> option::t<ty::t> {
item_impl_iface(lookup_item(def.node, data), def.crate, tcx, extres) item_impl_iface(lookup_item(id, cdata.data), tcx, cdata)
} }
fn get_symbol(data: @[u8], id: ast::node_id) -> str { fn get_symbol(data: @[u8], id: ast::node_id) -> str {
ret item_symbol(lookup_item(id, data)); ret item_symbol(lookup_item(id, data));
} }
fn get_tag_variants(_data: @[u8], def: ast::def_id, tcx: ty::ctxt, fn get_tag_variants(cdata: cmd, id: ast::node_id, tcx: ty::ctxt)
extres: external_resolver) -> [ty::variant_info] { -> [ty::variant_info] {
let external_crate_id = def.crate; let data = cdata.data;
let data =
cstore::get_crate_data(tcx.sess.get_cstore(), external_crate_id).data;
let items = ebml::get_doc(ebml::new_doc(data), tag_items); let items = ebml::get_doc(ebml::new_doc(data), tag_items);
let item = find_item(def.node, items); let item = find_item(id, items);
let infos: [ty::variant_info] = []; let infos: [ty::variant_info] = [];
let variant_ids = tag_variant_ids(item, external_crate_id); let variant_ids = tag_variant_ids(item, cdata);
for did: ast::def_id in variant_ids { for did: ast::def_id in variant_ids {
let item = find_item(did.node, items); let item = find_item(did.node, items);
let ctor_ty = item_type(item, external_crate_id, tcx, extres); let ctor_ty = item_type(item, tcx, cdata);
let arg_tys: [ty::t] = []; let arg_tys: [ty::t] = [];
alt ty::struct(tcx, ctor_ty) { alt ty::struct(tcx, ctor_ty) {
ty::ty_fn(f) { ty::ty_fn(f) {
@ -290,17 +268,17 @@ fn item_impl_methods(data: @[u8], item: ebml::doc, base_tps: uint)
rslt rslt
} }
fn get_impls_for_mod(data: @[u8], m_def: ast::def_id, fn get_impls_for_mod(cdata: cmd, m_id: ast::node_id,
name: option::t<ast::ident>, extres: external_resolver) name: option::t<ast::ident>)
-> @[@middle::resolve::_impl] { -> @[@middle::resolve::_impl] {
let mod_item = lookup_item(m_def.node, data), result = []; let data = cdata.data;
let mod_item = lookup_item(m_id, data), result = [];
ebml::tagged_docs(mod_item, tag_mod_impl) {|doc| ebml::tagged_docs(mod_item, tag_mod_impl) {|doc|
let did = parse_external_def_id( let did = translate_def_id(cdata, parse_def_id(ebml::doc_data(doc)));
m_def.crate, extres, str::unsafe_from_bytes(ebml::doc_data(doc)));
let item = lookup_item(did.node, data), nm = item_name(item); let item = lookup_item(did.node, data), nm = item_name(item);
if alt name { some(n) { n == nm } none. { true } } { if alt name { some(n) { n == nm } none. { true } } {
let base_tps = item_ty_param_count(doc); let base_tps = item_ty_param_count(doc);
let i_did = item_impl_iface_did(item, m_def.crate, extres); let i_did = item_impl_iface_did(item, cdata);
result += [@{did: did, iface_did: i_did, ident: nm, result += [@{did: did, iface_did: i_did, ident: nm,
methods: item_impl_methods(data, doc, base_tps)}]; methods: item_impl_methods(data, doc, base_tps)}];
} }
@ -308,13 +286,14 @@ fn get_impls_for_mod(data: @[u8], m_def: ast::def_id,
@result @result
} }
fn get_iface_methods(data: @[u8], def: ast::def_id, tcx: ty::ctxt, fn get_iface_methods(cdata: cmd, id: ast::node_id, tcx: ty::ctxt)
extres: external_resolver) -> @[ty::method] { -> @[ty::method] {
let item = lookup_item(def.node, data), result = []; let data = cdata.data;
let item = lookup_item(id, data), result = [];
ebml::tagged_docs(item, tag_item_method) {|mth| ebml::tagged_docs(item, tag_item_method) {|mth|
let bounds = item_ty_param_bounds(mth, def.crate, tcx, extres); let bounds = item_ty_param_bounds(mth, tcx, cdata);
let name = item_name(mth); let name = item_name(mth);
let ty = doc_type(mth, def.crate, tcx, extres); let ty = doc_type(mth, tcx, cdata);
let fty = alt ty::struct(tcx, ty) { ty::ty_fn(f) { f } }; let fty = alt ty::struct(tcx, ty) { ty::ty_fn(f) { f } };
result += [{ident: name, tps: bounds, fty: fty}]; result += [{ident: name, tps: bounds, fty: fty}];
} }
@ -489,6 +468,22 @@ fn list_crate_metadata(bytes: @[u8], out: io::writer) {
list_crate_items(bytes, md, out); list_crate_items(bytes, md, out);
} }
// Translates a def_id from an external crate to a def_id for the current
// compilation environment. We use this when trying to load types from
// external crates - if those types further refer to types in other crates
// then we must translate the crate number from that encoded in the external
// crate to the correct local crate number.
fn translate_def_id(cdata: cmd, did: ast::def_id) -> ast::def_id {
if did.crate == ast::local_crate {
ret {crate: cdata.cnum, node: did.node};
}
alt cdata.cnum_map.find(did.crate) {
option::some(n) { ret {crate: n, node: did.node}; }
option::none. { fail "didn't find a crate in the cnum_map"; }
}
}
// Local Variables: // Local Variables:
// mode: rust // mode: rust
// fill-column: 78; // fill-column: 78;

View File

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

View File

@ -8,8 +8,7 @@ import syntax::ast_util;
import syntax::ast_util::respan; import syntax::ast_util::respan;
import middle::ty; import middle::ty;
export parse_def_id; export parse_ty_data, parse_def_id;
export parse_ty_data;
export parse_bounds_data; export parse_bounds_data;
// Compact string representation for ty::t values. API ty_str & // Compact string representation for ty::t values. API ty_str &
@ -17,7 +16,7 @@ export parse_bounds_data;
// data buffer. Whatever format you choose should not contain pipe characters. // data buffer. Whatever format you choose should not contain pipe characters.
// Callback to translate defs to strs or back: // Callback to translate defs to strs or back:
type str_def = fn@(str) -> ast::def_id; type conv_did = block(ast::def_id) -> ast::def_id;
type pstate = {data: @[u8], crate: int, mutable pos: uint, tcx: ty::ctxt}; type pstate = {data: @[u8], crate: int, mutable pos: uint, tcx: ty::ctxt};
@ -31,12 +30,12 @@ fn next(st: @pstate) -> u8 {
ret ch; ret ch;
} }
fn parse_ident(st: @pstate, sd: str_def, last: char) -> ast::ident { fn parse_ident(st: @pstate, last: char) -> ast::ident {
fn is_last(b: char, c: char) -> bool { ret c == b; } fn is_last(b: char, c: char) -> bool { ret c == b; }
ret parse_ident_(st, sd, bind is_last(last, _)); ret parse_ident_(st, bind is_last(last, _));
} }
fn parse_ident_(st: @pstate, _sd: str_def, is_last: fn@(char) -> bool) -> fn parse_ident_(st: @pstate, is_last: fn@(char) -> bool) ->
ast::ident { ast::ident {
let rslt = ""; let rslt = "";
while !is_last(peek(st) as char) { while !is_last(peek(st) as char) {
@ -46,28 +45,26 @@ fn parse_ident_(st: @pstate, _sd: str_def, is_last: fn@(char) -> bool) ->
} }
fn parse_ty_data(data: @[u8], crate_num: int, pos: uint, sd: str_def, fn parse_ty_data(data: @[u8], crate_num: int, pos: uint, tcx: ty::ctxt,
tcx: ty::ctxt) -> ty::t { conv: conv_did) -> ty::t {
let st = @{data: data, crate: crate_num, mutable pos: pos, tcx: tcx}; let st = @{data: data, crate: crate_num, mutable pos: pos, tcx: tcx};
parse_ty(st, sd) parse_ty(st, conv)
} }
fn parse_ret_ty(st: @pstate, sd: str_def) -> (ast::ret_style, ty::t) { fn parse_ret_ty(st: @pstate, conv: conv_did) -> (ast::ret_style, ty::t) {
alt peek(st) as char { alt peek(st) as char {
'!' { next(st); (ast::noreturn, ty::mk_bot(st.tcx)) } '!' { next(st); (ast::noreturn, ty::mk_bot(st.tcx)) }
_ { (ast::return_val, parse_ty(st, sd)) } _ { (ast::return_val, parse_ty(st, conv)) }
} }
} }
fn parse_constrs(st: @pstate, sd: str_def) -> [@ty::constr] { fn parse_constrs(st: @pstate, conv: conv_did) -> [@ty::constr] {
let rslt: [@ty::constr] = []; let rslt: [@ty::constr] = [];
alt peek(st) as char { alt peek(st) as char {
':' { ':' {
do { do {
next(st); next(st);
let one: @ty::constr = rslt += [parse_constr(st, conv, parse_constr_arg)];
parse_constr::<uint>(st, sd, parse_constr_arg);
rslt += [one];
} while peek(st) as char == ';' } while peek(st) as char == ';'
} }
_ { } _ { }
@ -76,15 +73,13 @@ fn parse_constrs(st: @pstate, sd: str_def) -> [@ty::constr] {
} }
// FIXME less copy-and-paste // FIXME less copy-and-paste
fn parse_ty_constrs(st: @pstate, sd: str_def) -> [@ty::type_constr] { fn parse_ty_constrs(st: @pstate, conv: conv_did) -> [@ty::type_constr] {
let rslt: [@ty::type_constr] = []; let rslt: [@ty::type_constr] = [];
alt peek(st) as char { alt peek(st) as char {
':' { ':' {
do { do {
next(st); next(st);
let one: @ty::type_constr = rslt += [parse_constr(st, conv, parse_ty_constr_arg)];
parse_constr::<@path>(st, sd, parse_ty_constr_arg);
rslt += [one];
} while peek(st) as char == ';' } while peek(st) as char == ';'
} }
_ { } _ { }
@ -92,10 +87,10 @@ fn parse_ty_constrs(st: @pstate, sd: str_def) -> [@ty::type_constr] {
ret rslt; ret rslt;
} }
fn parse_path(st: @pstate, sd: str_def) -> @ast::path { fn parse_path(st: @pstate) -> @ast::path {
let idents: [ast::ident] = []; let idents: [ast::ident] = [];
fn is_last(c: char) -> bool { ret c == '(' || c == ':'; } fn is_last(c: char) -> bool { ret c == '(' || c == ':'; }
idents += [parse_ident_(st, sd, is_last)]; idents += [parse_ident_(st, is_last)];
while true { while true {
alt peek(st) as char { alt peek(st) as char {
':' { next(st); next(st); } ':' { next(st); next(st); }
@ -103,16 +98,14 @@ fn parse_path(st: @pstate, sd: str_def) -> @ast::path {
if c == '(' { if c == '(' {
ret @respan(ast_util::dummy_sp(), ret @respan(ast_util::dummy_sp(),
{global: false, idents: idents, types: []}); {global: false, idents: idents, types: []});
} else { idents += [parse_ident_(st, sd, is_last)]; } } else { idents += [parse_ident_(st, is_last)]; }
} }
} }
} }
fail "parse_path: ill-formed path"; fail "parse_path: ill-formed path";
} }
type arg_parser<T> = fn(@pstate, str_def) -> ast::constr_arg_general_<T>; fn parse_constr_arg(st: @pstate) -> ast::fn_constr_arg {
fn parse_constr_arg(st: @pstate, _sd: str_def) -> ast::fn_constr_arg {
alt peek(st) as char { alt peek(st) as char {
'*' { st.pos += 1u; ret ast::carg_base; } '*' { st.pos += 1u; ret ast::carg_base; }
c { c {
@ -129,7 +122,7 @@ fn parse_constr_arg(st: @pstate, _sd: str_def) -> ast::fn_constr_arg {
} }
/* /*
else { else {
auto lit = parse_lit(st, sd, ','); auto lit = parse_lit(st, conv, ',');
args += [respan(st.span, ast::carg_lit(lit))]; args += [respan(st.span, ast::carg_lit(lit))];
} }
*/ */
@ -137,25 +130,25 @@ fn parse_constr_arg(st: @pstate, _sd: str_def) -> ast::fn_constr_arg {
} }
} }
fn parse_ty_constr_arg(st: @pstate, sd: str_def) -> fn parse_ty_constr_arg(st: @pstate) -> ast::constr_arg_general_<@path> {
ast::constr_arg_general_<@path> {
alt peek(st) as char { alt peek(st) as char {
'*' { st.pos += 1u; ret ast::carg_base; } '*' { st.pos += 1u; ret ast::carg_base; }
c { ret ast::carg_ident(parse_path(st, sd)); } c { ret ast::carg_ident(parse_path(st)); }
} }
} }
fn parse_constr<copy T>(st: @pstate, sd: str_def, pser: arg_parser<T>) -> fn parse_constr<T: copy>(st: @pstate, conv: conv_did,
@ty::constr_general<T> { pser: block(@pstate) -> ast::constr_arg_general_<T>)
-> @ty::constr_general<T> {
let sp = ast_util::dummy_sp(); // FIXME: use a real span let sp = ast_util::dummy_sp(); // FIXME: use a real span
let args: [@sp_constr_arg<T>] = []; let args: [@sp_constr_arg<T>] = [];
let pth = parse_path(st, sd); let pth = parse_path(st);
let ignore: char = next(st) as char; let ignore: char = next(st) as char;
assert (ignore == '('); assert (ignore == '(');
let def = parse_def(st, sd); let def = parse_def(st, conv);
let an_arg: constr_arg_general_<T>; let an_arg: constr_arg_general_<T>;
do { do {
an_arg = pser(st, sd); an_arg = pser(st);
// FIXME use a real span // FIXME use a real span
args += [@respan(sp, an_arg)]; args += [@respan(sp, an_arg)];
ignore = next(st) as char; ignore = next(st) as char;
@ -164,11 +157,11 @@ fn parse_constr<copy T>(st: @pstate, sd: str_def, pser: arg_parser<T>) ->
ret @respan(sp, {path: pth, args: args, id: def}); ret @respan(sp, {path: pth, args: args, id: def});
} }
fn parse_ty_rust_fn(st: @pstate, sd: str_def, p: ast::proto) -> ty::t { fn parse_ty_rust_fn(st: @pstate, conv: conv_did, p: ast::proto) -> ty::t {
ret ty::mk_fn(st.tcx, {proto: p with parse_ty_fn(st, sd)}); ret ty::mk_fn(st.tcx, {proto: p with parse_ty_fn(st, conv)});
} }
fn parse_ty(st: @pstate, sd: str_def) -> ty::t { fn parse_ty(st: @pstate, conv: conv_did) -> ty::t {
alt next(st) as char { alt next(st) as char {
'n' { ret ty::mk_nil(st.tcx); } 'n' { ret ty::mk_nil(st.tcx); }
'z' { ret ty::mk_bot(st.tcx); } 'z' { ret ty::mk_bot(st.tcx); }
@ -194,28 +187,28 @@ fn parse_ty(st: @pstate, sd: str_def) -> ty::t {
'S' { ret ty::mk_str(st.tcx); } 'S' { ret ty::mk_str(st.tcx); }
't' { 't' {
assert (next(st) as char == '['); assert (next(st) as char == '[');
let def = parse_def(st, sd); let def = parse_def(st, conv);
let params: [ty::t] = []; let params: [ty::t] = [];
while peek(st) as char != ']' { params += [parse_ty(st, sd)]; } while peek(st) as char != ']' { params += [parse_ty(st, conv)]; }
st.pos = st.pos + 1u; st.pos = st.pos + 1u;
ret ty::mk_tag(st.tcx, def, params); ret ty::mk_tag(st.tcx, def, params);
} }
'x' { 'x' {
assert (next(st) as char == '['); assert (next(st) as char == '[');
let def = parse_def(st, sd); let def = parse_def(st, conv);
let params: [ty::t] = []; let params: [ty::t] = [];
while peek(st) as char != ']' { params += [parse_ty(st, sd)]; } while peek(st) as char != ']' { params += [parse_ty(st, conv)]; }
st.pos = st.pos + 1u; st.pos = st.pos + 1u;
ret ty::mk_iface(st.tcx, def, params); ret ty::mk_iface(st.tcx, def, params);
} }
'p' { 'p' {
let did = parse_def(st, sd); let did = parse_def(st, conv);
ret ty::mk_param(st.tcx, parse_int(st) as uint, did); ret ty::mk_param(st.tcx, parse_int(st) as uint, did);
} }
'@' { ret ty::mk_box(st.tcx, parse_mt(st, sd)); } '@' { ret ty::mk_box(st.tcx, parse_mt(st, conv)); }
'~' { ret ty::mk_uniq(st.tcx, parse_mt(st, sd)); } '~' { ret ty::mk_uniq(st.tcx, parse_mt(st, conv)); }
'*' { ret ty::mk_ptr(st.tcx, parse_mt(st, sd)); } '*' { ret ty::mk_ptr(st.tcx, parse_mt(st, conv)); }
'I' { ret ty::mk_vec(st.tcx, parse_mt(st, sd)); } 'I' { ret ty::mk_vec(st.tcx, parse_mt(st, conv)); }
'R' { 'R' {
assert (next(st) as char == '['); assert (next(st) as char == '[');
let fields: [ty::field] = []; let fields: [ty::field] = [];
@ -225,7 +218,7 @@ fn parse_ty(st: @pstate, sd: str_def) -> ty::t {
name += str::unsafe_from_byte(next(st)); name += str::unsafe_from_byte(next(st));
} }
st.pos = st.pos + 1u; st.pos = st.pos + 1u;
fields += [{ident: name, mt: parse_mt(st, sd)}]; fields += [{ident: name, mt: parse_mt(st, conv)}];
} }
st.pos = st.pos + 1u; st.pos = st.pos + 1u;
ret ty::mk_rec(st.tcx, fields); ret ty::mk_rec(st.tcx, fields);
@ -233,24 +226,24 @@ fn parse_ty(st: @pstate, sd: str_def) -> ty::t {
'T' { 'T' {
assert (next(st) as char == '['); assert (next(st) as char == '[');
let params = []; let params = [];
while peek(st) as char != ']' { params += [parse_ty(st, sd)]; } while peek(st) as char != ']' { params += [parse_ty(st, conv)]; }
st.pos = st.pos + 1u; st.pos = st.pos + 1u;
ret ty::mk_tup(st.tcx, params); ret ty::mk_tup(st.tcx, params);
} }
's' { 's' {
ret parse_ty_rust_fn(st, sd, ast::proto_send); ret parse_ty_rust_fn(st, conv, ast::proto_send);
} }
'F' { 'F' {
ret parse_ty_rust_fn(st, sd, ast::proto_shared(ast::sugar_normal)); ret parse_ty_rust_fn(st, conv, ast::proto_shared(ast::sugar_normal));
} }
'f' { 'f' {
ret parse_ty_rust_fn(st, sd, ast::proto_bare); ret parse_ty_rust_fn(st, conv, ast::proto_bare);
} }
'B' { 'B' {
ret parse_ty_rust_fn(st, sd, ast::proto_block); ret parse_ty_rust_fn(st, conv, ast::proto_block);
} }
'N' { 'N' {
let func = parse_ty_fn(st, sd); let func = parse_ty_fn(st, conv);
ret ty::mk_native_fn(st.tcx, func.inputs, func.output); ret ty::mk_native_fn(st.tcx, func.inputs, func.output);
} }
'O' { 'O' {
@ -266,22 +259,22 @@ fn parse_ty(st: @pstate, sd: str_def) -> ty::t {
name += str::unsafe_from_byte(next(st)); name += str::unsafe_from_byte(next(st));
} }
methods += [{ident: name, tps: @[], methods += [{ident: name, tps: @[],
fty: {proto: proto with parse_ty_fn(st, sd)}}]; fty: {proto: proto with parse_ty_fn(st, conv)}}];
} }
st.pos += 1u; st.pos += 1u;
ret ty::mk_obj(st.tcx, methods); ret ty::mk_obj(st.tcx, methods);
} }
'r' { 'r' {
assert (next(st) as char == '['); assert (next(st) as char == '[');
let def = parse_def(st, sd); let def = parse_def(st, conv);
let inner = parse_ty(st, sd); let inner = parse_ty(st, conv);
let params: [ty::t] = []; let params: [ty::t] = [];
while peek(st) as char != ']' { params += [parse_ty(st, sd)]; } while peek(st) as char != ']' { params += [parse_ty(st, conv)]; }
st.pos = st.pos + 1u; st.pos = st.pos + 1u;
ret ty::mk_res(st.tcx, def, inner, params); ret ty::mk_res(st.tcx, def, inner, params);
} }
'X' { ret ty::mk_var(st.tcx, parse_int(st)); } 'X' { ret ty::mk_var(st.tcx, parse_int(st)); }
'E' { let def = parse_def(st, sd); ret ty::mk_native(st.tcx, def); } 'E' { let def = parse_def(st, conv); ret ty::mk_native(st.tcx, def); }
'Y' { ret ty::mk_type(st.tcx); } 'Y' { ret ty::mk_type(st.tcx); }
'y' { ret ty::mk_send_type(st.tcx); } 'y' { ret ty::mk_send_type(st.tcx); }
'C' { ret ty::mk_opaque_closure(st.tcx); } 'C' { ret ty::mk_opaque_closure(st.tcx); }
@ -294,7 +287,7 @@ fn parse_ty(st: @pstate, sd: str_def) -> ty::t {
some(tt) { ret tt; } some(tt) { ret tt; }
none. { none. {
let ps = @{pos: pos with *st}; let ps = @{pos: pos with *st};
let tt = parse_ty(ps, sd); let tt = parse_ty(ps, conv);
st.tcx.rcache.insert({cnum: st.crate, pos: pos, len: len}, tt); st.tcx.rcache.insert({cnum: st.crate, pos: pos, len: len}, tt);
ret tt; ret tt;
} }
@ -302,8 +295,8 @@ fn parse_ty(st: @pstate, sd: str_def) -> ty::t {
} }
'A' { 'A' {
assert (next(st) as char == '['); assert (next(st) as char == '[');
let tt = parse_ty(st, sd); let tt = parse_ty(st, conv);
let tcs = parse_ty_constrs(st, sd); let tcs = parse_ty_constrs(st, conv);
assert (next(st) as char == ']'); assert (next(st) as char == ']');
ret ty::mk_constr(st.tcx, tt, tcs); ret ty::mk_constr(st.tcx, tt, tcs);
} }
@ -311,21 +304,21 @@ fn parse_ty(st: @pstate, sd: str_def) -> ty::t {
} }
} }
fn parse_mt(st: @pstate, sd: str_def) -> ty::mt { fn parse_mt(st: @pstate, conv: conv_did) -> ty::mt {
let mut; let mut;
alt peek(st) as char { alt peek(st) as char {
'm' { next(st); mut = ast::mut; } 'm' { next(st); mut = ast::mut; }
'?' { next(st); mut = ast::maybe_mut; } '?' { next(st); mut = ast::maybe_mut; }
_ { mut = ast::imm; } _ { mut = ast::imm; }
} }
ret {ty: parse_ty(st, sd), mut: mut}; ret {ty: parse_ty(st, conv), mut: mut};
} }
fn parse_def(st: @pstate, sd: str_def) -> ast::def_id { fn parse_def(st: @pstate, conv: conv_did) -> ast::def_id {
let def = ""; let def = [];
while peek(st) as char != '|' { def += str::unsafe_from_byte(next(st)); } while peek(st) as char != '|' { def += [next(st)]; }
st.pos = st.pos + 1u; st.pos = st.pos + 1u;
ret sd(def); ret conv(parse_def_id(def));
} }
fn parse_int(st: @pstate) -> int { fn parse_int(st: @pstate) -> int {
@ -354,7 +347,7 @@ fn parse_hex(st: @pstate) -> uint {
ret n; ret n;
} }
fn parse_ty_fn(st: @pstate, sd: str_def) -> ty::fn_ty { fn parse_ty_fn(st: @pstate, conv: conv_did) -> ty::fn_ty {
assert (next(st) as char == '['); assert (next(st) as char == '[');
let inputs: [ty::arg] = []; let inputs: [ty::arg] = [];
while peek(st) as char != ']' { while peek(st) as char != ']' {
@ -366,11 +359,11 @@ fn parse_ty_fn(st: @pstate, sd: str_def) -> ty::fn_ty {
'#' { ast::by_val } '#' { ast::by_val }
}; };
st.pos += 1u; st.pos += 1u;
inputs += [{mode: mode, ty: parse_ty(st, sd)}]; inputs += [{mode: mode, ty: parse_ty(st, conv)}];
} }
st.pos += 1u; // eat the ']' st.pos += 1u; // eat the ']'
let cs = parse_constrs(st, sd); let cs = parse_constrs(st, conv);
let (ret_style, ret_ty) = parse_ret_ty(st, sd); let (ret_style, ret_ty) = parse_ret_ty(st, conv);
ret {proto: ast::proto_bare, inputs: inputs, output: ret_ty, ret {proto: ast::proto_bare, inputs: inputs, output: ret_ty,
ret_style: ret_style, constraints: cs}; ret_style: ret_style, constraints: cs};
} }
@ -399,19 +392,19 @@ fn parse_def_id(buf: [u8]) -> ast::def_id {
} }
fn parse_bounds_data(data: @[u8], start: uint, fn parse_bounds_data(data: @[u8], start: uint,
crate_num: int, sd: str_def, tcx: ty::ctxt) crate_num: int, tcx: ty::ctxt, conv: conv_did)
-> @[ty::param_bound] { -> @[ty::param_bound] {
let st = @{data: data, crate: crate_num, mutable pos: start, tcx: tcx}; let st = @{data: data, crate: crate_num, mutable pos: start, tcx: tcx};
parse_bounds(st, sd) parse_bounds(st, conv)
} }
fn parse_bounds(st: @pstate, sd: str_def) -> @[ty::param_bound] { fn parse_bounds(st: @pstate, conv: conv_did) -> @[ty::param_bound] {
let bounds = []; let bounds = [];
while true { while true {
bounds += [alt next(st) as char { bounds += [alt next(st) as char {
'S' { ty::bound_send } 'S' { ty::bound_send }
'C' { ty::bound_copy } 'C' { ty::bound_copy }
'I' { ty::bound_iface(parse_ty(st, sd)) } 'I' { ty::bound_iface(parse_ty(st, conv)) }
'.' { break; } '.' { break; }
}]; }];
} }

View File

@ -98,7 +98,7 @@ fn map_expr(cx: ctx, ex: @expr) {
} }
} }
fn new_smallintmap_int_adapter<copy V>() -> std::map::hashmap<int, V> { fn new_smallintmap_int_adapter<V: copy>() -> std::map::hashmap<int, V> {
let key_idx = fn (&&key: int) -> uint { key as uint }; let key_idx = fn (&&key: int) -> uint { key as uint };
let idx_key = fn (idx: uint) -> int { idx as int }; let idx_key = fn (idx: uint) -> int { idx as int };
ret new_smallintmap_adapter(key_idx, idx_key); ret new_smallintmap_adapter(key_idx, idx_key);
@ -109,11 +109,11 @@ fn new_smallintmap_int_adapter<copy V>() -> std::map::hashmap<int, V> {
// the entire codebase adapting all the callsites to the different // the entire codebase adapting all the callsites to the different
// interface. // interface.
// FIXME: hashmap and smallintmap should support the same interface. // FIXME: hashmap and smallintmap should support the same interface.
fn new_smallintmap_adapter<copy K, copy V>(key_idx: fn(K) -> uint, fn new_smallintmap_adapter<K: copy, V: copy>(key_idx: fn(K) -> uint,
idx_key: fn(uint) -> K) idx_key: fn(uint) -> K)
-> std::map::hashmap<K, V> { -> std::map::hashmap<K, V> {
obj adapter<copy K, copy V>(map: smallintmap::smallintmap<V>, obj adapter<K: copy, V: copy>(map: smallintmap::smallintmap<V>,
key_idx: fn(K) -> uint, key_idx: fn(K) -> uint,
idx_key: fn(uint) -> K) { idx_key: fn(uint) -> K) {

View File

@ -118,7 +118,7 @@ tag debug_metadata {
retval_metadata(@metadata<retval_md>); retval_metadata(@metadata<retval_md>);
} }
fn cast_safely<copy T, U>(val: T) -> U unsafe { fn cast_safely<T: copy, U>(val: T) -> U unsafe {
let val2 = val; let val2 = val;
let val3 = unsafe::reinterpret_cast(val2); let val3 = unsafe::reinterpret_cast(val2);
unsafe::leak(val2); unsafe::leak(val2);
@ -138,7 +138,7 @@ fn md_from_metadata<T>(val: debug_metadata) -> T unsafe {
} }
} }
fn cached_metadata<copy T>(cache: metadata_cache, mdtag: int, fn cached_metadata<T: copy>(cache: metadata_cache, mdtag: int,
eq: block(md: T) -> bool) -> option::t<T> unsafe { eq: block(md: T) -> bool) -> option::t<T> unsafe {
if cache.contains_key(mdtag) { if cache.contains_key(mdtag) {
let items = cache.get(mdtag); let items = cache.get(mdtag);

View File

@ -5354,7 +5354,7 @@ fn collect_item(ccx: @crate_ctxt, abi: @mutable option::t<ast::native_abi>,
register_fn(ccx, i.span, new_pt, "obj_ctor", tps, ctor_id); register_fn(ccx, i.span, new_pt, "obj_ctor", tps, ctor_id);
} }
ast::item_impl(tps, _, _, methods) { ast::item_impl(tps, _, _, methods) {
let name = ccx.names.next(i.ident); let name = i.ident + int::str(i.id);
for m in methods { for m in methods {
register_fn(ccx, i.span, pt + [name, m.ident], register_fn(ccx, i.span, pt + [name, m.ident],
"impl_method", tps + m.tps, m.id); "impl_method", tps + m.tps, m.id);
@ -5418,9 +5418,7 @@ fn trans_constant(ccx: @crate_ctxt, it: @ast::item, &&pt: [str],
ast::item_impl(tps, some(@{node: ast::ty_path(_, id), _}), _, ms) { ast::item_impl(tps, some(@{node: ast::ty_path(_, id), _}), _, ms) {
let i_did = ast_util::def_id_of_def(ccx.tcx.def_map.get(id)); let i_did = ast_util::def_id_of_def(ccx.tcx.def_map.get(id));
let ty = ty::lookup_item_type(ccx.tcx, i_did).ty; let ty = ty::lookup_item_type(ccx.tcx, i_did).ty;
// FIXME[impl] use the same name as used in collect_items, for let new_pt = pt + [it.ident + int::str(it.id), "wrap"];
// slightly more consistent symbol names?
let new_pt = pt + [ccx.names.next(it.ident)];
let extra_tps = vec::map(tps, {|p| param_bounds(ccx, p)}); let extra_tps = vec::map(tps, {|p| param_bounds(ccx, p)});
let tbl = C_struct(vec::map(*ty::iface_methods(ccx.tcx, i_did), {|im| let tbl = C_struct(vec::map(*ty::iface_methods(ccx.tcx, i_did), {|im|
alt vec::find(ms, {|m| m.ident == im.ident}) { alt vec::find(ms, {|m| m.ident == im.ident}) {

View File

@ -414,7 +414,7 @@ fn mk_rcache() -> creader_cache {
ret map::mk_hashmap(hash_cache_entry, eq_cache_entries); ret map::mk_hashmap(hash_cache_entry, eq_cache_entries);
} }
fn new_ty_hash<copy V>() -> map::hashmap<t, V> { map::new_uint_hash() } fn new_ty_hash<V: copy>() -> map::hashmap<t, V> { map::new_uint_hash() }
fn mk_ctxt(s: session::session, dm: resolve::def_map, amap: ast_map::map, fn mk_ctxt(s: session::session, dm: resolve::def_map, amap: ast_map::map,
freevars: freevars::freevar_map) -> ctxt { freevars: freevars::freevar_map) -> ctxt {

View File

@ -2920,8 +2920,6 @@ mod dict {
bind_params(fcx, self_ty, n_tps) bind_params(fcx, self_ty, n_tps)
} else { {vars: [], ty: self_ty} }; } else { {vars: [], ty: self_ty} };
let im_bs = ty::lookup_item_type(tcx, im.did).bounds; let im_bs = ty::lookup_item_type(tcx, im.did).bounds;
// FIXME[impl] don't do this in fcx (or make
// unify transactional by scrubbing bindings on fail)
alt unify::unify(fcx, ty, self_ty) { alt unify::unify(fcx, ty, self_ty) {
ures_ok(_) { ures_ok(_) {
if option::is_some(found) { if option::is_some(found) {

View File

@ -1,7 +1,7 @@
import codemap::span; import codemap::span;
import ast::*; import ast::*;
fn respan<copy T>(sp: span, t: T) -> spanned<T> { fn respan<T: copy>(sp: span, t: T) -> spanned<T> {
ret {node: t, span: sp}; ret {node: t, span: sp};
} }
@ -201,7 +201,7 @@ fn eq_def_id(&&a: def_id, &&b: def_id) -> bool {
a == b a == b
} }
fn new_def_id_hash<copy T>() -> std::map::hashmap<def_id, T> { fn new_def_id_hash<T: copy>() -> std::map::hashmap<def_id, T> {
std::map::mk_hashmap(hash_def_id, eq_def_id) std::map::mk_hashmap(hash_def_id, eq_def_id)
} }

View File

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

View File

@ -210,7 +210,7 @@ fn expect_gt(p: parser) {
} }
} }
fn spanned<copy T>(lo: uint, hi: uint, node: T) -> spanned<T> { fn spanned<T: copy>(lo: uint, hi: uint, node: T) -> spanned<T> {
ret {node: node, span: ast_util::mk_sp(lo, hi)}; ret {node: node, span: ast_util::mk_sp(lo, hi)};
} }
@ -378,7 +378,7 @@ fn parse_constr_in_type(p: parser) -> @ast::ty_constr {
} }
fn parse_constrs<copy T>(pser: block(parser) -> @ast::constr_general<T>, fn parse_constrs<T: copy>(pser: block(parser) -> @ast::constr_general<T>,
p: parser) -> p: parser) ->
[@ast::constr_general<T>] { [@ast::constr_general<T>] {
let constrs: [@ast::constr_general<T>] = []; let constrs: [@ast::constr_general<T>] = [];
@ -554,7 +554,7 @@ fn parse_fn_block_arg(p: parser) -> ast::arg {
ret {mode: m, ty: t, ident: i, id: p.get_id()}; ret {mode: m, ty: t, ident: i, id: p.get_id()};
} }
fn parse_seq_to_before_gt<copy T>(sep: option::t<token::token>, fn parse_seq_to_before_gt<T: copy>(sep: option::t<token::token>,
f: block(parser) -> T, f: block(parser) -> T,
p: parser) -> [T] { p: parser) -> [T] {
let first = true; let first = true;
@ -571,7 +571,7 @@ fn parse_seq_to_before_gt<copy T>(sep: option::t<token::token>,
ret v; ret v;
} }
fn parse_seq_to_gt<copy T>(sep: option::t<token::token>, fn parse_seq_to_gt<T: copy>(sep: option::t<token::token>,
f: block(parser) -> T, p: parser) -> [T] { f: block(parser) -> T, p: parser) -> [T] {
let v = parse_seq_to_before_gt(sep, f, p); let v = parse_seq_to_before_gt(sep, f, p);
expect_gt(p); expect_gt(p);
@ -579,7 +579,7 @@ fn parse_seq_to_gt<copy T>(sep: option::t<token::token>,
ret v; ret v;
} }
fn parse_seq_lt_gt<copy T>(sep: option::t<token::token>, fn parse_seq_lt_gt<T: copy>(sep: option::t<token::token>,
f: block(parser) -> T, f: block(parser) -> T,
p: parser) -> spanned<[T]> { p: parser) -> spanned<[T]> {
let lo = p.get_lo_pos(); let lo = p.get_lo_pos();
@ -590,7 +590,7 @@ fn parse_seq_lt_gt<copy T>(sep: option::t<token::token>,
ret spanned(lo, hi, result); ret spanned(lo, hi, result);
} }
fn parse_seq_to_end<copy T>(ket: token::token, sep: seq_sep, fn parse_seq_to_end<T: copy>(ket: token::token, sep: seq_sep,
f: block(parser) -> T, p: parser) -> [T] { f: block(parser) -> T, p: parser) -> [T] {
let val = parse_seq_to_before_end(ket, sep, f, p); let val = parse_seq_to_before_end(ket, sep, f, p);
p.bump(); p.bump();
@ -612,7 +612,7 @@ fn seq_sep_none() -> seq_sep {
ret {sep: option::none, trailing_opt: false}; ret {sep: option::none, trailing_opt: false};
} }
fn parse_seq_to_before_end<copy T>(ket: token::token, fn parse_seq_to_before_end<T: copy>(ket: token::token,
sep: seq_sep, sep: seq_sep,
f: block(parser) -> T, p: parser) -> [T] { f: block(parser) -> T, p: parser) -> [T] {
let first: bool = true; let first: bool = true;
@ -629,7 +629,7 @@ fn parse_seq_to_before_end<copy T>(ket: token::token,
} }
fn parse_seq<copy T>(bra: token::token, ket: token::token, fn parse_seq<T: copy>(bra: token::token, ket: token::token,
sep: seq_sep, f: block(parser) -> T, sep: seq_sep, f: block(parser) -> T,
p: parser) -> spanned<[T]> { p: parser) -> spanned<[T]> {
let lo = p.get_lo_pos(); let lo = p.get_lo_pos();
@ -1700,8 +1700,6 @@ fn parse_block_tail(p: parser, lo: uint, s: ast::blk_check_mode) -> ast::blk {
fn parse_ty_param(p: parser) -> ast::ty_param { fn parse_ty_param(p: parser) -> ast::ty_param {
let bounds = []; let bounds = [];
if eat_word(p, "send") { bounds += [ast::bound_send]; }
else if eat_word(p, "copy") { bounds += [ast::bound_copy]; }
let ident = parse_ident(p); let ident = parse_ident(p);
if eat(p, token::COLON) { if eat(p, token::COLON) {
while p.peek() != token::COMMA && p.peek() != token::GT { while p.peek() != token::COMMA && p.peek() != token::GT {

View File

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

View File

@ -20,7 +20,7 @@ fn hash_def(d: ast::def_id) -> uint {
ret h; ret h;
} }
fn new_def_hash<copy V>() -> std::map::hashmap<ast::def_id, V> { fn new_def_hash<V: copy>() -> std::map::hashmap<ast::def_id, V> {
let hasher: std::map::hashfn<ast::def_id> = hash_def; let hasher: std::map::hashfn<ast::def_id> = hash_def;
let eqer: std::map::eqfn<ast::def_id> = def_eq; let eqer: std::map::eqfn<ast::def_id> = def_eq;
ret std::map::mk_hashmap::<ast::def_id, V>(hasher, eqer); ret std::map::mk_hashmap::<ast::def_id, V>(hasher, eqer);

View File

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

View File

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

View File

@ -39,7 +39,7 @@ native mod rustrt {
type void; type void;
type rust_port; type rust_port;
fn chan_id_send<send T>(t: *sys::type_desc, fn chan_id_send<T: send>(t: *sys::type_desc,
target_task: task::task, target_port: port_id, target_task: task::task, target_port: port_id,
data: T) -> ctypes::uintptr_t; data: T) -> ctypes::uintptr_t;
@ -55,7 +55,7 @@ native mod rustrt {
#[abi = "rust-intrinsic"] #[abi = "rust-intrinsic"]
native mod rusti { native mod rusti {
fn call_with_retptr<send T>(&&f: fn@(*uint)) -> T; fn call_with_retptr<T: send>(&&f: fn@(*uint)) -> T;
} }
type port_id = int; type port_id = int;
@ -78,11 +78,11 @@ dropped.
Channels may be duplicated and themselves transmitted over other channels. Channels may be duplicated and themselves transmitted over other channels.
*/ */
tag chan<send T> { tag chan<T: send> {
chan_t(task::task, port_id); chan_t(task::task, port_id);
} }
resource port_ptr<send T>(po: *rustrt::rust_port) { resource port_ptr<T: send>(po: *rustrt::rust_port) {
// Once the port is detached it's guaranteed not to receive further // Once the port is detached it's guaranteed not to receive further
// messages // messages
rustrt::rust_port_detach(po); rustrt::rust_port_detach(po);
@ -106,7 +106,7 @@ transmitted. If a port value is copied, both copies refer to the same port.
Ports may be associated with multiple <chan>s. Ports may be associated with multiple <chan>s.
*/ */
tag port<send T> { port_t(@port_ptr<T>); } tag port<T: send> { port_t(@port_ptr<T>); }
/* /*
Function: send Function: send
@ -116,7 +116,7 @@ Sends data over a channel.
The sent data is moved into the channel, whereupon the caller loses access The sent data is moved into the channel, whereupon the caller loses access
to it. to it.
*/ */
fn send<send T>(ch: chan<T>, -data: T) { fn send<T: send>(ch: chan<T>, -data: T) {
let chan_t(t, p) = ch; let chan_t(t, p) = ch;
let res = rustrt::chan_id_send(sys::get_type_desc::<T>(), t, p, data); let res = rustrt::chan_id_send(sys::get_type_desc::<T>(), t, p, data);
if res != 0u unsafe { if res != 0u unsafe {
@ -131,7 +131,7 @@ Function: port
Constructs a port. Constructs a port.
*/ */
fn port<send T>() -> port<T> { fn port<T: send>() -> port<T> {
port_t(@port_ptr(rustrt::new_port(sys::size_of::<T>()))) port_t(@port_ptr(rustrt::new_port(sys::size_of::<T>())))
} }
@ -143,10 +143,10 @@ Receive from a port.
If no data is available on the port then the task will block until data If no data is available on the port then the task will block until data
becomes available. becomes available.
*/ */
fn recv<send T>(p: port<T>) -> T { recv_(***p) } fn recv<T: send>(p: port<T>) -> T { recv_(***p) }
// Receive on a raw port pointer // Receive on a raw port pointer
fn recv_<send T>(p: *rustrt::rust_port) -> T { fn recv_<T: send>(p: *rustrt::rust_port) -> T {
// FIXME: Due to issue 1185 we can't use a return pointer when // FIXME: Due to issue 1185 we can't use a return pointer when
// calling C code, and since we can't create our own return // calling C code, and since we can't create our own return
// pointer on the stack, we're going to call a little intrinsic // pointer on the stack, we're going to call a little intrinsic
@ -179,6 +179,6 @@ Constructs a channel.
The channel is bound to the port used to construct it. The channel is bound to the port used to construct it.
*/ */
fn chan<send T>(p: port<T>) -> chan<T> { fn chan<T: send>(p: port<T>) -> chan<T> {
chan_t(task::get_task(), rustrt::get_port_id(***p)) chan_t(task::get_task(), rustrt::get_port_id(***p))
} }

View File

@ -39,7 +39,7 @@ Function: lefts
Extracts from a vector of either all the left values. Extracts from a vector of either all the left values.
*/ */
fn lefts<copy T, U>(eithers: [t<T, U>]) -> [T] { fn lefts<T: copy, U>(eithers: [t<T, U>]) -> [T] {
let result: [T] = []; let result: [T] = [];
for elt: t<T, U> in eithers { for elt: t<T, U> in eithers {
alt elt { left(l) { result += [l]; } _ {/* fallthrough */ } } alt elt { left(l) { result += [l]; } _ {/* fallthrough */ } }
@ -52,7 +52,7 @@ Function: rights
Extracts from a vector of either all the right values Extracts from a vector of either all the right values
*/ */
fn rights<T, copy U>(eithers: [t<T, U>]) -> [U] { fn rights<T, U: copy>(eithers: [t<T, U>]) -> [U] {
let result: [U] = []; let result: [U] = [];
for elt: t<T, U> in eithers { for elt: t<T, U> in eithers {
alt elt { right(r) { result += [r]; } _ {/* fallthrough */ } } alt elt { right(r) { result += [r]; } _ {/* fallthrough */ } }
@ -68,7 +68,7 @@ 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 Returns a structure containing a vector of left values and a vector of
right values. right values.
*/ */
fn partition<copy T, copy U>(eithers: [t<T, U>]) fn partition<T: copy, U: copy>(eithers: [t<T, U>])
-> {lefts: [T], rights: [U]} { -> {lefts: [T], rights: [U]} {
let lefts: [T] = []; let lefts: [T] = [];
let rights: [U] = []; let rights: [U] = [];
@ -83,7 +83,7 @@ Function: flip
Flips between left and right of a given either Flips between left and right of a given either
*/ */
pure fn flip<copy T, copy U>(eith: t<T, U>) -> t<U, T> { pure fn flip<T: copy, U: copy>(eith: t<T, U>) -> t<U, T> {
alt eith { alt eith {
right(r) { left(r) } right(r) { left(r) }
left(l) { right(l) } left(l) { right(l) }
@ -96,7 +96,7 @@ Function: to_result
Converts either::t to a result::t, making the "right" choice Converts either::t to a result::t, making the "right" choice
an ok result, and the "left" choice a fail an ok result, and the "left" choice a fail
*/ */
pure fn to_result<copy T, copy U>(eith: t<T, U>) -> result::t<U, T> { pure fn to_result<T: copy, U: copy>(eith: t<T, U>) -> result::t<U, T> {
alt eith { alt eith {
right(r) { result::ok(r) } right(r) { result::ok(r) }
left(l) { result::err(l) } left(l) { result::err(l) }

View File

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

View File

@ -30,13 +30,13 @@ Failure:
Fails if the value equals `none`. Fails if the value equals `none`.
*/ */
pure fn get<copy T>(opt: t<T>) -> T { pure fn get<T: copy>(opt: t<T>) -> T {
alt opt { some(x) { ret x; } none. { fail "option none"; } } alt opt { some(x) { ret x; } none. { fail "option none"; } }
} }
/* /*
*/ */
fn map<T, copy U>(opt: t<T>, f: block(T) -> U) -> t<U> { fn map<T, U: copy>(opt: t<T>, f: block(T) -> U) -> t<U> {
alt opt { some(x) { some(f(x)) } none. { none } } alt opt { some(x) { some(f(x)) } none. { none } }
} }
@ -61,7 +61,7 @@ Function: from_maybe
Returns the contained value or a default Returns the contained value or a default
*/ */
pure fn from_maybe<copy T>(def: T, opt: t<T>) -> T { pure fn from_maybe<T: copy>(def: T, opt: t<T>) -> T {
alt opt { some(x) { x } none. { def } } alt opt { some(x) { x } none. { def } }
} }
@ -70,7 +70,7 @@ Function: maybe
Applies a function to the contained value or returns a default Applies a function to the contained value or returns a default
*/ */
fn maybe<T, copy U>(def: U, opt: t<T>, f: block(T) -> U) -> U { fn maybe<T, U: copy>(def: U, opt: t<T>, f: block(T) -> U) -> U {
alt opt { none. { def } some(t) { f(t) } } alt opt { none. { def } some(t) { f(t) } }
} }

View File

@ -37,7 +37,7 @@ Failure:
If the result is an error If the result is an error
*/ */
fn get<copy T, U>(res: t<T, U>) -> T { fn get<T: copy, U>(res: t<T, U>) -> T {
alt res { alt res {
ok(t) { t } ok(t) { t }
err(_) { err(_) {
@ -57,7 +57,7 @@ Failure:
If the result is not an error If the result is not an error
*/ */
fn get_err<T, copy U>(res: t<T, U>) -> U { fn get_err<T, U: copy>(res: t<T, U>) -> U {
alt res { alt res {
err(u) { u } err(u) { u }
ok(_) { ok(_) {
@ -87,7 +87,7 @@ pure fn failure<T, U>(res: t<T, U>) -> bool {
!success(res) !success(res)
} }
pure fn to_either<copy T, copy U>(res: t<U, T>) -> either::t<T, U> { pure fn to_either<T: copy, U: copy>(res: t<U, T>) -> either::t<T, U> {
alt res { alt res {
ok(res) { either::right(res) } ok(res) { either::right(res) }
err(fail_) { either::left(fail_) } err(fail_) { either::left(fail_) }
@ -110,7 +110,7 @@ Example:
> }) > })
*/ */
fn chain<T, copy U, copy V>(res: t<T, V>, op: block(T) -> t<U, V>) fn chain<T, U: copy, V: copy>(res: t<T, V>, op: block(T) -> t<U, V>)
-> t<U, V> { -> t<U, V> {
alt res { alt res {
ok(t) { op(t) } ok(t) { op(t) }

View File

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

View File

@ -121,7 +121,7 @@ Creates and initializes an immutable vector.
Creates an immutable vector of size `n_elts` and initializes the elements Creates an immutable vector of size `n_elts` and initializes the elements
to the value `t`. to the value `t`.
*/ */
fn init_elt<copy T>(t: T, n_elts: uint) -> [T] { fn init_elt<T: copy>(t: T, n_elts: uint) -> [T] {
let v = []; let v = [];
reserve(v, n_elts); reserve(v, n_elts);
let i: uint = 0u; 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 Creates a mutable vector of size `n_elts` and initializes the elements
to the value `t`. to the value `t`.
*/ */
fn init_elt_mut<copy T>(t: T, n_elts: uint) -> [mutable T] { fn init_elt_mut<T: copy>(t: T, n_elts: uint) -> [mutable T] {
let v = [mutable]; let v = [mutable];
reserve(v, n_elts); reserve(v, n_elts);
let i: uint = 0u; let i: uint = 0u;
@ -153,7 +153,7 @@ Function: to_mut
Produces a mutable vector from an immutable vector. Produces a mutable vector from an immutable vector.
*/ */
fn to_mut<copy T>(v: [T]) -> [mutable T] { fn to_mut<T: copy>(v: [T]) -> [mutable T] {
let vres = [mutable]; let vres = [mutable];
for t: T in v { vres += [mutable t]; } for t: T in v { vres += [mutable t]; }
ret vres; ret vres;
@ -165,7 +165,7 @@ Function: from_mut
Produces an immutable vector from a mutable vector. Produces an immutable vector from a mutable vector.
*/ */
fn from_mut<copy T>(v: [mutable T]) -> [T] { fn from_mut<T: copy>(v: [mutable T]) -> [T] {
let vres = []; let vres = [];
for t: T in v { vres += [t]; } for t: T in v { vres += [t]; }
ret vres; ret vres;
@ -181,7 +181,7 @@ Returns the first element of a vector
Predicates: Predicates:
<is_not_empty> (v) <is_not_empty> (v)
*/ */
pure fn head<copy T>(v: [const T]) : is_not_empty(v) -> T { ret v[0]; } pure fn head<T: copy>(v: [const T]) : is_not_empty(v) -> T { ret v[0]; }
/* /*
Function: tail Function: tail
@ -191,7 +191,7 @@ Returns all but the first element of a vector
Predicates: Predicates:
<is_not_empty> (v) <is_not_empty> (v)
*/ */
fn tail<copy T>(v: [const T]) : is_not_empty(v) -> [T] { fn tail<T: copy>(v: [const T]) : is_not_empty(v) -> [T] {
ret slice(v, 1u, len(v)); ret slice(v, 1u, len(v));
} }
@ -206,7 +206,7 @@ Returns all but the last elemnt of a vector
Preconditions: Preconditions:
`v` is not empty `v` is not empty
*/ */
fn init<copy T>(v: [const T]) -> [T] { fn init<T: copy>(v: [const T]) -> [T] {
assert len(v) != 0u; assert len(v) != 0u;
slice(v, 0u, len(v) - 1u) 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 An option containing the last element of `v` if `v` is not empty, or
none if `v` is empty. none if `v` is empty.
*/ */
pure fn last<copy T>(v: [const T]) -> option::t<T> { pure fn last<T: copy>(v: [const T]) -> option::t<T> {
if len(v) == 0u { ret none; } if len(v) == 0u { ret none; }
ret some(v[len(v) - 1u]); ret some(v[len(v) - 1u]);
} }
@ -234,7 +234,7 @@ Returns the last element of a non-empty vector `v`
Predicates: Predicates:
<is_not_empty> (v) <is_not_empty> (v)
*/ */
pure fn last_total<copy T>(v: [const T]) : is_not_empty(v) -> T { pure fn last_total<T: copy>(v: [const T]) : is_not_empty(v) -> T {
ret v[len(v) - 1u]; ret v[len(v) - 1u];
} }
@ -243,7 +243,7 @@ Function: slice
Returns a copy of the elements from [`start`..`end`) from `v`. Returns a copy of the elements from [`start`..`end`) from `v`.
*/ */
fn slice<copy T>(v: [const T], start: uint, end: uint) -> [T] { fn slice<T: copy>(v: [const T], start: uint, end: uint) -> [T] {
assert (start <= end); assert (start <= end);
assert (end <= len(v)); assert (end <= len(v));
let result = []; let result = [];
@ -259,7 +259,7 @@ Function: slice_mut
Returns a copy of the elements from [`start`..`end`) from `v`. Returns a copy of the elements from [`start`..`end`) from `v`.
*/ */
fn slice_mut<copy T>(v: [const T], start: uint, end: uint) -> [mutable T] { fn slice_mut<T: copy>(v: [const T], start: uint, end: uint) -> [mutable T] {
assert (start <= end); assert (start <= end);
assert (end <= len(v)); assert (end <= len(v));
let result = [mutable]; let result = [mutable];
@ -277,7 +277,7 @@ Function: shift
Removes the first element from a vector and return it Removes the first element from a vector and return it
*/ */
fn shift<copy T>(&v: [const T]) -> T { fn shift<T: copy>(&v: [const T]) -> T {
let ln = len::<T>(v); let ln = len::<T>(v);
assert (ln > 0u); assert (ln > 0u);
let e = v[0]; let e = v[0];
@ -291,7 +291,7 @@ Function: pop
Remove the last element from a vector and return it Remove the last element from a vector and return it
*/ */
fn pop<copy T>(&v: [const T]) -> T { fn pop<T: copy>(&v: [const T]) -> T {
let ln = len(v); let ln = len(v);
assert (ln > 0u); assert (ln > 0u);
ln -= 1u; ln -= 1u;
@ -305,7 +305,7 @@ Function: push
Append an element to a vector and return it Append an element to a vector and return it
*/ */
fn push<copy T>(&v: [T], initval: T) { fn push<T: copy>(&v: [T], initval: T) {
grow(v, 1u, initval) grow(v, 1u, initval)
} }
@ -325,7 +325,7 @@ v - The vector to grow
n - The number of elements to add n - The number of elements to add
initval - The value for the new elements initval - The value for the new elements
*/ */
fn grow<copy T>(&v: [T], n: uint, initval: T) { fn grow<T: copy>(&v: [T], n: uint, initval: T) {
reserve(v, next_power_of_two(len(v) + n)); reserve(v, next_power_of_two(len(v) + n));
let i: uint = 0u; let i: uint = 0u;
while i < n { v += [initval]; i += 1u; } while i < n { v += [initval]; i += 1u; }
@ -344,7 +344,7 @@ v - The vector to grow
n - The number of elements to add n - The number of elements to add
initval - The value for the new elements initval - The value for the new elements
*/ */
fn grow_mut<copy T>(&v: [mutable T], n: uint, initval: T) { fn grow_mut<T: copy>(&v: [mutable T], n: uint, initval: T) {
reserve(v, next_power_of_two(len(v) + n)); reserve(v, next_power_of_two(len(v) + n));
let i: uint = 0u; let i: uint = 0u;
while i < n { v += [mutable initval]; i += 1u; } while i < n { v += [mutable initval]; i += 1u; }
@ -380,7 +380,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 of the vector, expands the vector by replicating `initval` to fill the
intervening space. intervening space.
*/ */
fn grow_set<copy T>(&v: [mutable T], index: uint, initval: T, val: T) { fn grow_set<T: copy>(&v: [mutable T], index: uint, initval: T, val: T) {
if index >= len(v) { grow_mut(v, index - len(v) + 1u, initval); } if index >= len(v) { grow_mut(v, index - len(v) + 1u, initval); }
v[index] = val; v[index] = val;
} }
@ -405,7 +405,7 @@ Function: map_mut
Apply a function to each element of a mutable vector and return the results Apply a function to each element of a mutable vector and return the results
*/ */
fn map_mut<copy T, U>(v: [const T], f: block(T) -> U) -> [U] { fn map_mut<T: copy, U>(v: [const T], f: block(T) -> U) -> [U] {
let result = []; let result = [];
reserve(result, len(v)); reserve(result, len(v));
for elem: T in v { for elem: T in v {
@ -420,7 +420,7 @@ Function: map2
Apply a function to each pair of elements and return the results Apply a function to each pair of elements and return the results
*/ */
fn map2<copy T, copy U, V>(v0: [T], v1: [U], f: block(T, U) -> V) -> [V] { fn map2<T: copy, U: copy, V>(v0: [T], v1: [U], f: block(T, U) -> V) -> [V] {
let v0_len = len(v0); let v0_len = len(v0);
if v0_len != len(v1) { fail; } if v0_len != len(v1) { fail; }
let u: [V] = []; let u: [V] = [];
@ -437,7 +437,7 @@ Apply a function to each element of a vector and return the results
If function `f` returns `none` then that element is excluded from If function `f` returns `none` then that element is excluded from
the resulting vector. the resulting vector.
*/ */
fn filter_map<copy T, copy U>(v: [const T], f: block(T) -> option::t<U>) fn filter_map<T: copy, U: copy>(v: [const T], f: block(T) -> option::t<U>)
-> [U] { -> [U] {
let result = []; let result = [];
for elem: T in v { for elem: T in v {
@ -458,7 +458,7 @@ holds.
Apply function `f` to each element of `v` and return a vector containing Apply function `f` to each element of `v` and return a vector containing
only those elements for which `f` returned true. only those elements for which `f` returned true.
*/ */
fn filter<copy T>(v: [T], f: block(T) -> bool) -> [T] { fn filter<T: copy>(v: [T], f: block(T) -> bool) -> [T] {
let result = []; let result = [];
for elem: T in v { for elem: T in v {
if f(elem) { result += [elem]; } if f(elem) { result += [elem]; }
@ -472,7 +472,7 @@ Function: concat
Concatenate a vector of vectors. Flattens a vector of vectors of T into Concatenate a vector of vectors. Flattens a vector of vectors of T into
a single vector of T. a single vector of T.
*/ */
fn concat<copy T>(v: [const [const T]]) -> [T] { fn concat<T: copy>(v: [const [const T]]) -> [T] {
let new: [T] = []; let new: [T] = [];
for inner: [T] in v { new += inner; } for inner: [T] in v { new += inner; }
ret new; ret new;
@ -483,7 +483,7 @@ Function: foldl
Reduce a vector from left to right Reduce a vector from left to right
*/ */
fn foldl<copy T, U>(z: T, v: [const U], p: block(T, U) -> T) -> T { fn foldl<T: copy, U>(z: T, v: [const U], p: block(T, U) -> T) -> T {
let accum = z; let accum = z;
iter(v) { |elt| iter(v) { |elt|
accum = p(accum, elt); accum = p(accum, elt);
@ -496,7 +496,7 @@ Function: foldr
Reduce a vector from right to left Reduce a vector from right to left
*/ */
fn foldr<T, copy U>(v: [const T], z: U, p: block(T, U) -> U) -> U { fn foldr<T, U: copy>(v: [const T], z: U, p: block(T, U) -> U) -> U {
let accum = z; let accum = z;
riter(v) { |elt| riter(v) { |elt|
accum = p(elt, accum); accum = p(elt, accum);
@ -591,7 +591,7 @@ Apply function `f` to each element of `v`, starting from the first.
When function `f` returns true then an option containing the element When function `f` returns true then an option containing the element
is returned. If `f` matches no elements then none is returned. is returned. If `f` matches no elements then none is returned.
*/ */
fn find<copy T>(v: [T], f: block(T) -> bool) -> option::t<T> { fn find<T: copy>(v: [T], f: block(T) -> bool) -> option::t<T> {
for elt: T in v { if f(elt) { ret some(elt); } } for elt: T in v { if f(elt) { ret some(elt); } }
ret none; ret none;
} }
@ -637,7 +637,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 and the i-th element of the second vector contains the second element
of the i-th tuple of the input vector. of the i-th tuple of the input vector.
*/ */
fn unzip<copy T, copy U>(v: [(T, U)]) -> ([T], [U]) { fn unzip<T: copy, U: copy>(v: [(T, U)]) -> ([T], [U]) {
let as = [], bs = []; let as = [], bs = [];
for (a, b) in v { as += [a]; bs += [b]; } for (a, b) in v { as += [a]; bs += [b]; }
ret (as, bs); ret (as, bs);
@ -655,7 +655,7 @@ Preconditions:
<same_length> (v, u) <same_length> (v, u)
*/ */
fn zip<copy T, copy U>(v: [T], u: [U]) : same_length(v, u) -> [(T, U)] { fn zip<T: copy, U: copy>(v: [T], u: [U]) : same_length(v, u) -> [(T, U)] {
let zipped = []; let zipped = [];
let sz = len(v), i = 0u; let sz = len(v), i = 0u;
assert (sz == len(u)); assert (sz == len(u));
@ -694,7 +694,7 @@ Function: reversed
Returns a vector with the order of elements reversed Returns a vector with the order of elements reversed
*/ */
fn reversed<copy T>(v: [const T]) -> [T] { fn reversed<T: copy>(v: [const T]) -> [T] {
let rs: [T] = []; let rs: [T] = [];
let i = len::<T>(v); let i = len::<T>(v);
if i == 0u { ret rs; } else { i -= 1u; } if i == 0u { ret rs; } else { i -= 1u; }
@ -805,7 +805,7 @@ is sorted then the permutations are lexicographically sorted).
The total number of permutations produced is `len(v)!`. If `v` contains The total number of permutations produced is `len(v)!`. If `v` contains
repeated elements, then some permutations are repeated. repeated elements, then some permutations are repeated.
*/ */
fn permute<copy T>(v: [const T], put: block([T])) { fn permute<T: copy>(v: [const T], put: block([T])) {
let ln = len(v); let ln = len(v);
if ln == 0u { if ln == 0u {
put([]); put([]);

View File

@ -108,7 +108,7 @@ Failure:
If `ofs` is greater or equal to the length of the vector If `ofs` is greater or equal to the length of the vector
*/ */
fn get<copy T>(t: t<T>, ofs: uint) -> T { fn get<T: copy>(t: t<T>, ofs: uint) -> T {
assert ofs < (*t).size; assert ofs < (*t).size;
ret unsafe { *ptr::mut_offset((*t).base, ofs) }; ret unsafe { *ptr::mut_offset((*t).base, ofs) };
} }
@ -122,7 +122,7 @@ Failure:
If `ofs` is greater or equal to the length of the vector If `ofs` is greater or equal to the length of the vector
*/ */
fn set<copy T>(t: t<T>, ofs: uint, v: T) { fn set<T: copy>(t: t<T>, ofs: uint, v: T) {
assert ofs < (*t).size; assert ofs < (*t).size;
unsafe { *ptr::mut_offset((*t).base, ofs) = v }; unsafe { *ptr::mut_offset((*t).base, ofs) = v };
} }

View File

@ -41,7 +41,7 @@ native mod rustrt {
type void; type void;
type rust_port; type rust_port;
fn chan_id_send<send T>(t: *sys::type_desc, fn chan_id_send<T: send>(t: *sys::type_desc,
target_task: task::task, target_port: port_id, target_task: task::task, target_port: port_id,
data: T) -> ctypes::uintptr_t; data: T) -> ctypes::uintptr_t;
@ -57,7 +57,7 @@ native mod rustrt {
#[abi = "rust-intrinsic"] #[abi = "rust-intrinsic"]
native mod rusti { native mod rusti {
fn call_with_retptr<send T>(&&f: fn@(*uint)) -> T; fn call_with_retptr<T: send>(&&f: fn@(*uint)) -> T;
} }
type port_id = int; type port_id = int;
@ -80,11 +80,11 @@ dropped.
Channels may be duplicated and themselves transmitted over other channels. Channels may be duplicated and themselves transmitted over other channels.
*/ */
tag chan<send T> { tag chan<T: send> {
chan_t(task::task, port_id); chan_t(task::task, port_id);
} }
resource port_ptr<send T>(po: *rustrt::rust_port) { resource port_ptr<T: send>(po: *rustrt::rust_port) {
// Once the port is detached it's guaranteed not to receive further // Once the port is detached it's guaranteed not to receive further
// messages // messages
rustrt::rust_port_detach(po); rustrt::rust_port_detach(po);
@ -108,7 +108,7 @@ transmitted. If a port value is copied, both copies refer to the same port.
Ports may be associated with multiple <chan>s. Ports may be associated with multiple <chan>s.
*/ */
tag port<send T> { port_t(@port_ptr<T>); } tag port<T: send> { port_t(@port_ptr<T>); }
/* /*
Function: send Function: send
@ -118,7 +118,7 @@ Sends data over a channel.
The sent data is moved into the channel, whereupon the caller loses access The sent data is moved into the channel, whereupon the caller loses access
to it. to it.
*/ */
fn send<send T>(ch: chan<T>, -data: T) { fn send<T: send>(ch: chan<T>, -data: T) {
let chan_t(t, p) = ch; let chan_t(t, p) = ch;
let res = rustrt::chan_id_send(sys::get_type_desc::<T>(), t, p, data); let res = rustrt::chan_id_send(sys::get_type_desc::<T>(), t, p, data);
if res != 0u unsafe { if res != 0u unsafe {
@ -133,7 +133,7 @@ Function: port
Constructs a port. Constructs a port.
*/ */
fn port<send T>() -> port<T> { fn port<T: send>() -> port<T> {
port_t(@port_ptr(rustrt::new_port(sys::size_of::<T>()))) port_t(@port_ptr(rustrt::new_port(sys::size_of::<T>())))
} }
@ -145,10 +145,10 @@ Receive from a port.
If no data is available on the port then the task will block until data If no data is available on the port then the task will block until data
becomes available. becomes available.
*/ */
fn recv<send T>(p: port<T>) -> T { recv_(***p) } fn recv<T: send>(p: port<T>) -> T { recv_(***p) }
// Receive on a raw port pointer // Receive on a raw port pointer
fn recv_<send T>(p: *rustrt::rust_port) -> T { fn recv_<T: send>(p: *rustrt::rust_port) -> T {
// FIXME: Due to issue 1185 we can't use a return pointer when // FIXME: Due to issue 1185 we can't use a return pointer when
// calling C code, and since we can't create our own return // calling C code, and since we can't create our own return
// pointer on the stack, we're going to call a little intrinsic // pointer on the stack, we're going to call a little intrinsic
@ -181,6 +181,6 @@ Constructs a channel.
The channel is bound to the port used to construct it. The channel is bound to the port used to construct it.
*/ */
fn chan<send T>(p: port<T>) -> chan<T> { fn chan<T: send>(p: port<T>) -> chan<T> {
chan_t(task::get_task(), rustrt::get_port_id(***p)) chan_t(task::get_task(), rustrt::get_port_id(***p))
} }

View File

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

View File

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

View File

@ -27,7 +27,7 @@ Function: from_vec
Create a list from a vector Create a list from a vector
*/ */
fn from_vec<copy T>(v: [const T]) -> list<T> { fn from_vec<T: copy>(v: [const T]) -> list<T> {
*vec::foldr(v, @nil::<T>, { |h, t| @cons(h, t) }) *vec::foldr(v, @nil::<T>, { |h, t| @cons(h, t) })
} }
@ -46,7 +46,7 @@ ls - The list to fold
z - The initial value z - The initial value
f - The function to apply f - The function to apply
*/ */
fn foldl<copy T, U>(ls: list<U>, z: T, f: block(T, U) -> T) -> T { fn foldl<T: copy, U>(ls: list<U>, z: T, f: block(T, U) -> T) -> T {
let accum: T = z; let accum: T = z;
iter(ls) {|elt| accum = f(accum, elt);} iter(ls) {|elt| accum = f(accum, elt);}
accum accum
@ -61,7 +61,7 @@ Apply function `f` to each element of `v`, starting from the first.
When function `f` returns true then an option containing the element When function `f` returns true then an option containing the element
is returned. If `f` matches no elements then none is returned. is returned. If `f` matches no elements then none is returned.
*/ */
fn find<copy T, copy U>(ls: list<T>, f: block(T) -> option::t<U>) fn find<T: copy, U: copy>(ls: list<T>, f: block(T) -> option::t<U>)
-> option::t<U> { -> option::t<U> {
let ls = ls; let ls = ls;
while true { while true {
@ -80,7 +80,7 @@ Function: has
Returns true if a list contains an element with the given value Returns true if a list contains an element with the given value
*/ */
fn has<copy T>(ls: list<T>, elt: T) -> bool { fn has<T: copy>(ls: list<T>, elt: T) -> bool {
let ls = ls; let ls = ls;
while true { while true {
alt ls { alt ls {
@ -96,7 +96,7 @@ Function: is_empty
Returns true if the list is empty. Returns true if the list is empty.
*/ */
pure fn is_empty<copy T>(ls: list<T>) -> bool { pure fn is_empty<T: copy>(ls: list<T>) -> bool {
alt ls { alt ls {
nil. { true } nil. { true }
_ { false } _ { false }
@ -108,7 +108,7 @@ Function: is_not_empty
Returns true if the list is not empty. Returns true if the list is not empty.
*/ */
pure fn is_not_empty<copy T>(ls: list<T>) -> bool { pure fn is_not_empty<T: copy>(ls: list<T>) -> bool {
ret !is_empty(ls); ret !is_empty(ls);
} }
@ -128,7 +128,7 @@ Function: tail
Returns all but the first element of a list Returns all but the first element of a list
*/ */
pure fn tail<copy T>(ls: list<T>) : is_not_empty(ls) -> list<T> { pure fn tail<T: copy>(ls: list<T>) : is_not_empty(ls) -> list<T> {
alt ls { alt ls {
cons(_, tl) { ret *tl; } cons(_, tl) { ret *tl; }
nil. { fail "list empty" } nil. { fail "list empty" }
@ -140,7 +140,7 @@ Function: head
Returns the first element of a list Returns the first element of a list
*/ */
pure fn head<copy T>(ls: list<T>) : is_not_empty(ls) -> T { pure fn head<T: copy>(ls: list<T>) : is_not_empty(ls) -> T {
alt ls { alt ls {
cons(hd, _) { ret hd; } cons(hd, _) { ret hd; }
nil. { fail "list empty" } nil. { fail "list empty" }
@ -152,7 +152,7 @@ Function: append
Appends one list to another Appends one list to another
*/ */
pure fn append<copy T>(l: list<T>, m: list<T>) -> list<T> { pure fn append<T: copy>(l: list<T>, m: list<T>) -> list<T> {
alt l { alt l {
nil. { ret m; } nil. { ret m; }
cons(x, xs) { let rest = append(*xs, m); ret cons(x, @rest); } cons(x, xs) { let rest = append(*xs, m); ret cons(x, @rest); }

View File

@ -108,32 +108,32 @@ type hashmap<K, V> = obj {
/* Section: Operations */ /* Section: Operations */
mod chained { mod chained {
type entry<copy K, copy V> = { type entry<K: copy, V: copy> = {
hash: uint, hash: uint,
key: K, key: K,
mutable value: V, mutable value: V,
mutable next: chain<K, V> mutable next: chain<K, V>
}; };
tag chain<copy K, copy V> { tag chain<K: copy, V: copy> {
present(@entry<K, V>); present(@entry<K, V>);
absent; absent;
} }
type t<copy K, copy V> = { type t<K: copy, V: copy> = {
mutable size: uint, mutable size: uint,
mutable chains: [mutable chain<K,V>], mutable chains: [mutable chain<K,V>],
hasher: hashfn<K>, hasher: hashfn<K>,
eqer: eqfn<K> eqer: eqfn<K>
}; };
tag search_result<copy K, copy V> { tag search_result<K: copy, V: copy> {
not_found; not_found;
found_first(uint, @entry<K,V>); found_first(uint, @entry<K,V>);
found_after(@entry<K,V>, @entry<K,V>); found_after(@entry<K,V>, @entry<K,V>);
} }
fn search_rem<copy K, copy V>(tbl: t<K,V>, fn search_rem<K: copy, V: copy>(tbl: t<K,V>,
k: K, k: K,
h: uint, h: uint,
idx: uint, idx: uint,
@ -163,7 +163,7 @@ mod chained {
util::unreachable(); util::unreachable();
} }
fn search_tbl<copy K, copy V>( fn search_tbl<K: copy, V: copy>(
tbl: t<K,V>, k: K, h: uint) -> search_result<K,V> { tbl: t<K,V>, k: K, h: uint) -> search_result<K,V> {
let idx = h % vec::len(tbl.chains); let idx = h % vec::len(tbl.chains);
alt tbl.chains[idx] { alt tbl.chains[idx] {
@ -185,7 +185,7 @@ mod chained {
} }
} }
fn insert<copy K, copy V>(tbl: t<K,V>, k: K, v: V) -> bool { fn insert<K: copy, V: copy>(tbl: t<K,V>, k: K, v: V) -> bool {
let hash = tbl.hasher(k); let hash = tbl.hasher(k);
alt search_tbl(tbl, k, hash) { alt search_tbl(tbl, k, hash) {
not_found. { not_found. {
@ -210,7 +210,7 @@ mod chained {
} }
} }
fn get<copy K, copy V>(tbl: t<K,V>, k: K) -> core::option::t<V> { fn get<K: copy, V: copy>(tbl: t<K,V>, k: K) -> core::option::t<V> {
alt search_tbl(tbl, k, tbl.hasher(k)) { alt search_tbl(tbl, k, tbl.hasher(k)) {
not_found. { not_found. {
ret core::option::none; ret core::option::none;
@ -226,7 +226,7 @@ mod chained {
} }
} }
fn remove<copy K, copy V>(tbl: t<K,V>, k: K) -> core::option::t<V> { fn remove<K: copy, V: copy>(tbl: t<K,V>, k: K) -> core::option::t<V> {
alt search_tbl(tbl, k, tbl.hasher(k)) { alt search_tbl(tbl, k, tbl.hasher(k)) {
not_found. { not_found. {
ret core::option::none; ret core::option::none;
@ -246,11 +246,11 @@ mod chained {
} }
} }
fn chains<copy K, copy V>(nchains: uint) -> [mutable chain<K,V>] { fn chains<K: copy, V: copy>(nchains: uint) -> [mutable chain<K,V>] {
ret vec::init_elt_mut(absent, nchains); ret vec::init_elt_mut(absent, nchains);
} }
fn foreach_entry<copy K, copy V>(chain0: chain<K,V>, fn foreach_entry<K: copy, V: copy>(chain0: chain<K,V>,
blk: block(@entry<K,V>)) { blk: block(@entry<K,V>)) {
let chain = chain0; let chain = chain0;
while true { while true {
@ -265,7 +265,7 @@ mod chained {
} }
} }
fn foreach_chain<copy K, copy V>(chains: [const chain<K,V>], fn foreach_chain<K: copy, V: copy>(chains: [const chain<K,V>],
blk: block(@entry<K,V>)) { blk: block(@entry<K,V>)) {
let i = 0u, n = vec::len(chains); let i = 0u, n = vec::len(chains);
while i < n { while i < n {
@ -274,7 +274,7 @@ mod chained {
} }
} }
fn rehash<copy K, copy V>(tbl: t<K,V>) { fn rehash<K: copy, V: copy>(tbl: t<K,V>) {
let old_chains = tbl.chains; let old_chains = tbl.chains;
let n_old_chains = vec::len(old_chains); let n_old_chains = vec::len(old_chains);
let n_new_chains: uint = uint::next_power_of_two(n_old_chains + 1u); let n_new_chains: uint = uint::next_power_of_two(n_old_chains + 1u);
@ -286,7 +286,7 @@ mod chained {
} }
} }
fn items<copy K, copy V>(tbl: t<K,V>, blk: block(K,V)) { fn items<K: copy, V: copy>(tbl: t<K,V>, blk: block(K,V)) {
let tbl_chains = tbl.chains; // Satisfy alias checker. let tbl_chains = tbl.chains; // Satisfy alias checker.
foreach_chain(tbl_chains) { |entry| foreach_chain(tbl_chains) { |entry|
let key = entry.key; let key = entry.key;
@ -295,7 +295,7 @@ mod chained {
} }
} }
obj o<copy K, copy V>(tbl: @t<K,V>, obj o<K: copy, V: copy>(tbl: @t<K,V>,
lf: util::rational) { lf: util::rational) {
fn size() -> uint { fn size() -> uint {
ret tbl.size; ret tbl.size;
@ -343,7 +343,8 @@ mod chained {
} }
} }
fn mk<copy K, copy V>(hasher: hashfn<K>, eqer: eqfn<K>) -> hashmap<K,V> { fn mk<K: copy, V: copy>(hasher: hashfn<K>, eqer: eqfn<K>)
-> hashmap<K,V> {
let initial_capacity: uint = 32u; // 2^5 let initial_capacity: uint = 32u; // 2^5
let t = @{mutable size: 0u, let t = @{mutable size: 0u,
mutable chains: chains(initial_capacity), mutable chains: chains(initial_capacity),
@ -363,7 +364,7 @@ Parameters:
hasher - The hash function for key type K hasher - The hash function for key type K
eqer - The equality function for key type K eqer - The equality function for key type K
*/ */
fn mk_hashmap<copy K, copy V>(hasher: hashfn<K>, eqer: eqfn<K>) fn mk_hashmap<K: copy, V: copy>(hasher: hashfn<K>, eqer: eqfn<K>)
-> hashmap<K, V> { -> hashmap<K, V> {
ret chained::mk(hasher, eqer); ret chained::mk(hasher, eqer);
} }
@ -373,7 +374,7 @@ Function: new_str_hash
Construct a hashmap for string keys Construct a hashmap for string keys
*/ */
fn new_str_hash<copy V>() -> hashmap<str, V> { fn new_str_hash<V: copy>() -> hashmap<str, V> {
ret mk_hashmap(str::hash, str::eq); ret mk_hashmap(str::hash, str::eq);
} }
@ -382,7 +383,7 @@ Function: new_int_hash
Construct a hashmap for int keys Construct a hashmap for int keys
*/ */
fn new_int_hash<copy V>() -> hashmap<int, V> { fn new_int_hash<V: copy>() -> hashmap<int, V> {
fn hash_int(&&x: int) -> uint { ret x as uint; } fn hash_int(&&x: int) -> uint { ret x as uint; }
fn eq_int(&&a: int, &&b: int) -> bool { ret a == b; } fn eq_int(&&a: int, &&b: int) -> bool { ret a == b; }
ret mk_hashmap(hash_int, eq_int); ret mk_hashmap(hash_int, eq_int);
@ -393,7 +394,7 @@ Function: new_uint_hash
Construct a hashmap for uint keys Construct a hashmap for uint keys
*/ */
fn new_uint_hash<copy V>() -> hashmap<uint, V> { fn new_uint_hash<V: copy>() -> hashmap<uint, V> {
fn hash_uint(&&x: uint) -> uint { ret x; } fn hash_uint(&&x: uint) -> uint { ret x; }
fn eq_uint(&&a: uint, &&b: uint) -> bool { ret a == b; } fn eq_uint(&&a: uint, &&b: uint) -> bool { ret a == b; }
ret mk_hashmap(hash_uint, eq_uint); ret mk_hashmap(hash_uint, eq_uint);

View File

@ -30,7 +30,7 @@ Function: insert
Add a value to the map. If the map already contains a value for Add a value to the map. If the map already contains a value for
the specified key then the original value is replaced. the specified key then the original value is replaced.
*/ */
fn insert<copy T>(m: smallintmap<T>, key: uint, val: T) { fn insert<T: copy>(m: smallintmap<T>, key: uint, val: T) {
vec::grow_set::<option::t<T>>(m.v, key, none::<T>, some::<T>(val)); vec::grow_set::<option::t<T>>(m.v, key, none::<T>, some::<T>(val));
} }
@ -40,7 +40,7 @@ Function: find
Get the value for the specified key. If the key does not exist Get the value for the specified key. If the key does not exist
in the map then returns none. in the map then returns none.
*/ */
fn find<copy T>(m: smallintmap<T>, key: uint) -> option::t<T> { fn find<T: copy>(m: smallintmap<T>, key: uint) -> option::t<T> {
if key < vec::len::<option::t<T>>(m.v) { ret m.v[key]; } if key < vec::len::<option::t<T>>(m.v) { ret m.v[key]; }
ret none::<T>; ret none::<T>;
} }
@ -54,7 +54,7 @@ Failure:
If the key does not exist in the map If the key does not exist in the map
*/ */
fn get<copy T>(m: smallintmap<T>, key: uint) -> T { fn get<T: copy>(m: smallintmap<T>, key: uint) -> T {
alt find(m, key) { alt find(m, key) {
none. { #error("smallintmap::get(): key not present"); fail; } none. { #error("smallintmap::get(): key not present"); fail; }
some(v) { ret v; } some(v) { ret v; }
@ -66,13 +66,13 @@ Method: contains_key
Returns true if the map contains a value for the specified key Returns true if the map contains a value for the specified key
*/ */
fn contains_key<copy T>(m: smallintmap<T>, key: uint) -> bool { fn contains_key<T: copy>(m: smallintmap<T>, key: uint) -> bool {
ret !option::is_none(find::<T>(m, key)); ret !option::is_none(find::<T>(m, key));
} }
// FIXME: Are these really useful? // FIXME: Are these really useful?
fn truncate<copy T>(m: smallintmap<T>, len: uint) { fn truncate<T: copy>(m: smallintmap<T>, len: uint) {
m.v = vec::slice_mut::<option::t<T>>(m.v, 0u, len); 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 Has worst case O(n log n) performance, best case O(n), but
is not space efficient. This is a stable sort. is not space efficient. This is a stable sort.
*/ */
fn merge_sort<copy T>(le: lteq<T>, v: [const T]) -> [T] { fn merge_sort<T: copy>(le: lteq<T>, v: [const T]) -> [T] {
fn merge<copy T>(le: lteq<T>, a: [T], b: [T]) -> [T] { fn merge<T: copy>(le: lteq<T>, a: [T], b: [T]) -> [T] {
let rs: [T] = []; let rs: [T] = [];
let a_len: uint = len::<T>(a); let a_len: uint = len::<T>(a);
let a_ix: uint = 0u; let a_ix: uint = 0u;
@ -46,7 +46,7 @@ fn merge_sort<copy T>(le: lteq<T>, v: [const T]) -> [T] {
ret merge::<T>(le, merge_sort::<T>(le, a), merge_sort::<T>(le, b)); ret merge::<T>(le, merge_sort::<T>(le, a), merge_sort::<T>(le, b));
} }
fn part<copy T>(compare_func: lteq<T>, arr: [mutable T], left: uint, fn part<T: copy>(compare_func: lteq<T>, arr: [mutable T], left: uint,
right: uint, pivot: uint) -> uint { right: uint, pivot: uint) -> uint {
let pivot_value = arr[pivot]; let pivot_value = arr[pivot];
arr[pivot] <-> arr[right]; arr[pivot] <-> arr[right];
@ -63,7 +63,7 @@ fn part<copy T>(compare_func: lteq<T>, arr: [mutable T], left: uint,
ret storage_index; ret storage_index;
} }
fn qsort<copy T>(compare_func: lteq<T>, arr: [mutable T], left: uint, fn qsort<T: copy>(compare_func: lteq<T>, arr: [mutable T], left: uint,
right: uint) { right: uint) {
if right > left { if right > left {
let pivot = (left + right) / 2u; let pivot = (left + right) / 2u;
@ -84,12 +84,12 @@ Quicksort. Sorts a mutable vector in place.
Has worst case O(n^2) performance, average case O(n log n). Has worst case O(n^2) performance, average case O(n log n).
This is an unstable sort. This is an unstable sort.
*/ */
fn quick_sort<copy T>(compare_func: lteq<T>, arr: [mutable T]) { fn quick_sort<T: copy>(compare_func: lteq<T>, arr: [mutable T]) {
if len::<T>(arr) == 0u { ret; } if len::<T>(arr) == 0u { ret; }
qsort::<T>(compare_func, arr, 0u, len::<T>(arr) - 1u); qsort::<T>(compare_func, arr, 0u, len::<T>(arr) - 1u);
} }
fn qsort3<copy T>(compare_func_lt: lteq<T>, compare_func_eq: lteq<T>, fn qsort3<T: copy>(compare_func_lt: lteq<T>, compare_func_eq: lteq<T>,
arr: [mutable T], left: int, right: int) { arr: [mutable T], left: int, right: int) {
if right <= left { ret; } if right <= left { ret; }
let v: T = arr[right]; let v: T = arr[right];
@ -150,7 +150,7 @@ According to these slides this is the algorithm of choice for
This is an unstable sort. This is an unstable sort.
*/ */
fn quick_sort3<copy T>(compare_func_lt: lteq<T>, compare_func_eq: lteq<T>, fn quick_sort3<T: copy>(compare_func_lt: lteq<T>, compare_func_eq: lteq<T>,
arr: [mutable T]) { arr: [mutable T]) {
if len::<T>(arr) == 0u { ret; } if len::<T>(arr) == 0u { ret; }
qsort3::<T>(compare_func_lt, compare_func_eq, arr, 0, qsort3::<T>(compare_func_lt, compare_func_eq, arr, 0,

View File

@ -115,7 +115,7 @@ fn run_tests_console(opts: test_opts,
run_tests_console_(opts, tests, default_test_to_task) run_tests_console_(opts, tests, default_test_to_task)
} }
fn run_tests_console_<copy T>(opts: test_opts, tests: [test_desc<T>], fn run_tests_console_<T: copy>(opts: test_opts, tests: [test_desc<T>],
to_task: test_to_task<T>) -> bool { to_task: test_to_task<T>) -> bool {
type test_state = type test_state =
@ -127,7 +127,7 @@ fn run_tests_console_<copy T>(opts: test_opts, tests: [test_desc<T>],
mutable ignored: uint, mutable ignored: uint,
mutable failures: [test_desc<T>]}; mutable failures: [test_desc<T>]};
fn callback<copy T>(event: testevent<T>, st: test_state) { fn callback<T: copy>(event: testevent<T>, st: test_state) {
alt event { alt event {
te_filtered(filtered_tests) { te_filtered(filtered_tests) {
st.total = vec::len(filtered_tests); st.total = vec::len(filtered_tests);
@ -220,7 +220,7 @@ tag testevent<T> {
te_result(test_desc<T>, test_result); te_result(test_desc<T>, test_result);
} }
fn run_tests<copy T>(opts: test_opts, tests: [test_desc<T>], fn run_tests<T: copy>(opts: test_opts, tests: [test_desc<T>],
to_task: test_to_task<T>, to_task: test_to_task<T>,
callback: fn@(testevent<T>)) { callback: fn@(testevent<T>)) {
@ -254,7 +254,7 @@ fn run_tests<copy T>(opts: test_opts, tests: [test_desc<T>],
fn get_concurrency() -> uint { rustrt::sched_threads() } fn get_concurrency() -> uint { rustrt::sched_threads() }
fn filter_tests<copy T>(opts: test_opts, fn filter_tests<T: copy>(opts: test_opts,
tests: [test_desc<T>]) -> [test_desc<T>] { tests: [test_desc<T>]) -> [test_desc<T>] {
let filtered = tests; let filtered = tests;
@ -268,7 +268,7 @@ fn filter_tests<copy T>(opts: test_opts,
option::none. { "" } option::none. { "" }
}; };
fn filter_fn<copy T>(test: test_desc<T>, filter_str: str) -> fn filter_fn<T: copy>(test: test_desc<T>, filter_str: str) ->
option::t<test_desc<T>> { option::t<test_desc<T>> {
if str::find(test.name, filter_str) >= 0 { if str::find(test.name, filter_str) >= 0 {
ret option::some(test); ret option::some(test);
@ -284,7 +284,7 @@ fn filter_tests<copy T>(opts: test_opts,
filtered = if !opts.run_ignored { filtered = if !opts.run_ignored {
filtered filtered
} else { } else {
fn filter<copy T>(test: test_desc<T>) -> option::t<test_desc<T>> { fn filter<T: copy>(test: test_desc<T>) -> option::t<test_desc<T>> {
if test.ignore { if test.ignore {
ret option::some({name: test.name, ret option::some({name: test.name,
fn: test.fn, fn: test.fn,
@ -310,7 +310,7 @@ fn filter_tests<copy T>(opts: test_opts,
type test_future<T> = {test: test_desc<T>, wait: fn@() -> test_result}; type test_future<T> = {test: test_desc<T>, wait: fn@() -> test_result};
fn run_test<copy T>(test: test_desc<T>, fn run_test<T: copy>(test: test_desc<T>,
to_task: test_to_task<T>) -> test_future<T> { to_task: test_to_task<T>) -> test_future<T> {
if test.ignore { if test.ignore {
ret {test: test, wait: fn () -> test_result { tr_ignored }}; ret {test: test, wait: fn () -> test_result { tr_ignored }};

View File

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

View File

@ -7,7 +7,7 @@ Function: id
The identity function The identity function
*/ */
pure fn id<copy T>(x: T) -> T { x } pure fn id<T: copy>(x: T) -> T { x }
/* /*
Function: unreachable Function: unreachable

View File

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

View File

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

View File

@ -1,5 +1,5 @@
// error-pattern: Unsatisfied precondition constraint // error-pattern: Unsatisfied precondition constraint
fn send<send T>(ch: _chan<T>, -data: T) { fn send<T: send>(ch: _chan<T>, -data: T) {
log(debug, ch); log(debug, ch);
log(debug, data); log(debug, data);
fail; fail;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -9,7 +9,7 @@ fn test_vec() {
} }
fn test_generic() { fn test_generic() {
fn f<copy T>(t: T) -> T { t } fn f<T: copy>(t: T) -> T { t }
assert (f(10) == 10); assert (f(10) == 10);
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -8,7 +8,7 @@ fn main() { test05(); }
type pair<A,B> = { a: A, b: B }; type pair<A,B> = { a: A, b: B };
fn make_generic_record<copy A,copy B>(a: A, b: B) -> pair<A,B> { fn make_generic_record<A: copy, B: copy>(a: A, b: B) -> pair<A,B> {
ret {a: a, b: b}; ret {a: a, b: b};
} }
@ -24,7 +24,7 @@ fn test05_start(&&f: sendfn(&&float, &&str) -> pair<float, str>) {
assert q.b == "Ho"; assert q.b == "Ho";
} }
fn spawn<copy A, copy B>(f: fn(sendfn(A,B)->pair<A,B>)) { fn spawn<A: copy, B: copy>(f: fn(sendfn(A,B)->pair<A,B>)) {
let arg = sendfn(a: A, b: B) -> pair<A,B> { let arg = sendfn(a: A, b: B) -> pair<A,B> {
ret make_generic_record(a, b); ret make_generic_record(a, b);
}; };

View File

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

View File

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

View File

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

View File

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

View File

@ -1,10 +1,10 @@
fn sendable() { fn sendable() {
fn f<send T>(i: T, j: T) { fn f<T: send>(i: T, j: T) {
assert i == j; assert i == j;
} }
fn g<send T>(i: T, j: T) { fn g<T: send>(i: T, j: T) {
assert i != j; assert i != j;
} }
@ -18,11 +18,11 @@ fn sendable() {
fn copyable() { fn copyable() {
fn f<copy T>(i: T, j: T) { fn f<T: copy>(i: T, j: T) {
assert i == j; assert i == j;
} }
fn g<copy T>(i: T, j: T) { fn g<T: copy>(i: T, j: T) {
assert i != j; assert i != j;
} }

View File

@ -1,5 +1,5 @@
fn push<copy T>(&v: [const T], t: T) { v += [t]; } fn push<T: copy>(&v: [const T], t: T) { v += [t]; }
fn main() { let v = [1, 2, 3]; push(v, 1); } 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; type eqfn<T> = fn@(T, T) -> bool;
fn test_parameterized<copy T>(e: eqfn<T>, a: T, b: T, c: T, d: T) { fn test_parameterized<T: copy>(e: eqfn<T>, a: T, b: T, c: T, d: T) {
let deq: deque::t<T> = deque::create::<T>(); let deq: deque::t<T> = deque::create::<T>();
assert (deq.size() == 0u); assert (deq.size() == 0u);
deq.add_front(a); deq.add_front(a);

View File

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