1
Fork 0
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) Version 0.2 (March 2012)
------------------------- -------------------------

View file

@ -2,9 +2,9 @@
export ptr_eq; 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"]; #[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] #[test]

View file

@ -231,7 +231,7 @@ fn test_to_digit() {
} }
#[test] #[test]
fn test_is_ascii() unsafe { fn test_is_ascii() {
assert str::all("banana", char::is_ascii); assert str::all("banana", char::is_ascii);
assert ! str::all("ประเทศไทย中华Việt Nam", 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; 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 rustrt::rust_port_size(p) != 0u as libc::size_t
} }
#[doc = "Receive on one of two ports"] #[doc = "Receive on one of two ports"]
fn select2<A: send, B: send>(p_a: port<A>, p_b: port<B>) 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 ports = [(**p_a).po, (**p_b).po];
let n_ports = 2 as libc::size_t; let n_ports = 2 as libc::size_t;
let yield = 0u, yieldp = ptr::addr_of(yield); let yield = 0u, yieldp = ptr::addr_of(yield);
@ -440,7 +440,7 @@ fn test_recv_chan_wrong_task() {
let po = port(); let po = port();
let ch = chan(po); let ch = chan(po);
send(ch, "flower"); send(ch, "flower");
assert result::is_failure(task::try {|| assert result::is_err(task::try {||
recv_chan(ch) recv_chan(ch)
}) })
} }

View file

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

View file

@ -81,7 +81,7 @@ mod ct {
enum piece { piece_string(str), piece_conv(conv), } enum piece { piece_string(str), piece_conv(conv), }
type error_fn = fn@(str) -> ! ; 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 mut pieces: [piece] = [];
let lim = str::len(s); let lim = str::len(s);
let mut buf = ""; let mut buf = "";
@ -225,7 +225,7 @@ mod ct {
} else { {count: count_implied, next: i} }; } else { {count: count_implied, next: i} };
} }
fn parse_type(s: str, i: uint, lim: uint, error: error_fn) -> 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"); } if i >= lim { error("missing type in conversion"); }
let tstr = str::slice(s, i, i+1u); let tstr = str::slice(s, i, i+1u);
// TODO: Do we really want two signed types here? // TODO: Do we really want two signed types here?
@ -314,7 +314,7 @@ mod rt {
let mut s = str::from_char(c); let mut s = str::from_char(c);
ret pad(cv, s, pad_nozero); 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 // For strings, precision is the maximum characters
// displayed // displayed
let mut unpadded = alt cv.precision { let mut unpadded = alt cv.precision {
@ -378,7 +378,7 @@ mod rt {
}; };
} }
enum pad_mode { pad_signed, pad_unsigned, pad_nozero, pad_float } 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 { let uwidth : uint = alt cv.width {
count_implied { ret s; } count_implied { ret s; }
count_is(width) { 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) } fn from_str(s: str) -> option<T> { parse_buf(str::bytes(s), 10u) }
#[doc = "Convert to a string in a given base"] #[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| to_str_bytes(n, radix) {|slice|
vec::unpack_slice(slice) {|p, len| 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 { 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]; let mut buf : [mut u8] = [mut];
vec::reserve(buf, len); vec::reserve(buf, len);
vec::as_mut_buf(buf) {|b| vec::as_mut_buf(buf) {|b|
let read = libc::fread(b as *mut c_void, 1u as size_t, let read = libc::fread(b as *mut c_void, 1u as size_t,
len as size_t, self); 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); 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 { impl of writer for *libc::FILE {
fn write(v: [const u8]/&) unsafe { fn write(v: [const u8]/&) {
vec::unpack_const_slice(v) {|vbuf, len| vec::unpack_const_slice(v) {|vbuf, len|
let nout = libc::fwrite(vbuf as *c_void, len as size_t, let nout = libc::fwrite(vbuf as *c_void, len as size_t,
1u as size_t, self); 1u as size_t, self);
@ -361,7 +361,7 @@ fn FILE_writer(f: *libc::FILE, cleanup: bool) -> writer {
} }
impl of writer for fd_t { impl of writer for fd_t {
fn write(v: [const u8]/&) unsafe { fn write(v: [const u8]/&) {
let mut count = 0u; let mut count = 0u;
vec::unpack_const_slice(v) {|vbuf, len| vec::unpack_const_slice(v) {|vbuf, len|
while count < 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); } } 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 = " #[doc = "
Moves a value out of an option type and returns it. 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. option types without copying them.
"]; "];
let addr = alt opt { unsafe {
some(x) { ptr::addr_of(x) } let addr = alt opt {
none { fail "option none" } some(x) { ptr::addr_of(x) }
}; none { fail "option none" }
let liberated_value = unsafe::reinterpret_cast(*addr); };
unsafe::forget(opt); let liberated_value = unsafe::reinterpret_cast(*addr);
ret liberated_value; unsafe::forget(opt);
ret liberated_value;
}
} }
impl extensions<T> for option<T> { 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 { fn global_env_task(msg_po: comm::port<msg>) {
priv::weaken_task {|weak_po| unsafe {
loop { priv::weaken_task {|weak_po|
alt comm::select2(msg_po, weak_po) { loop {
either::left(msg_getenv(n, resp_ch)) { alt comm::select2(msg_po, weak_po) {
comm::send(resp_ch, impl::getenv(n)) 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::left(msg_setenv(n, v, resp_ch)) {
} comm::send(resp_ch, impl::setenv(n, v))
either::right(_) { }
break; either::right(_) {
} break;
}
}
} }
} }
} }
@ -201,18 +203,20 @@ mod global_env {
mod impl { mod impl {
#[cfg(unix)] #[cfg(unix)]
fn getenv(n: str) -> option<str> unsafe { fn getenv(n: str) -> option<str> {
let s = str::as_c_str(n, libc::getenv); unsafe {
ret if unsafe::reinterpret_cast(s) == 0 { let s = str::as_c_str(n, libc::getenv);
option::none::<str> ret if unsafe::reinterpret_cast(s) == 0 {
} else { option::none::<str>
let s = unsafe::reinterpret_cast(s); } else {
option::some::<str>(str::unsafe::from_buf(s)) let s = unsafe::reinterpret_cast(s);
}; option::some::<str>(str::unsafe::from_buf(s))
};
}
} }
#[cfg(windows)] #[cfg(windows)]
fn getenv(n: str) -> option<str> unsafe { fn getenv(n: str) -> option<str> {
import libc::types::os::arch::extra::*; import libc::types::os::arch::extra::*;
import libc::funcs::extra::kernel32::*; import libc::funcs::extra::kernel32::*;
import win32::*; import win32::*;
@ -362,21 +366,23 @@ fn dll_filename(base: str) -> str {
fn self_exe_path() -> option<path> { fn self_exe_path() -> option<path> {
#[cfg(target_os = "freebsd")] #[cfg(target_os = "freebsd")]
fn load_self() -> option<path> unsafe { fn load_self() -> option<path> {
import libc::funcs::bsd44::*; unsafe {
import libc::consts::os::extra::*; import libc::funcs::bsd44::*;
fill_charp_buf() {|buf, sz| import libc::consts::os::extra::*;
let mib = [CTL_KERN as c_int, fill_charp_buf() {|buf, sz|
KERN_PROC as c_int, let mib = [CTL_KERN as c_int,
KERN_PROC_PATHNAME as c_int, -1 as c_int]; KERN_PROC as c_int,
sysctl(vec::unsafe::to_ptr(mib), vec::len(mib) as c_uint, KERN_PROC_PATHNAME as c_int, -1 as c_int];
buf as *mut c_void, ptr::mut_addr_of(sz), sysctl(vec::unsafe::to_ptr(mib), vec::len(mib) as c_uint,
ptr::null(), 0u as size_t) == (0 as c_int) buf as *mut c_void, ptr::mut_addr_of(sz),
ptr::null(), 0u as size_t) == (0 as c_int)
}
} }
} }
#[cfg(target_os = "linux")] #[cfg(target_os = "linux")]
fn load_self() -> option<path> unsafe { fn load_self() -> option<path> {
import libc::funcs::posix01::unistd::readlink; import libc::funcs::posix01::unistd::readlink;
fill_charp_buf() {|buf, sz| fill_charp_buf() {|buf, sz|
as_c_charp("/proc/self/exe") { |proc_self_buf| as_c_charp("/proc/self/exe") { |proc_self_buf|
@ -386,9 +392,10 @@ fn self_exe_path() -> option<path> {
} }
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
fn load_self() -> option<path> unsafe { fn load_self() -> option<path> {
// FIXME: remove imports when export globs work properly. #1238 // FIXME: remove imports when export globs work properly. #1238
import libc::funcs::extra::*; import libc::funcs::extra::*;
fill_charp_buf() {|buf, sz| fill_charp_buf() {|buf, sz|
_NSGetExecutablePath(buf, ptr::mut_addr_of(sz as u32)) _NSGetExecutablePath(buf, ptr::mut_addr_of(sz as u32))
== (0 as c_int) == (0 as c_int)
@ -396,7 +403,7 @@ fn self_exe_path() -> option<path> {
} }
#[cfg(windows)] #[cfg(windows)]
fn load_self() -> option<path> unsafe { fn load_self() -> option<path> {
// FIXME: remove imports when export globs work properly. #1238 // FIXME: remove imports when export globs work properly. #1238
import libc::types::os::arch::extra::*; import libc::types::os::arch::extra::*;
import libc::funcs::extra::kernel32::*; import libc::funcs::extra::kernel32::*;
@ -525,14 +532,14 @@ fn make_dir(p: path, mode: c_int) -> bool {
ret mkdir(p, mode); ret mkdir(p, mode);
#[cfg(windows)] #[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 // FIXME: remove imports when export globs work properly. #1238
import libc::types::os::arch::extra::*; import libc::types::os::arch::extra::*;
import libc::funcs::extra::kernel32::*; import libc::funcs::extra::kernel32::*;
import win32::*; import win32::*;
// FIXME: turn mode into something useful? #2623 // FIXME: turn mode into something useful? #2623
as_utf16_p(p) {|buf| as_utf16_p(p) {|buf|
CreateDirectoryW(buf, unsafe::reinterpret_cast(0)) CreateDirectoryW(buf, unsafe { unsafe::reinterpret_cast(0) })
!= (0 as BOOL) != (0 as BOOL)
} }
} }
@ -645,7 +652,7 @@ fn copy_file(from: path, to: path) -> bool {
} }
#[cfg(unix)] #[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| let istream = as_c_charp(from) {|fromp|
as_c_charp("rb") {|modebuf| as_c_charp("rb") {|modebuf|
libc::fopen(fromp, 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 any leading path separator on `post`, and returns the concatenation of the two
with a single path separator between them. 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 pre_ = pre;
let mut post_ = post; let mut post_ = post;
let sep = consts::path_sep as u8; let sep = consts::path_sep as u8;
let pre_len = str::len(pre); let pre_len = str::len(pre);
let post_len = str::len(post); let post_len = str::len(post);
if pre_len > 1u && pre[pre_len-1u] == sep { str::unsafe::pop_byte(pre_); } unsafe {
if post_len > 1u && post[0] == sep { str::unsafe::shift_byte(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_);
}
}
ret pre_ + path_sep() + post_; ret pre_ + path_sep() + post_;
} }

View file

@ -82,7 +82,7 @@ unsafe fn chan_from_global_ptr<T: send>(
} }
#[test] #[test]
fn test_from_global_chan1() unsafe { fn test_from_global_chan1() {
// This is unreadable, right? // This is unreadable, right?
@ -91,11 +91,13 @@ fn test_from_global_chan1() unsafe {
let globchanp = ptr::addr_of(globchan); let globchanp = ptr::addr_of(globchan);
// Create the global channel, attached to a new task // Create the global channel, attached to a new task
let ch = chan_from_global_ptr(globchanp, task::builder) {|po| let ch = unsafe {
let ch = comm::recv(po); chan_from_global_ptr(globchanp, task::builder) {|po|
comm::send(ch, true); let ch = comm::recv(po);
let ch = comm::recv(po); comm::send(ch, true);
comm::send(ch, true); let ch = comm::recv(po);
comm::send(ch, true);
}
}; };
// Talk to it // Talk to it
let po = comm::port(); let po = comm::port();
@ -103,9 +105,11 @@ fn test_from_global_chan1() unsafe {
assert comm::recv(po) == true; assert comm::recv(po) == true;
// This one just reuses the previous channel // This one just reuses the previous channel
let ch = chan_from_global_ptr(globchanp, task::builder) {|po| let ch = unsafe {
let ch = comm::recv(po); chan_from_global_ptr(globchanp, task::builder) {|po|
comm::send(ch, false); let ch = comm::recv(po);
comm::send(ch, false);
}
}; };
// Talk to the original global task // Talk to the original global task
@ -115,7 +119,7 @@ fn test_from_global_chan1() unsafe {
} }
#[test] #[test]
fn test_from_global_chan2() unsafe { fn test_from_global_chan2() {
iter::repeat(100u) {|| iter::repeat(100u) {||
// The global channel // The global channel
@ -129,12 +133,14 @@ fn test_from_global_chan2() unsafe {
// create the global channel // create the global channel
for uint::range(0u, 10u) {|i| for uint::range(0u, 10u) {|i|
task::spawn() {|| task::spawn() {||
let ch = chan_from_global_ptr( let ch = unsafe {
globchanp, task::builder) {|po| chan_from_global_ptr(
globchanp, task::builder) {|po|
for uint::range(0u, 10u) {|_j| for uint::range(0u, 10u) {|_j|
let ch = comm::recv(po); let ch = comm::recv(po);
comm::send(ch, {i}); comm::send(ch, {i});
}
} }
}; };
let po = comm::port(); 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 * Weak tasks must not be supervised. A supervised task keeps
a reference to its parent, so the parent will not die. 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 po = comm::port();
let ch = comm::chan(po); 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); let _unweaken = unweaken(ch);
f(po); f(po);
@ -191,50 +199,60 @@ unsafe fn weaken_task(f: fn(comm::port<()>)) unsafe {
} }
#[test] #[test]
fn test_weaken_task_then_unweaken() unsafe { fn test_weaken_task_then_unweaken() {
task::try {|| task::try {||
weaken_task {|_po| unsafe {
weaken_task {|_po|
}
} }
}; };
} }
#[test] #[test]
fn test_weaken_task_wait() unsafe { fn test_weaken_task_wait() {
let builder = task::builder(); let builder = task::builder();
task::unsupervise(builder); task::unsupervise(builder);
task::run(builder) {|| task::run(builder) {||
weaken_task {|po| unsafe {
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) {||
weaken_task {|po| weaken_task {|po|
// Wait for it to tell us to die
comm::recv(po); 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] #[test]
#[ignore(cfg(windows))] #[ignore(cfg(windows))]
fn test_weaken_task_fail() unsafe { fn test_weaken_task_fail() {
let res = task::try {|| let res = task::try {||
weaken_task {|_po| unsafe {
fail; 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"] #[doc = "Get an unsafe mut pointer to a value"]
#[inline(always)] #[inline(always)]
pure fn mut_addr_of<T>(val: T) -> *mut T unsafe { pure fn mut_addr_of<T>(val: T) -> *mut T {
unsafe::reinterpret_cast(rusti::addr_of(val)) unsafe {
unsafe::reinterpret_cast(rusti::addr_of(val))
}
} }
#[doc = "Calculate the offset from a pointer"] #[doc = "Calculate the offset from a pointer"]
#[inline(always)] #[inline(always)]
fn offset<T>(ptr: *T, count: uint) -> *T unsafe { fn offset<T>(ptr: *T, count: uint) -> *T {
(ptr as uint + count * sys::size_of::<T>()) as *T unsafe {
(ptr as uint + count * sys::size_of::<T>()) as *T
}
} }
#[doc = "Calculate the offset from a const pointer"] #[doc = "Calculate the offset from a const pointer"]
#[inline(always)] #[inline(always)]
fn const_offset<T>(ptr: *const T, count: uint) -> *const T unsafe { fn const_offset<T>(ptr: *const T, count: uint) -> *const T {
(ptr as uint + count * sys::size_of::<T>()) as *T unsafe {
(ptr as uint + count * sys::size_of::<T>()) as *T
}
} }
#[doc = "Calculate the offset from a mut pointer"] #[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"] #[doc = "Create an unsafe null pointer"]
#[inline(always)] #[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."] #[doc = "Returns true if the pointer is equal to the null pointer."]
pure fn is_null<T>(ptr: *const T) -> bool { ptr == null() } pure fn is_null<T>(ptr: *const T) -> bool { ptr == null() }
@ -127,48 +133,52 @@ impl extensions<T> for *T {
} }
#[test] #[test]
fn test() unsafe { fn test() {
type pair = {mut fst: int, mut snd: int}; unsafe {
let p = {mut fst: 10, mut snd: 20}; type pair = {mut fst: int, mut snd: int};
let pptr: *mut pair = mut_addr_of(p); let p = {mut fst: 10, mut snd: 20};
let iptr: *mut int = unsafe::reinterpret_cast(pptr); let pptr: *mut pair = mut_addr_of(p);
assert (*iptr == 10);; let iptr: *mut int = unsafe::reinterpret_cast(pptr);
*iptr = 30; assert (*iptr == 10);;
assert (*iptr == 30); *iptr = 30;
assert (p.fst == 30);; assert (*iptr == 30);
assert (p.fst == 30);;
*pptr = {mut fst: 50, mut snd: 60}; *pptr = {mut fst: 50, mut snd: 60};
assert (*iptr == 50); assert (*iptr == 50);
assert (p.fst == 50); assert (p.fst == 50);
assert (p.snd == 60); assert (p.snd == 60);
let v0 = [32000u16, 32001u16, 32002u16]; let v0 = [32000u16, 32001u16, 32002u16];
let v1 = [0u16, 0u16, 0u16]; let v1 = [0u16, 0u16, 0u16];
ptr::memcpy(ptr::offset(vec::unsafe::to_ptr(v1), 1u), ptr::memcpy(ptr::offset(vec::unsafe::to_ptr(v1), 1u),
ptr::offset(vec::unsafe::to_ptr(v0), 1u), 1u); ptr::offset(vec::unsafe::to_ptr(v0), 1u), 1u);
assert (v1[0] == 0u16 && v1[1] == 32001u16 && v1[2] == 0u16); assert (v1[0] == 0u16 && v1[1] == 32001u16 && v1[2] == 0u16);
ptr::memcpy(vec::unsafe::to_ptr(v1), ptr::memcpy(vec::unsafe::to_ptr(v1),
ptr::offset(vec::unsafe::to_ptr(v0), 2u), 1u); ptr::offset(vec::unsafe::to_ptr(v0), 2u), 1u);
assert (v1[0] == 32002u16 && v1[1] == 32001u16 && v1[2] == 0u16); assert (v1[0] == 32002u16 && v1[1] == 32001u16 && v1[2] == 0u16);
ptr::memcpy(ptr::offset(vec::unsafe::to_ptr(v1), 2u), ptr::memcpy(ptr::offset(vec::unsafe::to_ptr(v1), 2u),
vec::unsafe::to_ptr(v0), 1u); vec::unsafe::to_ptr(v0), 1u);
assert (v1[0] == 32002u16 && v1[1] == 32001u16 && v1[2] == 32000u16); assert (v1[0] == 32002u16 && v1[1] == 32001u16 && v1[2] == 32000u16);
}
} }
#[test] #[test]
fn test_position() unsafe { fn test_position() {
import str::as_c_str; import str::as_c_str;
import libc::c_char; import libc::c_char;
let s = "hello"; let s = "hello";
assert 2u == as_c_str(s) {|p| position(p) {|c| c == 'l' as c_char} }; unsafe {
assert 4u == as_c_str(s) {|p| position(p) {|c| c == 'o' as c_char} }; assert 2u == as_c_str(s) {|p| position(p) {|c| c == 'l' as c_char} };
assert 5u == as_c_str(s) {|p| position(p) {|c| c == 0 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] #[test]
fn test_buf_len() unsafe { fn test_buf_len() {
let s0 = "hello"; let s0 = "hello";
let s1 = "there"; let s1 = "there";
let s2 = "thing"; let s2 = "thing";
@ -177,7 +187,7 @@ fn test_buf_len() unsafe {
str::as_c_str(s2) {|p2| str::as_c_str(s2) {|p2|
let v = [p0, p1, p2, null()]; let v = [p0, p1, p2, null()];
vec::as_buf(v) {|vp| 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`"] #[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 { alt res {
ok(_) { true } ok(_) { true }
err(_) { false } err(_) { false }
} }
} }
#[doc = "Returns true if the result is `error`"] #[doc = "Returns true if the result is `err`"]
pure fn is_failure<T, U>(res: result<T, U>) -> bool { pure fn is_err<T, U>(res: result<T, U>) -> bool {
!is_success(res) !is_ok(res)
} }
#[doc = " #[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> { impl extensions<T, E> for result<T, E> {
fn get() -> T { get(self) } fn is_ok() -> bool { is_ok(self) }
fn get_err() -> E { get_err(self) } fn is_err() -> bool { is_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 iter(f: fn(T)) { fn iter(f: fn(T)) {
alt self { alt self {
@ -210,6 +198,21 @@ impl extensions<T:copy, E:copy> for result<T,E> {
err(e) { f(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> { fn map<U:copy>(op: fn(T) -> U) -> result<U,E> {
alt self { alt self {
@ -217,12 +220,15 @@ impl extensions<T:copy, E:copy> for result<T,E> {
err(e) { err(e) } err(e) { err(e) }
} }
} }
}
fn map_err<F:copy>(op: fn(E) -> F) -> result<T,F> { impl extensions<T:copy, E:copy> for result<T,E> {
alt self { fn chain<U:copy>(op: fn(T) -> result<U,E>) -> result<U,E> {
ok(t) { ok(t) } chain(self, op)
err(e) { err(op(e)) } }
}
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=" #[doc="
Unwraps a result, assuming it is an `ok(T)` Unwraps a result, assuming it is an `ok(T)`
"] "]
fn unwrap<T, U>(-res: result<T, U>) -> T unsafe { fn unwrap<T, U>(-res: result<T, U>) -> T {
let addr = alt res { unsafe {
ok(x) { ptr::addr_of(x) } let addr = alt res {
err(_) { fail "error result" } ok(x) { ptr::addr_of(x) }
}; err(_) { fail "error result" }
let liberated_value = unsafe::reinterpret_cast(*addr); };
unsafe::forget(res); let liberated_value = unsafe::reinterpret_cast(*addr);
ret liberated_value; unsafe::forget(res);
ret liberated_value;
}
} }
#[cfg(test)] #[cfg(test)]

View file

@ -66,7 +66,7 @@ fn spawn_process(prog: str, args: [str],
env: option<[(str,str)]>, env: option<[(str,str)]>,
dir: option<str>, dir: option<str>,
in_fd: c_int, out_fd: c_int, err_fd: c_int) in_fd: c_int, out_fd: c_int, err_fd: c_int)
-> pid_t unsafe { -> pid_t {
with_argv(prog, args) {|argv| with_argv(prog, args) {|argv|
with_envp(env) { |envp| with_envp(env) { |envp|
with_dirp(dir) { |dirp| with_dirp(dir) { |dirp|
@ -78,7 +78,7 @@ fn spawn_process(prog: str, args: [str],
} }
fn with_argv<T>(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 argptrs = str::as_c_str(prog) {|b| [b] };
let mut tmps = []; let mut tmps = [];
for vec::each(args) {|arg| for vec::each(args) {|arg|
@ -92,7 +92,7 @@ fn with_argv<T>(prog: str, args: [str],
#[cfg(unix)] #[cfg(unix)]
fn with_envp<T>(env: option<[(str,str)]>, 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 // On posixy systems we can pass a char** for envp, which is
// a null-terminated array of "k=v\n" strings. // a null-terminated array of "k=v\n" strings.
alt env { alt env {
@ -107,7 +107,9 @@ fn with_envp<T>(env: option<[(str,str)]>,
ptrs += str::as_c_str(*t) {|b| [b]}; ptrs += str::as_c_str(*t) {|b| [b]};
} }
ptrs += [ptr::null()]; 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()) cb(ptr::null())
@ -117,31 +119,33 @@ fn with_envp<T>(env: option<[(str,str)]>,
#[cfg(windows)] #[cfg(windows)]
fn with_envp<T>(env: option<[(str,str)]>, 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 // 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 // rather a concatenation of null-terminated k=v\0 sequences, with a final
// \0 to terminate. // \0 to terminate.
alt env { unsafe {
some(es) if !vec::is_empty(es) { alt env {
let mut blk : [u8] = []; some(es) if !vec::is_empty(es) {
for vec::each(es) {|e| let mut blk : [u8] = [];
let (k,v) = e; for vec::each(es) {|e|
let t = #fmt("%s=%s", k, v); let (k,v) = e;
let mut v : [u8] = ::unsafe::reinterpret_cast(t); let t = #fmt("%s=%s", k, v);
blk += v; let mut v : [u8] = ::unsafe::reinterpret_cast(t);
::unsafe::forget(v); 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>, fn with_dirp<T>(d: option<str>,
cb: fn(*libc::c_char) -> T) -> T unsafe { cb: fn(*libc::c_char) -> T) -> T {
alt d { alt d {
some(dir) { str::as_c_str(dir, cb) } some(dir) { str::as_c_str(dir, cb) }
none { cb(ptr::null()) } 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 Fails if invalid UTF-8
"] "]
pure fn from_bytes(vv: [u8]) -> str unsafe { pure fn from_bytes(vv: [u8]) -> str {
assert is_utf8(vv); assert is_utf8(vv);
ret unsafe::from_bytes(vv); ret unsafe { unsafe::from_bytes(vv) };
} }
#[doc = " #[doc = "
@ -134,83 +134,85 @@ Convert a byte to a UTF-8 string
Fails if invalid UTF-8 Fails if invalid UTF-8
"] "]
pure fn from_byte(b: u8) -> str unsafe { pure fn from_byte(b: u8) -> str {
assert b < 128u8; assert b < 128u8;
let mut v = [b, 0u8]; let mut v = [b, 0u8];
::unsafe::transmute(v) unsafe { ::unsafe::transmute(v) }
} }
#[doc = "Appends a character at the end of a string"] #[doc = "Appends a character at the end of a string"]
fn push_char(&s: str, ch: char) unsafe { fn push_char(&s: str, ch: char) {
let code = ch as uint; unsafe {
let nb = if code < max_one_b { 1u } let code = ch as uint;
let nb = if code < max_one_b { 1u }
else if code < max_two_b { 2u } else if code < max_two_b { 2u }
else if code < max_three_b { 3u } else if code < max_three_b { 3u }
else if code < max_four_b { 4u } else if code < max_four_b { 4u }
else if code < max_five_b { 5u } else if code < max_five_b { 5u }
else { 6u }; else { 6u };
let len = len(s); let len = len(s);
let new_len = len + nb; let new_len = len + nb;
reserve_at_least(s, new_len); reserve_at_least(s, new_len);
let off = len; let off = len;
as_buf(s) {|buf| as_buf(s) {|buf|
let buf: *mut u8 = ::unsafe::reinterpret_cast(buf); let buf: *mut u8 = ::unsafe::reinterpret_cast(buf);
if nb == 1u { if nb == 1u {
*ptr::mut_offset(buf, off) = *ptr::mut_offset(buf, off) =
code as u8; code as u8;
} else if nb == 2u { } else if nb == 2u {
*ptr::mut_offset(buf, off) = *ptr::mut_offset(buf, off) =
(code >> 6u & 31u | tag_two_b) as u8; (code >> 6u & 31u | tag_two_b) as u8;
*ptr::mut_offset(buf, off + 1u) = *ptr::mut_offset(buf, off + 1u) =
(code & 63u | tag_cont) as u8; (code & 63u | tag_cont) as u8;
} else if nb == 3u { } else if nb == 3u {
*ptr::mut_offset(buf, off) = *ptr::mut_offset(buf, off) =
(code >> 12u & 15u | tag_three_b) as u8; (code >> 12u & 15u | tag_three_b) as u8;
*ptr::mut_offset(buf, off + 1u) = *ptr::mut_offset(buf, off + 1u) =
(code >> 6u & 63u | tag_cont) as u8; (code >> 6u & 63u | tag_cont) as u8;
*ptr::mut_offset(buf, off + 2u) = *ptr::mut_offset(buf, off + 2u) =
(code & 63u | tag_cont) as u8; (code & 63u | tag_cont) as u8;
} else if nb == 4u { } else if nb == 4u {
*ptr::mut_offset(buf, off) = *ptr::mut_offset(buf, off) =
(code >> 18u & 7u | tag_four_b) as u8; (code >> 18u & 7u | tag_four_b) as u8;
*ptr::mut_offset(buf, off + 1u) = *ptr::mut_offset(buf, off + 1u) =
(code >> 12u & 63u | tag_cont) as u8; (code >> 12u & 63u | tag_cont) as u8;
*ptr::mut_offset(buf, off + 2u) = *ptr::mut_offset(buf, off + 2u) =
(code >> 6u & 63u | tag_cont) as u8; (code >> 6u & 63u | tag_cont) as u8;
*ptr::mut_offset(buf, off + 3u) = *ptr::mut_offset(buf, off + 3u) =
(code & 63u | tag_cont) as u8; (code & 63u | tag_cont) as u8;
} else if nb == 5u { } else if nb == 5u {
*ptr::mut_offset(buf, off) = *ptr::mut_offset(buf, off) =
(code >> 24u & 3u | tag_five_b) as u8; (code >> 24u & 3u | tag_five_b) as u8;
*ptr::mut_offset(buf, off + 1u) = *ptr::mut_offset(buf, off + 1u) =
(code >> 18u & 63u | tag_cont) as u8; (code >> 18u & 63u | tag_cont) as u8;
*ptr::mut_offset(buf, off + 2u) = *ptr::mut_offset(buf, off + 2u) =
(code >> 12u & 63u | tag_cont) as u8; (code >> 12u & 63u | tag_cont) as u8;
*ptr::mut_offset(buf, off + 3u) = *ptr::mut_offset(buf, off + 3u) =
(code >> 6u & 63u | tag_cont) as u8; (code >> 6u & 63u | tag_cont) as u8;
*ptr::mut_offset(buf, off + 4u) = *ptr::mut_offset(buf, off + 4u) =
(code & 63u | tag_cont) as u8; (code & 63u | tag_cont) as u8;
} else if nb == 6u { } else if nb == 6u {
*ptr::mut_offset(buf, off) = *ptr::mut_offset(buf, off) =
(code >> 30u & 1u | tag_six_b) as u8; (code >> 30u & 1u | tag_six_b) as u8;
*ptr::mut_offset(buf, off + 1u) = *ptr::mut_offset(buf, off + 1u) =
(code >> 24u & 63u | tag_cont) as u8; (code >> 24u & 63u | tag_cont) as u8;
*ptr::mut_offset(buf, off + 2u) = *ptr::mut_offset(buf, off + 2u) =
(code >> 18u & 63u | tag_cont) as u8; (code >> 18u & 63u | tag_cont) as u8;
*ptr::mut_offset(buf, off + 3u) = *ptr::mut_offset(buf, off + 3u) =
(code >> 12u & 63u | tag_cont) as u8; (code >> 12u & 63u | tag_cont) as u8;
*ptr::mut_offset(buf, off + 4u) = *ptr::mut_offset(buf, off + 4u) =
(code >> 6u & 63u | tag_cont) as u8; (code >> 6u & 63u | tag_cont) as u8;
*ptr::mut_offset(buf, off + 5u) = *ptr::mut_offset(buf, off + 5u) =
(code & 63u | tag_cont) as u8; (code & 63u | tag_cont) as u8;
}
*ptr::mut_offset(buf, off + nb) = 0u8;
} }
*ptr::mut_offset(buf, off + nb) = 0u8;
}
as_bytes(s) {|bytes| as_bytes(s) {|bytes|
let mut mut_bytes: [u8] = ::unsafe::reinterpret_cast(bytes); let mut mut_bytes: [u8] = ::unsafe::reinterpret_cast(bytes);
vec::unsafe::set_len(mut_bytes, new_len + 1u); vec::unsafe::set_len(mut_bytes, new_len + 1u);
::unsafe::forget(mut_bytes); ::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 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); 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; ret ch;
} }
@ -320,20 +322,22 @@ Converts a string to a vector of bytes
The result vector is not null-terminated. The result vector is not null-terminated.
"] "]
pure fn bytes(s: str) -> [u8] unsafe { pure fn bytes(s: str) -> [u8] {
let mut s_copy = s; unsafe {
let mut v: [u8] = ::unsafe::transmute(s_copy); let mut s_copy = s;
vec::unsafe::set_len(v, len(s)); let mut v: [u8] = ::unsafe::transmute(s_copy);
ret v; vec::unsafe::set_len(v, len(s));
ret v;
}
} }
#[doc = " #[doc = "
Work with the string as a byte slice, not including trailing null. Work with the string as a byte slice, not including trailing null.
"] "]
#[inline(always)] #[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| 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 Fails when `begin` and `end` do not point to valid characters or
beyond the last character of the string 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, begin);
assert is_char_boundary(s, end); assert is_char_boundary(s, end);
unsafe::slice_bytes(s, begin, end) unsafe { unsafe::slice_bytes(s, begin, end) }
} }
#[doc = " #[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) pure fn split_char_inner(s: str/&, sep: char, count: uint, allow_empty: bool)
-> [str] unsafe { -> [str] {
if sep < 128u as char { if sep < 128u as char {
let b = sep as u8, l = len(s); let b = sep as u8, l = len(s);
let mut result = [], done = 0u; 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 { while i < l && done < count {
if s[i] == b { if s[i] == b {
if allow_empty || start < i { if allow_empty || start < i {
result += [unsafe::slice_bytes(s, start, i)]; result += [unsafe { unsafe::slice_bytes(s, start, i) }];
} }
start = i + 1u; start = i + 1u;
done += 1u; done += 1u;
@ -412,7 +416,7 @@ pure fn split_char_inner(s: str/&, sep: char, count: uint, allow_empty: bool)
i += 1u; i += 1u;
} }
if allow_empty || start < l { if allow_empty || start < l {
result += [unsafe::slice_bytes(s, start, l)]; result += [unsafe { unsafe::slice_bytes(s, start, l) }];
} }
result result
} else { } 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, 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 l = len(s);
let mut result = [], i = 0u, start = 0u, done = 0u; let mut result = [], i = 0u, start = 0u, done = 0u;
while i < l && done < count { while i < l && done < count {
let {ch, next} = char_range_at(s, i); let {ch, next} = char_range_at(s, i);
if sepfn(ch) { if sepfn(ch) {
if allow_empty || start < i { if allow_empty || start < i {
result += [unsafe::slice_bytes(s, start, i)]; result += [unsafe { unsafe::slice_bytes(s, start, i) }];
} }
start = next; start = next;
done += 1u; done += 1u;
@ -455,7 +459,7 @@ pure fn split_inner(s: str/&, sepfn: fn(cc: char) -> bool, count: uint,
i = next; i = next;
} }
if allow_empty || start < l { if allow_empty || start < l {
result += [unsafe::slice_bytes(s, start, l)]; result += [unsafe { unsafe::slice_bytes(s, start, l) }];
} }
result result
} }
@ -578,7 +582,7 @@ Replace all occurrences of one string with another
The original string with all occurances of `from` replaced with `to` 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; let mut result = "", first = true;
iter_between_matches(s, from) {|start, end| iter_between_matches(s, from) {|start, end|
if first { first = false; } else { result += to; } 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 `count` times
"] "]
pure fn splitn_char_iter(ss: str/&, sep: char, count: uint, 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) 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 * haystack - The string to look in
* needle - The string to look for * 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); let haystack_len = len(haystack), needle_len = len(needle);
if needle_len == 0u { true } if needle_len == 0u { true }
else if needle_len > haystack_len { false } else if needle_len > haystack_len { false }
@ -1564,9 +1568,11 @@ interop.
let i = str::as_bytes(\"Hello World\") { |bytes| vec::len(bytes) }; let i = str::as_bytes(\"Hello World\") { |bytes| vec::len(bytes) };
~~~ ~~~
"] "]
pure fn as_bytes<T>(s: str, f: fn([u8]) -> T) -> T unsafe { pure fn as_bytes<T>(s: str, f: fn([u8]) -> T) -> T {
let v: *[u8] = ::unsafe::reinterpret_cast(ptr::addr_of(s)); unsafe {
f(*v) let v: *[u8] = ::unsafe::reinterpret_cast(ptr::addr_of(s));
f(*v)
}
} }
#[doc = " #[doc = "
@ -1575,8 +1581,8 @@ Work with the byte buffer of a string.
Allows for unsafe manipulation of strings, which is useful for native Allows for unsafe manipulation of strings, which is useful for native
interop. interop.
"] "]
pure fn as_buf<T>(s: str, f: fn(*u8) -> T) -> T unsafe { pure fn as_buf<T>(s: str, f: fn(*u8) -> T) -> T {
as_bytes(s) { |v| vec::as_buf(v, f) } as_bytes(s) { |v| unsafe { vec::as_buf(v, f) } }
} }
#[doc = " #[doc = "
@ -1591,7 +1597,7 @@ interop, without copying the original string.
let s = str::as_buf(\"PATH\", { |path_buf| libc::getenv(path_buf) }); 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) } 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. to full strings, or suffixes of them.
"] "]
#[inline(always)] #[inline(always)]
pure fn unpack_slice<T>(s: str/&, f: fn(*u8, uint) -> T) -> T unsafe { pure fn unpack_slice<T>(s: str/&, f: fn(*u8, uint) -> T) -> T {
let v : *(*u8,uint) = ::unsafe::reinterpret_cast(ptr::addr_of(s)); unsafe {
let (buf,len) = *v; let v : *(*u8,uint) = ::unsafe::reinterpret_cast(ptr::addr_of(s));
f(buf, len) let (buf,len) = *v;
f(buf, len)
}
} }
#[doc = " #[doc = "
@ -1653,7 +1661,7 @@ capacity, then no action is taken.
* s - A string * s - A string
* n - The number of bytes to reserve space for * 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) 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 Returns the number of single-byte characters the string can hold without
reallocating reallocating
"] "]
pure fn capacity(&&s: str) -> uint unsafe { pure fn capacity(&&s: str) -> uint {
as_bytes(s) {|buf| as_bytes(s) {|buf|
let vcap = vec::capacity(buf); let vcap = vec::capacity(buf);
assert vcap > 0u; assert vcap > 0u;
@ -1742,10 +1750,12 @@ mod unsafe {
Does not verify that the vector contains valid UTF-8. Does not verify that the vector contains valid UTF-8.
"] "]
unsafe fn from_bytes(v: [const u8]) -> str unsafe { unsafe fn from_bytes(v: [const u8]) -> str {
let mut vcopy : [u8] = ::unsafe::transmute(copy v); unsafe {
vec::push(vcopy, 0u8); let mut vcopy : [u8] = ::unsafe::transmute(copy v);
::unsafe::transmute(vcopy) vec::push(vcopy, 0u8);
::unsafe::transmute(vcopy)
}
} }
#[doc = " #[doc = "
@ -1765,20 +1775,22 @@ mod unsafe {
If begin is greater than end. If begin is greater than end.
If end is greater than the length of the string. 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| unpack_slice(s) { |sbuf, n|
assert (begin <= end); assert (begin <= end);
assert (end <= n); assert (end <= n);
let mut v = []; let mut v = [];
vec::reserve(v, end - begin + 1u); vec::reserve(v, end - begin + 1u);
vec::as_buf(v) { |vbuf| unsafe {
let src = ptr::offset(sbuf, begin); vec::as_buf(v) { |vbuf|
ptr::memcpy(vbuf, src, end - begin); 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 = " #[doc = "
Removes the last byte from a string and returns it. (Not UTF-8 safe). 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); let len = len(s);
assert (len > 0u); assert (len > 0u);
let b = s[len - 1u]; let b = s[len - 1u];
set_len(s, len - 1u); unsafe { set_len(s, len - 1u) };
ret b; ret b;
} }
#[doc = " #[doc = "
Removes the first byte from a string and returns it. (Not UTF-8 safe). 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); let len = len(s);
assert (len > 0u); assert (len > 0u);
let b = s[0]; let b = s[0];
s = unsafe::slice_bytes(s, 1u, len); s = unsafe { unsafe::slice_bytes(s, 1u, len) };
ret b; ret b;
} }
@ -1825,11 +1837,13 @@ mod unsafe {
} }
#[test] #[test]
fn test_from_buf_len() unsafe { fn test_from_buf_len() {
let a = [65u8, 65u8, 65u8, 65u8, 65u8, 65u8, 65u8, 0u8]; unsafe {
let b = vec::unsafe::to_ptr(a); let a = [65u8, 65u8, 65u8, 65u8, 65u8, 65u8, 65u8, 0u8];
let c = from_buf_len(b, 3u); let b = vec::unsafe::to_ptr(a);
assert (c == "AAA"); let c = from_buf_len(b, 3u);
assert (c == "AAA");
}
} }
} }
@ -2274,24 +2288,27 @@ mod tests {
} }
#[test] #[test]
fn test_unsafe_slice() unsafe { fn test_unsafe_slice() {
assert (eq("ab", unsafe::slice_bytes("abc", 0u, 2u))); unsafe {
assert (eq("bc", unsafe::slice_bytes("abc", 1u, 3u))); assert (eq("ab", unsafe::slice_bytes("abc", 0u, 2u)));
assert (eq("", unsafe::slice_bytes("abc", 1u, 1u))); assert (eq("bc", unsafe::slice_bytes("abc", 1u, 3u)));
fn a_million_letter_a() -> str { assert (eq("", unsafe::slice_bytes("abc", 1u, 1u)));
let mut i = 0; fn a_million_letter_a() -> str {
let mut rs = ""; let mut i = 0;
while i < 100000 { rs += "aaaaaaaaaa"; i += 1; } let mut rs = "";
ret 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] #[test]
@ -2483,25 +2500,25 @@ mod tests {
} }
#[test] #[test]
fn test_shift_byte() unsafe { fn test_shift_byte() {
let mut s = "ABC"; let mut s = "ABC";
let b = unsafe::shift_byte(s); let b = unsafe { unsafe::shift_byte(s) };
assert (s == "BC"); assert (s == "BC");
assert (b == 65u8); assert (b == 65u8);
} }
#[test] #[test]
fn test_pop_byte() unsafe { fn test_pop_byte() {
let mut s = "ABC"; let mut s = "ABC";
let b = unsafe::pop_byte(s); let b = unsafe { unsafe::pop_byte(s) };
assert (s == "AB"); assert (s == "AB");
assert (b == 67u8); assert (b == 67u8);
} }
#[test] #[test]
fn test_unsafe_from_bytes() unsafe { fn test_unsafe_from_bytes() {
let a = [65u8, 65u8, 65u8, 65u8, 65u8, 65u8, 65u8]; 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"); assert (b == "AAAAAAA");
} }
@ -2541,11 +2558,13 @@ mod tests {
} }
#[test] #[test]
fn test_from_buf() unsafe { fn test_from_buf() {
let a = [65u8, 65u8, 65u8, 65u8, 65u8, 65u8, 65u8, 0u8]; unsafe {
let b = vec::unsafe::to_ptr(a); let a = [65u8, 65u8, 65u8, 65u8, 65u8, 65u8, 65u8, 0u8];
let c = unsafe::from_buf(b); let b = vec::unsafe::to_ptr(a);
assert (c == "AAAAAAA"); let c = unsafe::from_buf(b);
assert (c == "AAAAAAA");
}
} }
#[test] #[test]
@ -2557,25 +2576,33 @@ mod tests {
} }
#[test] #[test]
fn test_as_buf() unsafe { fn test_as_buf() {
let a = "Abcdefg"; 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); assert (b == 100);
} }
#[test] #[test]
fn test_as_buf_small() unsafe { fn test_as_buf_small() {
let a = "A"; 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); assert (b == 100);
} }
#[test] #[test]
fn test_as_buf2() unsafe { fn test_as_buf2() {
let s = "hello"; unsafe {
let sb = as_buf(s, {|b| b }); let s = "hello";
let s_cstr = unsafe::from_buf(sb); let sb = as_buf(s, {|b| b });
assert (eq(s_cstr, s)); let s_cstr = unsafe::from_buf(sb);
assert (eq(s_cstr, s));
}
} }
#[test] #[test]
@ -2813,14 +2840,16 @@ mod tests {
} }
#[test] #[test]
fn test_unpack_slice() unsafe { fn test_unpack_slice() {
let a = "hello"; let a = "hello";
unpack_slice(a) {|buf, len| unpack_slice(a) {|buf, len|
assert a[0] == 'h' as u8; unsafe {
assert *buf == 'h' as u8; assert a[0] == 'h' as u8;
assert len == 6u; assert *buf == 'h' as u8;
assert *ptr::offset(buf,4u) == 'o' as u8; assert len == 6u;
assert *ptr::offset(buf,5u) == 0u8; 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"] #[doc = "Returns the size of a type"]
#[inline(always)] #[inline(always)]
pure fn size_of<T>() -> uint unsafe { pure fn size_of<T>() -> uint {
unchecked { rusti::size_of::<T>() } 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 This is the alignment used for struct fields. It may be smaller
than the preferred alignment. 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>() } unchecked { rusti::min_align_of::<T>() }
} }
#[doc = "Returns the preferred alignment of a type"] #[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>() } unchecked { rusti::pref_align_of::<T>() }
} }

View file

@ -504,7 +504,7 @@ type task_id = int;
type rust_task = libc::c_void; type rust_task = libc::c_void;
type rust_closure = 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 { let mut f = if opts.supervise {
f f
@ -519,26 +519,28 @@ fn spawn_raw(opts: task_opts, +f: fn~()) unsafe {
} }
}; };
let fptr = ptr::addr_of(f); unsafe {
let closure: *rust_closure = unsafe::reinterpret_cast(fptr); let fptr = ptr::addr_of(f);
let closure: *rust_closure = unsafe::reinterpret_cast(fptr);
let new_task = alt opts.sched { let new_task = alt opts.sched {
none { none {
rustrt::new_task() rustrt::new_task()
} }
some(sched_opts) { some(sched_opts) {
new_task_in_new_sched(sched_opts) new_task_in_new_sched(sched_opts)
} }
}; };
option::iter(opts.notify_chan) {|c| option::iter(opts.notify_chan) {|c|
// FIXME (#1087): Would like to do notification in Rust // FIXME (#1087): Would like to do notification in Rust
rustrt::rust_task_config_notify(new_task, c); 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 { fn new_task_in_new_sched(opts: sched_opts) -> *rust_task {
if opts.native_stack_size != none { if opts.native_stack_size != none {
fail "native_stack_size scheduler option unimplemented"; fail "native_stack_size scheduler option unimplemented";
@ -962,7 +964,7 @@ fn test_osmain() {
#[test] #[test]
#[ignore(cfg(windows))] #[ignore(cfg(windows))]
#[should_fail] #[should_fail]
fn test_unkillable() unsafe { fn test_unkillable() {
import comm::methods; import comm::methods;
let po = comm::port(); let po = comm::port();
let ch = po.chan(); let ch = po.chan();
@ -980,14 +982,16 @@ fn test_unkillable() unsafe {
fail; fail;
} }
unkillable {|| unsafe {
let p = ~0; unkillable {||
let pp: *uint = unsafe::transmute(p); let p = ~0;
let pp: *uint = unsafe::transmute(p);
// If we are killed here then the box will leak // If we are killed here then the box will leak
po.recv(); po.recv();
let _p: ~int = unsafe::transmute(pp); let _p: ~int = unsafe::transmute(pp);
}
} }
// Now we can be killed // 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 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| to_str_bytes(false, num, radix) {|slice|
vec::unpack_slice(slice) {|p, len| 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."] #[doc = "Low-level helper routine for string conversion."]
fn to_str_bytes<U>(neg: bool, num: T, radix: uint, fn to_str_bytes<U>(neg: bool, num: T, radix: uint,
f: fn([u8]/&) -> U) -> U unsafe { f: fn([u8]/&) -> U) -> U {
#[inline(always)] #[inline(always)]
fn digit(n: T) -> u8 { 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 // pointers and unsafe bits, and the codegen will prove it's all
// in-bounds, no extra cost. // in-bounds, no extra cost.
vec::unpack_slice(buf) {|p, len| unsafe {
let mp = p as *mut u8; vec::unpack_slice(buf) {|p, len|
let mut i = len; let mp = p as *mut u8;
let mut n = num; let mut i = len;
let radix = radix as T; let mut n = num;
loop { let radix = radix as T;
i -= 1u; 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; assert 0u < i && i < len;
*ptr::mut_offset(mp, i) = digit(n % radix);
n /= radix; if neg {
if n == 0 as T { break; } 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 { mod tests {
#[test] #[test]
fn test_reinterpret_cast() unsafe { fn test_reinterpret_cast() {
assert reinterpret_cast(1) == 1u; assert unsafe { reinterpret_cast(1) } == 1u;
} }
#[test] #[test]
fn test_transmute() unsafe { fn test_transmute() {
let x = @1; unsafe {
let x: *int = transmute(x); let x = @1;
assert *x == 1; let x: *int = transmute(x);
let _x: @int = transmute(x); assert *x == 1;
let _x: @int = transmute(x);
}
} }
#[test] #[test]
fn test_transmute2() unsafe { fn test_transmute2() {
assert transmute("L") == [76u8, 0u8]; 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 Returns the number of elements the vector can hold without reallocating
"] "]
#[inline(always)] #[inline(always)]
pure fn capacity<T>(&&v: [const T]) -> uint unsafe { pure fn capacity<T>(&&v: [const T]) -> uint {
let repr: **unsafe::vec_repr = ::unsafe::reinterpret_cast(addr_of(v)); unsafe {
(**repr).alloc / sys::size_of::<T>() let repr: **unsafe::vec_repr = ::unsafe::reinterpret_cast(addr_of(v));
(**repr).alloc / sys::size_of::<T>()
}
} }
#[doc = "Returns the length of a vector"] #[doc = "Returns the length of a vector"]
#[inline(always)] #[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} 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 = []; let mut v = [];
unchecked{reserve(v, n_elts);} unchecked{reserve(v, n_elts);}
let mut i: uint = 0u; 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; 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."] #[doc = "Produces a mut vector from an immutable vector."]
fn to_mut<T>(+v: [T]) -> [mut T] unsafe { fn to_mut<T>(+v: [T]) -> [mut T] {
::unsafe::transmute(v) unsafe { ::unsafe::transmute(v) }
} }
#[doc = "Produces an immutable vector from a mut vector."] #[doc = "Produces an immutable vector from a mut vector."]
fn from_mut<T>(+v: [mut T]) -> [T] unsafe { fn from_mut<T>(+v: [mut T]) -> [T] {
::unsafe::transmute(v) unsafe { ::unsafe::transmute(v) }
} }
// Accessors // Accessors
@ -385,7 +387,6 @@ fn shift<T>(&v: [T]) -> T {
let mut r <- *vv; let mut r <- *vv;
for uint::range(1u, ln) {|i| for uint::range(1u, ln) {|i|
// FIXME (#2703): this isn't legal, per se...
let r <- *ptr::offset(vv, i); let r <- *ptr::offset(vv, i);
push(v, r); 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"] #[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); let ln = len(v);
assert ln > 0u; assert ln > 0u;
let valptr = ptr::mut_addr_of(v[ln - 1u]); let valptr = ptr::mut_addr_of(v[ln - 1u]);
let val <- *valptr; unsafe {
unsafe::set_len(v, ln - 1u); let val <- *valptr;
val unsafe::set_len(v, ln - 1u);
val
}
} }
#[doc = "Append an element to a vector"] #[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] { pure fn mapi<T, U>(v: [T]/&, f: fn(uint, T) -> U) -> [U] {
let mut result = []; let mut result = [];
unchecked{reserve(result, len(v));} 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; ret result;
} }
@ -955,13 +967,15 @@ Iterates over a vector, with option to break
Return true to continue, false to break. Return true to continue, false to break.
"] "]
#[inline(always)] #[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| vec::unpack_slice(v) {|p, n|
let mut n = n; let mut n = n;
let mut p = p; let mut p = p;
while n > 0u { while n > 0u {
if !f(*p) { break; } unsafe {
p = ptr::offset(p, 1u); if !f(*p) { break; }
p = ptr::offset(p, 1u);
}
n -= 1u; n -= 1u;
} }
} }
@ -973,13 +987,15 @@ Iterates over a vector's elements and indices
Return true to continue, false to break. Return true to continue, false to break.
"] "]
#[inline(always)] #[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| vec::unpack_slice(v) {|p, n|
let mut i = 0u; let mut i = 0u;
let mut p = p; let mut p = p;
while i < n { while i < n {
if !f(i, *p) { break; } unsafe {
p = ptr::offset(p, 1u); if !f(i, *p) { break; }
p = ptr::offset(p, 1u);
}
i += 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 Allows for unsafe manipulation of vector contents, which is useful for native
interop. 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) } 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) } unpack_mut_slice(v) { |buf, _len| f(buf) }
} }
@ -1093,10 +1109,12 @@ Work with the buffer and length of a slice.
"] "]
#[inline(always)] #[inline(always)]
pure fn unpack_slice<T,U>(s: [const T]/&, pure fn unpack_slice<T,U>(s: [const T]/&,
f: fn(*T, uint) -> U) -> U unsafe { f: fn(*T, uint) -> U) -> U {
let v : *(*T,uint) = ::unsafe::reinterpret_cast(ptr::addr_of(s)); unsafe {
let (buf,len) = *v; let v : *(*T,uint) = ::unsafe::reinterpret_cast(ptr::addr_of(s));
f(buf, len / sys::size_of::<T>()) let (buf,len) = *v;
f(buf, len / sys::size_of::<T>())
}
} }
#[doc = " #[doc = "
@ -1104,10 +1122,13 @@ Work with the buffer and length of a slice.
"] "]
#[inline(always)] #[inline(always)]
pure fn unpack_const_slice<T,U>(s: [const T]/&, pure fn unpack_const_slice<T,U>(s: [const T]/&,
f: fn(*const T, uint) -> U) -> U unsafe { f: fn(*const T, uint) -> U) -> U {
let v : *(*const T,uint) = ::unsafe::reinterpret_cast(ptr::addr_of(s)); unsafe {
let (buf,len) = *v; let v : *(*const T,uint) =
f(buf, len / sys::size_of::<T>()) ::unsafe::reinterpret_cast(ptr::addr_of(s));
let (buf,len) = *v;
f(buf, len / sys::size_of::<T>())
}
} }
#[doc = " #[doc = "
@ -1115,10 +1136,13 @@ Work with the buffer and length of a slice.
"] "]
#[inline(always)] #[inline(always)]
pure fn unpack_mut_slice<T,U>(s: [mut T]/&, pure fn unpack_mut_slice<T,U>(s: [mut T]/&,
f: fn(*mut T, uint) -> U) -> U unsafe { f: fn(*mut T, uint) -> U) -> U {
let v : *(*const T,uint) = ::unsafe::reinterpret_cast(ptr::addr_of(s)); unsafe {
let (buf,len) = *v; let v : *(*const T,uint) =
f(buf, len / sys::size_of::<T>()) ::unsafe::reinterpret_cast(ptr::addr_of(s));
let (buf,len) = *v;
f(buf, len / sys::size_of::<T>())
}
} }
impl extensions<T: copy> for [T] { impl extensions<T: copy> for [T] {
@ -1372,12 +1396,14 @@ mod u8 {
export hash; export hash;
#[doc = "Bytewise string comparison"] #[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 a_len = len(a);
let b_len = len(b); let b_len = len(b);
let n = uint::min(a_len, b_len) as libc::size_t; let n = uint::min(a_len, b_len) as libc::size_t;
let r = libc::memcmp(unsafe::to_ptr(a) as *libc::c_void, let r = unsafe {
unsafe::to_ptr(b) as *libc::c_void, n) as int; 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 r != 0 { r } else {
if a_len == b_len { if a_len == b_len {
@ -1397,10 +1423,10 @@ mod u8 {
pure fn le(&&a: [u8], &&b: [u8]) -> bool { cmp(a, b) <= 0 } pure fn le(&&a: [u8], &&b: [u8]) -> bool { cmp(a, b) <= 0 }
#[doc = "Bytewise equality"] #[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"] #[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"] #[doc ="Bytewise greater than or equal"]
pure fn ge(&&a: [u8], &&b: [u8]) -> bool { cmp(a, b) >= 0 } 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; } fn add(&&x: uint, &&y: uint) -> uint { ret x + y; }
#[test] #[test]
fn test_unsafe_ptrs() unsafe { fn test_unsafe_ptrs() {
// Test on-stack copy-from-buf. unsafe {
let a = [1, 2, 3]; // Test on-stack copy-from-buf.
let mut ptr = unsafe::to_ptr(a); let a = [1, 2, 3];
let b = unsafe::from_buf(ptr, 3u); let mut ptr = unsafe::to_ptr(a);
assert (len(b) == 3u); let b = unsafe::from_buf(ptr, 3u);
assert (b[0] == 1); assert (len(b) == 3u);
assert (b[1] == 2); assert (b[0] == 1);
assert (b[2] == 3); assert (b[1] == 2);
assert (b[2] == 3);
// Test on-heap copy-from-buf. // Test on-heap copy-from-buf.
let c = [1, 2, 3, 4, 5]; let c = [1, 2, 3, 4, 5];
ptr = unsafe::to_ptr(c); ptr = unsafe::to_ptr(c);
let d = unsafe::from_buf(ptr, 5u); let d = unsafe::from_buf(ptr, 5u);
assert (len(d) == 5u); assert (len(d) == 5u);
assert (d[0] == 1); assert (d[0] == 1);
assert (d[1] == 2); assert (d[1] == 2);
assert (d[2] == 3); assert (d[2] == 3);
assert (d[3] == 4); assert (d[3] == 4);
assert (d[4] == 5); assert (d[4] == 5);
}
} }
#[test] #[test]
@ -2181,21 +2209,32 @@ mod tests {
} }
#[test] #[test]
fn to_mut_no_copy() unsafe { fn to_mut_no_copy() {
let x = [1, 2, 3]; unsafe {
let addr = unsafe::to_ptr(x); let x = [1, 2, 3];
let x_mut = to_mut(x); let addr = unsafe::to_ptr(x);
let addr_mut = unsafe::to_ptr(x_mut); let x_mut = to_mut(x);
assert addr == addr_mut; let addr_mut = unsafe::to_ptr(x_mut);
assert addr == addr_mut;
}
} }
#[test] #[test]
fn from_mut_no_copy() unsafe { fn from_mut_no_copy() {
let x = [mut 1, 2, 3]; unsafe {
let addr = unsafe::to_ptr(x); let x = [mut 1, 2, 3];
let x_imm = from_mut(x); let addr = unsafe::to_ptr(x);
let addr_imm = unsafe::to_ptr(x_imm); let x_imm = from_mut(x);
assert addr == addr_imm; 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] #[test]

View file

@ -822,7 +822,7 @@ fn read_common_impl(socket_data: *tcp_socket_data, timeout_msecs: uint)
log(debug, "starting tcp::read"); log(debug, "starting tcp::read");
let iotask = (*socket_data).iotask; let iotask = (*socket_data).iotask;
let rs_result = read_start_common_impl(socket_data); 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); let err_data = result::get_err(rs_result);
result::err(err_data) result::err(err_data)
} }
@ -1433,7 +1433,7 @@ mod test {
let accept_result = accept(new_conn); let accept_result = accept(new_conn);
log(debug, "SERVER: after accept()"); log(debug, "SERVER: after accept()");
if result::is_failure(accept_result) { if result::is_err(accept_result) {
log(debug, "SERVER: error accept connection"); log(debug, "SERVER: error accept connection");
let err_data = result::get_err(accept_result); let err_data = result::get_err(accept_result);
comm::send(kill_ch, some(err_data)); comm::send(kill_ch, some(err_data));
@ -1474,7 +1474,7 @@ mod test {
log(debug, "SERVER: recv'd on cont_ch..leaving listen cb"); log(debug, "SERVER: recv'd on cont_ch..leaving listen cb");
}); });
// err check on listen_result // 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); let err_data = result::get_err(listen_result);
log(debug, #fmt("SERVER: exited abnormally name %s msg %s", log(debug, #fmt("SERVER: exited abnormally name %s msg %s",
err_data.err_name, err_data.err_msg)); 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 server_ip_addr = ip::v4::parse_addr(server_ip);
let new_listener_result = let new_listener_result =
new_listener(server_ip_addr, server_port, 128u, iotask); 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); let err_data = result::get_err(new_listener_result);
log(debug, #fmt("SERVER: exited abnormally name %s msg %s", log(debug, #fmt("SERVER: exited abnormally name %s msg %s",
err_data.err_name, err_data.err_msg)); 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 // in a loop {}, but we're just going to take a single
// client.. get their req, write a resp and then exit // client.. get their req, write a resp and then exit
let new_conn_result = server_port.recv(); 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); let err_data = result::get_err(new_conn_result);
log(debug, #fmt("SERVER: exited abnormally name %s msg %s", log(debug, #fmt("SERVER: exited abnormally name %s msg %s",
err_data.err_name, err_data.err_msg)); err_data.err_name, err_data.err_msg));
@ -1544,7 +1544,7 @@ mod test {
log(debug, "CLIENT: starting.."); log(debug, "CLIENT: starting..");
let connect_result = connect(server_ip_addr, server_port, iotask); 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"); log(debug, "CLIENT: failed to connect");
let err_data = result::get_err(connect_result); let err_data = result::get_err(connect_result);
log(debug, #fmt("CLIENT: connect err name: %s msg: %s", log(debug, #fmt("CLIENT: connect err name: %s msg: %s",
@ -1556,7 +1556,7 @@ mod test {
let resp_bytes = str::bytes(resp); let resp_bytes = str::bytes(resp);
tcp_write_single(sock, resp_bytes); tcp_write_single(sock, resp_bytes);
let read_result = sock.read(0u); let read_result = sock.read(0u);
if read_result.is_failure() { if read_result.is_err() {
log(debug, "CLIENT: failure to read"); log(debug, "CLIENT: failure to read");
"" ""
} }
@ -1573,7 +1573,7 @@ mod test {
fn tcp_write_single(sock: tcp_socket, val: [u8]) { fn tcp_write_single(sock: tcp_socket, val: [u8]) {
let write_result_future = sock.write_future(val); let write_result_future = sock.write_future(val);
let write_result = write_result_future.get(); 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!"); log(debug, "tcp_write_single: write failed!");
let err_data = result::get_err(write_result); let err_data = result::get_err(write_result);
log(debug, #fmt("tcp_write_single err name: %s msg: %s", 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) // FIXME: why is the ::<A, ()> annotation required here? (#2617)
vec::unpack_slice::<A, ()>(xs) {|p, _len| vec::unpack_slice::<A, ()>(xs) {|p, _len|
let f = f(); let f = f();
futures += [future::spawn() {|copy base| let f = future::spawn() {|copy base|
unsafe { unsafe {
let len = end - base; let len = end - base;
let slice = (ptr::offset(p, 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); assert(vec::len(slice) == end - base);
f(base, slice) f(base, slice)
} }
}]; };
vec::push(futures, f);
}; };
base += items_per_task; base += items_per_task;
} }

View file

@ -452,10 +452,7 @@ fn ser_ty(cx: ext_ctxt, tps: ser_tps_map,
[] []
} }
ast::ty_vstore(_, _) { ast::ty_vstore(@{node: ast::ty_vec(mt),_}, ast::vstore_uniq) |
cx.span_unimpl(ty.span, "serialization for vstore types");
}
ast::ty_vec(mt) { ast::ty_vec(mt) {
let ser_e = let ser_e =
cx.expr( 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) }) 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{ fail }
} }
ast::ty_vstore(_, _) { ast::ty_vstore(@{node: ast::ty_vec(mt),_}, ast::vstore_uniq) |
cx.span_unimpl(ty.span, "deserialization for vstore types");
}
ast::ty_vec(mt) { ast::ty_vec(mt) {
let l = deser_lambda(cx, tps, mt.ty, cx.clone(d)); let l = deser_lambda(cx, tps, mt.ty, cx.clone(d));
#ast{ std::serialization::read_to_vec($(d), $(l)) } #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") { } else if self.eat_keyword("if") {
ret pexpr(self.parse_if_expr()); ret pexpr(self.parse_if_expr());
} else if self.eat_keyword("for") { } 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") { } 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") { } else if self.eat_keyword("while") {
ret pexpr(self.parse_while_expr()); ret pexpr(self.parse_while_expr());
} else if self.eat_keyword("loop") { } 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 lo = self.last_span;
let call = self.parse_expr_res(RESTRICT_STMT_EXPR); let call = self.parse_expr_res(RESTRICT_STMT_EXPR);
alt call.node { alt call.node {
expr_call(f, args, true) { expr_call(f, args, true) {
let b_arg = vec::last(args); let b_arg = vec::last(args);
let last = self.mk_expr(b_arg.span.lo, b_arg.span.hi, 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) @{node: expr_call(f, vec::init(args) + [last], true)
with *call} with *call}
} }
_ { _ {
self.span_fatal(lo, "`for` must be followed by a block call"); self.span_fatal(
} lo, #fmt("`%s` must be followed by a block call", keyword));
}
}
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");
} }
} }
} }
@ -1956,7 +1941,7 @@ class parser {
let rp = self.parse_region_param(); let rp = self.parse_region_param();
let ty_params = self.parse_ty_params(); let ty_params = self.parse_ty_params();
let class_path = self.ident_to_path_tys(class_name, rp, 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() } { self.parse_iface_ref_list() }
else { [] }; else { [] };
self.expect(token::LBRACE); self.expect(token::LBRACE);

View file

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

View file

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

View file

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

View file

@ -34,7 +34,7 @@ fn visit_expr(ex: @expr, cx: ctx, v: visit::vt<ctx>) {
i += 1u; i += 1u;
} }
} }
expr_loop_body(body) { expr_loop_body(body) | expr_do_body(body) {
cx.allow_block = true; cx.allow_block = true;
v.visit_expr(body, cx, v); 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)); arg_exprs([src]), save_in(target));
ret move_val(bcx, DROP_EXISTING, lhs_res.val, ret move_val(bcx, DROP_EXISTING, lhs_res.val,
// FIXME (#2704): should kind be owned?
{bcx: bcx, val: target, kind: owned}, {bcx: bcx, val: target, kind: owned},
dty); 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}) 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 { fn mk_evec(cx: ctxt, tm: mt, t: vstore) -> t {
mk_t(cx, ty_evec(tm, 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_nil | ty_bot | ty_bool | ty_int(_) | ty_uint(_) | ty_float(_) |
ty_ptr(_) { kind_implicitly_sendable() | kind_const() } ty_ptr(_) { kind_implicitly_sendable() | kind_const() }
// Implicit copyability of strs is configurable // Implicit copyability of strs is configurable
ty_str { ty_str | ty_estr(vstore_uniq) {
if cx.vecs_implicitly_copyable { if cx.vecs_implicitly_copyable {
kind_implicitly_sendable() | kind_const() kind_implicitly_sendable() | kind_const()
} else { kind_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)) remove_implicit(mutable_type_kind(cx, tm))
} }
// Implicit copyability of vecs is configurable // Implicit copyability of vecs is configurable
ty_vec(tm) { ty_vec(tm) | ty_evec(tm, vstore_uniq) {
if cx.vecs_implicitly_copyable { if cx.vecs_implicitly_copyable {
mutable_type_kind(cx, tm) mutable_type_kind(cx, tm)
} else { remove_implicit(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() kind_implicitly_copyable()
} }
} }
ty_evec(tm, vstore_uniq) {
remove_implicit(mutable_type_kind(cx, tm))
}
ty_evec(tm, vstore_fixed(_)) { ty_evec(tm, vstore_fixed(_)) {
mutable_type_kind(cx, tm) 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. // All estrs are copyable; uniques and interiors are sendable.
ty_estr(vstore_box) | ty_estr(vstore_box) |
ty_estr(vstore_slice(_)) { kind_implicitly_copyable() | kind_const() } 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() } ty_estr(vstore_fixed(_)) { kind_implicitly_sendable() | kind_const() }
// Records lower to the lowest of their members. // 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 { fn arg_is_argv_ty(_tcx: ty::ctxt, a: ty::arg) -> bool {
alt ty::get(a.ty).struct { alt ty::get(a.ty).struct {
ty::ty_vec(mt) { ty::ty_evec(mt, vstore_uniq) {
if mt.mutbl != ast::m_imm { ret false; } if mt.mutbl != ast::m_imm { ret false; }
alt ty::get(mt.ty).struct { alt ty::get(mt.ty).struct {
ty::ty_str { ret true; } 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; let tcx = ccx.tcx;
if !tcx.sess.building_library { if !tcx.sess.building_library {
alt copy tcx.sess.main_fn { alt copy tcx.sess.main_fn {
some((id, sp)) { check_main_fn_ty(ccx, id, sp); } 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}; tcx: tcx};
collect::collect_item_types(ccx, crate); collect::collect_item_types(ccx, crate);
check::check_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(); tcx.sess.abort_if_errors();
(ccx.method_map, ccx.vtable_map) (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); 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 { ty::ty_str {
ret ty::mk_estr(tcx, vst); 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 // Check that there's at least one field
let (fields,_) = split_class_items(members); let (fields,_) = split_class_items(members);
if fields.len() < 1u { 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"); field");
} }
// Check that the class is instantiable // Check that the class is instantiable
@ -938,7 +938,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
// separate case below. // separate case below.
tcx.sess.span_bug( tcx.sess.span_bug(
expr.span, expr.span,
#fmt["Comparison operator in expr_binop: %s", #fmt["comparison operator in expr_binop: %s",
ast_util::binop_to_str(op)]); ast_util::binop_to_str(op)]);
} }
_ { lhs_t } _ { lhs_t }
@ -1217,7 +1217,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
result::ok(_) { /* fall through */ } result::ok(_) { /* fall through */ }
result::err(_) { result::err(_) {
tcx.sess.span_err(expr.span, 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); } some(e) { check_expr_with(fcx, e, ret_ty); }
@ -1299,7 +1299,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
result::ok(_) {} result::ok(_) {}
result::err(err) { result::err(err) {
tcx.sess.span_fatal( 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`", should return `bool`, not `%s`",
fcx.infcx.ty_to_str(fty.output))); 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) (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 \ tcx.sess.span_fatal(expr.span, "a `loop` function's last \
should be of function type"); argument should be of function \
type");
} }
}; };
alt check b.node { alt check b.node {
@ -1334,7 +1335,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
(ty::mk_fn(tcx, fty), fty.proto) (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"); should be of function type");
} }
}; };
@ -1547,8 +1548,9 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
} }
none { none {
let t_err = fcx.infcx.resolve_type_vars_if_possible(expr_t); let t_err = fcx.infcx.resolve_type_vars_if_possible(expr_t);
let msg = #fmt["attempted access of field %s on type %s, but \ let msg = #fmt["attempted access of field `%s` on type `%s`, \
no public field or method with that name was found", but no public field or method with that name \
was found",
*field, fcx.infcx.ty_to_str(t_err)]; *field, fcx.infcx.ty_to_str(t_err)];
tcx.sess.span_err(expr.span, msg); tcx.sess.span_err(expr.span, msg);
// NB: Adding a bogus type to allow typechecking to continue // 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); let rty = ty::node_id_to_type(tcx, item_id);
if !ty::is_instantiable(tcx, rty) { if !ty::is_instantiable(tcx, rty) {
tcx.sess.span_err(sp, #fmt["this type cannot be instantiated \ tcx.sess.span_err(sp, #fmt["this type cannot be instantiated \
without an instance of itself. \ without an instance of itself; \
Consider using option<%s>.", consider using `option<%s>`",
ty_to_str(tcx, rty)]); ty_to_str(tcx, rty)]);
} }
} }
@ -1821,7 +1823,7 @@ fn check_enum_variants(ccx: @crate_ctxt,
} }
if vec::contains(disr_vals, disr_val) { if vec::contains(disr_vals, disr_val) {
ccx.tcx.sess.span_err(v.span, ccx.tcx.sess.span_err(v.span,
"discriminator value already exists."); "discriminator value already exists");
} }
disr_vals += [disr_val]; disr_vals += [disr_val];
let ctor_ty = ty::node_id_to_type(ccx.tcx, v.node.id); 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 } _ { 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 \ wrap the inner value in a box to \
make it representable"); make it representable");
} }
@ -2195,13 +2197,13 @@ fn check_bounds_are_used(ccx: @crate_ctxt,
if !r_used { if !r_used {
ccx.tcx.sess.span_err( ccx.tcx.sess.span_err(
span, "lifetime `self` unused inside \ span, "lifetime `self` unused inside \
reference-parameterized type."); reference-parameterized type");
} }
for tps_used.eachi { |i, b| for tps_used.eachi { |i, b|
if !b { if !b {
ccx.tcx.sess.span_err( 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(); let i_n_tps = (*i_ty.bounds).len();
if i_n_tps != n_tps { if i_n_tps != n_tps {
tcx.sess.span_err(it.span, #fmt("intrinsic has wrong number \ 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)); expected %u", i_n_tps, n_tps));
} else { } else {
require_same_types( require_same_types(
tcx, none, it.span, i_ty.ty, fty, tcx, none, it.span, i_ty.ty, fty,
{|| #fmt["intrinsic has wrong type. \ {|| #fmt["intrinsic has wrong type: \
expected %s", expected `%s`",
ty_to_str(ccx.tcx, fty)]}); ty_to_str(ccx.tcx, fty)]});
} }
} }

View file

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

View file

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

View file

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

View file

@ -77,7 +77,6 @@ mod map_reduce {
type putter<K: send, V: send> = fn(K, V); 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 mapper<K1: send, K2: send, V: send> = fn~(K1, putter<K2, V>);
type getter<V: send> = fn() -> option<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 { iface noisy {
fn speak(); fn speak();
} }
class cat implements noisy { class cat : noisy {
priv { priv {
let mut meows : uint; let mut meows : uint;
fn meow() { fn meow() {

View file

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

View file

@ -3,7 +3,7 @@ iface animal {
fn eat(); fn eat();
} }
class cat implements animal { class cat : animal {
let meows: uint; let meows: uint;
new(in_x : uint) { self.meows = in_x; } 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]; } fn main() { fail [0i]; }

View file

@ -1,6 +1,6 @@
// Issue #1763 - infer types correctly // 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 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() { } 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 // xfail-fast
// aux-build:cci_class_5.rs // aux-build:cci_class_5.rs
use cci_class_5; 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; } 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 // are prohibited by various checks, such as that the enum is
// instantiable and so forth). // 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() { fn main() {

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -2,7 +2,7 @@
use std; use std;
import std::map::*; import std::map::*;
class cat implements map<int, bool> { class cat : map<int, bool> {
priv { priv {
// Yes, you can have negative meows // Yes, you can have negative meows
let mut meows : int; 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 // for any int value that's less than the meows field
// ok: T should be in scope when resolving the iface ref for map // 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 { priv {
// Yes, you can have negative meows // Yes, you can have negative meows
let mut meows : int; let mut meows : int;

View file

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

View file

@ -2,7 +2,7 @@ iface noisy {
fn speak(); fn speak();
} }
class cat implements noisy { class cat : noisy {
priv { priv {
let mut meows : uint; let mut meows : uint;
fn meow() { 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 // vtables other than the 1st one don't seem to work
class cat implements noisy, scratchy, bitey { class cat : noisy, scratchy, bitey {
priv { priv {
let meows : @mut uint; let meows : @mut uint;
let scratched : dvec<furniture>; let scratched : dvec<furniture>;

View file

@ -2,7 +2,7 @@
fn adder(+x: @int, +y: @int) -> int { ret *x + *y; } fn adder(+x: @int, +y: @int) -> int { ret *x + *y; }
fn failer() -> @int { fail; } fn failer() -> @int { fail; }
fn main() { fn main() {
assert(result::is_failure(task::try {|| assert(result::is_err(task::try {||
adder(@2, failer()); () 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. A reduced test case for Issue #506, provided by Rob Arnold.
*/ */
@ -13,9 +7,7 @@ import task;
#[abi = "cdecl"] #[abi = "cdecl"]
native mod rustrt { native mod rustrt {
fn task_yield(); fn rust_task_allow_kill();
} }
fn yield_wrap(&&_arg: ()) { rustrt::task_yield(); } fn main() { task::spawn(rustrt::rust_task_allow_kill); }
fn main() { task::spawn((), yield_wrap); }

View file

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