This commit is contained in:
Tim Chevalier 2012-06-25 13:29:41 -07:00
commit da470ff5b8
63 changed files with 775 additions and 614 deletions

View File

@ -1,3 +1,47 @@
Version 0.3 (June 2012) - not yet!
-----------------------------------
* ~1500 changes, numerous bugfixes
* New coding conveniences
* Integer-literal suffix inference
* Per-module control over warnings, errors
* #[cfg(windows)] and #[cfg(unix)] attributes
* Semantic cleanup
* Resolve pass and exhaustiveness checker rewritten
* Borrow-check taking over from alias-analysis
* Liveness taking over from last-use, typestate
* Extensive work on region pointers
* Experimental new language features
* Slices and fixed-size, interior-allocated vectors
* #!-comments for lang versioning, shell execution
* More work on classes
* Type reflection
* Removal of various obsolete features
* Keywords: be, prove, syntax, note, mutable, do, bind
* Constructs: do-while loops, fn binding,
* Compiler reorganization
* Syntax-layer of compiler split into separate crate
* Clang (from LLVM project) integrated into build
* Typechecker split into sub-modules
* New library code
* New time functions
* Extension methods for many built-in types
* Arc: atomic-refcount read-only / exclusive-use shared cells
* Par: parallel map and search routines
* Extensive work on libuv interface
* Much vector code moved to libraries
* Syntax extensions: #line, #col, #file, #mod,
#stringify, #include, #include_str, #include_bin.
* Tool improvements
* Cargo automatically resolves dependencies
Version 0.2 (March 2012)
-------------------------

View File

@ -2,9 +2,9 @@
export ptr_eq;
pure fn ptr_eq<T>(a: @T, b: @T) -> bool unchecked {
pure fn ptr_eq<T>(a: @T, b: @T) -> bool {
#[doc = "Determine if two shared boxes point to the same object"];
ptr::addr_of(*a) == ptr::addr_of(*b)
unsafe { ptr::addr_of(*a) == ptr::addr_of(*b) }
}
#[test]

View File

@ -231,7 +231,7 @@ fn test_to_digit() {
}
#[test]
fn test_is_ascii() unsafe {
fn test_is_ascii() {
assert str::all("banana", char::is_ascii);
assert ! str::all("ประเทศไทย中华Việt Nam", char::is_ascii);
}

View File

@ -210,13 +210,13 @@ fn recv_<T: send>(p: *rust_port) -> T {
ret res;
}
fn peek_(p: *rust_port) -> bool unsafe {
fn peek_(p: *rust_port) -> bool {
rustrt::rust_port_size(p) != 0u as libc::size_t
}
#[doc = "Receive on one of two ports"]
fn select2<A: send, B: send>(p_a: port<A>, p_b: port<B>)
-> either<A, B> unsafe {
-> either<A, B> {
let ports = [(**p_a).po, (**p_b).po];
let n_ports = 2 as libc::size_t;
let yield = 0u, yieldp = ptr::addr_of(yield);
@ -440,7 +440,7 @@ fn test_recv_chan_wrong_task() {
let po = port();
let ch = chan(po);
send(ch, "flower");
assert result::is_failure(task::try {||
assert result::is_err(task::try {||
recv_chan(ch)
})
}

View File

@ -11,6 +11,7 @@ import option::extensions;
import option_iter::extensions;
import ptr::extensions;
import rand::extensions;
import result::extensions;
export path, option, some, none, unreachable;
export extensions;

View File

@ -81,7 +81,7 @@ mod ct {
enum piece { piece_string(str), piece_conv(conv), }
type error_fn = fn@(str) -> ! ;
fn parse_fmt_string(s: str, error: error_fn) -> [piece] unsafe {
fn parse_fmt_string(s: str, error: error_fn) -> [piece] {
let mut pieces: [piece] = [];
let lim = str::len(s);
let mut buf = "";
@ -225,7 +225,7 @@ mod ct {
} else { {count: count_implied, next: i} };
}
fn parse_type(s: str, i: uint, lim: uint, error: error_fn) ->
{ty: ty, next: uint} unsafe {
{ty: ty, next: uint} {
if i >= lim { error("missing type in conversion"); }
let tstr = str::slice(s, i, i+1u);
// TODO: Do we really want two signed types here?
@ -314,7 +314,7 @@ mod rt {
let mut s = str::from_char(c);
ret pad(cv, s, pad_nozero);
}
fn conv_str(cv: conv, s: str) -> str unsafe {
fn conv_str(cv: conv, s: str) -> str {
// For strings, precision is the maximum characters
// displayed
let mut unpadded = alt cv.precision {
@ -378,7 +378,7 @@ mod rt {
};
}
enum pad_mode { pad_signed, pad_unsigned, pad_nozero, pad_float }
fn pad(cv: conv, &s: str, mode: pad_mode) -> str unsafe {
fn pad(cv: conv, &s: str, mode: pad_mode) -> str {
let uwidth : uint = alt cv.width {
count_implied { ret s; }
count_is(width) {

View File

@ -93,10 +93,10 @@ fn parse_buf(buf: [u8], radix: uint) -> option<T> {
fn from_str(s: str) -> option<T> { parse_buf(str::bytes(s), 10u) }
#[doc = "Convert to a string in a given base"]
fn to_str(n: T, radix: uint) -> str unsafe {
fn to_str(n: T, radix: uint) -> str {
to_str_bytes(n, radix) {|slice|
vec::unpack_slice(slice) {|p, len|
str::unsafe::from_buf_len(p, len)
unsafe { str::unsafe::from_buf_len(p, len) }
}
}
}

View File

@ -192,13 +192,13 @@ fn convert_whence(whence: seek_style) -> i32 {
}
impl of reader for *libc::FILE {
fn read_bytes(len: uint) -> [u8] unsafe {
fn read_bytes(len: uint) -> [u8] {
let mut buf : [mut u8] = [mut];
vec::reserve(buf, len);
vec::as_mut_buf(buf) {|b|
let read = libc::fread(b as *mut c_void, 1u as size_t,
len as size_t, self);
vec::unsafe::set_len(buf, read as uint);
unsafe { vec::unsafe::set_len(buf, read as uint) };
}
ret vec::from_mut(buf);
}
@ -333,7 +333,7 @@ impl <T: writer, C> of writer for {base: T, cleanup: C} {
}
impl of writer for *libc::FILE {
fn write(v: [const u8]/&) unsafe {
fn write(v: [const u8]/&) {
vec::unpack_const_slice(v) {|vbuf, len|
let nout = libc::fwrite(vbuf as *c_void, len as size_t,
1u as size_t, self);
@ -361,7 +361,7 @@ fn FILE_writer(f: *libc::FILE, cleanup: bool) -> writer {
}
impl of writer for fd_t {
fn write(v: [const u8]/&) unsafe {
fn write(v: [const u8]/&) {
let mut count = 0u;
vec::unpack_const_slice(v) {|vbuf, len|
while count < len {

View File

@ -70,7 +70,7 @@ pure fn iter<T>(opt: option<T>, f: fn(T)) {
alt opt { none { } some(t) { f(t); } }
}
pure fn unwrap<T>(-opt: option<T>) -> T unsafe {
pure fn unwrap<T>(-opt: option<T>) -> T {
#[doc = "
Moves a value out of an option type and returns it.
@ -78,13 +78,15 @@ pure fn unwrap<T>(-opt: option<T>) -> T unsafe {
option types without copying them.
"];
let addr = alt opt {
some(x) { ptr::addr_of(x) }
none { fail "option none" }
};
let liberated_value = unsafe::reinterpret_cast(*addr);
unsafe::forget(opt);
ret liberated_value;
unsafe {
let addr = alt opt {
some(x) { ptr::addr_of(x) }
none { fail "option none" }
};
let liberated_value = unsafe::reinterpret_cast(*addr);
unsafe::forget(opt);
ret liberated_value;
}
}
impl extensions<T> for option<T> {

View File

@ -180,19 +180,21 @@ mod global_env {
}
}
fn global_env_task(msg_po: comm::port<msg>) unsafe {
priv::weaken_task {|weak_po|
loop {
alt comm::select2(msg_po, weak_po) {
either::left(msg_getenv(n, resp_ch)) {
comm::send(resp_ch, impl::getenv(n))
}
either::left(msg_setenv(n, v, resp_ch)) {
comm::send(resp_ch, impl::setenv(n, v))
}
either::right(_) {
break;
}
fn global_env_task(msg_po: comm::port<msg>) {
unsafe {
priv::weaken_task {|weak_po|
loop {
alt comm::select2(msg_po, weak_po) {
either::left(msg_getenv(n, resp_ch)) {
comm::send(resp_ch, impl::getenv(n))
}
either::left(msg_setenv(n, v, resp_ch)) {
comm::send(resp_ch, impl::setenv(n, v))
}
either::right(_) {
break;
}
}
}
}
}
@ -201,18 +203,20 @@ mod global_env {
mod impl {
#[cfg(unix)]
fn getenv(n: str) -> option<str> unsafe {
let s = str::as_c_str(n, libc::getenv);
ret if unsafe::reinterpret_cast(s) == 0 {
option::none::<str>
} else {
let s = unsafe::reinterpret_cast(s);
option::some::<str>(str::unsafe::from_buf(s))
};
fn getenv(n: str) -> option<str> {
unsafe {
let s = str::as_c_str(n, libc::getenv);
ret if unsafe::reinterpret_cast(s) == 0 {
option::none::<str>
} else {
let s = unsafe::reinterpret_cast(s);
option::some::<str>(str::unsafe::from_buf(s))
};
}
}
#[cfg(windows)]
fn getenv(n: str) -> option<str> unsafe {
fn getenv(n: str) -> option<str> {
import libc::types::os::arch::extra::*;
import libc::funcs::extra::kernel32::*;
import win32::*;
@ -362,21 +366,23 @@ fn dll_filename(base: str) -> str {
fn self_exe_path() -> option<path> {
#[cfg(target_os = "freebsd")]
fn load_self() -> option<path> unsafe {
import libc::funcs::bsd44::*;
import libc::consts::os::extra::*;
fill_charp_buf() {|buf, sz|
let mib = [CTL_KERN as c_int,
KERN_PROC as c_int,
KERN_PROC_PATHNAME as c_int, -1 as c_int];
sysctl(vec::unsafe::to_ptr(mib), vec::len(mib) as c_uint,
buf as *mut c_void, ptr::mut_addr_of(sz),
ptr::null(), 0u as size_t) == (0 as c_int)
fn load_self() -> option<path> {
unsafe {
import libc::funcs::bsd44::*;
import libc::consts::os::extra::*;
fill_charp_buf() {|buf, sz|
let mib = [CTL_KERN as c_int,
KERN_PROC as c_int,
KERN_PROC_PATHNAME as c_int, -1 as c_int];
sysctl(vec::unsafe::to_ptr(mib), vec::len(mib) as c_uint,
buf as *mut c_void, ptr::mut_addr_of(sz),
ptr::null(), 0u as size_t) == (0 as c_int)
}
}
}
#[cfg(target_os = "linux")]
fn load_self() -> option<path> unsafe {
fn load_self() -> option<path> {
import libc::funcs::posix01::unistd::readlink;
fill_charp_buf() {|buf, sz|
as_c_charp("/proc/self/exe") { |proc_self_buf|
@ -386,9 +392,10 @@ fn self_exe_path() -> option<path> {
}
#[cfg(target_os = "macos")]
fn load_self() -> option<path> unsafe {
fn load_self() -> option<path> {
// FIXME: remove imports when export globs work properly. #1238
import libc::funcs::extra::*;
fill_charp_buf() {|buf, sz|
_NSGetExecutablePath(buf, ptr::mut_addr_of(sz as u32))
== (0 as c_int)
@ -396,7 +403,7 @@ fn self_exe_path() -> option<path> {
}
#[cfg(windows)]
fn load_self() -> option<path> unsafe {
fn load_self() -> option<path> {
// FIXME: remove imports when export globs work properly. #1238
import libc::types::os::arch::extra::*;
import libc::funcs::extra::kernel32::*;
@ -525,14 +532,14 @@ fn make_dir(p: path, mode: c_int) -> bool {
ret mkdir(p, mode);
#[cfg(windows)]
fn mkdir(p: path, _mode: c_int) -> bool unsafe {
fn mkdir(p: path, _mode: c_int) -> bool {
// FIXME: remove imports when export globs work properly. #1238
import libc::types::os::arch::extra::*;
import libc::funcs::extra::kernel32::*;
import win32::*;
// FIXME: turn mode into something useful? #2623
as_utf16_p(p) {|buf|
CreateDirectoryW(buf, unsafe::reinterpret_cast(0))
CreateDirectoryW(buf, unsafe { unsafe::reinterpret_cast(0) })
!= (0 as BOOL)
}
}
@ -645,7 +652,7 @@ fn copy_file(from: path, to: path) -> bool {
}
#[cfg(unix)]
fn do_copy_file(from: path, to: path) -> bool unsafe {
fn do_copy_file(from: path, to: path) -> bool {
let istream = as_c_charp(from) {|fromp|
as_c_charp("rb") {|modebuf|
libc::fopen(fromp, modebuf)

View File

@ -105,14 +105,20 @@ Given paths `pre` and `post, removes any trailing path separator on `pre` and
any leading path separator on `post`, and returns the concatenation of the two
with a single path separator between them.
"]
fn connect(pre: path, post: path) -> path unsafe {
fn connect(pre: path, post: path) -> path {
let mut pre_ = pre;
let mut post_ = post;
let sep = consts::path_sep as u8;
let pre_len = str::len(pre);
let post_len = str::len(post);
if pre_len > 1u && pre[pre_len-1u] == sep { str::unsafe::pop_byte(pre_); }
if post_len > 1u && post[0] == sep { str::unsafe::shift_byte(post_); }
unsafe {
if pre_len > 1u && pre[pre_len-1u] == sep {
str::unsafe::pop_byte(pre_);
}
if post_len > 1u && post[0] == sep {
str::unsafe::shift_byte(post_);
}
}
ret pre_ + path_sep() + post_;
}

View File

@ -82,7 +82,7 @@ unsafe fn chan_from_global_ptr<T: send>(
}
#[test]
fn test_from_global_chan1() unsafe {
fn test_from_global_chan1() {
// This is unreadable, right?
@ -91,11 +91,13 @@ fn test_from_global_chan1() unsafe {
let globchanp = ptr::addr_of(globchan);
// Create the global channel, attached to a new task
let ch = chan_from_global_ptr(globchanp, task::builder) {|po|
let ch = comm::recv(po);
comm::send(ch, true);
let ch = comm::recv(po);
comm::send(ch, true);
let ch = unsafe {
chan_from_global_ptr(globchanp, task::builder) {|po|
let ch = comm::recv(po);
comm::send(ch, true);
let ch = comm::recv(po);
comm::send(ch, true);
}
};
// Talk to it
let po = comm::port();
@ -103,9 +105,11 @@ fn test_from_global_chan1() unsafe {
assert comm::recv(po) == true;
// This one just reuses the previous channel
let ch = chan_from_global_ptr(globchanp, task::builder) {|po|
let ch = comm::recv(po);
comm::send(ch, false);
let ch = unsafe {
chan_from_global_ptr(globchanp, task::builder) {|po|
let ch = comm::recv(po);
comm::send(ch, false);
}
};
// Talk to the original global task
@ -115,7 +119,7 @@ fn test_from_global_chan1() unsafe {
}
#[test]
fn test_from_global_chan2() unsafe {
fn test_from_global_chan2() {
iter::repeat(100u) {||
// The global channel
@ -129,12 +133,14 @@ fn test_from_global_chan2() unsafe {
// create the global channel
for uint::range(0u, 10u) {|i|
task::spawn() {||
let ch = chan_from_global_ptr(
globchanp, task::builder) {|po|
let ch = unsafe {
chan_from_global_ptr(
globchanp, task::builder) {|po|
for uint::range(0u, 10u) {|_j|
let ch = comm::recv(po);
comm::send(ch, {i});
for uint::range(0u, 10u) {|_j|
let ch = comm::recv(po);
comm::send(ch, {i});
}
}
};
let po = comm::port();
@ -174,10 +180,12 @@ This function is super-unsafe. Do not use.
* Weak tasks must not be supervised. A supervised task keeps
a reference to its parent, so the parent will not die.
"]
unsafe fn weaken_task(f: fn(comm::port<()>)) unsafe {
unsafe fn weaken_task(f: fn(comm::port<()>)) {
let po = comm::port();
let ch = comm::chan(po);
rustrt::rust_task_weaken(unsafe::reinterpret_cast(ch));
unsafe {
rustrt::rust_task_weaken(unsafe::reinterpret_cast(ch));
}
let _unweaken = unweaken(ch);
f(po);
@ -191,50 +199,60 @@ unsafe fn weaken_task(f: fn(comm::port<()>)) unsafe {
}
#[test]
fn test_weaken_task_then_unweaken() unsafe {
fn test_weaken_task_then_unweaken() {
task::try {||
weaken_task {|_po|
unsafe {
weaken_task {|_po|
}
}
};
}
#[test]
fn test_weaken_task_wait() unsafe {
fn test_weaken_task_wait() {
let builder = task::builder();
task::unsupervise(builder);
task::run(builder) {||
weaken_task {|po|
comm::recv(po);
}
}
}
#[test]
fn test_weaken_task_stress() unsafe {
// Create a bunch of weak tasks
iter::repeat(100u) {||
task::spawn {||
weaken_task {|_po|
}
}
let builder = task::builder();
task::unsupervise(builder);
task::run(builder) {||
unsafe {
weaken_task {|po|
// Wait for it to tell us to die
comm::recv(po);
}
}
}
}
#[test]
fn test_weaken_task_stress() {
// Create a bunch of weak tasks
iter::repeat(100u) {||
task::spawn {||
unsafe {
weaken_task {|_po|
}
}
}
let builder = task::builder();
task::unsupervise(builder);
task::run(builder) {||
unsafe {
weaken_task {|po|
// Wait for it to tell us to die
comm::recv(po);
}
}
}
}
}
#[test]
#[ignore(cfg(windows))]
fn test_weaken_task_fail() unsafe {
fn test_weaken_task_fail() {
let res = task::try {||
weaken_task {|_po|
fail;
unsafe {
weaken_task {|_po|
fail;
}
}
};
assert result::is_failure(res);
assert result::is_err(res);
}

View File

@ -39,20 +39,26 @@ pure fn addr_of<T>(val: T) -> *T { unchecked { rusti::addr_of(val) } }
#[doc = "Get an unsafe mut pointer to a value"]
#[inline(always)]
pure fn mut_addr_of<T>(val: T) -> *mut T unsafe {
unsafe::reinterpret_cast(rusti::addr_of(val))
pure fn mut_addr_of<T>(val: T) -> *mut T {
unsafe {
unsafe::reinterpret_cast(rusti::addr_of(val))
}
}
#[doc = "Calculate the offset from a pointer"]
#[inline(always)]
fn offset<T>(ptr: *T, count: uint) -> *T unsafe {
(ptr as uint + count * sys::size_of::<T>()) as *T
fn offset<T>(ptr: *T, count: uint) -> *T {
unsafe {
(ptr as uint + count * sys::size_of::<T>()) as *T
}
}
#[doc = "Calculate the offset from a const pointer"]
#[inline(always)]
fn const_offset<T>(ptr: *const T, count: uint) -> *const T unsafe {
(ptr as uint + count * sys::size_of::<T>()) as *T
fn const_offset<T>(ptr: *const T, count: uint) -> *const T {
unsafe {
(ptr as uint + count * sys::size_of::<T>()) as *T
}
}
#[doc = "Calculate the offset from a mut pointer"]
@ -79,7 +85,7 @@ unsafe fn position<T>(buf: *T, f: fn(T) -> bool) -> uint {
#[doc = "Create an unsafe null pointer"]
#[inline(always)]
pure fn null<T>() -> *T unsafe { ret unsafe::reinterpret_cast(0u); }
pure fn null<T>() -> *T { unsafe { unsafe::reinterpret_cast(0u) } }
#[doc = "Returns true if the pointer is equal to the null pointer."]
pure fn is_null<T>(ptr: *const T) -> bool { ptr == null() }
@ -127,48 +133,52 @@ impl extensions<T> for *T {
}
#[test]
fn test() unsafe {
type pair = {mut fst: int, mut snd: int};
let p = {mut fst: 10, mut snd: 20};
let pptr: *mut pair = mut_addr_of(p);
let iptr: *mut int = unsafe::reinterpret_cast(pptr);
assert (*iptr == 10);;
*iptr = 30;
assert (*iptr == 30);
assert (p.fst == 30);;
fn test() {
unsafe {
type pair = {mut fst: int, mut snd: int};
let p = {mut fst: 10, mut snd: 20};
let pptr: *mut pair = mut_addr_of(p);
let iptr: *mut int = unsafe::reinterpret_cast(pptr);
assert (*iptr == 10);;
*iptr = 30;
assert (*iptr == 30);
assert (p.fst == 30);;
*pptr = {mut fst: 50, mut snd: 60};
assert (*iptr == 50);
assert (p.fst == 50);
assert (p.snd == 60);
*pptr = {mut fst: 50, mut snd: 60};
assert (*iptr == 50);
assert (p.fst == 50);
assert (p.snd == 60);
let v0 = [32000u16, 32001u16, 32002u16];
let v1 = [0u16, 0u16, 0u16];
let v0 = [32000u16, 32001u16, 32002u16];
let v1 = [0u16, 0u16, 0u16];
ptr::memcpy(ptr::offset(vec::unsafe::to_ptr(v1), 1u),
ptr::offset(vec::unsafe::to_ptr(v0), 1u), 1u);
assert (v1[0] == 0u16 && v1[1] == 32001u16 && v1[2] == 0u16);
ptr::memcpy(vec::unsafe::to_ptr(v1),
ptr::offset(vec::unsafe::to_ptr(v0), 2u), 1u);
assert (v1[0] == 32002u16 && v1[1] == 32001u16 && v1[2] == 0u16);
ptr::memcpy(ptr::offset(vec::unsafe::to_ptr(v1), 2u),
vec::unsafe::to_ptr(v0), 1u);
assert (v1[0] == 32002u16 && v1[1] == 32001u16 && v1[2] == 32000u16);
ptr::memcpy(ptr::offset(vec::unsafe::to_ptr(v1), 1u),
ptr::offset(vec::unsafe::to_ptr(v0), 1u), 1u);
assert (v1[0] == 0u16 && v1[1] == 32001u16 && v1[2] == 0u16);
ptr::memcpy(vec::unsafe::to_ptr(v1),
ptr::offset(vec::unsafe::to_ptr(v0), 2u), 1u);
assert (v1[0] == 32002u16 && v1[1] == 32001u16 && v1[2] == 0u16);
ptr::memcpy(ptr::offset(vec::unsafe::to_ptr(v1), 2u),
vec::unsafe::to_ptr(v0), 1u);
assert (v1[0] == 32002u16 && v1[1] == 32001u16 && v1[2] == 32000u16);
}
}
#[test]
fn test_position() unsafe {
fn test_position() {
import str::as_c_str;
import libc::c_char;
let s = "hello";
assert 2u == as_c_str(s) {|p| position(p) {|c| c == 'l' as c_char} };
assert 4u == as_c_str(s) {|p| position(p) {|c| c == 'o' as c_char} };
assert 5u == as_c_str(s) {|p| position(p) {|c| c == 0 as c_char } };
unsafe {
assert 2u == as_c_str(s) {|p| position(p) {|c| c == 'l' as c_char} };
assert 4u == as_c_str(s) {|p| position(p) {|c| c == 'o' as c_char} };
assert 5u == as_c_str(s) {|p| position(p) {|c| c == 0 as c_char } };
}
}
#[test]
fn test_buf_len() unsafe {
fn test_buf_len() {
let s0 = "hello";
let s1 = "there";
let s2 = "thing";
@ -177,7 +187,7 @@ fn test_buf_len() unsafe {
str::as_c_str(s2) {|p2|
let v = [p0, p1, p2, null()];
vec::as_buf(v) {|vp|
assert buf_len(vp) == 3u;
assert unsafe { buf_len(vp) } == 3u;
}
}
}

View File

@ -43,16 +43,16 @@ pure fn get_err<T, U: copy>(res: result<T, U>) -> U {
}
#[doc = "Returns true if the result is `ok`"]
pure fn is_success<T, U>(res: result<T, U>) -> bool {
pure fn is_ok<T, U>(res: result<T, U>) -> bool {
alt res {
ok(_) { true }
err(_) { false }
}
}
#[doc = "Returns true if the result is `error`"]
pure fn is_failure<T, U>(res: result<T, U>) -> bool {
!is_success(res)
#[doc = "Returns true if the result is `err`"]
pure fn is_err<T, U>(res: result<T, U>) -> bool {
!is_ok(res)
}
#[doc = "
@ -180,22 +180,10 @@ fn map_err<T: copy, E, F: copy>(res: result<T, E>, op: fn(E) -> F)
}
}
impl extensions<T:copy, E:copy> for result<T,E> {
fn get() -> T { get(self) }
impl extensions<T, E> for result<T, E> {
fn is_ok() -> bool { is_ok(self) }
fn get_err() -> E { get_err(self) }
fn is_success() -> bool { is_success(self) }
fn is_failure() -> bool { is_failure(self) }
fn chain<U:copy>(op: fn(T) -> result<U,E>) -> result<U,E> {
chain(self, op)
}
fn chain_err<F:copy>(op: fn(E) -> result<T,F>) -> result<T,F> {
chain_err(self, op)
}
fn is_err() -> bool { is_err(self) }
fn iter(f: fn(T)) {
alt self {
@ -210,6 +198,21 @@ impl extensions<T:copy, E:copy> for result<T,E> {
err(e) { f(e) }
}
}
}
impl extensions<T:copy, E> for result<T, E> {
fn get() -> T { get(self) }
fn map_err<F:copy>(op: fn(E) -> F) -> result<T,F> {
alt self {
ok(t) { ok(t) }
err(e) { err(op(e)) }
}
}
}
impl extensions<T, E:copy> for result<T, E> {
fn get_err() -> E { get_err(self) }
fn map<U:copy>(op: fn(T) -> U) -> result<U,E> {
alt self {
@ -217,12 +220,15 @@ impl extensions<T:copy, E:copy> for result<T,E> {
err(e) { err(e) }
}
}
}
fn map_err<F:copy>(op: fn(E) -> F) -> result<T,F> {
alt self {
ok(t) { ok(t) }
err(e) { err(op(e)) }
}
impl extensions<T:copy, E:copy> for result<T,E> {
fn chain<U:copy>(op: fn(T) -> result<U,E>) -> result<U,E> {
chain(self, op)
}
fn chain_err<F:copy>(op: fn(E) -> result<T,F>) -> result<T,F> {
chain_err(self, op)
}
}
@ -320,14 +326,16 @@ fn iter_vec2<S,T,U:copy>(ss: [S], ts: [T],
#[doc="
Unwraps a result, assuming it is an `ok(T)`
"]
fn unwrap<T, U>(-res: result<T, U>) -> T unsafe {
let addr = alt res {
ok(x) { ptr::addr_of(x) }
err(_) { fail "error result" }
};
let liberated_value = unsafe::reinterpret_cast(*addr);
unsafe::forget(res);
ret liberated_value;
fn unwrap<T, U>(-res: result<T, U>) -> T {
unsafe {
let addr = alt res {
ok(x) { ptr::addr_of(x) }
err(_) { fail "error result" }
};
let liberated_value = unsafe::reinterpret_cast(*addr);
unsafe::forget(res);
ret liberated_value;
}
}
#[cfg(test)]

View File

@ -66,7 +66,7 @@ fn spawn_process(prog: str, args: [str],
env: option<[(str,str)]>,
dir: option<str>,
in_fd: c_int, out_fd: c_int, err_fd: c_int)
-> pid_t unsafe {
-> pid_t {
with_argv(prog, args) {|argv|
with_envp(env) { |envp|
with_dirp(dir) { |dirp|
@ -78,7 +78,7 @@ fn spawn_process(prog: str, args: [str],
}
fn with_argv<T>(prog: str, args: [str],
cb: fn(**libc::c_char) -> T) -> T unsafe {
cb: fn(**libc::c_char) -> T) -> T {
let mut argptrs = str::as_c_str(prog) {|b| [b] };
let mut tmps = [];
for vec::each(args) {|arg|
@ -92,7 +92,7 @@ fn with_argv<T>(prog: str, args: [str],
#[cfg(unix)]
fn with_envp<T>(env: option<[(str,str)]>,
cb: fn(*c_void) -> T) -> T unsafe {
cb: fn(*c_void) -> T) -> T {
// On posixy systems we can pass a char** for envp, which is
// a null-terminated array of "k=v\n" strings.
alt env {
@ -107,7 +107,9 @@ fn with_envp<T>(env: option<[(str,str)]>,
ptrs += str::as_c_str(*t) {|b| [b]};
}
ptrs += [ptr::null()];
vec::as_buf(ptrs) { |p| cb(::unsafe::reinterpret_cast(p)) }
vec::as_buf(ptrs) { |p|
unsafe { cb(::unsafe::reinterpret_cast(p)) }
}
}
_ {
cb(ptr::null())
@ -117,31 +119,33 @@ fn with_envp<T>(env: option<[(str,str)]>,
#[cfg(windows)]
fn with_envp<T>(env: option<[(str,str)]>,
cb: fn(*c_void) -> T) -> T unsafe {
cb: fn(*c_void) -> T) -> T {
// On win32 we pass an "environment block" which is not a char**, but
// rather a concatenation of null-terminated k=v\0 sequences, with a final
// \0 to terminate.
alt env {
some(es) if !vec::is_empty(es) {
let mut blk : [u8] = [];
for vec::each(es) {|e|
let (k,v) = e;
let t = #fmt("%s=%s", k, v);
let mut v : [u8] = ::unsafe::reinterpret_cast(t);
blk += v;
::unsafe::forget(v);
unsafe {
alt env {
some(es) if !vec::is_empty(es) {
let mut blk : [u8] = [];
for vec::each(es) {|e|
let (k,v) = e;
let t = #fmt("%s=%s", k, v);
let mut v : [u8] = ::unsafe::reinterpret_cast(t);
blk += v;
::unsafe::forget(v);
}
blk += [0_u8];
vec::as_buf(blk) {|p| cb(::unsafe::reinterpret_cast(p)) }
}
_ {
cb(ptr::null())
}
}
blk += [0_u8];
vec::as_buf(blk) {|p| cb(::unsafe::reinterpret_cast(p)) }
}
_ {
cb(ptr::null())
}
}
}
fn with_dirp<T>(d: option<str>,
cb: fn(*libc::c_char) -> T) -> T unsafe {
cb: fn(*libc::c_char) -> T) -> T {
alt d {
some(dir) { str::as_c_str(dir, cb) }
none { cb(ptr::null()) }

View File

@ -122,9 +122,9 @@ Convert a vector of bytes to a UTF-8 string
Fails if invalid UTF-8
"]
pure fn from_bytes(vv: [u8]) -> str unsafe {
assert is_utf8(vv);
ret unsafe::from_bytes(vv);
pure fn from_bytes(vv: [u8]) -> str {
assert is_utf8(vv);
ret unsafe { unsafe::from_bytes(vv) };
}
#[doc = "
@ -134,83 +134,85 @@ Convert a byte to a UTF-8 string
Fails if invalid UTF-8
"]
pure fn from_byte(b: u8) -> str unsafe {
pure fn from_byte(b: u8) -> str {
assert b < 128u8;
let mut v = [b, 0u8];
::unsafe::transmute(v)
unsafe { ::unsafe::transmute(v) }
}
#[doc = "Appends a character at the end of a string"]
fn push_char(&s: str, ch: char) unsafe {
let code = ch as uint;
let nb = if code < max_one_b { 1u }
fn push_char(&s: str, ch: char) {
unsafe {
let code = ch as uint;
let nb = if code < max_one_b { 1u }
else if code < max_two_b { 2u }
else if code < max_three_b { 3u }
else if code < max_four_b { 4u }
else if code < max_five_b { 5u }
else { 6u };
let len = len(s);
let new_len = len + nb;
reserve_at_least(s, new_len);
let off = len;
as_buf(s) {|buf|
let buf: *mut u8 = ::unsafe::reinterpret_cast(buf);
if nb == 1u {
*ptr::mut_offset(buf, off) =
code as u8;
} else if nb == 2u {
*ptr::mut_offset(buf, off) =
(code >> 6u & 31u | tag_two_b) as u8;
*ptr::mut_offset(buf, off + 1u) =
(code & 63u | tag_cont) as u8;
} else if nb == 3u {
*ptr::mut_offset(buf, off) =
(code >> 12u & 15u | tag_three_b) as u8;
*ptr::mut_offset(buf, off + 1u) =
(code >> 6u & 63u | tag_cont) as u8;
*ptr::mut_offset(buf, off + 2u) =
(code & 63u | tag_cont) as u8;
} else if nb == 4u {
*ptr::mut_offset(buf, off) =
(code >> 18u & 7u | tag_four_b) as u8;
*ptr::mut_offset(buf, off + 1u) =
(code >> 12u & 63u | tag_cont) as u8;
*ptr::mut_offset(buf, off + 2u) =
(code >> 6u & 63u | tag_cont) as u8;
*ptr::mut_offset(buf, off + 3u) =
(code & 63u | tag_cont) as u8;
} else if nb == 5u {
*ptr::mut_offset(buf, off) =
(code >> 24u & 3u | tag_five_b) as u8;
*ptr::mut_offset(buf, off + 1u) =
(code >> 18u & 63u | tag_cont) as u8;
*ptr::mut_offset(buf, off + 2u) =
(code >> 12u & 63u | tag_cont) as u8;
*ptr::mut_offset(buf, off + 3u) =
(code >> 6u & 63u | tag_cont) as u8;
*ptr::mut_offset(buf, off + 4u) =
(code & 63u | tag_cont) as u8;
} else if nb == 6u {
*ptr::mut_offset(buf, off) =
(code >> 30u & 1u | tag_six_b) as u8;
*ptr::mut_offset(buf, off + 1u) =
(code >> 24u & 63u | tag_cont) as u8;
*ptr::mut_offset(buf, off + 2u) =
(code >> 18u & 63u | tag_cont) as u8;
*ptr::mut_offset(buf, off + 3u) =
(code >> 12u & 63u | tag_cont) as u8;
*ptr::mut_offset(buf, off + 4u) =
(code >> 6u & 63u | tag_cont) as u8;
*ptr::mut_offset(buf, off + 5u) =
(code & 63u | tag_cont) as u8;
let len = len(s);
let new_len = len + nb;
reserve_at_least(s, new_len);
let off = len;
as_buf(s) {|buf|
let buf: *mut u8 = ::unsafe::reinterpret_cast(buf);
if nb == 1u {
*ptr::mut_offset(buf, off) =
code as u8;
} else if nb == 2u {
*ptr::mut_offset(buf, off) =
(code >> 6u & 31u | tag_two_b) as u8;
*ptr::mut_offset(buf, off + 1u) =
(code & 63u | tag_cont) as u8;
} else if nb == 3u {
*ptr::mut_offset(buf, off) =
(code >> 12u & 15u | tag_three_b) as u8;
*ptr::mut_offset(buf, off + 1u) =
(code >> 6u & 63u | tag_cont) as u8;
*ptr::mut_offset(buf, off + 2u) =
(code & 63u | tag_cont) as u8;
} else if nb == 4u {
*ptr::mut_offset(buf, off) =
(code >> 18u & 7u | tag_four_b) as u8;
*ptr::mut_offset(buf, off + 1u) =
(code >> 12u & 63u | tag_cont) as u8;
*ptr::mut_offset(buf, off + 2u) =
(code >> 6u & 63u | tag_cont) as u8;
*ptr::mut_offset(buf, off + 3u) =
(code & 63u | tag_cont) as u8;
} else if nb == 5u {
*ptr::mut_offset(buf, off) =
(code >> 24u & 3u | tag_five_b) as u8;
*ptr::mut_offset(buf, off + 1u) =
(code >> 18u & 63u | tag_cont) as u8;
*ptr::mut_offset(buf, off + 2u) =
(code >> 12u & 63u | tag_cont) as u8;
*ptr::mut_offset(buf, off + 3u) =
(code >> 6u & 63u | tag_cont) as u8;
*ptr::mut_offset(buf, off + 4u) =
(code & 63u | tag_cont) as u8;
} else if nb == 6u {
*ptr::mut_offset(buf, off) =
(code >> 30u & 1u | tag_six_b) as u8;
*ptr::mut_offset(buf, off + 1u) =
(code >> 24u & 63u | tag_cont) as u8;
*ptr::mut_offset(buf, off + 2u) =
(code >> 18u & 63u | tag_cont) as u8;
*ptr::mut_offset(buf, off + 3u) =
(code >> 12u & 63u | tag_cont) as u8;
*ptr::mut_offset(buf, off + 4u) =
(code >> 6u & 63u | tag_cont) as u8;
*ptr::mut_offset(buf, off + 5u) =
(code & 63u | tag_cont) as u8;
}
*ptr::mut_offset(buf, off + nb) = 0u8;
}
*ptr::mut_offset(buf, off + nb) = 0u8;
}
as_bytes(s) {|bytes|
let mut mut_bytes: [u8] = ::unsafe::reinterpret_cast(bytes);
vec::unsafe::set_len(mut_bytes, new_len + 1u);
::unsafe::forget(mut_bytes);
as_bytes(s) {|bytes|
let mut mut_bytes: [u8] = ::unsafe::reinterpret_cast(bytes);
vec::unsafe::set_len(mut_bytes, new_len + 1u);
::unsafe::forget(mut_bytes);
}
}
}
@ -276,9 +278,9 @@ Remove the first character from a string and return it
If the string does not contain any characters
"]
fn shift_char(&s: str) -> char unsafe {
fn shift_char(&s: str) -> char {
let {ch, next} = char_range_at(s, 0u);
s = unsafe::slice_bytes(s, next, len(s));
s = unsafe { unsafe::slice_bytes(s, next, len(s)) };
ret ch;
}
@ -320,20 +322,22 @@ Converts a string to a vector of bytes
The result vector is not null-terminated.
"]
pure fn bytes(s: str) -> [u8] unsafe {
let mut s_copy = s;
let mut v: [u8] = ::unsafe::transmute(s_copy);
vec::unsafe::set_len(v, len(s));
ret v;
pure fn bytes(s: str) -> [u8] {
unsafe {
let mut s_copy = s;
let mut v: [u8] = ::unsafe::transmute(s_copy);
vec::unsafe::set_len(v, len(s));
ret v;
}
}
#[doc = "
Work with the string as a byte slice, not including trailing null.
"]
#[inline(always)]
pure fn byte_slice<T>(s: str/&, f: fn([u8]/&) -> T) -> T unsafe {
pure fn byte_slice<T>(s: str/&, f: fn([u8]/&) -> T) -> T {
unpack_slice(s) {|p,n|
vec::unsafe::form_slice(p, n-1u, f)
unsafe { vec::unsafe::form_slice(p, n-1u, f) }
}
}
@ -365,10 +369,10 @@ Returns a slice of the given string from the byte range [`begin`..`end`)
Fails when `begin` and `end` do not point to valid characters or
beyond the last character of the string
"]
pure fn slice(s: str/&, begin: uint, end: uint) -> str unsafe {
pure fn slice(s: str/&, begin: uint, end: uint) -> str {
assert is_char_boundary(s, begin);
assert is_char_boundary(s, end);
unsafe::slice_bytes(s, begin, end)
unsafe { unsafe::slice_bytes(s, begin, end) }
}
#[doc = "
@ -396,7 +400,7 @@ pure fn split_char_nonempty(s: str/&, sep: char) -> [str] {
}
pure fn split_char_inner(s: str/&, sep: char, count: uint, allow_empty: bool)
-> [str] unsafe {
-> [str] {
if sep < 128u as char {
let b = sep as u8, l = len(s);
let mut result = [], done = 0u;
@ -404,7 +408,7 @@ pure fn split_char_inner(s: str/&, sep: char, count: uint, allow_empty: bool)
while i < l && done < count {
if s[i] == b {
if allow_empty || start < i {
result += [unsafe::slice_bytes(s, start, i)];
result += [unsafe { unsafe::slice_bytes(s, start, i) }];
}
start = i + 1u;
done += 1u;
@ -412,7 +416,7 @@ pure fn split_char_inner(s: str/&, sep: char, count: uint, allow_empty: bool)
i += 1u;
}
if allow_empty || start < l {
result += [unsafe::slice_bytes(s, start, l)];
result += [unsafe { unsafe::slice_bytes(s, start, l) }];
}
result
} else {
@ -440,14 +444,14 @@ pure fn split_nonempty(s: str/&, sepfn: fn(char) -> bool) -> [str] {
}
pure fn split_inner(s: str/&, sepfn: fn(cc: char) -> bool, count: uint,
allow_empty: bool) -> [str] unsafe {
allow_empty: bool) -> [str] {
let l = len(s);
let mut result = [], i = 0u, start = 0u, done = 0u;
while i < l && done < count {
let {ch, next} = char_range_at(s, i);
if sepfn(ch) {
if allow_empty || start < i {
result += [unsafe::slice_bytes(s, start, i)];
result += [unsafe { unsafe::slice_bytes(s, start, i) }];
}
start = next;
done += 1u;
@ -455,7 +459,7 @@ pure fn split_inner(s: str/&, sepfn: fn(cc: char) -> bool, count: uint,
i = next;
}
if allow_empty || start < l {
result += [unsafe::slice_bytes(s, start, l)];
result += [unsafe { unsafe::slice_bytes(s, start, l) }];
}
result
}
@ -578,7 +582,7 @@ Replace all occurrences of one string with another
The original string with all occurances of `from` replaced with `to`
"]
pure fn replace(s: str, from: str, to: str) -> str unsafe {
pure fn replace(s: str, from: str, to: str) -> str {
let mut result = "", first = true;
iter_between_matches(s, from) {|start, end|
if first { first = false; } else { result += to; }
@ -709,7 +713,7 @@ Apply a function to each substring after splitting by character, up to
`count` times
"]
pure fn splitn_char_iter(ss: str/&, sep: char, count: uint,
ff: fn(&&str)) unsafe {
ff: fn(&&str)) {
vec::iter(splitn_char(ss, sep, count), ff)
}
@ -1149,7 +1153,7 @@ Returns true if one string starts with another
* haystack - The string to look in
* needle - The string to look for
"]
pure fn starts_with(haystack: str/&a, needle: str/&b) -> bool unsafe {
pure fn starts_with(haystack: str/&a, needle: str/&b) -> bool {
let haystack_len = len(haystack), needle_len = len(needle);
if needle_len == 0u { true }
else if needle_len > haystack_len { false }
@ -1564,9 +1568,11 @@ interop.
let i = str::as_bytes(\"Hello World\") { |bytes| vec::len(bytes) };
~~~
"]
pure fn as_bytes<T>(s: str, f: fn([u8]) -> T) -> T unsafe {
let v: *[u8] = ::unsafe::reinterpret_cast(ptr::addr_of(s));
f(*v)
pure fn as_bytes<T>(s: str, f: fn([u8]) -> T) -> T {
unsafe {
let v: *[u8] = ::unsafe::reinterpret_cast(ptr::addr_of(s));
f(*v)
}
}
#[doc = "
@ -1575,8 +1581,8 @@ Work with the byte buffer of a string.
Allows for unsafe manipulation of strings, which is useful for native
interop.
"]
pure fn as_buf<T>(s: str, f: fn(*u8) -> T) -> T unsafe {
as_bytes(s) { |v| vec::as_buf(v, f) }
pure fn as_buf<T>(s: str, f: fn(*u8) -> T) -> T {
as_bytes(s) { |v| unsafe { vec::as_buf(v, f) } }
}
#[doc = "
@ -1591,7 +1597,7 @@ interop, without copying the original string.
let s = str::as_buf(\"PATH\", { |path_buf| libc::getenv(path_buf) });
~~~
"]
pure fn as_c_str<T>(s: str, f: fn(*libc::c_char) -> T) -> T unsafe {
pure fn as_c_str<T>(s: str, f: fn(*libc::c_char) -> T) -> T {
as_buf(s) {|buf| f(buf as *libc::c_char) }
}
@ -1605,10 +1611,12 @@ indexable area for a null byte, as is the case in slices pointing
to full strings, or suffixes of them.
"]
#[inline(always)]
pure fn unpack_slice<T>(s: str/&, f: fn(*u8, uint) -> T) -> T unsafe {
let v : *(*u8,uint) = ::unsafe::reinterpret_cast(ptr::addr_of(s));
let (buf,len) = *v;
f(buf, len)
pure fn unpack_slice<T>(s: str/&, f: fn(*u8, uint) -> T) -> T {
unsafe {
let v : *(*u8,uint) = ::unsafe::reinterpret_cast(ptr::addr_of(s));
let (buf,len) = *v;
f(buf, len)
}
}
#[doc = "
@ -1653,7 +1661,7 @@ capacity, then no action is taken.
* s - A string
* n - The number of bytes to reserve space for
"]
fn reserve_at_least(&s: str, n: uint) unsafe {
fn reserve_at_least(&s: str, n: uint) {
reserve(s, uint::next_power_of_two(n + 1u) - 1u)
}
@ -1661,7 +1669,7 @@ fn reserve_at_least(&s: str, n: uint) unsafe {
Returns the number of single-byte characters the string can hold without
reallocating
"]
pure fn capacity(&&s: str) -> uint unsafe {
pure fn capacity(&&s: str) -> uint {
as_bytes(s) {|buf|
let vcap = vec::capacity(buf);
assert vcap > 0u;
@ -1742,10 +1750,12 @@ mod unsafe {
Does not verify that the vector contains valid UTF-8.
"]
unsafe fn from_bytes(v: [const u8]) -> str unsafe {
let mut vcopy : [u8] = ::unsafe::transmute(copy v);
vec::push(vcopy, 0u8);
::unsafe::transmute(vcopy)
unsafe fn from_bytes(v: [const u8]) -> str {
unsafe {
let mut vcopy : [u8] = ::unsafe::transmute(copy v);
vec::push(vcopy, 0u8);
::unsafe::transmute(vcopy)
}
}
#[doc = "
@ -1765,20 +1775,22 @@ mod unsafe {
If begin is greater than end.
If end is greater than the length of the string.
"]
unsafe fn slice_bytes(s: str/&, begin: uint, end: uint) -> str unsafe {
unsafe fn slice_bytes(s: str/&, begin: uint, end: uint) -> str {
unpack_slice(s) { |sbuf, n|
assert (begin <= end);
assert (end <= n);
let mut v = [];
vec::reserve(v, end - begin + 1u);
vec::as_buf(v) { |vbuf|
let src = ptr::offset(sbuf, begin);
ptr::memcpy(vbuf, src, end - begin);
unsafe {
vec::as_buf(v) { |vbuf|
let src = ptr::offset(sbuf, begin);
ptr::memcpy(vbuf, src, end - begin);
}
vec::unsafe::set_len(v, end - begin);
v += [0u8];
::unsafe::transmute(v)
}
vec::unsafe::set_len(v, end - begin);
v += [0u8];
::unsafe::transmute(v)
}
}
@ -1795,22 +1807,22 @@ mod unsafe {
#[doc = "
Removes the last byte from a string and returns it. (Not UTF-8 safe).
"]
unsafe fn pop_byte(&s: str) -> u8 unsafe {
unsafe fn pop_byte(&s: str) -> u8 {
let len = len(s);
assert (len > 0u);
let b = s[len - 1u];
set_len(s, len - 1u);
unsafe { set_len(s, len - 1u) };
ret b;
}
#[doc = "
Removes the first byte from a string and returns it. (Not UTF-8 safe).
"]
unsafe fn shift_byte(&s: str) -> u8 unsafe {
unsafe fn shift_byte(&s: str) -> u8 {
let len = len(s);
assert (len > 0u);
let b = s[0];
s = unsafe::slice_bytes(s, 1u, len);
s = unsafe { unsafe::slice_bytes(s, 1u, len) };
ret b;
}
@ -1825,11 +1837,13 @@ mod unsafe {
}
#[test]
fn test_from_buf_len() unsafe {
let a = [65u8, 65u8, 65u8, 65u8, 65u8, 65u8, 65u8, 0u8];
let b = vec::unsafe::to_ptr(a);
let c = from_buf_len(b, 3u);
assert (c == "AAA");
fn test_from_buf_len() {
unsafe {
let a = [65u8, 65u8, 65u8, 65u8, 65u8, 65u8, 65u8, 0u8];
let b = vec::unsafe::to_ptr(a);
let c = from_buf_len(b, 3u);
assert (c == "AAA");
}
}
}
@ -2274,24 +2288,27 @@ mod tests {
}
#[test]
fn test_unsafe_slice() unsafe {
assert (eq("ab", unsafe::slice_bytes("abc", 0u, 2u)));
assert (eq("bc", unsafe::slice_bytes("abc", 1u, 3u)));
assert (eq("", unsafe::slice_bytes("abc", 1u, 1u)));
fn a_million_letter_a() -> str {
let mut i = 0;
let mut rs = "";
while i < 100000 { rs += "aaaaaaaaaa"; i += 1; }
ret rs;
fn test_unsafe_slice() {
unsafe {
assert (eq("ab", unsafe::slice_bytes("abc", 0u, 2u)));
assert (eq("bc", unsafe::slice_bytes("abc", 1u, 3u)));
assert (eq("", unsafe::slice_bytes("abc", 1u, 1u)));
fn a_million_letter_a() -> str {
let mut i = 0;
let mut rs = "";
while i < 100000 { rs += "aaaaaaaaaa"; i += 1; }
ret rs;
}
fn half_a_million_letter_a() -> str {
let mut i = 0;
let mut rs = "";
while i < 100000 { rs += "aaaaa"; i += 1; }
ret rs;
}
assert eq(half_a_million_letter_a(),
unsafe::slice_bytes(a_million_letter_a(),
0u, 500000u));
}
fn half_a_million_letter_a() -> str {
let mut i = 0;
let mut rs = "";
while i < 100000 { rs += "aaaaa"; i += 1; }
ret rs;
}
assert (eq(half_a_million_letter_a(),
unsafe::slice_bytes(a_million_letter_a(), 0u, 500000u)));
}
#[test]
@ -2483,25 +2500,25 @@ mod tests {
}
#[test]
fn test_shift_byte() unsafe {
fn test_shift_byte() {
let mut s = "ABC";
let b = unsafe::shift_byte(s);
let b = unsafe { unsafe::shift_byte(s) };
assert (s == "BC");
assert (b == 65u8);
}
#[test]
fn test_pop_byte() unsafe {
fn test_pop_byte() {
let mut s = "ABC";
let b = unsafe::pop_byte(s);
let b = unsafe { unsafe::pop_byte(s) };
assert (s == "AB");
assert (b == 67u8);
}
#[test]
fn test_unsafe_from_bytes() unsafe {
fn test_unsafe_from_bytes() {
let a = [65u8, 65u8, 65u8, 65u8, 65u8, 65u8, 65u8];
let b = unsafe::from_bytes(a);
let b = unsafe { unsafe::from_bytes(a) };
assert (b == "AAAAAAA");
}
@ -2541,11 +2558,13 @@ mod tests {
}
#[test]
fn test_from_buf() unsafe {
let a = [65u8, 65u8, 65u8, 65u8, 65u8, 65u8, 65u8, 0u8];
let b = vec::unsafe::to_ptr(a);
let c = unsafe::from_buf(b);
assert (c == "AAAAAAA");
fn test_from_buf() {
unsafe {
let a = [65u8, 65u8, 65u8, 65u8, 65u8, 65u8, 65u8, 0u8];
let b = vec::unsafe::to_ptr(a);
let c = unsafe::from_buf(b);
assert (c == "AAAAAAA");
}
}
#[test]
@ -2557,25 +2576,33 @@ mod tests {
}
#[test]
fn test_as_buf() unsafe {
fn test_as_buf() {
let a = "Abcdefg";
let b = as_buf(a, {|buf| assert (*buf == 65u8); 100 });
let b = as_buf(a, {|buf|
assert unsafe { *buf } == 65u8;
100
});
assert (b == 100);
}
#[test]
fn test_as_buf_small() unsafe {
fn test_as_buf_small() {
let a = "A";
let b = as_buf(a, {|buf| assert (*buf == 65u8); 100 });
let b = as_buf(a, {|buf|
assert unsafe { *buf } == 65u8;
100
});
assert (b == 100);
}
#[test]
fn test_as_buf2() unsafe {
let s = "hello";
let sb = as_buf(s, {|b| b });
let s_cstr = unsafe::from_buf(sb);
assert (eq(s_cstr, s));
fn test_as_buf2() {
unsafe {
let s = "hello";
let sb = as_buf(s, {|b| b });
let s_cstr = unsafe::from_buf(sb);
assert (eq(s_cstr, s));
}
}
#[test]
@ -2813,14 +2840,16 @@ mod tests {
}
#[test]
fn test_unpack_slice() unsafe {
fn test_unpack_slice() {
let a = "hello";
unpack_slice(a) {|buf, len|
assert a[0] == 'h' as u8;
assert *buf == 'h' as u8;
assert len == 6u;
assert *ptr::offset(buf,4u) == 'o' as u8;
assert *ptr::offset(buf,5u) == 0u8;
unsafe {
assert a[0] == 'h' as u8;
assert *buf == 'h' as u8;
assert len == 6u;
assert *ptr::offset(buf,4u) == 'o' as u8;
assert *ptr::offset(buf,5u) == 0u8;
}
}
}

View File

@ -52,7 +52,7 @@ pure fn get_type_desc<T>() -> *type_desc {
#[doc = "Returns the size of a type"]
#[inline(always)]
pure fn size_of<T>() -> uint unsafe {
pure fn size_of<T>() -> uint {
unchecked { rusti::size_of::<T>() }
}
@ -62,12 +62,12 @@ Returns the ABI-required minimum alignment of a type
This is the alignment used for struct fields. It may be smaller
than the preferred alignment.
"]
pure fn min_align_of<T>() -> uint unsafe {
pure fn min_align_of<T>() -> uint {
unchecked { rusti::min_align_of::<T>() }
}
#[doc = "Returns the preferred alignment of a type"]
pure fn pref_align_of<T>() -> uint unsafe {
pure fn pref_align_of<T>() -> uint {
unchecked { rusti::pref_align_of::<T>() }
}

View File

@ -504,7 +504,7 @@ type task_id = int;
type rust_task = libc::c_void;
type rust_closure = libc::c_void;
fn spawn_raw(opts: task_opts, +f: fn~()) unsafe {
fn spawn_raw(opts: task_opts, +f: fn~()) {
let mut f = if opts.supervise {
f
@ -519,26 +519,28 @@ fn spawn_raw(opts: task_opts, +f: fn~()) unsafe {
}
};
let fptr = ptr::addr_of(f);
let closure: *rust_closure = unsafe::reinterpret_cast(fptr);
unsafe {
let fptr = ptr::addr_of(f);
let closure: *rust_closure = unsafe::reinterpret_cast(fptr);
let new_task = alt opts.sched {
none {
rustrt::new_task()
}
some(sched_opts) {
new_task_in_new_sched(sched_opts)
}
};
let new_task = alt opts.sched {
none {
rustrt::new_task()
}
some(sched_opts) {
new_task_in_new_sched(sched_opts)
}
};
option::iter(opts.notify_chan) {|c|
// FIXME (#1087): Would like to do notification in Rust
rustrt::rust_task_config_notify(new_task, c);
option::iter(opts.notify_chan) {|c|
// FIXME (#1087): Would like to do notification in Rust
rustrt::rust_task_config_notify(new_task, c);
}
rustrt::start_task(new_task, closure);
unsafe::forget(f);
}
rustrt::start_task(new_task, closure);
unsafe::forget(f);
fn new_task_in_new_sched(opts: sched_opts) -> *rust_task {
if opts.native_stack_size != none {
fail "native_stack_size scheduler option unimplemented";
@ -962,7 +964,7 @@ fn test_osmain() {
#[test]
#[ignore(cfg(windows))]
#[should_fail]
fn test_unkillable() unsafe {
fn test_unkillable() {
import comm::methods;
let po = comm::port();
let ch = po.chan();
@ -980,14 +982,16 @@ fn test_unkillable() unsafe {
fail;
}
unkillable {||
let p = ~0;
let pp: *uint = unsafe::transmute(p);
unsafe {
unkillable {||
let p = ~0;
let pp: *uint = unsafe::transmute(p);
// If we are killed here then the box will leak
po.recv();
// If we are killed here then the box will leak
po.recv();
let _p: ~int = unsafe::transmute(pp);
let _p: ~int = unsafe::transmute(pp);
}
}
// Now we can be killed

View File

@ -131,17 +131,17 @@ Convert to a string in a given base
Fails if `radix` < 2 or `radix` > 16
"]
fn to_str(num: T, radix: uint) -> str unsafe {
fn to_str(num: T, radix: uint) -> str {
to_str_bytes(false, num, radix) {|slice|
vec::unpack_slice(slice) {|p, len|
str::unsafe::from_buf_len(p, len)
unsafe { str::unsafe::from_buf_len(p, len) }
}
}
}
#[doc = "Low-level helper routine for string conversion."]
fn to_str_bytes<U>(neg: bool, num: T, radix: uint,
f: fn([u8]/&) -> U) -> U unsafe {
f: fn([u8]/&) -> U) -> U {
#[inline(always)]
fn digit(n: T) -> u8 {
@ -177,28 +177,30 @@ fn to_str_bytes<U>(neg: bool, num: T, radix: uint,
// pointers and unsafe bits, and the codegen will prove it's all
// in-bounds, no extra cost.
vec::unpack_slice(buf) {|p, len|
let mp = p as *mut u8;
let mut i = len;
let mut n = num;
let radix = radix as T;
loop {
i -= 1u;
unsafe {
vec::unpack_slice(buf) {|p, len|
let mp = p as *mut u8;
let mut i = len;
let mut n = num;
let radix = radix as T;
loop {
i -= 1u;
assert 0u < i && i < len;
*ptr::mut_offset(mp, i) = digit(n % radix);
n /= radix;
if n == 0 as T { break; }
}
assert 0u < i && i < len;
*ptr::mut_offset(mp, i) = digit(n % radix);
n /= radix;
if n == 0 as T { break; }
if neg {
i -= 1u;
*ptr::mut_offset(mp, i) = '-' as u8;
}
vec::unsafe::form_slice(ptr::offset(p, i),
len - i, f)
}
assert 0u < i && i < len;
if neg {
i -= 1u;
*ptr::mut_offset(mp, i) = '-' as u8;
}
vec::unsafe::form_slice(ptr::offset(p, i),
len - i, f)
}
}

View File

@ -45,20 +45,24 @@ unsafe fn transmute<L, G>(-thing: L) -> G {
mod tests {
#[test]
fn test_reinterpret_cast() unsafe {
assert reinterpret_cast(1) == 1u;
fn test_reinterpret_cast() {
assert unsafe { reinterpret_cast(1) } == 1u;
}
#[test]
fn test_transmute() unsafe {
let x = @1;
let x: *int = transmute(x);
assert *x == 1;
let _x: @int = transmute(x);
fn test_transmute() {
unsafe {
let x = @1;
let x: *int = transmute(x);
assert *x == 1;
let _x: @int = transmute(x);
}
}
#[test]
fn test_transmute2() unsafe {
assert transmute("L") == [76u8, 0u8];
fn test_transmute2() {
unsafe {
assert transmute("L") == [76u8, 0u8];
}
}
}

View File

@ -158,14 +158,16 @@ fn reserve_at_least<T>(&v: [const T], n: uint) {
Returns the number of elements the vector can hold without reallocating
"]
#[inline(always)]
pure fn capacity<T>(&&v: [const T]) -> uint unsafe {
let repr: **unsafe::vec_repr = ::unsafe::reinterpret_cast(addr_of(v));
(**repr).alloc / sys::size_of::<T>()
pure fn capacity<T>(&&v: [const T]) -> uint {
unsafe {
let repr: **unsafe::vec_repr = ::unsafe::reinterpret_cast(addr_of(v));
(**repr).alloc / sys::size_of::<T>()
}
}
#[doc = "Returns the length of a vector"]
#[inline(always)]
pure fn len<T>(&&v: [const T]/&) -> uint unsafe {
pure fn len<T>(&&v: [const T]/&) -> uint {
unpack_const_slice(v) {|_p, len| len}
}
@ -179,7 +181,7 @@ pure fn from_fn<T>(n_elts: uint, op: init_op<T>) -> [T] {
let mut v = [];
unchecked{reserve(v, n_elts);}
let mut i: uint = 0u;
while i < n_elts { v += [op(i)]; i += 1u; }
while i < n_elts unsafe { push(v, op(i)); i += 1u; }
ret v;
}
@ -200,13 +202,13 @@ pure fn from_elem<T: copy>(n_elts: uint, t: T) -> [T] {
}
#[doc = "Produces a mut vector from an immutable vector."]
fn to_mut<T>(+v: [T]) -> [mut T] unsafe {
::unsafe::transmute(v)
fn to_mut<T>(+v: [T]) -> [mut T] {
unsafe { ::unsafe::transmute(v) }
}
#[doc = "Produces an immutable vector from a mut vector."]
fn from_mut<T>(+v: [mut T]) -> [T] unsafe {
::unsafe::transmute(v)
fn from_mut<T>(+v: [mut T]) -> [T] {
unsafe { ::unsafe::transmute(v) }
}
// Accessors
@ -385,7 +387,6 @@ fn shift<T>(&v: [T]) -> T {
let mut r <- *vv;
for uint::range(1u, ln) {|i|
// FIXME (#2703): this isn't legal, per se...
let r <- *ptr::offset(vv, i);
push(v, r);
}
@ -397,14 +398,25 @@ fn shift<T>(&v: [T]) -> T {
}
}
#[doc = "Prepend an element to the vector"]
fn unshift<T>(&v: [T], +x: T) {
let mut vv = [x];
v <-> vv;
while len(vv) > 0 {
push(v, shift(vv));
}
}
#[doc = "Remove the last element from a vector and return it"]
fn pop<T>(&v: [const T]) -> T unsafe {
fn pop<T>(&v: [const T]) -> T {
let ln = len(v);
assert ln > 0u;
let valptr = ptr::mut_addr_of(v[ln - 1u]);
let val <- *valptr;
unsafe::set_len(v, ln - 1u);
val
unsafe {
let val <- *valptr;
unsafe::set_len(v, ln - 1u);
val
}
}
#[doc = "Append an element to a vector"]
@ -556,7 +568,7 @@ Apply a function to each element of a vector and return the results
pure fn mapi<T, U>(v: [T]/&, f: fn(uint, T) -> U) -> [U] {
let mut result = [];
unchecked{reserve(result, len(v));}
for eachi(v) {|i, elem| result += [f(i, elem)]; }
for eachi(v) {|i, elem| unsafe { push(result, f(i, elem)); } }
ret result;
}
@ -955,13 +967,15 @@ Iterates over a vector, with option to break
Return true to continue, false to break.
"]
#[inline(always)]
pure fn each<T>(v: [const T]/&, f: fn(T) -> bool) unsafe {
pure fn each<T>(v: [const T]/&, f: fn(T) -> bool) {
vec::unpack_slice(v) {|p, n|
let mut n = n;
let mut p = p;
while n > 0u {
if !f(*p) { break; }
p = ptr::offset(p, 1u);
unsafe {
if !f(*p) { break; }
p = ptr::offset(p, 1u);
}
n -= 1u;
}
}
@ -973,13 +987,15 @@ Iterates over a vector's elements and indices
Return true to continue, false to break.
"]
#[inline(always)]
pure fn eachi<T>(v: [const T]/&, f: fn(uint, T) -> bool) unsafe {
pure fn eachi<T>(v: [const T]/&, f: fn(uint, T) -> bool) {
vec::unpack_slice(v) {|p, n|
let mut i = 0u;
let mut p = p;
while i < n {
if !f(i, *p) { break; }
p = ptr::offset(p, 1u);
unsafe {
if !f(i, *p) { break; }
p = ptr::offset(p, 1u);
}
i += 1u;
}
}
@ -1080,11 +1096,11 @@ Work with the buffer of a vector.
Allows for unsafe manipulation of vector contents, which is useful for native
interop.
"]
fn as_buf<E,T>(v: [E]/&, f: fn(*E) -> T) -> T unsafe {
fn as_buf<E,T>(v: [E]/&, f: fn(*E) -> T) -> T {
unpack_slice(v) { |buf, _len| f(buf) }
}
fn as_mut_buf<E,T>(v: [mut E]/&, f: fn(*mut E) -> T) -> T unsafe {
fn as_mut_buf<E,T>(v: [mut E]/&, f: fn(*mut E) -> T) -> T {
unpack_mut_slice(v) { |buf, _len| f(buf) }
}
@ -1093,10 +1109,12 @@ Work with the buffer and length of a slice.
"]
#[inline(always)]
pure fn unpack_slice<T,U>(s: [const T]/&,
f: fn(*T, uint) -> U) -> U unsafe {
let v : *(*T,uint) = ::unsafe::reinterpret_cast(ptr::addr_of(s));
let (buf,len) = *v;
f(buf, len / sys::size_of::<T>())
f: fn(*T, uint) -> U) -> U {
unsafe {
let v : *(*T,uint) = ::unsafe::reinterpret_cast(ptr::addr_of(s));
let (buf,len) = *v;
f(buf, len / sys::size_of::<T>())
}
}
#[doc = "
@ -1104,10 +1122,13 @@ Work with the buffer and length of a slice.
"]
#[inline(always)]
pure fn unpack_const_slice<T,U>(s: [const T]/&,
f: fn(*const T, uint) -> U) -> U unsafe {
let v : *(*const T,uint) = ::unsafe::reinterpret_cast(ptr::addr_of(s));
let (buf,len) = *v;
f(buf, len / sys::size_of::<T>())
f: fn(*const T, uint) -> U) -> U {
unsafe {
let v : *(*const T,uint) =
::unsafe::reinterpret_cast(ptr::addr_of(s));
let (buf,len) = *v;
f(buf, len / sys::size_of::<T>())
}
}
#[doc = "
@ -1115,10 +1136,13 @@ Work with the buffer and length of a slice.
"]
#[inline(always)]
pure fn unpack_mut_slice<T,U>(s: [mut T]/&,
f: fn(*mut T, uint) -> U) -> U unsafe {
let v : *(*const T,uint) = ::unsafe::reinterpret_cast(ptr::addr_of(s));
let (buf,len) = *v;
f(buf, len / sys::size_of::<T>())
f: fn(*mut T, uint) -> U) -> U {
unsafe {
let v : *(*const T,uint) =
::unsafe::reinterpret_cast(ptr::addr_of(s));
let (buf,len) = *v;
f(buf, len / sys::size_of::<T>())
}
}
impl extensions<T: copy> for [T] {
@ -1372,12 +1396,14 @@ mod u8 {
export hash;
#[doc = "Bytewise string comparison"]
pure fn cmp(&&a: [u8], &&b: [u8]) -> int unsafe {
pure fn cmp(&&a: [u8], &&b: [u8]) -> int {
let a_len = len(a);
let b_len = len(b);
let n = uint::min(a_len, b_len) as libc::size_t;
let r = libc::memcmp(unsafe::to_ptr(a) as *libc::c_void,
unsafe::to_ptr(b) as *libc::c_void, n) as int;
let r = unsafe {
libc::memcmp(unsafe::to_ptr(a) as *libc::c_void,
unsafe::to_ptr(b) as *libc::c_void, n) as int
};
if r != 0 { r } else {
if a_len == b_len {
@ -1397,10 +1423,10 @@ mod u8 {
pure fn le(&&a: [u8], &&b: [u8]) -> bool { cmp(a, b) <= 0 }
#[doc = "Bytewise equality"]
pure fn eq(&&a: [u8], &&b: [u8]) -> bool unsafe { cmp(a, b) == 0 }
pure fn eq(&&a: [u8], &&b: [u8]) -> bool { unsafe { cmp(a, b) == 0 } }
#[doc = "Bytewise inequality"]
pure fn ne(&&a: [u8], &&b: [u8]) -> bool unsafe { cmp(a, b) != 0 }
pure fn ne(&&a: [u8], &&b: [u8]) -> bool { unsafe { cmp(a, b) != 0 } }
#[doc ="Bytewise greater than or equal"]
pure fn ge(&&a: [u8], &&b: [u8]) -> bool { cmp(a, b) >= 0 }
@ -1474,26 +1500,28 @@ mod tests {
fn add(&&x: uint, &&y: uint) -> uint { ret x + y; }
#[test]
fn test_unsafe_ptrs() unsafe {
// Test on-stack copy-from-buf.
let a = [1, 2, 3];
let mut ptr = unsafe::to_ptr(a);
let b = unsafe::from_buf(ptr, 3u);
assert (len(b) == 3u);
assert (b[0] == 1);
assert (b[1] == 2);
assert (b[2] == 3);
fn test_unsafe_ptrs() {
unsafe {
// Test on-stack copy-from-buf.
let a = [1, 2, 3];
let mut ptr = unsafe::to_ptr(a);
let b = unsafe::from_buf(ptr, 3u);
assert (len(b) == 3u);
assert (b[0] == 1);
assert (b[1] == 2);
assert (b[2] == 3);
// Test on-heap copy-from-buf.
let c = [1, 2, 3, 4, 5];
ptr = unsafe::to_ptr(c);
let d = unsafe::from_buf(ptr, 5u);
assert (len(d) == 5u);
assert (d[0] == 1);
assert (d[1] == 2);
assert (d[2] == 3);
assert (d[3] == 4);
assert (d[4] == 5);
// Test on-heap copy-from-buf.
let c = [1, 2, 3, 4, 5];
ptr = unsafe::to_ptr(c);
let d = unsafe::from_buf(ptr, 5u);
assert (len(d) == 5u);
assert (d[0] == 1);
assert (d[1] == 2);
assert (d[2] == 3);
assert (d[3] == 4);
assert (d[4] == 5);
}
}
#[test]
@ -2181,21 +2209,32 @@ mod tests {
}
#[test]
fn to_mut_no_copy() unsafe {
let x = [1, 2, 3];
let addr = unsafe::to_ptr(x);
let x_mut = to_mut(x);
let addr_mut = unsafe::to_ptr(x_mut);
assert addr == addr_mut;
fn to_mut_no_copy() {
unsafe {
let x = [1, 2, 3];
let addr = unsafe::to_ptr(x);
let x_mut = to_mut(x);
let addr_mut = unsafe::to_ptr(x_mut);
assert addr == addr_mut;
}
}
#[test]
fn from_mut_no_copy() unsafe {
let x = [mut 1, 2, 3];
let addr = unsafe::to_ptr(x);
let x_imm = from_mut(x);
let addr_imm = unsafe::to_ptr(x_imm);
assert addr == addr_imm;
fn from_mut_no_copy() {
unsafe {
let x = [mut 1, 2, 3];
let addr = unsafe::to_ptr(x);
let x_imm = from_mut(x);
let addr_imm = unsafe::to_ptr(x_imm);
assert addr == addr_imm;
}
}
#[test]
fn test_unshift() {
let mut x = [1, 2, 3];
unshift(x, 0);
assert x == [0, 1, 2, 3];
}
#[test]

View File

@ -822,7 +822,7 @@ fn read_common_impl(socket_data: *tcp_socket_data, timeout_msecs: uint)
log(debug, "starting tcp::read");
let iotask = (*socket_data).iotask;
let rs_result = read_start_common_impl(socket_data);
if result::is_failure(rs_result) {
if result::is_err(rs_result) {
let err_data = result::get_err(rs_result);
result::err(err_data)
}
@ -1433,7 +1433,7 @@ mod test {
let accept_result = accept(new_conn);
log(debug, "SERVER: after accept()");
if result::is_failure(accept_result) {
if result::is_err(accept_result) {
log(debug, "SERVER: error accept connection");
let err_data = result::get_err(accept_result);
comm::send(kill_ch, some(err_data));
@ -1474,7 +1474,7 @@ mod test {
log(debug, "SERVER: recv'd on cont_ch..leaving listen cb");
});
// err check on listen_result
if result::is_failure(listen_result) {
if result::is_err(listen_result) {
let err_data = result::get_err(listen_result);
log(debug, #fmt("SERVER: exited abnormally name %s msg %s",
err_data.err_name, err_data.err_msg));
@ -1495,7 +1495,7 @@ mod test {
let server_ip_addr = ip::v4::parse_addr(server_ip);
let new_listener_result =
new_listener(server_ip_addr, server_port, 128u, iotask);
if result::is_failure(new_listener_result) {
if result::is_err(new_listener_result) {
let err_data = result::get_err(new_listener_result);
log(debug, #fmt("SERVER: exited abnormally name %s msg %s",
err_data.err_name, err_data.err_msg));
@ -1507,7 +1507,7 @@ mod test {
// in a loop {}, but we're just going to take a single
// client.. get their req, write a resp and then exit
let new_conn_result = server_port.recv();
if result::is_failure(new_conn_result) {
if result::is_err(new_conn_result) {
let err_data = result::get_err(new_conn_result);
log(debug, #fmt("SERVER: exited abnormally name %s msg %s",
err_data.err_name, err_data.err_msg));
@ -1544,7 +1544,7 @@ mod test {
log(debug, "CLIENT: starting..");
let connect_result = connect(server_ip_addr, server_port, iotask);
if result::is_failure(connect_result) {
if result::is_err(connect_result) {
log(debug, "CLIENT: failed to connect");
let err_data = result::get_err(connect_result);
log(debug, #fmt("CLIENT: connect err name: %s msg: %s",
@ -1556,7 +1556,7 @@ mod test {
let resp_bytes = str::bytes(resp);
tcp_write_single(sock, resp_bytes);
let read_result = sock.read(0u);
if read_result.is_failure() {
if read_result.is_err() {
log(debug, "CLIENT: failure to read");
""
}
@ -1573,7 +1573,7 @@ mod test {
fn tcp_write_single(sock: tcp_socket, val: [u8]) {
let write_result_future = sock.write_future(val);
let write_result = write_result_future.get();
if result::is_failure(write_result) {
if result::is_err(write_result) {
log(debug, "tcp_write_single: write failed!");
let err_data = result::get_err(write_result);
log(debug, #fmt("tcp_write_single err name: %s msg: %s",

View File

@ -42,7 +42,7 @@ fn map_slices<A: copy send, B: copy send>(
// FIXME: why is the ::<A, ()> annotation required here? (#2617)
vec::unpack_slice::<A, ()>(xs) {|p, _len|
let f = f();
futures += [future::spawn() {|copy base|
let f = future::spawn() {|copy base|
unsafe {
let len = end - base;
let slice = (ptr::offset(p, base),
@ -55,7 +55,8 @@ fn map_slices<A: copy send, B: copy send>(
assert(vec::len(slice) == end - base);
f(base, slice)
}
}];
};
vec::push(futures, f);
};
base += items_per_task;
}

View File

@ -452,10 +452,7 @@ fn ser_ty(cx: ext_ctxt, tps: ser_tps_map,
[]
}
ast::ty_vstore(_, _) {
cx.span_unimpl(ty.span, "serialization for vstore types");
}
ast::ty_vstore(@{node: ast::ty_vec(mt),_}, ast::vstore_uniq) |
ast::ty_vec(mt) {
let ser_e =
cx.expr(
@ -472,6 +469,11 @@ fn ser_ty(cx: ext_ctxt, tps: ser_tps_map,
std::serialization::emit_from_vec($(s), $(v), {|__e| $(ser_e) })
}]
}
ast::ty_vstore(_, _) {
cx.span_unimpl(ty.span, "serialization for vstore types");
}
}
}
@ -673,14 +675,15 @@ fn deser_ty(cx: ext_ctxt, tps: deser_tps_map,
#ast{ fail }
}
ast::ty_vstore(_, _) {
cx.span_unimpl(ty.span, "deserialization for vstore types");
}
ast::ty_vstore(@{node: ast::ty_vec(mt),_}, ast::vstore_uniq) |
ast::ty_vec(mt) {
let l = deser_lambda(cx, tps, mt.ty, cx.clone(d));
#ast{ std::serialization::read_to_vec($(d), $(l)) }
}
ast::ty_vstore(_, _) {
cx.span_unimpl(ty.span, "deserialization for vstore types");
}
}
}

View File

@ -771,9 +771,9 @@ class parser {
} else if self.eat_keyword("if") {
ret pexpr(self.parse_if_expr());
} else if self.eat_keyword("for") {
ret pexpr(self.parse_for_expr());
ret pexpr(self.parse_sugary_call_expr("for", expr_loop_body));
} else if self.eat_keyword("do") {
ret pexpr(self.parse_do_expr());
ret pexpr(self.parse_sugary_call_expr("do", expr_do_body));
} else if self.eat_keyword("while") {
ret pexpr(self.parse_while_expr());
} else if self.eat_keyword("loop") {
@ -1283,36 +1283,21 @@ class parser {
}
}
fn parse_for_expr() -> @expr {
fn parse_sugary_call_expr(keyword: str,
ctor: fn(+@expr) -> expr_) -> @expr {
let lo = self.last_span;
let call = self.parse_expr_res(RESTRICT_STMT_EXPR);
alt call.node {
expr_call(f, args, true) {
let b_arg = vec::last(args);
let last = self.mk_expr(b_arg.span.lo, b_arg.span.hi,
expr_loop_body(b_arg));
ctor(b_arg));
@{node: expr_call(f, vec::init(args) + [last], true)
with *call}
}
_ {
self.span_fatal(lo, "`for` must be followed by a block call");
}
}
}
fn parse_do_expr() -> @expr {
let lo = self.last_span;
let call = self.parse_expr_res(RESTRICT_STMT_EXPR);
alt call.node {
expr_call(f, args, true) {
let b_arg = vec::last(args);
let last = self.mk_expr(b_arg.span.lo, b_arg.span.hi,
expr_do_body(b_arg));
@{node: expr_call(f, vec::init(args) + [last], true)
with *call}
}
_ {
self.span_fatal(lo, "`do` must be followed by a block call");
self.span_fatal(
lo, #fmt("`%s` must be followed by a block call", keyword));
}
}
}
@ -1956,7 +1941,7 @@ class parser {
let rp = self.parse_region_param();
let ty_params = self.parse_ty_params();
let class_path = self.ident_to_path_tys(class_name, rp, ty_params);
let ifaces : [@iface_ref] = if self.eat_keyword("implements")
let ifaces : [@iface_ref] = if self.eat(token::COLON)
{ self.parse_iface_ref_list() }
else { [] };
self.expect(token::LBRACE);

View File

@ -251,7 +251,6 @@ fn contextual_keyword_table() -> hashmap<str, ()> {
let keys = [
"as",
"else",
"implements",
"move",
"of",
"priv", "pub",

View File

@ -495,9 +495,11 @@ fn print_item(s: ps, &&item: @ast::item) {
word_nbsp(s, *item.ident);
print_region_param(s, rp);
print_type_params(s, tps);
word_space(s, "implements");
commasep(s, inconsistent, ifaces, {|s, p|
print_path(s, p.path, false)});
if vec::len(ifaces) != 0u {
word_space(s, ":");
commasep(s, inconsistent, ifaces, {|s, p|
print_path(s, p.path, false)});
}
bopen(s);
hardbreak_if_not_bol(s);
maybe_print_comment(s, ctor.span.lo);

View File

@ -891,9 +891,7 @@ rust_unlock_cond_lock(rust_cond_lock *lock) {
extern "C" void
rust_wait_cond_lock(rust_cond_lock *lock) {
rust_task *task = rust_get_current_task();
#ifdef DEBUG_LOCKS
assert(lock->lock.lock_held_by_current_thread());
#endif
lock->lock.must_have_lock();
assert(NULL == lock->waiting);
lock->waiting = task;
task->block(lock, "waiting for signal");
@ -905,9 +903,7 @@ rust_wait_cond_lock(rust_cond_lock *lock) {
extern "C" bool
rust_signal_cond_lock(rust_cond_lock *lock) {
#ifdef DEBUG_LOCKS
assert(lock->lock.lock_held_by_current_thread());
#endif
lock->lock.must_have_lock();
if(NULL == lock->waiting) {
return false;
}

View File

@ -34,7 +34,7 @@ fn visit_expr(ex: @expr, cx: ctx, v: visit::vt<ctx>) {
i += 1u;
}
}
expr_loop_body(body) {
expr_loop_body(body) | expr_do_body(body) {
cx.allow_block = true;
v.visit_expr(body, cx, v);
}

View File

@ -1752,7 +1752,6 @@ fn trans_assign_op(bcx: block, ex: @ast::expr, op: ast::binop,
arg_exprs([src]), save_in(target));
ret move_val(bcx, DROP_EXISTING, lhs_res.val,
// FIXME (#2704): should kind be owned?
{bcx: bcx, val: target, kind: owned},
dty);
}

View File

@ -677,7 +677,7 @@ fn mk_nil_ptr(cx: ctxt) -> t {
mk_ptr(cx, {ty: mk_nil(cx), mutbl: ast::m_imm})
}
fn mk_vec(cx: ctxt, tm: mt) -> t { mk_t(cx, ty_vec(tm)) }
fn mk_vec(cx: ctxt, tm: mt) -> t { mk_evec(cx, tm, vstore_uniq) }
fn mk_evec(cx: ctxt, tm: mt, t: vstore) -> t {
mk_t(cx, ty_evec(tm, t))
@ -1472,7 +1472,7 @@ fn type_kind(cx: ctxt, ty: t) -> kind {
ty_nil | ty_bot | ty_bool | ty_int(_) | ty_uint(_) | ty_float(_) |
ty_ptr(_) { kind_implicitly_sendable() | kind_const() }
// Implicit copyability of strs is configurable
ty_str {
ty_str | ty_estr(vstore_uniq) {
if cx.vecs_implicitly_copyable {
kind_implicitly_sendable() | kind_const()
} else { kind_sendable() | kind_const() }
@ -1502,7 +1502,7 @@ fn type_kind(cx: ctxt, ty: t) -> kind {
remove_implicit(mutable_type_kind(cx, tm))
}
// Implicit copyability of vecs is configurable
ty_vec(tm) {
ty_vec(tm) | ty_evec(tm, vstore_uniq) {
if cx.vecs_implicitly_copyable {
mutable_type_kind(cx, tm)
} else { remove_implicit(mutable_type_kind(cx, tm)) }
@ -1520,9 +1520,6 @@ fn type_kind(cx: ctxt, ty: t) -> kind {
kind_implicitly_copyable()
}
}
ty_evec(tm, vstore_uniq) {
remove_implicit(mutable_type_kind(cx, tm))
}
ty_evec(tm, vstore_fixed(_)) {
mutable_type_kind(cx, tm)
}
@ -1530,7 +1527,6 @@ fn type_kind(cx: ctxt, ty: t) -> kind {
// All estrs are copyable; uniques and interiors are sendable.
ty_estr(vstore_box) |
ty_estr(vstore_slice(_)) { kind_implicitly_copyable() | kind_const() }
ty_estr(vstore_uniq) { kind_sendable() | kind_const() }
ty_estr(vstore_fixed(_)) { kind_implicitly_sendable() | kind_const() }
// Records lower to the lowest of their members.

View File

@ -218,7 +218,7 @@ fn require_same_types(
fn arg_is_argv_ty(_tcx: ty::ctxt, a: ty::arg) -> bool {
alt ty::get(a.ty).struct {
ty::ty_vec(mt) {
ty::ty_evec(mt, vstore_uniq) {
if mt.mutbl != ast::m_imm { ret false; }
alt ty::get(mt.ty).struct {
ty::ty_str { ret true; }
@ -271,12 +271,12 @@ fn check_main_fn_ty(ccx: @crate_ctxt,
}
}
fn check_for_main_fn(ccx: @crate_ctxt, crate: @ast::crate) {
fn check_for_main_fn(ccx: @crate_ctxt) {
let tcx = ccx.tcx;
if !tcx.sess.building_library {
alt copy tcx.sess.main_fn {
some((id, sp)) { check_main_fn_ty(ccx, id, sp); }
none { tcx.sess.span_err(crate.span, "main function not found"); }
none { tcx.sess.err("main function not found"); }
}
}
}
@ -289,7 +289,7 @@ fn check_crate(tcx: ty::ctxt, impl_map: resolve::impl_map,
tcx: tcx};
collect::collect_item_types(ccx, crate);
check::check_item_types(ccx, crate);
check_for_main_fn(ccx, crate);
check_for_main_fn(ccx);
tcx.sess.abort_if_errors();
(ccx.method_map, ccx.vtable_map)
}

View File

@ -170,6 +170,12 @@ fn ast_ty_to_ty<AC: ast_conv, RS: region_scope copy>(
ret ty::mk_evec(tcx, mt, vst);
}
// HACK: if we get a []/~, we assume that it was actually a
// [] that got written down, and we throw away the /~...
ty::ty_evec(mt, vstore_uniq) {
ret ty::mk_evec(tcx, mt, vst);
}
ty::ty_str {
ret ty::mk_estr(tcx, vst);
}

View File

@ -381,7 +381,7 @@ fn check_item(ccx: @crate_ctxt, it: @ast::item) {
// Check that there's at least one field
let (fields,_) = split_class_items(members);
if fields.len() < 1u {
ccx.tcx.sess.span_err(it.span, "A class must have at least one \
ccx.tcx.sess.span_err(it.span, "a class must have at least one \
field");
}
// Check that the class is instantiable
@ -938,7 +938,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
// separate case below.
tcx.sess.span_bug(
expr.span,
#fmt["Comparison operator in expr_binop: %s",
#fmt["comparison operator in expr_binop: %s",
ast_util::binop_to_str(op)]);
}
_ { lhs_t }
@ -1217,7 +1217,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
result::ok(_) { /* fall through */ }
result::err(_) {
tcx.sess.span_err(expr.span,
"ret; in function returning non-nil"); }
"`ret;` in function returning non-nil"); }
}
}
some(e) { check_expr_with(fcx, e, ret_ty); }
@ -1299,7 +1299,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
result::ok(_) {}
result::err(err) {
tcx.sess.span_fatal(
expr.span, #fmt("a loop function's last argument \
expr.span, #fmt("a `loop` function's last argument \
should return `bool`, not `%s`",
fcx.infcx.ty_to_str(fty.output)));
}
@ -1307,8 +1307,9 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
(ty::mk_fn(tcx, {output: ty::mk_nil(tcx) with fty}), fty.proto)
}
_ {
tcx.sess.span_fatal(expr.span, "a loop function's last argument \
should be of function type");
tcx.sess.span_fatal(expr.span, "a `loop` function's last \
argument should be of function \
type");
}
};
alt check b.node {
@ -1334,7 +1335,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
(ty::mk_fn(tcx, fty), fty.proto)
}
_ {
tcx.sess.span_fatal(expr.span, "a do function's last argument \
tcx.sess.span_fatal(expr.span, "a `do` function's last argument \
should be of function type");
}
};
@ -1547,8 +1548,9 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
}
none {
let t_err = fcx.infcx.resolve_type_vars_if_possible(expr_t);
let msg = #fmt["attempted access of field %s on type %s, but \
no public field or method with that name was found",
let msg = #fmt["attempted access of field `%s` on type `%s`, \
but no public field or method with that name \
was found",
*field, fcx.infcx.ty_to_str(t_err)];
tcx.sess.span_err(expr.span, msg);
// NB: Adding a bogus type to allow typechecking to continue
@ -1781,8 +1783,8 @@ fn check_instantiable(tcx: ty::ctxt,
let rty = ty::node_id_to_type(tcx, item_id);
if !ty::is_instantiable(tcx, rty) {
tcx.sess.span_err(sp, #fmt["this type cannot be instantiated \
without an instance of itself. \
Consider using option<%s>.",
without an instance of itself; \
consider using `option<%s>`",
ty_to_str(tcx, rty)]);
}
}
@ -1821,7 +1823,7 @@ fn check_enum_variants(ccx: @crate_ctxt,
}
if vec::contains(disr_vals, disr_val) {
ccx.tcx.sess.span_err(v.span,
"discriminator value already exists.");
"discriminator value already exists");
}
disr_vals += [disr_val];
let ctor_ty = ty::node_id_to_type(ccx.tcx, v.node.id);
@ -1848,7 +1850,7 @@ fn check_enum_variants(ccx: @crate_ctxt,
_ { false }
}
}) {
ccx.tcx.sess.span_err(sp, "illegal recursive enum type. \
ccx.tcx.sess.span_err(sp, "illegal recursive enum type; \
wrap the inner value in a box to \
make it representable");
}
@ -2195,13 +2197,13 @@ fn check_bounds_are_used(ccx: @crate_ctxt,
if !r_used {
ccx.tcx.sess.span_err(
span, "lifetime `self` unused inside \
reference-parameterized type.");
reference-parameterized type");
}
for tps_used.eachi { |i, b|
if !b {
ccx.tcx.sess.span_err(
span, #fmt["Type parameter %s is unused.", *tps[i].ident]);
span, #fmt["type parameter `%s` is unused", *tps[i].ident]);
}
}
}
@ -2268,13 +2270,13 @@ fn check_intrinsic_type(ccx: @crate_ctxt, it: @ast::native_item) {
let i_n_tps = (*i_ty.bounds).len();
if i_n_tps != n_tps {
tcx.sess.span_err(it.span, #fmt("intrinsic has wrong number \
of type parameters. found %u, \
of type parameters: found %u, \
expected %u", i_n_tps, n_tps));
} else {
require_same_types(
tcx, none, it.span, i_ty.ty, fty,
{|| #fmt["intrinsic has wrong type. \
expected %s",
{|| #fmt["intrinsic has wrong type: \
expected `%s`",
ty_to_str(ccx.tcx, fty)]});
}
}

View File

@ -3,7 +3,7 @@ import to_str::to_str;
mod kitty {
class cat implements to_str {
class cat : to_str {
priv {
let mut meows : uint;
fn meow() {

View File

@ -305,7 +305,7 @@ fn validate(edges: [(node_id, node_id)],
status = false;
}
path += [parent];
vec::push(path, parent);
parent = tree[parent];
}

View File

@ -40,7 +40,7 @@ fn run(args: [str]) {
let mut worker_results = [];
for uint::range(0u, workers) {|_i|
let builder = task::builder();
worker_results += [task::future_result(builder)];
vec::push(worker_results, task::future_result(builder));
task::run(builder) {||
for uint::range(0u, size / workers) {|_i|
comm::send(to_child, bytes(100u));

View File

@ -77,7 +77,6 @@ mod map_reduce {
type putter<K: send, V: send> = fn(K, V);
// FIXME: the first K1 parameter should probably be a - (#2599)
type mapper<K1: send, K2: send, V: send> = fn~(K1, putter<K2, V>);
type getter<V: send> = fn() -> option<V>;

View File

@ -1,9 +1,9 @@
// error-pattern: attempted access of field eat on type noisy
// error-pattern: attempted access of field `eat` on type `noisy`
iface noisy {
fn speak();
}
class cat implements noisy {
class cat : noisy {
priv {
let mut meows : uint;
fn meow() {

View File

@ -1,5 +1,5 @@
// error-pattern:unresolved typename: nonexistent
class cat implements nonexistent {
class cat : nonexistent {
let meows: uint;
new(in_x : uint) { self.meows = in_x; }
}

View File

@ -1,4 +1,4 @@
class cat implements int { //! ERROR can only implement interface types
class cat : int { //! ERROR can only implement interface types
let meows: uint;
new(in_x : uint) { self.meows = in_x; }
}

View File

@ -3,7 +3,7 @@ iface animal {
fn eat();
}
class cat implements animal {
class cat : animal {
let meows: uint;
new(in_x : uint) { self.meows = in_x; }
}

View File

@ -1,2 +1,2 @@
// error-pattern:expected `str` but found `[int]`
// error-pattern:expected `str` but found `[int]/~`
fn main() { fail [0i]; }

View File

@ -1,6 +1,6 @@
// Issue #1763 - infer types correctly
type actor<T> = { //! ERROR Type parameter T is unused.
type actor<T> = { //! ERROR type parameter `T` is unused
unused: bool
};

View File

@ -1,4 +1,4 @@
class c { //! ERROR A class must have at least one field
class c { //! ERROR a class must have at least one field
new() { }
}

View File

@ -1,4 +1,4 @@
// error-pattern:attempted access of field nap on type
// error-pattern:attempted access of field `nap` on type
// xfail-fast
// aux-build:cci_class_5.rs
use cci_class_5;

View File

@ -1,4 +1,4 @@
// error-pattern: ret; in function returning non-nil
// error-pattern: `ret;` in function returning non-nil
fn f() { ret; }

View File

@ -15,7 +15,7 @@ fn f(p: *rec) -> int {
// are prohibited by various checks, such as that the enum is
// instantiable and so forth).
ret p.f; //! ERROR attempted access of field f on type *rec
ret p.f; //! ERROR attempted access of field `f` on type `*rec`
}
fn main() {

View File

@ -1,8 +1,8 @@
// xfail-test
// FIXME: + should allow immutable or mutable vectors on the right
// hand side in all cases. We are getting compiler errors about this
// now, so I'm xfailing the test for now. -eholk
// FIXME (Issue #2711): + should allow immutable or mutable vectors on
// the right hand side in all cases. We are getting compiler errors
// about this now, so I'm xfailing the test for now. -eholk
fn add(i: [int], m: [mut int], c: [const int]) {

View File

@ -1,4 +1,4 @@
// error-pattern:attempted access of field some_field_name on type [int]
// error-pattern:attempted access of field `some_field_name` on type `[int]/~`
// issue #367
fn f() {

View File

@ -1,7 +1,7 @@
import to_str::*;
import to_str::to_str;
class cat implements to_str {
class cat : to_str {
priv {
let mut meows : uint;
fn meow() {

View File

@ -2,7 +2,7 @@ iface noisy {
fn speak() -> int;
}
class dog implements noisy {
class dog : noisy {
priv {
let barks : @mut uint;
fn bark() -> int {
@ -26,7 +26,7 @@ class dog implements noisy {
fn speak() -> int { self.bark() }
}
class cat implements noisy {
class cat : noisy {
priv {
let meows : @mut uint;
fn meow() -> uint {

View File

@ -2,7 +2,7 @@ iface noisy {
fn speak();
}
class cat implements noisy {
class cat : noisy {
priv {
let mut meows : uint;
fn meow() {

View File

@ -2,7 +2,7 @@ use std;
import std::map::{map, hashmap, int_hash};
class keys<K: copy, V: copy, M: copy map<K,V>>
implements iter::base_iter<K> {
: iter::base_iter<K> {
let map: M;

View File

@ -2,7 +2,7 @@
use std;
import std::map::*;
class cat implements map<int, bool> {
class cat : map<int, bool> {
priv {
// Yes, you can have negative meows
let mut meows : int;

View File

@ -7,7 +7,7 @@ enum cat_type { tuxedo, tabby, tortoiseshell }
// for any int value that's less than the meows field
// ok: T should be in scope when resolving the iface ref for map
class cat<T: copy> implements map<int, T> {
class cat<T: copy> : map<int, T> {
priv {
// Yes, you can have negative meows
let mut meows : int;

View File

@ -3,7 +3,7 @@
use cci_class_iface;
import cci_class_iface::animals::*;
class cat implements noisy {
class cat : noisy {
priv {
let mut meows : uint;
fn meow() {

View File

@ -2,7 +2,7 @@ iface noisy {
fn speak();
}
class cat implements noisy {
class cat : noisy {
priv {
let mut meows : uint;
fn meow() {

View File

@ -24,7 +24,7 @@ fn vec_includes<T>(xs: [T], x: T) -> bool {
}
// vtables other than the 1st one don't seem to work
class cat implements noisy, scratchy, bitey {
class cat : noisy, scratchy, bitey {
priv {
let meows : @mut uint;
let scratched : dvec<furniture>;

View File

@ -2,7 +2,7 @@
fn adder(+x: @int, +y: @int) -> int { ret *x + *y; }
fn failer() -> @int { fail; }
fn main() {
assert(result::is_failure(task::try {||
assert(result::is_err(task::try {||
adder(@2, failer()); ()
}));
}

View File

@ -0,0 +1,5 @@
fn f(f: fn&(int)) { f(10) }
fn main() {
do f() { |i| assert i == 10 }
}

View File

@ -1,9 +1,3 @@
// xfail-test
// FIXME: This test is no longer testing what it was intended to. It should
// be testing spawning of a native function, but is actually testing
// spawning some other function, then executing a native function.
// #2602
/*
A reduced test case for Issue #506, provided by Rob Arnold.
*/
@ -13,9 +7,7 @@ import task;
#[abi = "cdecl"]
native mod rustrt {
fn task_yield();
fn rust_task_allow_kill();
}
fn yield_wrap(&&_arg: ()) { rustrt::task_yield(); }
fn main() { task::spawn((), yield_wrap); }
fn main() { task::spawn(rustrt::rust_task_allow_kill); }

View File

@ -52,8 +52,6 @@ fn test_tag() {
send(ch, tag1);
send(ch, tag2(10));
send(ch, tag3(10, 11u8, 'A'));
// FIXME: Do port semantics really guarantee these happen in order?
// (#2605)
let mut t1: t;
t1 = recv(po);
assert (t1 == tag1);