diff options
| author | Eric Reed <ereed@mozilla.com> | 2013-06-25 11:45:44 -0700 |
|---|---|---|
| committer | Eric Reed <ereed@mozilla.com> | 2013-06-25 11:45:44 -0700 |
| commit | 4870dce3ebfd0e988a2e45360c724ebe912c3ad5 (patch) | |
| tree | c676e677bf36924cbf177b0723b4ffe0fc435d40 /src/libstd | |
| parent | 794923c99511398bc90400e380dd11770ec8e614 (diff) | |
| parent | e65d0cbabebc73f2c9733a7ed158576c9702e71e (diff) | |
| download | rust-4870dce3ebfd0e988a2e45360c724ebe912c3ad5.tar.gz rust-4870dce3ebfd0e988a2e45360c724ebe912c3ad5.zip | |
Merge remote-tracking branch 'upstream/io' into io
Conflicts: src/rt/rustrt.def.in
Diffstat (limited to 'src/libstd')
79 files changed, 2699 insertions, 2265 deletions
diff --git a/src/libstd/at_vec.rs b/src/libstd/at_vec.rs index a118e445fe2..18dfbd82c5a 100644 --- a/src/libstd/at_vec.rs +++ b/src/libstd/at_vec.rs @@ -23,22 +23,8 @@ use vec; /// Code for dealing with @-vectors. This is pretty incomplete, and /// contains a bunch of duplication from the code for ~-vectors. -pub mod rustrt { - use libc; - use sys; - use vec; - - #[abi = "cdecl"] - #[link_name = "rustrt"] - pub extern { - pub unsafe fn vec_reserve_shared_actual(t: *sys::TypeDesc, - v: **vec::raw::VecRepr, - n: libc::size_t); - } -} - /// Returns the number of elements the vector can hold without reallocating -#[inline(always)] +#[inline] pub fn capacity<T>(v: @[T]) -> uint { unsafe { let repr: **raw::VecRepr = transmute(&v); @@ -58,7 +44,7 @@ pub fn capacity<T>(v: @[T]) -> uint { * as an argument a function that will push an element * onto the vector being constructed. */ -#[inline(always)] +#[inline] pub fn build_sized<A>(size: uint, builder: &fn(push: &fn(v: A))) -> @[A] { let mut vec: @[A] = @[]; unsafe { raw::reserve(&mut vec, size); } @@ -76,7 +62,7 @@ pub fn build_sized<A>(size: uint, builder: &fn(push: &fn(v: A))) -> @[A] { * as an argument a function that will push an element * onto the vector being constructed. */ -#[inline(always)] +#[inline] pub fn build<A>(builder: &fn(push: &fn(v: A))) -> @[A] { build_sized(4, builder) } @@ -93,7 +79,7 @@ pub fn build<A>(builder: &fn(push: &fn(v: A))) -> @[A] { * as an argument a function that will push an element * onto the vector being constructed. */ -#[inline(always)] +#[inline] pub fn build_sized_opt<A>(size: Option<uint>, builder: &fn(push: &fn(v: A))) -> @[A] { @@ -104,11 +90,11 @@ pub fn build_sized_opt<A>(size: Option<uint>, /// Iterates over the `rhs` vector, copying each element and appending it to the /// `lhs`. Afterwards, the `lhs` is then returned for use again. -#[inline(always)] +#[inline] pub fn append<T:Copy>(lhs: @[T], rhs: &const [T]) -> @[T] { do build_sized(lhs.len() + rhs.len()) |push| { - for lhs.each |x| { push(*x); } - for uint::range(0, rhs.len()) |i| { push(rhs[i]); } + for lhs.each |x| { push(copy *x); } + for uint::range(0, rhs.len()) |i| { push(copy rhs[i]); } } } @@ -168,7 +154,7 @@ pub fn to_managed_consume<T>(v: ~[T]) -> @[T] { * elements of a slice. */ pub fn to_managed<T:Copy>(v: &[T]) -> @[T] { - from_fn(v.len(), |i| v[i]) + from_fn(v.len(), |i| copy v[i]) } #[cfg(not(test))] @@ -178,7 +164,7 @@ pub mod traits { use ops::Add; impl<'self,T:Copy> Add<&'self const [T],@[T]> for @[T] { - #[inline(always)] + #[inline] fn add(&self, rhs: & &'self const [T]) -> @[T] { append(*self, (*rhs)) } @@ -189,7 +175,7 @@ pub mod traits { pub mod traits {} pub mod raw { - use at_vec::{capacity, rustrt}; + use at_vec::capacity; use cast::{transmute, transmute_copy}; use libc; use ptr; @@ -197,6 +183,8 @@ pub mod raw { use uint; use unstable::intrinsics::{move_val_init}; use vec; + use vec::UnboxedVecRepr; + use sys::TypeDesc; pub type VecRepr = vec::raw::VecRepr; pub type SliceRepr = vec::raw::SliceRepr; @@ -208,7 +196,7 @@ pub mod raw { * modifing its buffers, so it is up to the caller to ensure that * the vector is actually the specified size. */ - #[inline(always)] + #[inline] pub unsafe fn set_len<T>(v: @[T], new_len: uint) { let repr: **mut VecRepr = transmute(&v); (**repr).unboxed.fill = new_len * sys::size_of::<T>(); @@ -217,7 +205,7 @@ pub mod raw { /** * Pushes a new value onto this vector. */ - #[inline(always)] + #[inline] pub unsafe fn push<T>(v: &mut @[T], initval: T) { let repr: **VecRepr = transmute_copy(&v); let fill = (**repr).unboxed.fill; @@ -228,7 +216,7 @@ pub mod raw { } } - #[inline(always)] // really pretty please + #[inline] // really pretty please unsafe fn push_fast<T>(v: &mut @[T], initval: T) { let repr: **mut VecRepr = ::cast::transmute(v); let fill = (**repr).unboxed.fill; @@ -257,9 +245,47 @@ pub mod raw { pub unsafe fn reserve<T>(v: &mut @[T], n: uint) { // Only make the (slow) call into the runtime if we have to if capacity(*v) < n { - let ptr: **VecRepr = transmute(v); - rustrt::vec_reserve_shared_actual(sys::get_type_desc::<T>(), - ptr, n as libc::size_t); + let ptr: *mut *mut VecRepr = transmute(v); + let ty = sys::get_type_desc::<T>(); + return reserve_raw(ty, ptr, n); + } + } + + // Implementation detail. Shouldn't be public + #[allow(missing_doc)] + pub fn reserve_raw(ty: *TypeDesc, ptr: *mut *mut VecRepr, n: uint) { + + unsafe { + let size_in_bytes = n * (*ty).size; + if size_in_bytes > (**ptr).unboxed.alloc { + let total_size = size_in_bytes + sys::size_of::<UnboxedVecRepr>(); + // XXX: UnboxedVecRepr has an extra u8 at the end + let total_size = total_size - sys::size_of::<u8>(); + (*ptr) = local_realloc(*ptr as *(), total_size) as *mut VecRepr; + (**ptr).unboxed.alloc = size_in_bytes; + } + } + + fn local_realloc(ptr: *(), size: uint) -> *() { + use rt; + use rt::OldTaskContext; + use rt::local::Local; + use rt::task::Task; + + if rt::context() == OldTaskContext { + unsafe { + return rust_local_realloc(ptr, size as libc::size_t); + } + + extern { + #[fast_ffi] + fn rust_local_realloc(ptr: *(), size: libc::size_t) -> *(); + } + } else { + do Local::borrow::<Task, *()> |task| { + task.heap.realloc(ptr as *libc::c_void, size) as *() + } + } } } diff --git a/src/libstd/bool.rs b/src/libstd/bool.rs index 66a5bfa944f..e6be164099b 100644 --- a/src/libstd/bool.rs +++ b/src/libstd/bool.rs @@ -212,7 +212,7 @@ impl FromStr for bool { * ~~~ */ impl ToStr for bool { - #[inline(always)] + #[inline] fn to_str(&self) -> ~str { if *self { ~"true" } else { ~"false" } } @@ -250,24 +250,24 @@ pub fn all_values(blk: &fn(v: bool)) { * 0 * ~~~ */ -#[inline(always)] +#[inline] pub fn to_bit(v: bool) -> u8 { if v { 1u8 } else { 0u8 } } #[cfg(not(test))] impl Ord for bool { - #[inline(always)] + #[inline] fn lt(&self, other: &bool) -> bool { to_bit(*self) < to_bit(*other) } - #[inline(always)] + #[inline] fn le(&self, other: &bool) -> bool { to_bit(*self) <= to_bit(*other) } - #[inline(always)] + #[inline] fn gt(&self, other: &bool) -> bool { to_bit(*self) > to_bit(*other) } - #[inline(always)] + #[inline] fn ge(&self, other: &bool) -> bool { to_bit(*self) >= to_bit(*other) } } #[cfg(not(test))] impl TotalOrd for bool { - #[inline(always)] + #[inline] fn cmp(&self, other: &bool) -> Ordering { to_bit(*self).cmp(&to_bit(*other)) } } @@ -298,9 +298,9 @@ impl TotalOrd for bool { */ #[cfg(not(test))] impl Eq for bool { - #[inline(always)] + #[inline] fn eq(&self, other: &bool) -> bool { (*self) == (*other) } - #[inline(always)] + #[inline] fn ne(&self, other: &bool) -> bool { (*self) != (*other) } } diff --git a/src/libstd/borrow.rs b/src/libstd/borrow.rs index 703011aea7f..9e3a3a28fe8 100644 --- a/src/libstd/borrow.rs +++ b/src/libstd/borrow.rs @@ -14,13 +14,13 @@ use prelude::*; /// Cast a region pointer - &T - to a uint. -#[inline(always)] +#[inline] pub fn to_uint<T>(thing: &T) -> uint { thing as *T as uint } /// Determine if two borrowed pointers point to the same thing. -#[inline(always)] +#[inline] pub fn ref_eq<'a, 'b, T>(thing: &'a T, other: &'b T) -> bool { to_uint(thing) == to_uint(other) } @@ -28,11 +28,11 @@ pub fn ref_eq<'a, 'b, T>(thing: &'a T, other: &'b T) -> bool { // Equality for region pointers #[cfg(not(test))] impl<'self, T: Eq> Eq for &'self T { - #[inline(always)] + #[inline] fn eq(&self, other: & &'self T) -> bool { *(*self) == *(*other) } - #[inline(always)] + #[inline] fn ne(&self, other: & &'self T) -> bool { *(*self) != *(*other) } @@ -41,19 +41,19 @@ impl<'self, T: Eq> Eq for &'self T { // Comparison for region pointers #[cfg(not(test))] impl<'self, T: Ord> Ord for &'self T { - #[inline(always)] + #[inline] fn lt(&self, other: & &'self T) -> bool { *(*self) < *(*other) } - #[inline(always)] + #[inline] fn le(&self, other: & &'self T) -> bool { *(*self) <= *(*other) } - #[inline(always)] + #[inline] fn ge(&self, other: & &'self T) -> bool { *(*self) >= *(*other) } - #[inline(always)] + #[inline] fn gt(&self, other: & &'self T) -> bool { *(*self) > *(*other) } diff --git a/src/libstd/cast.rs b/src/libstd/cast.rs index 2109568a0a4..30b6b030dba 100644 --- a/src/libstd/cast.rs +++ b/src/libstd/cast.rs @@ -14,22 +14,9 @@ use sys; use unstable::intrinsics; /// Casts the value at `src` to U. The two types must have the same length. -#[cfg(stage0)] -pub unsafe fn transmute_copy<T, U>(src: &T) -> U { - let mut dest: U = intrinsics::uninit(); - { - let dest_ptr: *mut u8 = transmute(&mut dest); - let src_ptr: *u8 = transmute(src); - intrinsics::memmove64(dest_ptr, - src_ptr, - sys::size_of::<U>() as u64); - } - dest -} - /// Casts the value at `src` to U. The two types must have the same length. -#[cfg(target_word_size = "32", not(stage0))] -#[inline(always)] +#[cfg(target_word_size = "32")] +#[inline] pub unsafe fn transmute_copy<T, U>(src: &T) -> U { let mut dest: U = intrinsics::uninit(); let dest_ptr: *mut u8 = transmute(&mut dest); @@ -39,8 +26,8 @@ pub unsafe fn transmute_copy<T, U>(src: &T) -> U { } /// Casts the value at `src` to U. The two types must have the same length. -#[cfg(target_word_size = "64", not(stage0))] -#[inline(always)] +#[cfg(target_word_size = "64")] +#[inline] pub unsafe fn transmute_copy<T, U>(src: &T) -> U { let mut dest: U = intrinsics::uninit(); let dest_ptr: *mut u8 = transmute(&mut dest); @@ -54,19 +41,16 @@ pub unsafe fn transmute_copy<T, U>(src: &T) -> U { * * The forget function will take ownership of the provided value but neglect * to run any required cleanup or memory-management operations on it. This - * can be used for various acts of magick, particularly when using - * reinterpret_cast on pointer types. + * can be used for various acts of magick. */ -#[inline(always)] +#[inline] pub unsafe fn forget<T>(thing: T) { intrinsics::forget(thing); } /** * Force-increment the reference count on a shared box. If used - * carelessly, this can leak the box. Use this in conjunction with transmute - * and/or reinterpret_cast when such calls would otherwise scramble a box's - * reference count + * carelessly, this can leak the box. */ -#[inline(always)] +#[inline] pub unsafe fn bump_box_refcount<T>(t: @T) { forget(t); } /** @@ -77,59 +61,59 @@ pub unsafe fn bump_box_refcount<T>(t: @T) { forget(t); } * * assert!(transmute("L") == ~[76u8, 0u8]); */ -#[inline(always)] +#[inline] pub unsafe fn transmute<L, G>(thing: L) -> G { intrinsics::transmute(thing) } /// Coerce an immutable reference to be mutable. -#[inline(always)] +#[inline] pub unsafe fn transmute_mut<'a,T>(ptr: &'a T) -> &'a mut T { transmute(ptr) } /// Coerce a mutable reference to be immutable. -#[inline(always)] +#[inline] pub unsafe fn transmute_immut<'a,T>(ptr: &'a mut T) -> &'a T { transmute(ptr) } /// Coerce a borrowed pointer to have an arbitrary associated region. -#[inline(always)] +#[inline] pub unsafe fn transmute_region<'a,'b,T>(ptr: &'a T) -> &'b T { transmute(ptr) } /// Coerce an immutable reference to be mutable. -#[inline(always)] +#[inline] pub unsafe fn transmute_mut_unsafe<T>(ptr: *const T) -> *mut T { transmute(ptr) } /// Coerce an immutable reference to be mutable. -#[inline(always)] +#[inline] pub unsafe fn transmute_immut_unsafe<T>(ptr: *const T) -> *T { transmute(ptr) } /// Coerce a borrowed mutable pointer to have an arbitrary associated region. -#[inline(always)] +#[inline] pub unsafe fn transmute_mut_region<'a,'b,T>(ptr: &'a mut T) -> &'b mut T { transmute(ptr) } /// Transforms lifetime of the second pointer to match the first. -#[inline(always)] +#[inline] pub unsafe fn copy_lifetime<'a,S,T>(_ptr: &'a S, ptr: &T) -> &'a T { transmute_region(ptr) } /// Transforms lifetime of the second pointer to match the first. -#[inline(always)] +#[inline] pub unsafe fn copy_mut_lifetime<'a,S,T>(_ptr: &'a mut S, ptr: &mut T) -> &'a mut T { transmute_mut_region(ptr) } /// Transforms lifetime of the second pointer to match the first. -#[inline(always)] +#[inline] pub unsafe fn copy_lifetime_vec<'a,S,T>(_ptr: &'a [S], ptr: &T) -> &'a T { transmute_region(ptr) } diff --git a/src/libstd/char.rs b/src/libstd/char.rs index 073ced8988a..797fd9e8c02 100644 --- a/src/libstd/char.rs +++ b/src/libstd/char.rs @@ -17,8 +17,8 @@ use u32; use uint; use unicode::{derived_property, general_category}; -#[cfg(not(test))] -use cmp::{Eq, Ord}; +#[cfg(not(test))] use cmp::{Eq, Ord}; +#[cfg(not(test))] use num::Zero; /* Lu Uppercase_Letter an uppercase letter @@ -65,14 +65,14 @@ pub fn is_XID_continue(c: char) -> bool { derived_property::XID_Continue(c) } /// Indicates whether a character is in lower case, defined /// in terms of the Unicode General Category 'Ll' /// -#[inline(always)] +#[inline] pub fn is_lowercase(c: char) -> bool { general_category::Ll(c) } /// /// Indicates whether a character is in upper case, defined /// in terms of the Unicode General Category 'Lu'. /// -#[inline(always)] +#[inline] pub fn is_uppercase(c: char) -> bool { general_category::Lu(c) } /// @@ -80,7 +80,7 @@ pub fn is_uppercase(c: char) -> bool { general_category::Lu(c) } /// terms of the Unicode General Categories 'Zs', 'Zl', 'Zp' /// additional 'Cc'-category control codes in the range [0x09, 0x0d] /// -#[inline(always)] +#[inline] pub fn is_whitespace(c: char) -> bool { ('\x09' <= c && c <= '\x0d') || general_category::Zs(c) @@ -93,7 +93,7 @@ pub fn is_whitespace(c: char) -> bool { /// defined in terms of the Unicode General Categories 'Nd', 'Nl', 'No' /// and the Derived Core Property 'Alphabetic'. /// -#[inline(always)] +#[inline] pub fn is_alphanumeric(c: char) -> bool { derived_property::Alphabetic(c) || general_category::Nd(c) @@ -102,7 +102,7 @@ pub fn is_alphanumeric(c: char) -> bool { } /// Indicates whether the character is numeric (Nd, Nl, or No) -#[inline(always)] +#[inline] pub fn is_digit(c: char) -> bool { general_category::Nd(c) || general_category::Nl(c) @@ -127,7 +127,7 @@ pub fn is_digit(c: char) -> bool { /// /// This just wraps `to_digit()`. /// -#[inline(always)] +#[inline] pub fn is_digit_radix(c: char, radix: uint) -> bool { match to_digit(c, radix) { Some(_) => true, @@ -310,24 +310,30 @@ impl Char for char { #[cfg(not(test))] impl Eq for char { - #[inline(always)] + #[inline] fn eq(&self, other: &char) -> bool { (*self) == (*other) } - #[inline(always)] + #[inline] fn ne(&self, other: &char) -> bool { (*self) != (*other) } } #[cfg(not(test))] impl Ord for char { - #[inline(always)] + #[inline] fn lt(&self, other: &char) -> bool { *self < *other } - #[inline(always)] + #[inline] fn le(&self, other: &char) -> bool { *self <= *other } - #[inline(always)] + #[inline] fn gt(&self, other: &char) -> bool { *self > *other } - #[inline(always)] + #[inline] fn ge(&self, other: &char) -> bool { *self >= *other } } +#[cfg(not(test))] +impl Zero for char { + fn zero() -> char { 0 as char } + fn is_zero(&self) -> bool { *self == 0 as char } +} + #[test] fn test_is_lowercase() { assert!('a'.is_lowercase()); diff --git a/src/libstd/cleanup.rs b/src/libstd/cleanup.rs index d1460b7a3c9..36c1fdf781b 100644 --- a/src/libstd/cleanup.rs +++ b/src/libstd/cleanup.rs @@ -13,107 +13,14 @@ use libc::{c_char, c_void, intptr_t, uintptr_t}; use ptr::mut_null; use repr::BoxRepr; +use rt; +use rt::OldTaskContext; use sys::TypeDesc; use cast::transmute; -#[cfg(not(test))] use unstable::lang::clear_task_borrow_list; #[cfg(not(test))] use ptr::to_unsafe_ptr; -/** - * Runtime structures - * - * NB: These must match the representation in the C++ runtime. - */ - type DropGlue<'self> = &'self fn(**TypeDesc, *c_void); -type FreeGlue<'self> = &'self fn(**TypeDesc, *c_void); - -type TaskID = uintptr_t; - -struct StackSegment { priv opaque: () } -struct Scheduler { priv opaque: () } -struct SchedulerLoop { priv opaque: () } -struct Kernel { priv opaque: () } -struct Env { priv opaque: () } -struct AllocHeader { priv opaque: () } -struct MemoryRegion { priv opaque: () } - -#[cfg(target_arch="x86")] -struct Registers { - data: [u32, ..16] -} - -#[cfg(target_arch="arm")] -#[cfg(target_arch="mips")] -struct Registers { - data: [u32, ..32] -} - -#[cfg(target_arch="x86")] -#[cfg(target_arch="arm")] -#[cfg(target_arch="mips")] -struct Context { - regs: Registers, - next: *Context, - pad: [u32, ..3] -} - -#[cfg(target_arch="x86_64")] -struct Registers { - data: [u64, ..22] -} - -#[cfg(target_arch="x86_64")] -struct Context { - regs: Registers, - next: *Context, - pad: uintptr_t -} - -struct BoxedRegion { - env: *Env, - backing_region: *MemoryRegion, - live_allocs: *BoxRepr -} - -#[cfg(target_arch="x86")] -#[cfg(target_arch="arm")] -#[cfg(target_arch="mips")] -struct Task { - // Public fields - refcount: intptr_t, // 0 - id: TaskID, // 4 - pad: [u32, ..2], // 8 - ctx: Context, // 16 - stack_segment: *StackSegment, // 96 - runtime_sp: uintptr_t, // 100 - scheduler: *Scheduler, // 104 - scheduler_loop: *SchedulerLoop, // 108 - - // Fields known only to the runtime - kernel: *Kernel, // 112 - name: *c_char, // 116 - list_index: i32, // 120 - boxed_region: BoxedRegion // 128 -} - -#[cfg(target_arch="x86_64")] -struct Task { - // Public fields - refcount: intptr_t, - id: TaskID, - ctx: Context, - stack_segment: *StackSegment, - runtime_sp: uintptr_t, - scheduler: *Scheduler, - scheduler_loop: *SchedulerLoop, - - // Fields known only to the runtime - kernel: *Kernel, - name: *c_char, - list_index: i32, - boxed_region: BoxedRegion -} /* * Box annihilation @@ -132,9 +39,9 @@ unsafe fn each_live_alloc(read_next_before: bool, //! Walks the internal list of allocations use managed; + use rt::local_heap; - let task: *Task = transmute(rustrt::rust_get_task()); - let box = (*task).boxed_region.live_allocs; + let box = local_heap::live_allocs(); let mut box: *mut BoxRepr = transmute(copy box); while box != mut_null() { let next_before = transmute(copy (*box).header.next); @@ -156,7 +63,11 @@ unsafe fn each_live_alloc(read_next_before: bool, #[cfg(unix)] fn debug_mem() -> bool { - ::rt::env::get().debug_mem + // XXX: Need to port the environment struct to newsched + match rt::context() { + OldTaskContext => ::rt::env::get().debug_mem, + _ => false + } } #[cfg(windows)] @@ -165,13 +76,12 @@ fn debug_mem() -> bool { } /// Destroys all managed memory (i.e. @ boxes) held by the current task. -#[cfg(not(test))] -#[lang="annihilate"] pub unsafe fn annihilate() { - use unstable::lang::local_free; + use rt::local_heap::local_free; use io::WriterUtil; use io; use libc; + use rt::borrowck; use sys; use managed; @@ -183,7 +93,7 @@ pub unsafe fn annihilate() { // Quick hack: we need to free this list upon task exit, and this // is a convenient place to do it. - clear_task_borrow_list(); + borrowck::clear_task_borrow_list(); // Pass 1: Make all boxes immortal. // @@ -207,7 +117,7 @@ pub unsafe fn annihilate() { if !uniq { let tydesc: *TypeDesc = transmute(copy (*box).header.type_desc); let drop_glue: DropGlue = transmute(((*tydesc).drop_glue, 0)); - drop_glue(to_unsafe_ptr(&tydesc), transmute(&(*box).data)); + drop_glue(&tydesc, transmute(&(*box).data)); } } diff --git a/src/libstd/clone.rs b/src/libstd/clone.rs index 266dd1a35e3..5ec594cef7e 100644 --- a/src/libstd/clone.rs +++ b/src/libstd/clone.rs @@ -34,25 +34,25 @@ pub trait Clone { impl<T: Clone> Clone for ~T { /// Return a deep copy of the owned box. - #[inline(always)] + #[inline] fn clone(&self) -> ~T { ~(**self).clone() } } impl<T> Clone for @T { /// Return a shallow copy of the managed box. - #[inline(always)] + #[inline] fn clone(&self) -> @T { *self } } impl<T> Clone for @mut T { /// Return a shallow copy of the managed box. - #[inline(always)] + #[inline] fn clone(&self) -> @mut T { *self } } impl<'self, T> Clone for &'self T { /// Return a shallow copy of the borrowed pointer. - #[inline(always)] + #[inline] fn clone(&self) -> &'self T { *self } } @@ -60,7 +60,7 @@ macro_rules! clone_impl( ($t:ty) => { impl Clone for $t { /// Return a deep copy of the value. - #[inline(always)] + #[inline] fn clone(&self) -> $t { *self } } } @@ -96,7 +96,7 @@ pub trait DeepClone { impl<T: DeepClone> DeepClone for ~T { /// Return a deep copy of the owned box. - #[inline(always)] + #[inline] fn deep_clone(&self) -> ~T { ~(**self).deep_clone() } } @@ -104,7 +104,7 @@ impl<T: DeepClone> DeepClone for ~T { impl<T: Const + DeepClone> DeepClone for @T { /// Return a deep copy of the managed box. The `Const` trait is required to prevent performing /// a deep clone of a potentially cyclical type. - #[inline(always)] + #[inline] fn deep_clone(&self) -> @T { @(**self).deep_clone() } } @@ -112,7 +112,7 @@ impl<T: Const + DeepClone> DeepClone for @T { impl<T: Const + DeepClone> DeepClone for @mut T { /// Return a deep copy of the managed box. The `Const` trait is required to prevent performing /// a deep clone of a potentially cyclical type. - #[inline(always)] + #[inline] fn deep_clone(&self) -> @mut T { @mut (**self).deep_clone() } } @@ -120,7 +120,7 @@ macro_rules! deep_clone_impl( ($t:ty) => { impl DeepClone for $t { /// Return a deep copy of the value. - #[inline(always)] + #[inline] fn deep_clone(&self) -> $t { *self } } } diff --git a/src/libstd/cmp.rs b/src/libstd/cmp.rs index ce6a04c3688..2c4bb46b23b 100644 --- a/src/libstd/cmp.rs +++ b/src/libstd/cmp.rs @@ -45,7 +45,7 @@ pub trait TotalEq { macro_rules! totaleq_impl( ($t:ty) => { impl TotalEq for $t { - #[inline(always)] + #[inline] fn equals(&self, other: &$t) -> bool { *self == *other } } } @@ -84,27 +84,27 @@ pub trait TotalOrd: TotalEq { } impl TotalOrd for Ordering { - #[inline(always)] + #[inline] fn cmp(&self, other: &Ordering) -> Ordering { (*self as int).cmp(&(*other as int)) } } impl Ord for Ordering { - #[inline(always)] + #[inline] fn lt(&self, other: &Ordering) -> bool { (*self as int) < (*other as int) } - #[inline(always)] + #[inline] fn le(&self, other: &Ordering) -> bool { (*self as int) <= (*other as int) } - #[inline(always)] + #[inline] fn gt(&self, other: &Ordering) -> bool { (*self as int) > (*other as int) } - #[inline(always)] + #[inline] fn ge(&self, other: &Ordering) -> bool { (*self as int) >= (*other as int) } } macro_rules! totalord_impl( ($t:ty) => { impl TotalOrd for $t { - #[inline(always)] + #[inline] fn cmp(&self, other: &$t) -> Ordering { if *self < *other { Less } else if *self > *other { Greater } @@ -146,7 +146,7 @@ Return `o1` if it is not `Equal`, otherwise `o2`. Simulates the lexical ordering on a type `(int, int)`. */ // used in deriving code in libsyntax -#[inline(always)] +#[inline] pub fn lexical_ordering(o1: Ordering, o2: Ordering) -> Ordering { match o1 { Equal => o2, @@ -180,12 +180,12 @@ pub trait Equiv<T> { fn equiv(&self, other: &T) -> bool; } -#[inline(always)] +#[inline] pub fn min<T:Ord>(v1: T, v2: T) -> T { if v1 < v2 { v1 } else { v2 } } -#[inline(always)] +#[inline] pub fn max<T:Ord>(v1: T, v2: T) -> T { if v1 > v2 { v1 } else { v2 } } diff --git a/src/libstd/comm.rs b/src/libstd/comm.rs index f0c353c8d62..00c33c8ab32 100644 --- a/src/libstd/comm.rs +++ b/src/libstd/comm.rs @@ -20,7 +20,6 @@ use either::{Either, Left, Right}; use kinds::Owned; use option::{Option, Some, None}; use uint; -use vec; use vec::OwnedVector; use util::replace; use unstable::sync::{Exclusive, exclusive}; @@ -209,7 +208,7 @@ impl<T: Owned> Peekable<T> for PortSet<T> { fn peek(&self) -> bool { // It'd be nice to use self.port.each, but that version isn't // pure. - for uint::range(0, vec::uniq_len(&const self.ports)) |i| { + for uint::range(0, self.ports.len()) |i| { let port: &pipesy::Port<T> = &self.ports[i]; if port.peek() { return true; @@ -221,7 +220,7 @@ impl<T: Owned> Peekable<T> for PortSet<T> { /// A channel that can be shared between many senders. pub struct SharedChan<T> { - ch: Exclusive<pipesy::Chan<T>> + inner: Either<Exclusive<pipesy::Chan<T>>, rtcomm::SharedChan<T>> } impl<T: Owned> SharedChan<T> { @@ -229,40 +228,50 @@ impl<T: Owned> SharedChan<T> { pub fn new(c: Chan<T>) -> SharedChan<T> { let Chan { inner } = c; let c = match inner { - Left(c) => c, - Right(_) => fail!("SharedChan not implemented") + Left(c) => Left(exclusive(c)), + Right(c) => Right(rtcomm::SharedChan::new(c)) }; - SharedChan { ch: exclusive(c) } + SharedChan { inner: c } } } impl<T: Owned> GenericChan<T> for SharedChan<T> { fn send(&self, x: T) { - unsafe { - let mut xx = Some(x); - do self.ch.with_imm |chan| { - let x = replace(&mut xx, None); - chan.send(x.unwrap()) + match self.inner { + Left(ref chan) => { + unsafe { + let mut xx = Some(x); + do chan.with_imm |chan| { + let x = replace(&mut xx, None); + chan.send(x.unwrap()) + } + } } + Right(ref chan) => chan.send(x) } } } impl<T: Owned> GenericSmartChan<T> for SharedChan<T> { fn try_send(&self, x: T) -> bool { - unsafe { - let mut xx = Some(x); - do self.ch.with_imm |chan| { - let x = replace(&mut xx, None); - chan.try_send(x.unwrap()) + match self.inner { + Left(ref chan) => { + unsafe { + let mut xx = Some(x); + do chan.with_imm |chan| { + let x = replace(&mut xx, None); + chan.try_send(x.unwrap()) + } + } } + Right(ref chan) => chan.try_send(x) } } } impl<T: Owned> ::clone::Clone for SharedChan<T> { fn clone(&self) -> SharedChan<T> { - SharedChan { ch: self.ch.clone() } + SharedChan { inner: self.inner.clone() } } } @@ -625,7 +634,7 @@ mod pipesy { } impl<T: Owned> GenericChan<T> for Chan<T> { - #[inline(always)] + #[inline] fn send(&self, x: T) { unsafe { let self_endp = transmute_mut(&self.endp); @@ -636,7 +645,7 @@ mod pipesy { } impl<T: Owned> GenericSmartChan<T> for Chan<T> { - #[inline(always)] + #[inline] fn try_send(&self, x: T) -> bool { unsafe { let self_endp = transmute_mut(&self.endp); @@ -653,7 +662,7 @@ mod pipesy { } impl<T: Owned> GenericPort<T> for Port<T> { - #[inline(always)] + #[inline] fn recv(&self) -> T { unsafe { let self_endp = transmute_mut(&self.endp); @@ -664,7 +673,7 @@ mod pipesy { } } - #[inline(always)] + #[inline] fn try_recv(&self) -> Option<T> { unsafe { let self_endp = transmute_mut(&self.endp); @@ -681,7 +690,7 @@ mod pipesy { } impl<T: Owned> Peekable<T> for Port<T> { - #[inline(always)] + #[inline] fn peek(&self) -> bool { unsafe { let self_endp = transmute_mut(&self.endp); diff --git a/src/libstd/container.rs b/src/libstd/container.rs index 065582e2e0d..c1b656f1cd9 100644 --- a/src/libstd/container.rs +++ b/src/libstd/container.rs @@ -16,10 +16,10 @@ use option::Option; /// knowledge known is the number of elements contained within. pub trait Container { /// Return the number of elements in the container - fn len(&const self) -> uint; + fn len(&self) -> uint; /// Return true if the container contains no elements - fn is_empty(&const self) -> bool; + fn is_empty(&self) -> bool; } /// A trait to represent mutable containers diff --git a/src/libstd/core.rc b/src/libstd/core.rc index 8e09a9b17fd..6911c00e55b 100644 --- a/src/libstd/core.rc +++ b/src/libstd/core.rc @@ -12,19 +12,20 @@ # The Rust standard library -The Rust standard library provides runtime features required by the language, -including the task scheduler and memory allocators, as well as library -support for Rust built-in types, platform abstractions, and other commonly -used features. - -`std` includes modules corresponding to each of the integer types, each of -the floating point types, the `bool` type, tuples, characters, strings -(`str`), vectors (`vec`), managed boxes (`managed`), owned boxes (`owned`), -and unsafe and borrowed pointers (`ptr`). Additionally, `std` provides -pervasive types (`option` and `result`), task creation and communication -primitives (`task`, `comm`), platform abstractions (`os` and `path`), basic -I/O abstractions (`io`), common traits (`kinds`, `ops`, `cmp`, `num`, -`to_str`), and complete bindings to the C standard library (`libc`). +The Rust standard library is a group of interrelated modules defining +the core language traits, operations on built-in data types, collections, +platform abstractions, the task scheduler, runtime support for language +features and other common functionality. + +`std` includes modules corresponding to each of the integer types, +each of the floating point types, the `bool` type, tuples, characters, +strings (`str`), vectors (`vec`), managed boxes (`managed`), owned +boxes (`owned`), and unsafe and borrowed pointers (`ptr`, `borrowed`). +Additionally, `std` provides pervasive types (`option` and `result`), +task creation and communication primitives (`task`, `comm`), platform +abstractions (`os` and `path`), basic I/O abstractions (`io`), common +traits (`kinds`, `ops`, `cmp`, `num`, `to_str`), and complete bindings +to the C standard library (`libc`). # Standard library injection and the Rust prelude @@ -38,7 +39,7 @@ with the `std::` path prefix, as in `use std::vec`, `use std::task::spawn`, etc. Additionally, `std` contains a `prelude` module that reexports many of the -most common std modules, types and traits. The contents of the prelude are +most common types, traits and functions. The contents of the prelude are imported into every *module* by default. Implicitly, all modules behave as if they contained the following prologue: @@ -56,17 +57,13 @@ they contained the following prologue: #[license = "MIT/ASL2"]; #[crate_type = "lib"]; -// NOTE: remove these two attributes after the next snapshot -#[no_core]; // for stage0 -#[allow(unrecognized_lint)]; // otherwise stage0 is seriously ugly - // Don't link to std. We are std. #[no_std]; #[deny(non_camel_case_types)]; #[deny(missing_doc)]; -// Make core testable by not duplicating lang items. See #2912 +// Make std testable by not duplicating lang items. See #2912 #[cfg(test)] extern mod realstd(name = "std"); #[cfg(test)] pub use kinds = realstd::kinds; #[cfg(test)] pub use ops = realstd::ops; diff --git a/src/libstd/either.rs b/src/libstd/either.rs index fac0866f17e..681a7fbc821 100644 --- a/src/libstd/either.rs +++ b/src/libstd/either.rs @@ -33,7 +33,7 @@ pub enum Either<T, U> { /// If `value` is left(T) then `f_left` is applied to its contents, if /// `value` is right(U) then `f_right` is applied to its contents, and the /// result is returned. -#[inline(always)] +#[inline] pub fn either<T, U, V>(f_left: &fn(&T) -> V, f_right: &fn(&U) -> V, value: &Either<T, U>) -> V { match *value { @@ -47,7 +47,7 @@ pub fn lefts<T:Copy,U>(eithers: &[Either<T, U>]) -> ~[T] { do vec::build_sized(eithers.len()) |push| { for eithers.each |elt| { match *elt { - Left(ref l) => { push(*l); } + Left(ref l) => { push(copy *l); } _ => { /* fallthrough */ } } } @@ -59,7 +59,7 @@ pub fn rights<T, U: Copy>(eithers: &[Either<T, U>]) -> ~[U] { do vec::build_sized(eithers.len()) |push| { for eithers.each |elt| { match *elt { - Right(ref r) => { push(*r); } + Right(ref r) => { push(copy *r); } _ => { /* fallthrough */ } } } @@ -83,7 +83,7 @@ pub fn partition<T, U>(eithers: ~[Either<T, U>]) -> (~[T], ~[U]) { } /// Flips between left and right of a given either -#[inline(always)] +#[inline] pub fn flip<T, U>(eith: Either<T, U>) -> Either<U, T> { match eith { Right(r) => Left(r), @@ -95,7 +95,7 @@ pub fn flip<T, U>(eith: Either<T, U>) -> Either<U, T> { /// /// Converts an `either` type to a `result` type, making the "right" choice /// an ok result, and the "left" choice a fail -#[inline(always)] +#[inline] pub fn to_result<T, U>(eith: Either<T, U>) -> Result<U, T> { match eith { Right(r) => result::Ok(r), @@ -104,7 +104,7 @@ pub fn to_result<T, U>(eith: Either<T, U>) -> Result<U, T> { } /// Checks whether the given value is a left -#[inline(always)] +#[inline] pub fn is_left<T, U>(eith: &Either<T, U>) -> bool { match *eith { Left(_) => true, @@ -113,7 +113,7 @@ pub fn is_left<T, U>(eith: &Either<T, U>) -> bool { } /// Checks whether the given value is a right -#[inline(always)] +#[inline] pub fn is_right<T, U>(eith: &Either<T, U>) -> bool { match *eith { Right(_) => true, @@ -122,7 +122,7 @@ pub fn is_right<T, U>(eith: &Either<T, U>) -> bool { } /// Retrieves the value in the left branch. Fails if the either is Right. -#[inline(always)] +#[inline] pub fn unwrap_left<T,U>(eith: Either<T,U>) -> T { match eith { Left(x) => x, @@ -131,7 +131,7 @@ pub fn unwrap_left<T,U>(eith: Either<T,U>) -> T { } /// Retrieves the value in the right branch. Fails if the either is Left. -#[inline(always)] +#[inline] pub fn unwrap_right<T,U>(eith: Either<T,U>) -> U { match eith { Right(x) => x, @@ -140,27 +140,27 @@ pub fn unwrap_right<T,U>(eith: Either<T,U>) -> U { } impl<T, U> Either<T, U> { - #[inline(always)] + #[inline] pub fn either<V>(&self, f_left: &fn(&T) -> V, f_right: &fn(&U) -> V) -> V { either(f_left, f_right, self) } - #[inline(always)] + #[inline] pub fn flip(self) -> Either<U, T> { flip(self) } - #[inline(always)] + #[inline] pub fn to_result(self) -> Result<U, T> { to_result(self) } - #[inline(always)] + #[inline] pub fn is_left(&self) -> bool { is_left(self) } - #[inline(always)] + #[inline] pub fn is_right(&self) -> bool { is_right(self) } - #[inline(always)] + #[inline] pub fn unwrap_left(self) -> T { unwrap_left(self) } - #[inline(always)] + #[inline] pub fn unwrap_right(self) -> U { unwrap_right(self) } } diff --git a/src/libstd/hash.rs b/src/libstd/hash.rs index e9022445786..1967a57e867 100644 --- a/src/libstd/hash.rs +++ b/src/libstd/hash.rs @@ -64,7 +64,7 @@ pub trait HashUtil { } impl<A:Hash> HashUtil for A { - #[inline(always)] + #[inline] fn hash(&self) -> u64 { self.hash_keyed(0,0) } } @@ -79,7 +79,7 @@ pub trait Streaming { } impl<A:IterBytes> Hash for A { - #[inline(always)] + #[inline] fn hash_keyed(&self, k0: u64, k1: u64) -> u64 { let mut s = State::new(k0, k1); for self.iter_bytes(true) |bytes| { @@ -176,7 +176,7 @@ fn hash_keyed_5<A: IterBytes, s.result_u64() } -#[inline(always)] +#[inline] pub fn default_state() -> State { State::new(0, 0) } @@ -194,7 +194,7 @@ struct SipState { } impl SipState { - #[inline(always)] + #[inline] fn new(key0: u64, key1: u64) -> SipState { let mut state = SipState { k0: key0, @@ -248,7 +248,7 @@ macro_rules! compress ( impl Writer for SipState { // Methods for io::writer - #[inline(always)] + #[inline] fn write(&mut self, msg: &[u8]) { let length = msg.len(); self.length += length; @@ -315,12 +315,12 @@ impl Writer for SipState { } impl Streaming for SipState { - #[inline(always)] + #[inline] fn input(&mut self, buf: &[u8]) { self.write(buf); } - #[inline(always)] + #[inline] fn result_u64(&mut self) -> u64 { let mut v0 = self.v0; let mut v1 = self.v1; @@ -373,7 +373,7 @@ impl Streaming for SipState { s } - #[inline(always)] + #[inline] fn reset(&mut self) { self.length = 0; self.v0 = self.k0 ^ 0x736f6d6570736575; @@ -558,4 +558,15 @@ mod tests { val & !(0xff << (byte * 8)) } } + + #[test] + fn test_float_hashes_differ() { + assert!(0.0.hash() != 1.0.hash()); + assert!(1.0.hash() != (-1.0).hash()); + } + + #[test] + fn test_float_hashes_of_zero() { + assert_eq!(0.0.hash(), (-0.0).hash()); + } } diff --git a/src/libstd/hashmap.rs b/src/libstd/hashmap.rs index 85156d6996d..d05fa63a6f9 100644 --- a/src/libstd/hashmap.rs +++ b/src/libstd/hashmap.rs @@ -59,7 +59,7 @@ enum SearchResult { FoundEntry(uint), FoundHole(uint), TableFull } -#[inline(always)] +#[inline] fn resize_at(capacity: uint) -> uint { ((capacity as float) * 3. / 4.) as uint } @@ -85,19 +85,19 @@ fn linear_map_with_capacity_and_keys<K:Eq + Hash,V>( } impl<K:Hash + Eq,V> HashMap<K, V> { - #[inline(always)] + #[inline] fn to_bucket(&self, h: uint) -> uint { // A good hash function with entropy spread over all of the // bits is assumed. SipHash is more than good enough. h % self.buckets.len() } - #[inline(always)] + #[inline] fn next_bucket(&self, idx: uint, len_buckets: uint) -> uint { (idx + 1) % len_buckets } - #[inline(always)] + #[inline] fn bucket_sequence(&self, hash: uint, op: &fn(uint) -> bool) -> bool { let start_idx = self.to_bucket(hash); @@ -112,20 +112,20 @@ impl<K:Hash + Eq,V> HashMap<K, V> { } } - #[inline(always)] + #[inline] fn bucket_for_key(&self, k: &K) -> SearchResult { let hash = k.hash_keyed(self.k0, self.k1) as uint; self.bucket_for_key_with_hash(hash, k) } - #[inline(always)] + #[inline] fn bucket_for_key_equiv<Q:Hash + Equiv<K>>(&self, k: &Q) -> SearchResult { let hash = k.hash_keyed(self.k0, self.k1) as uint; self.bucket_for_key_with_hash_equiv(hash, k) } - #[inline(always)] + #[inline] fn bucket_for_key_with_hash(&self, hash: uint, k: &K) @@ -141,7 +141,7 @@ impl<K:Hash + Eq,V> HashMap<K, V> { TableFull } - #[inline(always)] + #[inline] fn bucket_for_key_with_hash_equiv<Q:Equiv<K>>(&self, hash: uint, k: &Q) @@ -161,7 +161,7 @@ impl<K:Hash + Eq,V> HashMap<K, V> { /// Expand the capacity of the array to the next power of two /// and re-insert each of the existing buckets. - #[inline(always)] + #[inline] fn expand(&mut self) { let new_capacity = self.buckets.len() * 2; self.resize(new_capacity); @@ -190,7 +190,7 @@ impl<K:Hash + Eq,V> HashMap<K, V> { } } - #[inline(always)] + #[inline] fn value_for_bucket<'a>(&'a self, idx: uint) -> &'a V { match self.buckets[idx] { Some(ref bkt) => &bkt.value, @@ -198,7 +198,7 @@ impl<K:Hash + Eq,V> HashMap<K, V> { } } - #[inline(always)] + #[inline] fn mut_value_for_bucket<'a>(&'a mut self, idx: uint) -> &'a mut V { match self.buckets[idx] { Some(ref mut bkt) => &mut bkt.value, diff --git a/src/libstd/io.rs b/src/libstd/io.rs index 6f065d74fa2..e5e8a4cb601 100644 --- a/src/libstd/io.rs +++ b/src/libstd/io.rs @@ -1654,9 +1654,7 @@ impl Writer for BytesWriter { vec::reserve(bytes, count); unsafe { - // Silly stage0 borrow check workaround... - let casted: &mut ~[u8] = cast::transmute_copy(&bytes); - vec::raw::set_len(casted, count); + vec::raw::set_len(bytes, count); let view = vec::mut_slice(*bytes, *self.pos, count); vec::bytes::copy_memory(view, v, v_len); @@ -1667,7 +1665,7 @@ impl Writer for BytesWriter { fn seek(&self, offset: int, whence: SeekStyle) { let pos = *self.pos; - let len = vec::uniq_len(&const *self.bytes); + let len = self.bytes.len(); *self.pos = seek_in_buf(offset, pos, len, whence); } @@ -1779,7 +1777,7 @@ pub mod fsync { None => (), Some(level) => { // fail hard if not succesful - assert!(((self.arg.fsync_fn)(self.arg.val, level) + assert!(((self.arg.fsync_fn)(copy self.arg.val, level) != -1)); } } diff --git a/src/libstd/iter.rs b/src/libstd/iter.rs index 2197feea452..7053cbe0df5 100644 --- a/src/libstd/iter.rs +++ b/src/libstd/iter.rs @@ -73,7 +73,7 @@ pub trait FromIter<T> { * assert!(!any(|&x: &uint| x > 5, |f| xs.each(f))); * ~~~ */ -#[inline(always)] +#[inline] pub fn any<T>(predicate: &fn(T) -> bool, iter: &fn(f: &fn(T) -> bool) -> bool) -> bool { for iter |x| { @@ -94,7 +94,7 @@ pub fn any<T>(predicate: &fn(T) -> bool, * assert!(!all(|&x: &uint| x < 5, |f| uint::range(1, 6, f))); * ~~~ */ -#[inline(always)] +#[inline] pub fn all<T>(predicate: &fn(T) -> bool, iter: &fn(f: &fn(T) -> bool) -> bool) -> bool { // If we ever break, iter will return false, so this will only return true @@ -112,7 +112,7 @@ pub fn all<T>(predicate: &fn(T) -> bool, * assert_eq!(*find(|& &x: & &uint| x > 3, |f| xs.each(f)).unwrap(), 4); * ~~~ */ -#[inline(always)] +#[inline] pub fn find<T>(predicate: &fn(&T) -> bool, iter: &fn(f: &fn(T) -> bool) -> bool) -> Option<T> { for iter |x| { @@ -226,7 +226,7 @@ pub fn fold_ref<T, U>(start: T, iter: &fn(f: &fn(&U) -> bool) -> bool, f: &fn(&m * assert_eq!(do sum |f| { xs.each(f) }, 10); * ~~~ */ -#[inline(always)] +#[inline] pub fn sum<T: Zero + Add<T, T>>(iter: &fn(f: &fn(&T) -> bool) -> bool) -> T { fold_ref(Zero::zero::<T>(), iter, |a, x| *a = a.add(x)) } @@ -241,7 +241,7 @@ pub fn sum<T: Zero + Add<T, T>>(iter: &fn(f: &fn(&T) -> bool) -> bool) -> T { * assert_eq!(do product |f| { xs.each(f) }, 24); * ~~~ */ -#[inline(always)] +#[inline] pub fn product<T: One + Mul<T, T>>(iter: &fn(f: &fn(&T) -> bool) -> bool) -> T { fold_ref(One::one::<T>(), iter, |a, x| *a = a.mul(x)) } diff --git a/src/libstd/iterator.rs b/src/libstd/iterator.rs index e65904a6899..eefad1a03dc 100644 --- a/src/libstd/iterator.rs +++ b/src/libstd/iterator.rs @@ -308,6 +308,12 @@ pub trait IteratorUtil<A> { /// assert!(!it.any_(|&x| *x == 3)); /// ~~~ fn any_(&mut self, f: &fn(A) -> bool) -> bool; + + /// Return the first element satisfying the specified predicate + fn find_(&mut self, predicate: &fn(&A) -> bool) -> Option<A>; + + /// Return the index of the first element satisfying the specified predicate + fn position_(&mut self, predicate: &fn(A) -> bool) -> Option<uint>; } /// Iterator adaptors provided for every `Iterator` implementation. The adaptor objects are also @@ -315,59 +321,59 @@ pub trait IteratorUtil<A> { /// /// In the future these will be default methods instead of a utility trait. impl<A, T: Iterator<A>> IteratorUtil<A> for T { - #[inline(always)] + #[inline] fn chain_<U: Iterator<A>>(self, other: U) -> ChainIterator<A, T, U> { ChainIterator{a: self, b: other, flag: false} } - #[inline(always)] + #[inline] fn zip<B, U: Iterator<B>>(self, other: U) -> ZipIterator<A, T, B, U> { ZipIterator{a: self, b: other} } // FIXME: #5898: should be called map - #[inline(always)] + #[inline] fn transform<'r, B>(self, f: &'r fn(A) -> B) -> MapIterator<'r, A, B, T> { MapIterator{iter: self, f: f} } - #[inline(always)] + #[inline] fn filter<'r>(self, predicate: &'r fn(&A) -> bool) -> FilterIterator<'r, A, T> { FilterIterator{iter: self, predicate: predicate} } - #[inline(always)] + #[inline] fn filter_map<'r, B>(self, f: &'r fn(A) -> Option<B>) -> FilterMapIterator<'r, A, B, T> { FilterMapIterator { iter: self, f: f } } - #[inline(always)] + #[inline] fn enumerate(self) -> EnumerateIterator<A, T> { EnumerateIterator{iter: self, count: 0} } - #[inline(always)] + #[inline] fn skip_while<'r>(self, predicate: &'r fn(&A) -> bool) -> SkipWhileIterator<'r, A, T> { SkipWhileIterator{iter: self, flag: false, predicate: predicate} } - #[inline(always)] + #[inline] fn take_while<'r>(self, predicate: &'r fn(&A) -> bool) -> TakeWhileIterator<'r, A, T> { TakeWhileIterator{iter: self, flag: false, predicate: predicate} } - #[inline(always)] + #[inline] fn skip(self, n: uint) -> SkipIterator<A, T> { SkipIterator{iter: self, n: n} } // FIXME: #5898: should be called take - #[inline(always)] + #[inline] fn take_(self, n: uint) -> TakeIterator<A, T> { TakeIterator{iter: self, n: n} } - #[inline(always)] + #[inline] fn scan<'r, St, B>(self, initial_state: St, f: &'r fn(&mut St, A) -> Option<B>) -> ScanIterator<'r, A, B, T, St> { ScanIterator{iter: self, f: f, state: initial_state} @@ -386,13 +392,13 @@ impl<A, T: Iterator<A>> IteratorUtil<A> for T { } } - #[inline(always)] + #[inline] fn collect<B: FromIter<A>>(&mut self) -> B { FromIter::from_iter::<A, B>(|f| self.advance(f)) } /// Return the `n`th item yielded by an iterator. - #[inline(always)] + #[inline] fn nth(&mut self, mut n: uint) -> Option<A> { loop { match self.next() { @@ -404,7 +410,7 @@ impl<A, T: Iterator<A>> IteratorUtil<A> for T { } /// Return the last item yielded by an iterator. - #[inline(always)] + #[inline] fn last_(&mut self) -> Option<A> { let mut last = None; for self.advance |x| { last = Some(x); } @@ -421,23 +427,45 @@ impl<A, T: Iterator<A>> IteratorUtil<A> for T { None => { break; } } } - return accum; + accum } /// Count the number of items yielded by an iterator - #[inline(always)] + #[inline] fn count(&mut self) -> uint { self.fold(0, |cnt, _x| cnt + 1) } - #[inline(always)] + #[inline] fn all(&mut self, f: &fn(A) -> bool) -> bool { for self.advance |x| { if !f(x) { return false; } } - return true; + true } - #[inline(always)] + #[inline] fn any_(&mut self, f: &fn(A) -> bool) -> bool { for self.advance |x| { if f(x) { return true; } } - return false; + false + } + + /// Return the first element satisfying the specified predicate + #[inline] + fn find_(&mut self, predicate: &fn(&A) -> bool) -> Option<A> { + for self.advance |x| { + if predicate(&x) { return Some(x) } + } + None + } + + /// Return the index of the first element satisfying the specified predicate + #[inline] + fn position_(&mut self, predicate: &fn(A) -> bool) -> Option<uint> { + let mut i = 0; + for self.advance |x| { + if predicate(x) { + return Some(i); + } + i += 1; + } + None } } @@ -456,7 +484,7 @@ pub trait AdditiveIterator<A> { } impl<A: Add<A, A> + Zero, T: Iterator<A>> AdditiveIterator<A> for T { - #[inline(always)] + #[inline] fn sum(&mut self) -> A { self.fold(Zero::zero::<A>(), |s, x| s + x) } } @@ -481,7 +509,7 @@ pub trait MultiplicativeIterator<A> { } impl<A: Mul<A, A> + One, T: Iterator<A>> MultiplicativeIterator<A> for T { - #[inline(always)] + #[inline] fn product(&mut self) -> A { self.fold(One::one::<A>(), |p, x| p * x) } } @@ -510,7 +538,7 @@ pub trait OrdIterator<A> { } impl<A: Ord, T: Iterator<A>> OrdIterator<A> for T { - #[inline(always)] + #[inline] fn max(&mut self) -> Option<A> { self.fold(None, |max, x| { match max { @@ -520,7 +548,7 @@ impl<A: Ord, T: Iterator<A>> OrdIterator<A> for T { }) } - #[inline(always)] + #[inline] fn min(&mut self) -> Option<A> { self.fold(None, |min, x| { match min { @@ -788,8 +816,8 @@ impl<'self, A, St> UnfoldrIterator<'self, A, St> { /// Creates a new iterator with the specified closure as the "iterator /// function" and an initial state to eventually pass to the iterator #[inline] - pub fn new(f: &'self fn(&mut St) -> Option<A>, initial_state: St) - -> UnfoldrIterator<'self, A, St> { + pub fn new<'a>(f: &'a fn(&mut St) -> Option<A>, initial_state: St) + -> UnfoldrIterator<'a, A, St> { UnfoldrIterator { f: f, state: initial_state @@ -815,14 +843,14 @@ pub struct Counter<A> { impl<A> Counter<A> { /// Creates a new counter with the specified start/step - #[inline(always)] + #[inline] pub fn new(start: A, step: A) -> Counter<A> { Counter{state: start, step: step} } } impl<A: Add<A, A> + Clone> Iterator<A> for Counter<A> { - #[inline(always)] + #[inline] fn next(&mut self) -> Option<A> { let result = self.state.clone(); self.state = self.state.add(&self.step); // FIXME: #6050 @@ -1055,4 +1083,20 @@ mod tests { assert!(!v.iter().any_(|&x| x > 100)); assert!(!v.slice(0, 0).iter().any_(|_| fail!())); } + + #[test] + fn test_find() { + let v = &[1, 3, 9, 27, 103, 14, 11]; + assert_eq!(*v.iter().find_(|x| *x & 1 == 0).unwrap(), 14); + assert_eq!(*v.iter().find_(|x| *x % 3 == 0).unwrap(), 3); + assert!(v.iter().find_(|x| *x % 12 == 0).is_none()); + } + + #[test] + fn test_position() { + let v = &[1, 3, 9, 27, 103, 14, 11]; + assert_eq!(v.iter().position_(|x| *x & 1 == 0).unwrap(), 5); + assert_eq!(v.iter().position_(|x| *x % 3 == 0).unwrap(), 1); + assert!(v.iter().position_(|x| *x % 12 == 0).is_none()); + } } diff --git a/src/libstd/libc.rs b/src/libstd/libc.rs index 26205c930f0..07b2ac6ed01 100644 --- a/src/libstd/libc.rs +++ b/src/libstd/libc.rs @@ -14,8 +14,8 @@ * This module contains bindings to the C standard library, * organized into modules by their defining standard. * Additionally, it contains some assorted platform-specific definitions. -* For convenience, most functions and types are reexported from `core::libc`, -* so `pub use core::libc::*` will import the available +* For convenience, most functions and types are reexported from `std::libc`, +* so `pub use std::libc::*` will import the available * C bindings as appropriate for the target platform. The exact * set of functions available are platform specific. * @@ -1457,11 +1457,11 @@ pub mod funcs { // These are fine to execute on the Rust stack. They must be, // in fact, because LLVM generates calls to them! #[rust_stack] - #[inline(always)] + #[inline] unsafe fn memcmp(cx: *c_void, ct: *c_void, n: size_t) -> c_int; #[rust_stack] - #[inline(always)] + #[inline] unsafe fn memchr(cx: *c_void, c: c_int, n: size_t) -> *c_void; } } diff --git a/src/libstd/logging.rs b/src/libstd/logging.rs index c2f854179b8..743b71e33ea 100644 --- a/src/libstd/logging.rs +++ b/src/libstd/logging.rs @@ -11,13 +11,20 @@ //! Logging use option::*; +use os; use either::*; +use rt; +use rt::OldTaskContext; use rt::logging::{Logger, StdErrLogger}; /// Turns on logging to stdout globally pub fn console_on() { - unsafe { - rustrt::rust_log_console_on(); + if rt::context() == OldTaskContext { + unsafe { + rustrt::rust_log_console_on(); + } + } else { + rt::logging::console_on(); } } @@ -29,8 +36,17 @@ pub fn console_on() { * the RUST_LOG environment variable */ pub fn console_off() { - unsafe { - rustrt::rust_log_console_off(); + // If RUST_LOG is set then the console can't be turned off + if os::getenv("RUST_LOG").is_some() { + return; + } + + if rt::context() == OldTaskContext { + unsafe { + rustrt::rust_log_console_off(); + } + } else { + rt::logging::console_off(); } } diff --git a/src/libstd/managed.rs b/src/libstd/managed.rs index 7d0defea05a..d514612b5af 100644 --- a/src/libstd/managed.rs +++ b/src/libstd/managed.rs @@ -38,14 +38,14 @@ pub mod raw { } /// Determine if two shared boxes point to the same object -#[inline(always)] +#[inline] pub fn ptr_eq<T>(a: @T, b: @T) -> bool { let (a_ptr, b_ptr): (*T, *T) = (to_unsafe_ptr(&*a), to_unsafe_ptr(&*b)); a_ptr == b_ptr } /// Determine if two mutable shared boxes point to the same object -#[inline(always)] +#[inline] pub fn mut_ptr_eq<T>(a: @mut T, b: @mut T) -> bool { let (a_ptr, b_ptr): (*T, *T) = (to_unsafe_ptr(&*a), to_unsafe_ptr(&*b)); a_ptr == b_ptr @@ -53,41 +53,41 @@ pub fn mut_ptr_eq<T>(a: @mut T, b: @mut T) -> bool { #[cfg(not(test))] impl<T:Eq> Eq for @T { - #[inline(always)] + #[inline] fn eq(&self, other: &@T) -> bool { *(*self) == *(*other) } - #[inline(always)] + #[inline] fn ne(&self, other: &@T) -> bool { *(*self) != *(*other) } } #[cfg(not(test))] impl<T:Eq> Eq for @mut T { - #[inline(always)] + #[inline] fn eq(&self, other: &@mut T) -> bool { *(*self) == *(*other) } - #[inline(always)] + #[inline] fn ne(&self, other: &@mut T) -> bool { *(*self) != *(*other) } } #[cfg(not(test))] impl<T:Ord> Ord for @T { - #[inline(always)] + #[inline] fn lt(&self, other: &@T) -> bool { *(*self) < *(*other) } - #[inline(always)] + #[inline] fn le(&self, other: &@T) -> bool { *(*self) <= *(*other) } - #[inline(always)] + #[inline] fn ge(&self, other: &@T) -> bool { *(*self) >= *(*other) } - #[inline(always)] + #[inline] fn gt(&self, other: &@T) -> bool { *(*self) > *(*other) } } #[cfg(not(test))] impl<T:Ord> Ord for @mut T { - #[inline(always)] + #[inline] fn lt(&self, other: &@mut T) -> bool { *(*self) < *(*other) } - #[inline(always)] + #[inline] fn le(&self, other: &@mut T) -> bool { *(*self) <= *(*other) } - #[inline(always)] + #[inline] fn ge(&self, other: &@mut T) -> bool { *(*self) >= *(*other) } - #[inline(always)] + #[inline] fn gt(&self, other: &@mut T) -> bool { *(*self) > *(*other) } } diff --git a/src/libstd/nil.rs b/src/libstd/nil.rs index 833bd3459ce..40f6d53ed22 100644 --- a/src/libstd/nil.rs +++ b/src/libstd/nil.rs @@ -19,32 +19,32 @@ use prelude::*; #[cfg(not(test))] impl Eq for () { - #[inline(always)] + #[inline] fn eq(&self, _other: &()) -> bool { true } - #[inline(always)] + #[inline] fn ne(&self, _other: &()) -> bool { false } } #[cfg(not(test))] impl Ord for () { - #[inline(always)] + #[inline] fn lt(&self, _other: &()) -> bool { false } - #[inline(always)] + #[inline] fn le(&self, _other: &()) -> bool { true } - #[inline(always)] + #[inline] fn ge(&self, _other: &()) -> bool { true } - #[inline(always)] + #[inline] fn gt(&self, _other: &()) -> bool { false } } #[cfg(not(test))] impl TotalOrd for () { - #[inline(always)] + #[inline] fn cmp(&self, _other: &()) -> Ordering { Equal } } #[cfg(not(test))] impl TotalEq for () { - #[inline(always)] + #[inline] fn equals(&self, _other: &()) -> bool { true } } diff --git a/src/libstd/num/f32.rs b/src/libstd/num/f32.rs index 7f981187300..117a474ffd7 100644 --- a/src/libstd/num/f32.rs +++ b/src/libstd/num/f32.rs @@ -20,7 +20,7 @@ use to_str; pub use cmath::c_float_targ_consts::*; -// An inner module is required to get the #[inline(always)] attribute on the +// An inner module is required to get the #[inline] attribute on the // functions. pub use self::delegated::*; @@ -40,7 +40,7 @@ macro_rules! delegate( use unstable::intrinsics; $( - #[inline(always)] + #[inline] pub fn $name($( $arg : $arg_ty ),*) -> $rv { unsafe { $bound_name($( $arg ),*) @@ -115,45 +115,45 @@ pub static infinity: f32 = 1.0_f32/0.0_f32; pub static neg_infinity: f32 = -1.0_f32/0.0_f32; -#[inline(always)] +#[inline] pub fn add(x: f32, y: f32) -> f32 { return x + y; } -#[inline(always)] +#[inline] pub fn sub(x: f32, y: f32) -> f32 { return x - y; } -#[inline(always)] +#[inline] pub fn mul(x: f32, y: f32) -> f32 { return x * y; } -#[inline(always)] +#[inline] pub fn div(x: f32, y: f32) -> f32 { return x / y; } -#[inline(always)] +#[inline] pub fn rem(x: f32, y: f32) -> f32 { return x % y; } -#[inline(always)] +#[inline] pub fn lt(x: f32, y: f32) -> bool { return x < y; } -#[inline(always)] +#[inline] pub fn le(x: f32, y: f32) -> bool { return x <= y; } -#[inline(always)] +#[inline] pub fn eq(x: f32, y: f32) -> bool { return x == y; } -#[inline(always)] +#[inline] pub fn ne(x: f32, y: f32) -> bool { return x != y; } -#[inline(always)] +#[inline] pub fn ge(x: f32, y: f32) -> bool { return x >= y; } -#[inline(always)] +#[inline] pub fn gt(x: f32, y: f32) -> bool { return x > y; } -#[inline(always)] +#[inline] pub fn fmax(x: f32, y: f32) -> f32 { if x >= y || y.is_NaN() { x } else { y } } -#[inline(always)] +#[inline] pub fn fmin(x: f32, y: f32) -> f32 { if x <= y || y.is_NaN() { x } else { y } } @@ -212,23 +212,23 @@ impl Num for f32 {} #[cfg(not(test))] impl Eq for f32 { - #[inline(always)] + #[inline] fn eq(&self, other: &f32) -> bool { (*self) == (*other) } - #[inline(always)] + #[inline] fn ne(&self, other: &f32) -> bool { (*self) != (*other) } } #[cfg(not(test))] impl ApproxEq<f32> for f32 { - #[inline(always)] + #[inline] fn approx_epsilon() -> f32 { 1.0e-6 } - #[inline(always)] + #[inline] fn approx_eq(&self, other: &f32) -> bool { self.approx_eq_eps(other, &ApproxEq::approx_epsilon::<f32, f32>()) } - #[inline(always)] + #[inline] fn approx_eq_eps(&self, other: &f32, approx_epsilon: &f32) -> bool { (*self - *other).abs() < *approx_epsilon } @@ -236,32 +236,32 @@ impl ApproxEq<f32> for f32 { #[cfg(not(test))] impl Ord for f32 { - #[inline(always)] + #[inline] fn lt(&self, other: &f32) -> bool { (*self) < (*other) } - #[inline(always)] + #[inline] fn le(&self, other: &f32) -> bool { (*self) <= (*other) } - #[inline(always)] + #[inline] fn ge(&self, other: &f32) -> bool { (*self) >= (*other) } - #[inline(always)] + #[inline] fn gt(&self, other: &f32) -> bool { (*self) > (*other) } } impl Orderable for f32 { /// Returns `NaN` if either of the numbers are `NaN`. - #[inline(always)] + #[inline] fn min(&self, other: &f32) -> f32 { if self.is_NaN() || other.is_NaN() { Float::NaN() } else { fmin(*self, *other) } } /// Returns `NaN` if either of the numbers are `NaN`. - #[inline(always)] + #[inline] fn max(&self, other: &f32) -> f32 { if self.is_NaN() || other.is_NaN() { Float::NaN() } else { fmax(*self, *other) } } /// Returns the number constrained within the range `mn <= self <= mx`. /// If any of the numbers are `NaN` then `NaN` is returned. - #[inline(always)] + #[inline] fn clamp(&self, mn: &f32, mx: &f32) -> f32 { cond!( (self.is_NaN()) { *self } @@ -273,65 +273,65 @@ impl Orderable for f32 { } impl Zero for f32 { - #[inline(always)] + #[inline] fn zero() -> f32 { 0.0 } /// Returns true if the number is equal to either `0.0` or `-0.0` - #[inline(always)] + #[inline] fn is_zero(&self) -> bool { *self == 0.0 || *self == -0.0 } } impl One for f32 { - #[inline(always)] + #[inline] fn one() -> f32 { 1.0 } } #[cfg(not(test))] impl Add<f32,f32> for f32 { - #[inline(always)] + #[inline] fn add(&self, other: &f32) -> f32 { *self + *other } } #[cfg(not(test))] impl Sub<f32,f32> for f32 { - #[inline(always)] + #[inline] fn sub(&self, other: &f32) -> f32 { *self - *other } } #[cfg(not(test))] impl Mul<f32,f32> for f32 { - #[inline(always)] + #[inline] fn mul(&self, other: &f32) -> f32 { *self * *other } } #[cfg(not(test))] impl Div<f32,f32> for f32 { - #[inline(always)] + #[inline] fn div(&self, other: &f32) -> f32 { *self / *other } } #[cfg(not(test))] impl Rem<f32,f32> for f32 { - #[inline(always)] + #[inline] fn rem(&self, other: &f32) -> f32 { *self % *other } } #[cfg(not(test))] impl Neg<f32> for f32 { - #[inline(always)] + #[inline] fn neg(&self) -> f32 { -*self } } impl Signed for f32 { /// Computes the absolute value. Returns `NaN` if the number is `NaN`. - #[inline(always)] + #[inline] fn abs(&self) -> f32 { abs(*self) } /// /// The positive difference of two numbers. Returns `0.0` if the number is less than or /// equal to `other`, otherwise the difference between`self` and `other` is returned. /// - #[inline(always)] + #[inline] fn abs_sub(&self, other: &f32) -> f32 { abs_sub(*self, *other) } /// @@ -341,35 +341,35 @@ impl Signed for f32 { /// - `-1.0` if the number is negative, `-0.0` or `neg_infinity` /// - `NaN` if the number is NaN /// - #[inline(always)] + #[inline] fn signum(&self) -> f32 { if self.is_NaN() { NaN } else { copysign(1.0, *self) } } /// Returns `true` if the number is positive, including `+0.0` and `infinity` - #[inline(always)] + #[inline] fn is_positive(&self) -> bool { *self > 0.0 || (1.0 / *self) == infinity } /// Returns `true` if the number is negative, including `-0.0` and `neg_infinity` - #[inline(always)] + #[inline] fn is_negative(&self) -> bool { *self < 0.0 || (1.0 / *self) == neg_infinity } } impl Round for f32 { /// Round half-way cases toward `neg_infinity` - #[inline(always)] + #[inline] fn floor(&self) -> f32 { floor(*self) } /// Round half-way cases toward `infinity` - #[inline(always)] + #[inline] fn ceil(&self) -> f32 { ceil(*self) } /// Round half-way cases away from `0.0` - #[inline(always)] + #[inline] fn round(&self) -> f32 { round(*self) } /// The integer part of the number (rounds towards `0.0`) - #[inline(always)] + #[inline] fn trunc(&self) -> f32 { trunc(*self) } /// @@ -379,57 +379,57 @@ impl Round for f32 { /// assert!(x == trunc(x) + fract(x)) /// ~~~ /// - #[inline(always)] + #[inline] fn fract(&self) -> f32 { *self - self.trunc() } } impl Fractional for f32 { /// The reciprocal (multiplicative inverse) of the number - #[inline(always)] + #[inline] fn recip(&self) -> f32 { 1.0 / *self } } impl Algebraic for f32 { - #[inline(always)] + #[inline] fn pow(&self, n: &f32) -> f32 { pow(*self, *n) } - #[inline(always)] + #[inline] fn sqrt(&self) -> f32 { sqrt(*self) } - #[inline(always)] + #[inline] fn rsqrt(&self) -> f32 { self.sqrt().recip() } - #[inline(always)] + #[inline] fn cbrt(&self) -> f32 { cbrt(*self) } - #[inline(always)] + #[inline] fn hypot(&self, other: &f32) -> f32 { hypot(*self, *other) } } impl Trigonometric for f32 { - #[inline(always)] + #[inline] fn sin(&self) -> f32 { sin(*self) } - #[inline(always)] + #[inline] fn cos(&self) -> f32 { cos(*self) } - #[inline(always)] + #[inline] fn tan(&self) -> f32 { tan(*self) } - #[inline(always)] + #[inline] fn asin(&self) -> f32 { asin(*self) } - #[inline(always)] + #[inline] fn acos(&self) -> f32 { acos(*self) } - #[inline(always)] + #[inline] fn atan(&self) -> f32 { atan(*self) } - #[inline(always)] + #[inline] fn atan2(&self, other: &f32) -> f32 { atan2(*self, *other) } /// Simultaneously computes the sine and cosine of the number - #[inline(always)] + #[inline] fn sin_cos(&self) -> (f32, f32) { (self.sin(), self.cos()) } @@ -437,38 +437,38 @@ impl Trigonometric for f32 { impl Exponential for f32 { /// Returns the exponential of the number - #[inline(always)] + #[inline] fn exp(&self) -> f32 { exp(*self) } /// Returns 2 raised to the power of the number - #[inline(always)] + #[inline] fn exp2(&self) -> f32 { exp2(*self) } /// Returns the natural logarithm of the number - #[inline(always)] + #[inline] fn ln(&self) -> f32 { ln(*self) } /// Returns the logarithm of the number with respect to an arbitrary base - #[inline(always)] + #[inline] fn log(&self, base: &f32) -> f32 { self.ln() / base.ln() } /// Returns the base 2 logarithm of the number - #[inline(always)] + #[inline] fn log2(&self) -> f32 { log2(*self) } /// Returns the base 10 logarithm of the number - #[inline(always)] + #[inline] fn log10(&self) -> f32 { log10(*self) } } impl Hyperbolic for f32 { - #[inline(always)] + #[inline] fn sinh(&self) -> f32 { sinh(*self) } - #[inline(always)] + #[inline] fn cosh(&self) -> f32 { cosh(*self) } - #[inline(always)] + #[inline] fn tanh(&self) -> f32 { tanh(*self) } /// @@ -480,7 +480,7 @@ impl Hyperbolic for f32 { /// - `self` if `self` is `0.0`, `-0.0`, `infinity`, or `neg_infinity` /// - `NaN` if `self` is `NaN` /// - #[inline(always)] + #[inline] fn asinh(&self) -> f32 { match *self { neg_infinity => neg_infinity, @@ -497,7 +497,7 @@ impl Hyperbolic for f32 { /// - `infinity` if `self` is `infinity` /// - `NaN` if `self` is `NaN` or `self < 1.0` (including `neg_infinity`) /// - #[inline(always)] + #[inline] fn acosh(&self) -> f32 { match *self { x if x < 1.0 => Float::NaN(), @@ -517,7 +517,7 @@ impl Hyperbolic for f32 { /// - `NaN` if the `self` is `NaN` or outside the domain of `-1.0 <= self <= 1.0` /// (including `infinity` and `neg_infinity`) /// - #[inline(always)] + #[inline] fn atanh(&self) -> f32 { 0.5 * ((2.0 * *self) / (1.0 - *self)).ln_1p() } @@ -525,129 +525,129 @@ impl Hyperbolic for f32 { impl Real for f32 { /// Archimedes' constant - #[inline(always)] + #[inline] fn pi() -> f32 { 3.14159265358979323846264338327950288 } /// 2.0 * pi - #[inline(always)] + #[inline] fn two_pi() -> f32 { 6.28318530717958647692528676655900576 } /// pi / 2.0 - #[inline(always)] + #[inline] fn frac_pi_2() -> f32 { 1.57079632679489661923132169163975144 } /// pi / 3.0 - #[inline(always)] + #[inline] fn frac_pi_3() -> f32 { 1.04719755119659774615421446109316763 } /// pi / 4.0 - #[inline(always)] + #[inline] fn frac_pi_4() -> f32 { 0.785398163397448309615660845819875721 } /// pi / 6.0 - #[inline(always)] + #[inline] fn frac_pi_6() -> f32 { 0.52359877559829887307710723054658381 } /// pi / 8.0 - #[inline(always)] + #[inline] fn frac_pi_8() -> f32 { 0.39269908169872415480783042290993786 } /// 1 .0/ pi - #[inline(always)] + #[inline] fn frac_1_pi() -> f32 { 0.318309886183790671537767526745028724 } /// 2.0 / pi - #[inline(always)] + #[inline] fn frac_2_pi() -> f32 { 0.636619772367581343075535053490057448 } /// 2.0 / sqrt(pi) - #[inline(always)] + #[inline] fn frac_2_sqrtpi() -> f32 { 1.12837916709551257389615890312154517 } /// sqrt(2.0) - #[inline(always)] + #[inline] fn sqrt2() -> f32 { 1.41421356237309504880168872420969808 } /// 1.0 / sqrt(2.0) - #[inline(always)] + #[inline] fn frac_1_sqrt2() -> f32 { 0.707106781186547524400844362104849039 } /// Euler's number - #[inline(always)] + #[inline] fn e() -> f32 { 2.71828182845904523536028747135266250 } /// log2(e) - #[inline(always)] + #[inline] fn log2_e() -> f32 { 1.44269504088896340735992468100189214 } /// log10(e) - #[inline(always)] + #[inline] fn log10_e() -> f32 { 0.434294481903251827651128918916605082 } /// ln(2.0) - #[inline(always)] + #[inline] fn ln_2() -> f32 { 0.693147180559945309417232121458176568 } /// ln(10.0) - #[inline(always)] + #[inline] fn ln_10() -> f32 { 2.30258509299404568401799145468436421 } /// Converts to degrees, assuming the number is in radians - #[inline(always)] + #[inline] fn to_degrees(&self) -> f32 { *self * (180.0 / Real::pi::<f32>()) } /// Converts to radians, assuming the number is in degrees - #[inline(always)] + #[inline] fn to_radians(&self) -> f32 { *self * (Real::pi::<f32>() / 180.0) } } impl Bounded for f32 { - #[inline(always)] + #[inline] fn min_value() -> f32 { 1.17549435e-38 } - #[inline(always)] + #[inline] fn max_value() -> f32 { 3.40282347e+38 } } impl Primitive for f32 { - #[inline(always)] + #[inline] fn bits() -> uint { 32 } - #[inline(always)] + #[inline] fn bytes() -> uint { Primitive::bits::<f32>() / 8 } } impl Float for f32 { - #[inline(always)] + #[inline] fn NaN() -> f32 { 0.0 / 0.0 } - #[inline(always)] + #[inline] fn infinity() -> f32 { 1.0 / 0.0 } - #[inline(always)] + #[inline] fn neg_infinity() -> f32 { -1.0 / 0.0 } - #[inline(always)] + #[inline] fn neg_zero() -> f32 { -0.0 } /// Returns `true` if the number is NaN - #[inline(always)] + #[inline] fn is_NaN(&self) -> bool { *self != *self } /// Returns `true` if the number is infinite - #[inline(always)] + #[inline] fn is_infinite(&self) -> bool { *self == Float::infinity() || *self == Float::neg_infinity() } /// Returns `true` if the number is neither infinite or NaN - #[inline(always)] + #[inline] fn is_finite(&self) -> bool { !(self.is_NaN() || self.is_infinite()) } /// Returns `true` if the number is neither zero, infinite, subnormal or NaN - #[inline(always)] + #[inline] fn is_normal(&self) -> bool { self.classify() == FPNormal } @@ -670,29 +670,29 @@ impl Float for f32 { } } - #[inline(always)] + #[inline] fn mantissa_digits() -> uint { 24 } - #[inline(always)] + #[inline] fn digits() -> uint { 6 } - #[inline(always)] + #[inline] fn epsilon() -> f32 { 1.19209290e-07 } - #[inline(always)] + #[inline] fn min_exp() -> int { -125 } - #[inline(always)] + #[inline] fn max_exp() -> int { 128 } - #[inline(always)] + #[inline] fn min_10_exp() -> int { -37 } - #[inline(always)] + #[inline] fn max_10_exp() -> int { 38 } /// Constructs a floating point number by multiplying `x` by 2 raised to the power of `exp` - #[inline(always)] + #[inline] fn ldexp(x: f32, exp: int) -> f32 { ldexp(x, exp as c_int) } @@ -703,7 +703,7 @@ impl Float for f32 { /// - `self = x * pow(2, exp)` /// - `0.5 <= abs(x) < 1.0` /// - #[inline(always)] + #[inline] fn frexp(&self) -> (f32, int) { let mut exp = 0; let x = frexp(*self, &mut exp); @@ -714,14 +714,14 @@ impl Float for f32 { /// Returns the exponential of the number, minus `1`, in a way that is accurate /// even if the number is close to zero /// - #[inline(always)] + #[inline] fn exp_m1(&self) -> f32 { exp_m1(*self) } /// /// Returns the natural logarithm of the number plus `1` (`ln(1+n)`) more accurately /// than if the operations were performed separately /// - #[inline(always)] + #[inline] fn ln_1p(&self) -> f32 { ln_1p(*self) } /// @@ -729,13 +729,13 @@ impl Float for f32 { /// produces a more accurate result with better performance than a separate multiplication /// operation followed by an add. /// - #[inline(always)] + #[inline] fn mul_add(&self, a: f32, b: f32) -> f32 { mul_add(*self, a, b) } /// Returns the next representable floating-point value in the direction of `other` - #[inline(always)] + #[inline] fn next_after(&self, other: f32) -> f32 { next_after(*self, other) } @@ -752,7 +752,7 @@ impl Float for f32 { /// /// * num - The float value /// -#[inline(always)] +#[inline] pub fn to_str(num: f32) -> ~str { let (r, _) = strconv::to_str_common( &num, 10u, true, strconv::SignNeg, strconv::DigAll); @@ -766,7 +766,7 @@ pub fn to_str(num: f32) -> ~str { /// /// * num - The float value /// -#[inline(always)] +#[inline] pub fn to_str_hex(num: f32) -> ~str { let (r, _) = strconv::to_str_common( &num, 16u, true, strconv::SignNeg, strconv::DigAll); @@ -787,7 +787,7 @@ pub fn to_str_hex(num: f32) -> ~str { /// possible misinterpretation of the result at higher bases. If those values /// are expected, use `to_str_radix_special()` instead. /// -#[inline(always)] +#[inline] pub fn to_str_radix(num: f32, rdx: uint) -> ~str { let (r, special) = strconv::to_str_common( &num, rdx, true, strconv::SignNeg, strconv::DigAll); @@ -805,7 +805,7 @@ pub fn to_str_radix(num: f32, rdx: uint) -> ~str { /// * num - The float value /// * radix - The base to use /// -#[inline(always)] +#[inline] pub fn to_str_radix_special(num: f32, rdx: uint) -> (~str, bool) { strconv::to_str_common(&num, rdx, true, strconv::SignNeg, strconv::DigAll) @@ -820,7 +820,7 @@ pub fn to_str_radix_special(num: f32, rdx: uint) -> (~str, bool) { /// * num - The float value /// * digits - The number of significant digits /// -#[inline(always)] +#[inline] pub fn to_str_exact(num: f32, dig: uint) -> ~str { let (r, _) = strconv::to_str_common( &num, 10u, true, strconv::SignNeg, strconv::DigExact(dig)); @@ -836,7 +836,7 @@ pub fn to_str_exact(num: f32, dig: uint) -> ~str { /// * num - The float value /// * digits - The number of significant digits /// -#[inline(always)] +#[inline] pub fn to_str_digits(num: f32, dig: uint) -> ~str { let (r, _) = strconv::to_str_common( &num, 10u, true, strconv::SignNeg, strconv::DigMax(dig)); @@ -844,12 +844,12 @@ pub fn to_str_digits(num: f32, dig: uint) -> ~str { } impl to_str::ToStr for f32 { - #[inline(always)] + #[inline] fn to_str(&self) -> ~str { to_str_digits(*self, 8) } } impl num::ToStrRadix for f32 { - #[inline(always)] + #[inline] fn to_str_radix(&self, rdx: uint) -> ~str { to_str_radix(*self, rdx) } @@ -882,7 +882,7 @@ impl num::ToStrRadix for f32 { /// `none` if the string did not represent a valid number. Otherwise, /// `Some(n)` where `n` is the floating-point number represented by `num`. /// -#[inline(always)] +#[inline] pub fn from_str(num: &str) -> Option<f32> { strconv::from_str_common(num, 10u, true, true, true, strconv::ExpDec, false, false) @@ -915,7 +915,7 @@ pub fn from_str(num: &str) -> Option<f32> { /// `none` if the string did not represent a valid number. Otherwise, /// `Some(n)` where `n` is the floating-point number represented by `[num]`. /// -#[inline(always)] +#[inline] pub fn from_str_hex(num: &str) -> Option<f32> { strconv::from_str_common(num, 16u, true, true, true, strconv::ExpBin, false, false) @@ -940,19 +940,19 @@ pub fn from_str_hex(num: &str) -> Option<f32> { /// `none` if the string did not represent a valid number. Otherwise, /// `Some(n)` where `n` is the floating-point number represented by `num`. /// -#[inline(always)] +#[inline] pub fn from_str_radix(num: &str, rdx: uint) -> Option<f32> { strconv::from_str_common(num, rdx, true, true, false, strconv::ExpNone, false, false) } impl FromStr for f32 { - #[inline(always)] + #[inline] fn from_str(val: &str) -> Option<f32> { from_str(val) } } impl num::FromStrRadix for f32 { - #[inline(always)] + #[inline] fn from_str_radix(val: &str, rdx: uint) -> Option<f32> { from_str_radix(val, rdx) } diff --git a/src/libstd/num/f64.rs b/src/libstd/num/f64.rs index 6303e304576..e13dff1e623 100644 --- a/src/libstd/num/f64.rs +++ b/src/libstd/num/f64.rs @@ -22,7 +22,7 @@ use to_str; pub use cmath::c_double_targ_consts::*; pub use cmp::{min, max}; -// An inner module is required to get the #[inline(always)] attribute on the +// An inner module is required to get the #[inline] attribute on the // functions. pub use self::delegated::*; @@ -42,7 +42,7 @@ macro_rules! delegate( use unstable::intrinsics; $( - #[inline(always)] + #[inline] pub fn $name($( $arg : $arg_ty ),*) -> $rv { unsafe { $bound_name($( $arg ),*) @@ -141,45 +141,45 @@ pub static infinity: f64 = 1.0_f64/0.0_f64; pub static neg_infinity: f64 = -1.0_f64/0.0_f64; -#[inline(always)] +#[inline] pub fn add(x: f64, y: f64) -> f64 { return x + y; } -#[inline(always)] +#[inline] pub fn sub(x: f64, y: f64) -> f64 { return x - y; } -#[inline(always)] +#[inline] pub fn mul(x: f64, y: f64) -> f64 { return x * y; } -#[inline(always)] +#[inline] pub fn div(x: f64, y: f64) -> f64 { return x / y; } -#[inline(always)] +#[inline] pub fn rem(x: f64, y: f64) -> f64 { return x % y; } -#[inline(always)] +#[inline] pub fn lt(x: f64, y: f64) -> bool { return x < y; } -#[inline(always)] +#[inline] pub fn le(x: f64, y: f64) -> bool { return x <= y; } -#[inline(always)] +#[inline] pub fn eq(x: f64, y: f64) -> bool { return x == y; } -#[inline(always)] +#[inline] pub fn ne(x: f64, y: f64) -> bool { return x != y; } -#[inline(always)] +#[inline] pub fn ge(x: f64, y: f64) -> bool { return x >= y; } -#[inline(always)] +#[inline] pub fn gt(x: f64, y: f64) -> bool { return x > y; } -#[inline(always)] +#[inline] pub fn fmax(x: f64, y: f64) -> f64 { if x >= y || y.is_NaN() { x } else { y } } -#[inline(always)] +#[inline] pub fn fmin(x: f64, y: f64) -> f64 { if x <= y || y.is_NaN() { x } else { y } } @@ -234,23 +234,23 @@ impl Num for f64 {} #[cfg(not(test))] impl Eq for f64 { - #[inline(always)] + #[inline] fn eq(&self, other: &f64) -> bool { (*self) == (*other) } - #[inline(always)] + #[inline] fn ne(&self, other: &f64) -> bool { (*self) != (*other) } } #[cfg(not(test))] impl ApproxEq<f64> for f64 { - #[inline(always)] + #[inline] fn approx_epsilon() -> f64 { 1.0e-6 } - #[inline(always)] + #[inline] fn approx_eq(&self, other: &f64) -> bool { self.approx_eq_eps(other, &ApproxEq::approx_epsilon::<f64, f64>()) } - #[inline(always)] + #[inline] fn approx_eq_eps(&self, other: &f64, approx_epsilon: &f64) -> bool { (*self - *other).abs() < *approx_epsilon } @@ -258,32 +258,32 @@ impl ApproxEq<f64> for f64 { #[cfg(not(test))] impl Ord for f64 { - #[inline(always)] + #[inline] fn lt(&self, other: &f64) -> bool { (*self) < (*other) } - #[inline(always)] + #[inline] fn le(&self, other: &f64) -> bool { (*self) <= (*other) } - #[inline(always)] + #[inline] fn ge(&self, other: &f64) -> bool { (*self) >= (*other) } - #[inline(always)] + #[inline] fn gt(&self, other: &f64) -> bool { (*self) > (*other) } } impl Orderable for f64 { /// Returns `NaN` if either of the numbers are `NaN`. - #[inline(always)] + #[inline] fn min(&self, other: &f64) -> f64 { if self.is_NaN() || other.is_NaN() { Float::NaN() } else { fmin(*self, *other) } } /// Returns `NaN` if either of the numbers are `NaN`. - #[inline(always)] + #[inline] fn max(&self, other: &f64) -> f64 { if self.is_NaN() || other.is_NaN() { Float::NaN() } else { fmax(*self, *other) } } /// Returns the number constrained within the range `mn <= self <= mx`. /// If any of the numbers are `NaN` then `NaN` is returned. - #[inline(always)] + #[inline] fn clamp(&self, mn: &f64, mx: &f64) -> f64 { cond!( (self.is_NaN()) { *self } @@ -295,16 +295,16 @@ impl Orderable for f64 { } impl Zero for f64 { - #[inline(always)] + #[inline] fn zero() -> f64 { 0.0 } /// Returns true if the number is equal to either `0.0` or `-0.0` - #[inline(always)] + #[inline] fn is_zero(&self) -> bool { *self == 0.0 || *self == -0.0 } } impl One for f64 { - #[inline(always)] + #[inline] fn one() -> f64 { 1.0 } } @@ -326,7 +326,7 @@ impl Div<f64,f64> for f64 { } #[cfg(not(test))] impl Rem<f64,f64> for f64 { - #[inline(always)] + #[inline] fn rem(&self, other: &f64) -> f64 { *self % *other } } #[cfg(not(test))] @@ -336,14 +336,14 @@ impl Neg<f64> for f64 { impl Signed for f64 { /// Computes the absolute value. Returns `NaN` if the number is `NaN`. - #[inline(always)] + #[inline] fn abs(&self) -> f64 { abs(*self) } /// /// The positive difference of two numbers. Returns `0.0` if the number is less than or /// equal to `other`, otherwise the difference between`self` and `other` is returned. /// - #[inline(always)] + #[inline] fn abs_sub(&self, other: &f64) -> f64 { abs_sub(*self, *other) } /// @@ -353,35 +353,35 @@ impl Signed for f64 { /// - `-1.0` if the number is negative, `-0.0` or `neg_infinity` /// - `NaN` if the number is NaN /// - #[inline(always)] + #[inline] fn signum(&self) -> f64 { if self.is_NaN() { NaN } else { copysign(1.0, *self) } } /// Returns `true` if the number is positive, including `+0.0` and `infinity` - #[inline(always)] + #[inline] fn is_positive(&self) -> bool { *self > 0.0 || (1.0 / *self) == infinity } /// Returns `true` if the number is negative, including `-0.0` and `neg_infinity` - #[inline(always)] + #[inline] fn is_negative(&self) -> bool { *self < 0.0 || (1.0 / *self) == neg_infinity } } impl Round for f64 { /// Round half-way cases toward `neg_infinity` - #[inline(always)] + #[inline] fn floor(&self) -> f64 { floor(*self) } /// Round half-way cases toward `infinity` - #[inline(always)] + #[inline] fn ceil(&self) -> f64 { ceil(*self) } /// Round half-way cases away from `0.0` - #[inline(always)] + #[inline] fn round(&self) -> f64 { round(*self) } /// The integer part of the number (rounds towards `0.0`) - #[inline(always)] + #[inline] fn trunc(&self) -> f64 { trunc(*self) } /// @@ -391,57 +391,57 @@ impl Round for f64 { /// assert!(x == trunc(x) + fract(x)) /// ~~~ /// - #[inline(always)] + #[inline] fn fract(&self) -> f64 { *self - self.trunc() } } impl Fractional for f64 { /// The reciprocal (multiplicative inverse) of the number - #[inline(always)] + #[inline] fn recip(&self) -> f64 { 1.0 / *self } } impl Algebraic for f64 { - #[inline(always)] + #[inline] fn pow(&self, n: &f64) -> f64 { pow(*self, *n) } - #[inline(always)] + #[inline] fn sqrt(&self) -> f64 { sqrt(*self) } - #[inline(always)] + #[inline] fn rsqrt(&self) -> f64 { self.sqrt().recip() } - #[inline(always)] + #[inline] fn cbrt(&self) -> f64 { cbrt(*self) } - #[inline(always)] + #[inline] fn hypot(&self, other: &f64) -> f64 { hypot(*self, *other) } } impl Trigonometric for f64 { - #[inline(always)] + #[inline] fn sin(&self) -> f64 { sin(*self) } - #[inline(always)] + #[inline] fn cos(&self) -> f64 { cos(*self) } - #[inline(always)] + #[inline] fn tan(&self) -> f64 { tan(*self) } - #[inline(always)] + #[inline] fn asin(&self) -> f64 { asin(*self) } - #[inline(always)] + #[inline] fn acos(&self) -> f64 { acos(*self) } - #[inline(always)] + #[inline] fn atan(&self) -> f64 { atan(*self) } - #[inline(always)] + #[inline] fn atan2(&self, other: &f64) -> f64 { atan2(*self, *other) } /// Simultaneously computes the sine and cosine of the number - #[inline(always)] + #[inline] fn sin_cos(&self) -> (f64, f64) { (self.sin(), self.cos()) } @@ -449,38 +449,38 @@ impl Trigonometric for f64 { impl Exponential for f64 { /// Returns the exponential of the number - #[inline(always)] + #[inline] fn exp(&self) -> f64 { exp(*self) } /// Returns 2 raised to the power of the number - #[inline(always)] + #[inline] fn exp2(&self) -> f64 { exp2(*self) } /// Returns the natural logarithm of the number - #[inline(always)] + #[inline] fn ln(&self) -> f64 { ln(*self) } /// Returns the logarithm of the number with respect to an arbitrary base - #[inline(always)] + #[inline] fn log(&self, base: &f64) -> f64 { self.ln() / base.ln() } /// Returns the base 2 logarithm of the number - #[inline(always)] + #[inline] fn log2(&self) -> f64 { log2(*self) } /// Returns the base 10 logarithm of the number - #[inline(always)] + #[inline] fn log10(&self) -> f64 { log10(*self) } } impl Hyperbolic for f64 { - #[inline(always)] + #[inline] fn sinh(&self) -> f64 { sinh(*self) } - #[inline(always)] + #[inline] fn cosh(&self) -> f64 { cosh(*self) } - #[inline(always)] + #[inline] fn tanh(&self) -> f64 { tanh(*self) } /// @@ -492,7 +492,7 @@ impl Hyperbolic for f64 { /// - `self` if `self` is `0.0`, `-0.0`, `infinity`, or `neg_infinity` /// - `NaN` if `self` is `NaN` /// - #[inline(always)] + #[inline] fn asinh(&self) -> f64 { match *self { neg_infinity => neg_infinity, @@ -509,7 +509,7 @@ impl Hyperbolic for f64 { /// - `infinity` if `self` is `infinity` /// - `NaN` if `self` is `NaN` or `self < 1.0` (including `neg_infinity`) /// - #[inline(always)] + #[inline] fn acosh(&self) -> f64 { match *self { x if x < 1.0 => Float::NaN(), @@ -529,7 +529,7 @@ impl Hyperbolic for f64 { /// - `NaN` if the `self` is `NaN` or outside the domain of `-1.0 <= self <= 1.0` /// (including `infinity` and `neg_infinity`) /// - #[inline(always)] + #[inline] fn atanh(&self) -> f64 { 0.5 * ((2.0 * *self) / (1.0 - *self)).ln_1p() } @@ -537,159 +537,159 @@ impl Hyperbolic for f64 { impl Real for f64 { /// Archimedes' constant - #[inline(always)] + #[inline] fn pi() -> f64 { 3.14159265358979323846264338327950288 } /// 2.0 * pi - #[inline(always)] + #[inline] fn two_pi() -> f64 { 6.28318530717958647692528676655900576 } /// pi / 2.0 - #[inline(always)] + #[inline] fn frac_pi_2() -> f64 { 1.57079632679489661923132169163975144 } /// pi / 3.0 - #[inline(always)] + #[inline] fn frac_pi_3() -> f64 { 1.04719755119659774615421446109316763 } /// pi / 4.0 - #[inline(always)] + #[inline] fn frac_pi_4() -> f64 { 0.785398163397448309615660845819875721 } /// pi / 6.0 - #[inline(always)] + #[inline] fn frac_pi_6() -> f64 { 0.52359877559829887307710723054658381 } /// pi / 8.0 - #[inline(always)] + #[inline] fn frac_pi_8() -> f64 { 0.39269908169872415480783042290993786 } /// 1.0 / pi - #[inline(always)] + #[inline] fn frac_1_pi() -> f64 { 0.318309886183790671537767526745028724 } /// 2.0 / pi - #[inline(always)] + #[inline] fn frac_2_pi() -> f64 { 0.636619772367581343075535053490057448 } /// 2.0 / sqrt(pi) - #[inline(always)] + #[inline] fn frac_2_sqrtpi() -> f64 { 1.12837916709551257389615890312154517 } /// sqrt(2.0) - #[inline(always)] + #[inline] fn sqrt2() -> f64 { 1.41421356237309504880168872420969808 } /// 1.0 / sqrt(2.0) - #[inline(always)] + #[inline] fn frac_1_sqrt2() -> f64 { 0.707106781186547524400844362104849039 } /// Euler's number - #[inline(always)] + #[inline] fn e() -> f64 { 2.71828182845904523536028747135266250 } /// log2(e) - #[inline(always)] + #[inline] fn log2_e() -> f64 { 1.44269504088896340735992468100189214 } /// log10(e) - #[inline(always)] + #[inline] fn log10_e() -> f64 { 0.434294481903251827651128918916605082 } /// ln(2.0) - #[inline(always)] + #[inline] fn ln_2() -> f64 { 0.693147180559945309417232121458176568 } /// ln(10.0) - #[inline(always)] + #[inline] fn ln_10() -> f64 { 2.30258509299404568401799145468436421 } /// Converts to degrees, assuming the number is in radians - #[inline(always)] + #[inline] fn to_degrees(&self) -> f64 { *self * (180.0 / Real::pi::<f64>()) } /// Converts to radians, assuming the number is in degrees - #[inline(always)] + #[inline] fn to_radians(&self) -> f64 { *self * (Real::pi::<f64>() / 180.0) } } impl RealExt for f64 { - #[inline(always)] + #[inline] fn lgamma(&self) -> (int, f64) { let mut sign = 0; let result = lgamma(*self, &mut sign); (sign as int, result) } - #[inline(always)] + #[inline] fn tgamma(&self) -> f64 { tgamma(*self) } - #[inline(always)] + #[inline] fn j0(&self) -> f64 { j0(*self) } - #[inline(always)] + #[inline] fn j1(&self) -> f64 { j1(*self) } - #[inline(always)] + #[inline] fn jn(&self, n: int) -> f64 { jn(n as c_int, *self) } - #[inline(always)] + #[inline] fn y0(&self) -> f64 { y0(*self) } - #[inline(always)] + #[inline] fn y1(&self) -> f64 { y1(*self) } - #[inline(always)] + #[inline] fn yn(&self, n: int) -> f64 { yn(n as c_int, *self) } } impl Bounded for f64 { - #[inline(always)] + #[inline] fn min_value() -> f64 { 2.2250738585072014e-308 } - #[inline(always)] + #[inline] fn max_value() -> f64 { 1.7976931348623157e+308 } } impl Primitive for f64 { - #[inline(always)] + #[inline] fn bits() -> uint { 64 } - #[inline(always)] + #[inline] fn bytes() -> uint { Primitive::bits::<f64>() / 8 } } impl Float for f64 { - #[inline(always)] + #[inline] fn NaN() -> f64 { 0.0 / 0.0 } - #[inline(always)] + #[inline] fn infinity() -> f64 { 1.0 / 0.0 } - #[inline(always)] + #[inline] fn neg_infinity() -> f64 { -1.0 / 0.0 } - #[inline(always)] + #[inline] fn neg_zero() -> f64 { -0.0 } /// Returns `true` if the number is NaN - #[inline(always)] + #[inline] fn is_NaN(&self) -> bool { *self != *self } /// Returns `true` if the number is infinite - #[inline(always)] + #[inline] fn is_infinite(&self) -> bool { *self == Float::infinity() || *self == Float::neg_infinity() } /// Returns `true` if the number is neither infinite or NaN - #[inline(always)] + #[inline] fn is_finite(&self) -> bool { !(self.is_NaN() || self.is_infinite()) } /// Returns `true` if the number is neither zero, infinite, subnormal or NaN - #[inline(always)] + #[inline] fn is_normal(&self) -> bool { self.classify() == FPNormal } @@ -712,29 +712,29 @@ impl Float for f64 { } } - #[inline(always)] + #[inline] fn mantissa_digits() -> uint { 53 } - #[inline(always)] + #[inline] fn digits() -> uint { 15 } - #[inline(always)] + #[inline] fn epsilon() -> f64 { 2.2204460492503131e-16 } - #[inline(always)] + #[inline] fn min_exp() -> int { -1021 } - #[inline(always)] + #[inline] fn max_exp() -> int { 1024 } - #[inline(always)] + #[inline] fn min_10_exp() -> int { -307 } - #[inline(always)] + #[inline] fn max_10_exp() -> int { 308 } /// Constructs a floating point number by multiplying `x` by 2 raised to the power of `exp` - #[inline(always)] + #[inline] fn ldexp(x: f64, exp: int) -> f64 { ldexp(x, exp as c_int) } @@ -745,7 +745,7 @@ impl Float for f64 { /// - `self = x * pow(2, exp)` /// - `0.5 <= abs(x) < 1.0` /// - #[inline(always)] + #[inline] fn frexp(&self) -> (f64, int) { let mut exp = 0; let x = frexp(*self, &mut exp); @@ -756,14 +756,14 @@ impl Float for f64 { /// Returns the exponential of the number, minus `1`, in a way that is accurate /// even if the number is close to zero /// - #[inline(always)] + #[inline] fn exp_m1(&self) -> f64 { exp_m1(*self) } /// /// Returns the natural logarithm of the number plus `1` (`ln(1+n)`) more accurately /// than if the operations were performed separately /// - #[inline(always)] + #[inline] fn ln_1p(&self) -> f64 { ln_1p(*self) } /// @@ -771,13 +771,13 @@ impl Float for f64 { /// produces a more accurate result with better performance than a separate multiplication /// operation followed by an add. /// - #[inline(always)] + #[inline] fn mul_add(&self, a: f64, b: f64) -> f64 { mul_add(*self, a, b) } /// Returns the next representable floating-point value in the direction of `other` - #[inline(always)] + #[inline] fn next_after(&self, other: f64) -> f64 { next_after(*self, other) } @@ -794,7 +794,7 @@ impl Float for f64 { /// /// * num - The float value /// -#[inline(always)] +#[inline] pub fn to_str(num: f64) -> ~str { let (r, _) = strconv::to_str_common( &num, 10u, true, strconv::SignNeg, strconv::DigAll); @@ -808,7 +808,7 @@ pub fn to_str(num: f64) -> ~str { /// /// * num - The float value /// -#[inline(always)] +#[inline] pub fn to_str_hex(num: f64) -> ~str { let (r, _) = strconv::to_str_common( &num, 16u, true, strconv::SignNeg, strconv::DigAll); @@ -829,7 +829,7 @@ pub fn to_str_hex(num: f64) -> ~str { /// possible misinterpretation of the result at higher bases. If those values /// are expected, use `to_str_radix_special()` instead. /// -#[inline(always)] +#[inline] pub fn to_str_radix(num: f64, rdx: uint) -> ~str { let (r, special) = strconv::to_str_common( &num, rdx, true, strconv::SignNeg, strconv::DigAll); @@ -847,7 +847,7 @@ pub fn to_str_radix(num: f64, rdx: uint) -> ~str { /// * num - The float value /// * radix - The base to use /// -#[inline(always)] +#[inline] pub fn to_str_radix_special(num: f64, rdx: uint) -> (~str, bool) { strconv::to_str_common(&num, rdx, true, strconv::SignNeg, strconv::DigAll) @@ -862,7 +862,7 @@ pub fn to_str_radix_special(num: f64, rdx: uint) -> (~str, bool) { /// * num - The float value /// * digits - The number of significant digits /// -#[inline(always)] +#[inline] pub fn to_str_exact(num: f64, dig: uint) -> ~str { let (r, _) = strconv::to_str_common( &num, 10u, true, strconv::SignNeg, strconv::DigExact(dig)); @@ -878,7 +878,7 @@ pub fn to_str_exact(num: f64, dig: uint) -> ~str { /// * num - The float value /// * digits - The number of significant digits /// -#[inline(always)] +#[inline] pub fn to_str_digits(num: f64, dig: uint) -> ~str { let (r, _) = strconv::to_str_common( &num, 10u, true, strconv::SignNeg, strconv::DigMax(dig)); @@ -886,12 +886,12 @@ pub fn to_str_digits(num: f64, dig: uint) -> ~str { } impl to_str::ToStr for f64 { - #[inline(always)] + #[inline] fn to_str(&self) -> ~str { to_str_digits(*self, 8) } } impl num::ToStrRadix for f64 { - #[inline(always)] + #[inline] fn to_str_radix(&self, rdx: uint) -> ~str { to_str_radix(*self, rdx) } @@ -924,7 +924,7 @@ impl num::ToStrRadix for f64 { /// `none` if the string did not represent a valid number. Otherwise, /// `Some(n)` where `n` is the floating-point number represented by `num`. /// -#[inline(always)] +#[inline] pub fn from_str(num: &str) -> Option<f64> { strconv::from_str_common(num, 10u, true, true, true, strconv::ExpDec, false, false) @@ -957,7 +957,7 @@ pub fn from_str(num: &str) -> Option<f64> { /// `none` if the string did not represent a valid number. Otherwise, /// `Some(n)` where `n` is the floating-point number represented by `[num]`. /// -#[inline(always)] +#[inline] pub fn from_str_hex(num: &str) -> Option<f64> { strconv::from_str_common(num, 16u, true, true, true, strconv::ExpBin, false, false) @@ -982,19 +982,19 @@ pub fn from_str_hex(num: &str) -> Option<f64> { /// `none` if the string did not represent a valid number. Otherwise, /// `Some(n)` where `n` is the floating-point number represented by `num`. /// -#[inline(always)] +#[inline] pub fn from_str_radix(num: &str, rdx: uint) -> Option<f64> { strconv::from_str_common(num, rdx, true, true, false, strconv::ExpNone, false, false) } impl FromStr for f64 { - #[inline(always)] + #[inline] fn from_str(val: &str) -> Option<f64> { from_str(val) } } impl num::FromStrRadix for f64 { - #[inline(always)] + #[inline] fn from_str_radix(val: &str, rdx: uint) -> Option<f64> { from_str_radix(val, rdx) } diff --git a/src/libstd/num/float.rs b/src/libstd/num/float.rs index 267a8890e82..c583aeacf16 100644 --- a/src/libstd/num/float.rs +++ b/src/libstd/num/float.rs @@ -99,7 +99,7 @@ pub mod consts { /// /// * num - The float value /// -#[inline(always)] +#[inline] pub fn to_str(num: float) -> ~str { let (r, _) = strconv::to_str_common( &num, 10u, true, strconv::SignNeg, strconv::DigAll); @@ -113,7 +113,7 @@ pub fn to_str(num: float) -> ~str { /// /// * num - The float value /// -#[inline(always)] +#[inline] pub fn to_str_hex(num: float) -> ~str { let (r, _) = strconv::to_str_common( &num, 16u, true, strconv::SignNeg, strconv::DigAll); @@ -134,7 +134,7 @@ pub fn to_str_hex(num: float) -> ~str { /// possible misinterpretation of the result at higher bases. If those values /// are expected, use `to_str_radix_special()` instead. /// -#[inline(always)] +#[inline] pub fn to_str_radix(num: float, radix: uint) -> ~str { let (r, special) = strconv::to_str_common( &num, radix, true, strconv::SignNeg, strconv::DigAll); @@ -152,7 +152,7 @@ pub fn to_str_radix(num: float, radix: uint) -> ~str { /// * num - The float value /// * radix - The base to use /// -#[inline(always)] +#[inline] pub fn to_str_radix_special(num: float, radix: uint) -> (~str, bool) { strconv::to_str_common(&num, radix, true, strconv::SignNeg, strconv::DigAll) @@ -167,7 +167,7 @@ pub fn to_str_radix_special(num: float, radix: uint) -> (~str, bool) { /// * num - The float value /// * digits - The number of significant digits /// -#[inline(always)] +#[inline] pub fn to_str_exact(num: float, digits: uint) -> ~str { let (r, _) = strconv::to_str_common( &num, 10u, true, strconv::SignNeg, strconv::DigExact(digits)); @@ -183,7 +183,7 @@ pub fn to_str_exact(num: float, digits: uint) -> ~str { /// * num - The float value /// * digits - The number of significant digits /// -#[inline(always)] +#[inline] pub fn to_str_digits(num: float, digits: uint) -> ~str { let (r, _) = strconv::to_str_common( &num, 10u, true, strconv::SignNeg, strconv::DigMax(digits)); @@ -191,12 +191,12 @@ pub fn to_str_digits(num: float, digits: uint) -> ~str { } impl to_str::ToStr for float { - #[inline(always)] + #[inline] fn to_str(&self) -> ~str { to_str_digits(*self, 8) } } impl num::ToStrRadix for float { - #[inline(always)] + #[inline] fn to_str_radix(&self, radix: uint) -> ~str { to_str_radix(*self, radix) } @@ -229,7 +229,7 @@ impl num::ToStrRadix for float { /// `none` if the string did not represent a valid number. Otherwise, /// `Some(n)` where `n` is the floating-point number represented by `num`. /// -#[inline(always)] +#[inline] pub fn from_str(num: &str) -> Option<float> { strconv::from_str_common(num, 10u, true, true, true, strconv::ExpDec, false, false) @@ -262,7 +262,7 @@ pub fn from_str(num: &str) -> Option<float> { /// `none` if the string did not represent a valid number. Otherwise, /// `Some(n)` where `n` is the floating-point number represented by `[num]`. /// -#[inline(always)] +#[inline] pub fn from_str_hex(num: &str) -> Option<float> { strconv::from_str_common(num, 16u, true, true, true, strconv::ExpBin, false, false) @@ -287,19 +287,19 @@ pub fn from_str_hex(num: &str) -> Option<float> { /// `none` if the string did not represent a valid number. Otherwise, /// `Some(n)` where `n` is the floating-point number represented by `num`. /// -#[inline(always)] +#[inline] pub fn from_str_radix(num: &str, radix: uint) -> Option<float> { strconv::from_str_common(num, radix, true, true, false, strconv::ExpNone, false, false) } impl FromStr for float { - #[inline(always)] + #[inline] fn from_str(val: &str) -> Option<float> { from_str(val) } } impl num::FromStrRadix for float { - #[inline(always)] + #[inline] fn from_str_radix(val: &str, radix: uint) -> Option<float> { from_str_radix(val, radix) } @@ -341,27 +341,27 @@ pub fn pow_with_uint(base: uint, pow: uint) -> float { return total; } -#[inline(always)] +#[inline] pub fn abs(x: float) -> float { f64::abs(x as f64) as float } -#[inline(always)] +#[inline] pub fn sqrt(x: float) -> float { f64::sqrt(x as f64) as float } -#[inline(always)] +#[inline] pub fn atan(x: float) -> float { f64::atan(x as f64) as float } -#[inline(always)] +#[inline] pub fn sin(x: float) -> float { f64::sin(x as f64) as float } -#[inline(always)] +#[inline] pub fn cos(x: float) -> float { f64::cos(x as f64) as float } -#[inline(always)] +#[inline] pub fn tan(x: float) -> float { f64::tan(x as f64) as float } @@ -370,23 +370,23 @@ impl Num for float {} #[cfg(not(test))] impl Eq for float { - #[inline(always)] + #[inline] fn eq(&self, other: &float) -> bool { (*self) == (*other) } - #[inline(always)] + #[inline] fn ne(&self, other: &float) -> bool { (*self) != (*other) } } #[cfg(not(test))] impl ApproxEq<float> for float { - #[inline(always)] + #[inline] fn approx_epsilon() -> float { 1.0e-6 } - #[inline(always)] + #[inline] fn approx_eq(&self, other: &float) -> bool { self.approx_eq_eps(other, &ApproxEq::approx_epsilon::<float, float>()) } - #[inline(always)] + #[inline] fn approx_eq_eps(&self, other: &float, approx_epsilon: &float) -> bool { (*self - *other).abs() < *approx_epsilon } @@ -394,66 +394,66 @@ impl ApproxEq<float> for float { #[cfg(not(test))] impl Ord for float { - #[inline(always)] + #[inline] fn lt(&self, other: &float) -> bool { (*self) < (*other) } - #[inline(always)] + #[inline] fn le(&self, other: &float) -> bool { (*self) <= (*other) } - #[inline(always)] + #[inline] fn ge(&self, other: &float) -> bool { (*self) >= (*other) } - #[inline(always)] + #[inline] fn gt(&self, other: &float) -> bool { (*self) > (*other) } } impl Orderable for float { /// Returns `NaN` if either of the numbers are `NaN`. - #[inline(always)] + #[inline] fn min(&self, other: &float) -> float { (*self as f64).min(&(*other as f64)) as float } /// Returns `NaN` if either of the numbers are `NaN`. - #[inline(always)] + #[inline] fn max(&self, other: &float) -> float { (*self as f64).max(&(*other as f64)) as float } /// Returns the number constrained within the range `mn <= self <= mx`. /// If any of the numbers are `NaN` then `NaN` is returned. - #[inline(always)] + #[inline] fn clamp(&self, mn: &float, mx: &float) -> float { (*self as f64).clamp(&(*mn as f64), &(*mx as f64)) as float } } impl Zero for float { - #[inline(always)] + #[inline] fn zero() -> float { 0.0 } /// Returns true if the number is equal to either `0.0` or `-0.0` - #[inline(always)] + #[inline] fn is_zero(&self) -> bool { *self == 0.0 || *self == -0.0 } } impl One for float { - #[inline(always)] + #[inline] fn one() -> float { 1.0 } } impl Round for float { /// Round half-way cases toward `neg_infinity` - #[inline(always)] + #[inline] fn floor(&self) -> float { floor(*self as f64) as float } /// Round half-way cases toward `infinity` - #[inline(always)] + #[inline] fn ceil(&self) -> float { ceil(*self as f64) as float } /// Round half-way cases away from `0.0` - #[inline(always)] + #[inline] fn round(&self) -> float { round(*self as f64) as float } /// The integer part of the number (rounds towards `0.0`) - #[inline(always)] + #[inline] fn trunc(&self) -> float { trunc(*self as f64) as float } /// @@ -463,81 +463,81 @@ impl Round for float { /// assert!(x == trunc(x) + fract(x)) /// ~~~ /// - #[inline(always)] + #[inline] fn fract(&self) -> float { *self - self.trunc() } } impl Fractional for float { /// The reciprocal (multiplicative inverse) of the number - #[inline(always)] + #[inline] fn recip(&self) -> float { 1.0 / *self } } impl Algebraic for float { - #[inline(always)] + #[inline] fn pow(&self, n: &float) -> float { (*self as f64).pow(&(*n as f64)) as float } - #[inline(always)] + #[inline] fn sqrt(&self) -> float { (*self as f64).sqrt() as float } - #[inline(always)] + #[inline] fn rsqrt(&self) -> float { (*self as f64).rsqrt() as float } - #[inline(always)] + #[inline] fn cbrt(&self) -> float { (*self as f64).cbrt() as float } - #[inline(always)] + #[inline] fn hypot(&self, other: &float) -> float { (*self as f64).hypot(&(*other as f64)) as float } } impl Trigonometric for float { - #[inline(always)] + #[inline] fn sin(&self) -> float { (*self as f64).sin() as float } - #[inline(always)] + #[inline] fn cos(&self) -> float { (*self as f64).cos() as float } - #[inline(always)] + #[inline] fn tan(&self) -> float { (*self as f64).tan() as float } - #[inline(always)] + #[inline] fn asin(&self) -> float { (*self as f64).asin() as float } - #[inline(always)] + #[inline] fn acos(&self) -> float { (*self as f64).acos() as float } - #[inline(always)] + #[inline] fn atan(&self) -> float { (*self as f64).atan() as float } - #[inline(always)] + #[inline] fn atan2(&self, other: &float) -> float { (*self as f64).atan2(&(*other as f64)) as float } /// Simultaneously computes the sine and cosine of the number - #[inline(always)] + #[inline] fn sin_cos(&self) -> (float, float) { match (*self as f64).sin_cos() { (s, c) => (s as float, c as float) @@ -547,54 +547,54 @@ impl Trigonometric for float { impl Exponential for float { /// Returns the exponential of the number - #[inline(always)] + #[inline] fn exp(&self) -> float { (*self as f64).exp() as float } /// Returns 2 raised to the power of the number - #[inline(always)] + #[inline] fn exp2(&self) -> float { (*self as f64).exp2() as float } /// Returns the natural logarithm of the number - #[inline(always)] + #[inline] fn ln(&self) -> float { (*self as f64).ln() as float } /// Returns the logarithm of the number with respect to an arbitrary base - #[inline(always)] + #[inline] fn log(&self, base: &float) -> float { (*self as f64).log(&(*base as f64)) as float } /// Returns the base 2 logarithm of the number - #[inline(always)] + #[inline] fn log2(&self) -> float { (*self as f64).log2() as float } /// Returns the base 10 logarithm of the number - #[inline(always)] + #[inline] fn log10(&self) -> float { (*self as f64).log10() as float } } impl Hyperbolic for float { - #[inline(always)] + #[inline] fn sinh(&self) -> float { (*self as f64).sinh() as float } - #[inline(always)] + #[inline] fn cosh(&self) -> float { (*self as f64).cosh() as float } - #[inline(always)] + #[inline] fn tanh(&self) -> float { (*self as f64).tanh() as float } @@ -608,7 +608,7 @@ impl Hyperbolic for float { /// - `self` if `self` is `0.0`, `-0.0`, `infinity`, or `neg_infinity` /// - `NaN` if `self` is `NaN` /// - #[inline(always)] + #[inline] fn asinh(&self) -> float { (*self as f64).asinh() as float } @@ -622,7 +622,7 @@ impl Hyperbolic for float { /// - `infinity` if `self` is `infinity` /// - `NaN` if `self` is `NaN` or `self < 1.0` (including `neg_infinity`) /// - #[inline(always)] + #[inline] fn acosh(&self) -> float { (*self as f64).acosh() as float } @@ -639,7 +639,7 @@ impl Hyperbolic for float { /// - `NaN` if the `self` is `NaN` or outside the domain of `-1.0 <= self <= 1.0` /// (including `infinity` and `neg_infinity`) /// - #[inline(always)] + #[inline] fn atanh(&self) -> float { (*self as f64).atanh() as float } @@ -647,157 +647,157 @@ impl Hyperbolic for float { impl Real for float { /// Archimedes' constant - #[inline(always)] + #[inline] fn pi() -> float { 3.14159265358979323846264338327950288 } /// 2.0 * pi - #[inline(always)] + #[inline] fn two_pi() -> float { 6.28318530717958647692528676655900576 } /// pi / 2.0 - #[inline(always)] + #[inline] fn frac_pi_2() -> float { 1.57079632679489661923132169163975144 } /// pi / 3.0 - #[inline(always)] + #[inline] fn frac_pi_3() -> float { 1.04719755119659774615421446109316763 } /// pi / 4.0 - #[inline(always)] + #[inline] fn frac_pi_4() -> float { 0.785398163397448309615660845819875721 } /// pi / 6.0 - #[inline(always)] + #[inline] fn frac_pi_6() -> float { 0.52359877559829887307710723054658381 } /// pi / 8.0 - #[inline(always)] + #[inline] fn frac_pi_8() -> float { 0.39269908169872415480783042290993786 } /// 1.0 / pi - #[inline(always)] + #[inline] fn frac_1_pi() -> float { 0.318309886183790671537767526745028724 } /// 2.0 / pi - #[inline(always)] + #[inline] fn frac_2_pi() -> float { 0.636619772367581343075535053490057448 } /// 2 .0/ sqrt(pi) - #[inline(always)] + #[inline] fn frac_2_sqrtpi() -> float { 1.12837916709551257389615890312154517 } /// sqrt(2.0) - #[inline(always)] + #[inline] fn sqrt2() -> float { 1.41421356237309504880168872420969808 } /// 1.0 / sqrt(2.0) - #[inline(always)] + #[inline] fn frac_1_sqrt2() -> float { 0.707106781186547524400844362104849039 } /// Euler's number - #[inline(always)] + #[inline] fn e() -> float { 2.71828182845904523536028747135266250 } /// log2(e) - #[inline(always)] + #[inline] fn log2_e() -> float { 1.44269504088896340735992468100189214 } /// log10(e) - #[inline(always)] + #[inline] fn log10_e() -> float { 0.434294481903251827651128918916605082 } /// ln(2.0) - #[inline(always)] + #[inline] fn ln_2() -> float { 0.693147180559945309417232121458176568 } /// ln(10.0) - #[inline(always)] + #[inline] fn ln_10() -> float { 2.30258509299404568401799145468436421 } /// Converts to degrees, assuming the number is in radians - #[inline(always)] + #[inline] fn to_degrees(&self) -> float { (*self as f64).to_degrees() as float } /// Converts to radians, assuming the number is in degrees - #[inline(always)] + #[inline] fn to_radians(&self) -> float { (*self as f64).to_radians() as float } } impl RealExt for float { - #[inline(always)] + #[inline] fn lgamma(&self) -> (int, float) { let mut sign = 0; let result = lgamma(*self as f64, &mut sign); (sign as int, result as float) } - #[inline(always)] + #[inline] fn tgamma(&self) -> float { tgamma(*self as f64) as float } - #[inline(always)] + #[inline] fn j0(&self) -> float { j0(*self as f64) as float } - #[inline(always)] + #[inline] fn j1(&self) -> float { j1(*self as f64) as float } - #[inline(always)] + #[inline] fn jn(&self, n: int) -> float { jn(n as c_int, *self as f64) as float } - #[inline(always)] + #[inline] fn y0(&self) -> float { y0(*self as f64) as float } - #[inline(always)] + #[inline] fn y1(&self) -> float { y1(*self as f64) as float } - #[inline(always)] + #[inline] fn yn(&self, n: int) -> float { yn(n as c_int, *self as f64) as float } } #[cfg(not(test))] impl Add<float,float> for float { - #[inline(always)] + #[inline] fn add(&self, other: &float) -> float { *self + *other } } #[cfg(not(test))] impl Sub<float,float> for float { - #[inline(always)] + #[inline] fn sub(&self, other: &float) -> float { *self - *other } } #[cfg(not(test))] impl Mul<float,float> for float { - #[inline(always)] + #[inline] fn mul(&self, other: &float) -> float { *self * *other } } #[cfg(not(test))] impl Div<float,float> for float { - #[inline(always)] + #[inline] fn div(&self, other: &float) -> float { *self / *other } } #[cfg(not(test))] impl Rem<float,float> for float { - #[inline(always)] + #[inline] fn rem(&self, other: &float) -> float { *self % *other } } #[cfg(not(test))] impl Neg<float> for float { - #[inline(always)] + #[inline] fn neg(&self) -> float { -*self } } impl Signed for float { /// Computes the absolute value. Returns `NaN` if the number is `NaN`. - #[inline(always)] + #[inline] fn abs(&self) -> float { abs(*self) } /// /// The positive difference of two numbers. Returns `0.0` if the number is less than or /// equal to `other`, otherwise the difference between`self` and `other` is returned. /// - #[inline(always)] + #[inline] fn abs_sub(&self, other: &float) -> float { (*self as f64).abs_sub(&(*other as f64)) as float } @@ -809,93 +809,93 @@ impl Signed for float { /// - `-1.0` if the number is negative, `-0.0` or `neg_infinity` /// - `NaN` if the number is NaN /// - #[inline(always)] + #[inline] fn signum(&self) -> float { if self.is_NaN() { NaN } else { f64::copysign(1.0, *self as f64) as float } } /// Returns `true` if the number is positive, including `+0.0` and `infinity` - #[inline(always)] + #[inline] fn is_positive(&self) -> bool { *self > 0.0 || (1.0 / *self) == infinity } /// Returns `true` if the number is negative, including `-0.0` and `neg_infinity` - #[inline(always)] + #[inline] fn is_negative(&self) -> bool { *self < 0.0 || (1.0 / *self) == neg_infinity } } impl Bounded for float { - #[inline(always)] + #[inline] fn min_value() -> float { Bounded::min_value::<f64>() as float } - #[inline(always)] + #[inline] fn max_value() -> float { Bounded::max_value::<f64>() as float } } impl Primitive for float { - #[inline(always)] + #[inline] fn bits() -> uint { Primitive::bits::<f64>() } - #[inline(always)] + #[inline] fn bytes() -> uint { Primitive::bytes::<f64>() } } impl Float for float { - #[inline(always)] + #[inline] fn NaN() -> float { Float::NaN::<f64>() as float } - #[inline(always)] + #[inline] fn infinity() -> float { Float::infinity::<f64>() as float } - #[inline(always)] + #[inline] fn neg_infinity() -> float { Float::neg_infinity::<f64>() as float } - #[inline(always)] + #[inline] fn neg_zero() -> float { Float::neg_zero::<f64>() as float } /// Returns `true` if the number is NaN - #[inline(always)] + #[inline] fn is_NaN(&self) -> bool { (*self as f64).is_NaN() } /// Returns `true` if the number is infinite - #[inline(always)] + #[inline] fn is_infinite(&self) -> bool { (*self as f64).is_infinite() } /// Returns `true` if the number is neither infinite or NaN - #[inline(always)] + #[inline] fn is_finite(&self) -> bool { (*self as f64).is_finite() } /// Returns `true` if the number is neither zero, infinite, subnormal or NaN - #[inline(always)] + #[inline] fn is_normal(&self) -> bool { (*self as f64).is_normal() } /// Returns the floating point category of the number. If only one property is going to /// be tested, it is generally faster to use the specific predicate instead. - #[inline(always)] + #[inline] fn classify(&self) -> FPCategory { (*self as f64).classify() } - #[inline(always)] + #[inline] fn mantissa_digits() -> uint { Float::mantissa_digits::<f64>() } - #[inline(always)] + #[inline] fn digits() -> uint { Float::digits::<f64>() } - #[inline(always)] + #[inline] fn epsilon() -> float { Float::epsilon::<f64>() as float } - #[inline(always)] + #[inline] fn min_exp() -> int { Float::min_exp::<f64>() } - #[inline(always)] + #[inline] fn max_exp() -> int { Float::max_exp::<f64>() } - #[inline(always)] + #[inline] fn min_10_exp() -> int { Float::min_10_exp::<f64>() } - #[inline(always)] + #[inline] fn max_10_exp() -> int { Float::max_10_exp::<f64>() } /// Constructs a floating point number by multiplying `x` by 2 raised to the power of `exp` - #[inline(always)] + #[inline] fn ldexp(x: float, exp: int) -> float { Float::ldexp(x as f64, exp) as float } @@ -906,7 +906,7 @@ impl Float for float { /// - `self = x * pow(2, exp)` /// - `0.5 <= abs(x) < 1.0` /// - #[inline(always)] + #[inline] fn frexp(&self) -> (float, int) { match (*self as f64).frexp() { (x, exp) => (x as float, exp) @@ -917,7 +917,7 @@ impl Float for float { /// Returns the exponential of the number, minus `1`, in a way that is accurate /// even if the number is close to zero /// - #[inline(always)] + #[inline] fn exp_m1(&self) -> float { (*self as f64).exp_m1() as float } @@ -926,7 +926,7 @@ impl Float for float { /// Returns the natural logarithm of the number plus `1` (`ln(1+n)`) more accurately /// than if the operations were performed separately /// - #[inline(always)] + #[inline] fn ln_1p(&self) -> float { (*self as f64).ln_1p() as float } @@ -936,13 +936,13 @@ impl Float for float { /// produces a more accurate result with better performance than a separate multiplication /// operation followed by an add. /// - #[inline(always)] + #[inline] fn mul_add(&self, a: float, b: float) -> float { mul_add(*self as f64, a as f64, b as f64) as float } /// Returns the next representable floating-point value in the direction of `other` - #[inline(always)] + #[inline] fn next_after(&self, other: float) -> float { next_after(*self as f64, other as f64) as float } diff --git a/src/libstd/num/i16.rs b/src/libstd/num/i16.rs index 9977247b249..eec20297a53 100644 --- a/src/libstd/num/i16.rs +++ b/src/libstd/num/i16.rs @@ -19,14 +19,14 @@ int_module!(i16, 16) impl BitCount for i16 { /// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic. - #[inline(always)] + #[inline] fn population_count(&self) -> i16 { unsafe { intrinsics::ctpop16(*self) } } /// Counts the number of leading zeros. Wraps LLVM's `ctlz` intrinsic. - #[inline(always)] + #[inline] fn leading_zeros(&self) -> i16 { unsafe { intrinsics::ctlz16(*self) } } /// Counts the number of trailing zeros. Wraps LLVM's `cttz` intrinsic. - #[inline(always)] + #[inline] fn trailing_zeros(&self) -> i16 { unsafe { intrinsics::cttz16(*self) } } } diff --git a/src/libstd/num/i32.rs b/src/libstd/num/i32.rs index 0115f306e4e..769187cc66d 100644 --- a/src/libstd/num/i32.rs +++ b/src/libstd/num/i32.rs @@ -19,14 +19,14 @@ int_module!(i32, 32) impl BitCount for i32 { /// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic. - #[inline(always)] + #[inline] fn population_count(&self) -> i32 { unsafe { intrinsics::ctpop32(*self) } } /// Counts the number of leading zeros. Wraps LLVM's `ctlz` intrinsic. - #[inline(always)] + #[inline] fn leading_zeros(&self) -> i32 { unsafe { intrinsics::ctlz32(*self) } } /// Counts the number of trailing zeros. Wraps LLVM's `cttz` intrinsic. - #[inline(always)] + #[inline] fn trailing_zeros(&self) -> i32 { unsafe { intrinsics::cttz32(*self) } } } diff --git a/src/libstd/num/i64.rs b/src/libstd/num/i64.rs index 4e280f01f27..ae0e59d1661 100644 --- a/src/libstd/num/i64.rs +++ b/src/libstd/num/i64.rs @@ -19,14 +19,14 @@ int_module!(i64, 64) impl BitCount for i64 { /// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic. - #[inline(always)] + #[inline] fn population_count(&self) -> i64 { unsafe { intrinsics::ctpop64(*self) } } /// Counts the number of leading zeros. Wraps LLVM's `ctlz` intrinsic. - #[inline(always)] + #[inline] fn leading_zeros(&self) -> i64 { unsafe { intrinsics::ctlz64(*self) } } /// Counts the number of trailing zeros. Wraps LLVM's `cttz` intrinsic. - #[inline(always)] + #[inline] fn trailing_zeros(&self) -> i64 { unsafe { intrinsics::cttz64(*self) } } } diff --git a/src/libstd/num/i8.rs b/src/libstd/num/i8.rs index 939965b9691..31a1f4241f5 100644 --- a/src/libstd/num/i8.rs +++ b/src/libstd/num/i8.rs @@ -19,14 +19,14 @@ int_module!(i8, 8) impl BitCount for i8 { /// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic. - #[inline(always)] + #[inline] fn population_count(&self) -> i8 { unsafe { intrinsics::ctpop8(*self) } } /// Counts the number of leading zeros. Wraps LLVM's `ctlz` intrinsic. - #[inline(always)] + #[inline] fn leading_zeros(&self) -> i8 { unsafe { intrinsics::ctlz8(*self) } } /// Counts the number of trailing zeros. Wraps LLVM's `cttz` intrinsic. - #[inline(always)] + #[inline] fn trailing_zeros(&self) -> i8 { unsafe { intrinsics::cttz8(*self) } } } diff --git a/src/libstd/num/int.rs b/src/libstd/num/int.rs index 96ef7e9e341..d3c2733b47d 100644 --- a/src/libstd/num/int.rs +++ b/src/libstd/num/int.rs @@ -22,30 +22,30 @@ int_module!(int, super::bits) #[cfg(target_word_size = "32")] impl BitCount for int { /// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic. - #[inline(always)] + #[inline] fn population_count(&self) -> int { (*self as i32).population_count() as int } /// Counts the number of leading zeros. Wraps LLVM's `ctlz` intrinsic. - #[inline(always)] + #[inline] fn leading_zeros(&self) -> int { (*self as i32).leading_zeros() as int } /// Counts the number of trailing zeros. Wraps LLVM's `cttz` intrinsic. - #[inline(always)] + #[inline] fn trailing_zeros(&self) -> int { (*self as i32).trailing_zeros() as int } } #[cfg(target_word_size = "64")] impl BitCount for int { /// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic. - #[inline(always)] + #[inline] fn population_count(&self) -> int { (*self as i64).population_count() as int } /// Counts the number of leading zeros. Wraps LLVM's `ctlz` intrinsic. - #[inline(always)] + #[inline] fn leading_zeros(&self) -> int { (*self as i64).leading_zeros() as int } /// Counts the number of trailing zeros. Wraps LLVM's `cttz` intrinsic. - #[inline(always)] + #[inline] fn trailing_zeros(&self) -> int { (*self as i64).trailing_zeros() as int } } diff --git a/src/libstd/num/int_macros.rs b/src/libstd/num/int_macros.rs index 74f74d11b73..74ec46ccfcd 100644 --- a/src/libstd/num/int_macros.rs +++ b/src/libstd/num/int_macros.rs @@ -27,17 +27,17 @@ pub static min_value: $T = (-1 as $T) << (bits - 1); pub static max_value: $T = min_value - 1 as $T; /// Calculates the sum of two numbers -#[inline(always)] +#[inline] pub fn add(x: $T, y: $T) -> $T { x + y } /// Subtracts the second number from the first -#[inline(always)] +#[inline] pub fn sub(x: $T, y: $T) -> $T { x - y } /// Multiplies two numbers together -#[inline(always)] +#[inline] pub fn mul(x: $T, y: $T) -> $T { x * y } /// Divides the first argument by the second argument (using integer division) /// Divides the first argument by the second argument (using integer division) -#[inline(always)] +#[inline] pub fn div(x: $T, y: $T) -> $T { x / y } /// @@ -60,26 +60,26 @@ pub fn div(x: $T, y: $T) -> $T { x / y } /// ~~~ /// /// -#[inline(always)] +#[inline] pub fn rem(x: $T, y: $T) -> $T { x % y } /// Returns true iff `x < y` -#[inline(always)] +#[inline] pub fn lt(x: $T, y: $T) -> bool { x < y } /// Returns true iff `x <= y` -#[inline(always)] +#[inline] pub fn le(x: $T, y: $T) -> bool { x <= y } /// Returns true iff `x == y` -#[inline(always)] +#[inline] pub fn eq(x: $T, y: $T) -> bool { x == y } /// Returns true iff `x != y` -#[inline(always)] +#[inline] pub fn ne(x: $T, y: $T) -> bool { x != y } /// Returns true iff `x >= y` -#[inline(always)] +#[inline] pub fn ge(x: $T, y: $T) -> bool { x >= y } /// Returns true iff `x > y` -#[inline(always)] +#[inline] pub fn gt(x: $T, y: $T) -> bool { x > y } /// @@ -99,7 +99,7 @@ pub fn gt(x: $T, y: $T) -> bool { x > y } /// assert!(sum == 10); /// ~~~ /// -#[inline(always)] +#[inline] pub fn range_step(start: $T, stop: $T, step: $T, it: &fn($T) -> bool) -> bool { let mut i = start; if step == 0 { @@ -122,62 +122,62 @@ pub fn range_step(start: $T, stop: $T, step: $T, it: &fn($T) -> bool) -> bool { return true; } -#[inline(always)] +#[inline] /// Iterate over the range [`lo`..`hi`) pub fn range(lo: $T, hi: $T, it: &fn($T) -> bool) -> bool { range_step(lo, hi, 1 as $T, it) } -#[inline(always)] +#[inline] /// Iterate over the range [`hi`..`lo`) pub fn range_rev(hi: $T, lo: $T, it: &fn($T) -> bool) -> bool { range_step(hi, lo, -1 as $T, it) } /// Computes the bitwise complement -#[inline(always)] +#[inline] pub fn compl(i: $T) -> $T { -1 as $T ^ i } /// Computes the absolute value -#[inline(always)] +#[inline] pub fn abs(i: $T) -> $T { i.abs() } impl Num for $T {} #[cfg(not(test))] impl Ord for $T { - #[inline(always)] + #[inline] fn lt(&self, other: &$T) -> bool { return (*self) < (*other); } - #[inline(always)] + #[inline] fn le(&self, other: &$T) -> bool { return (*self) <= (*other); } - #[inline(always)] + #[inline] fn ge(&self, other: &$T) -> bool { return (*self) >= (*other); } - #[inline(always)] + #[inline] fn gt(&self, other: &$T) -> bool { return (*self) > (*other); } } #[cfg(not(test))] impl Eq for $T { - #[inline(always)] + #[inline] fn eq(&self, other: &$T) -> bool { return (*self) == (*other); } - #[inline(always)] + #[inline] fn ne(&self, other: &$T) -> bool { return (*self) != (*other); } } impl Orderable for $T { - #[inline(always)] + #[inline] fn min(&self, other: &$T) -> $T { if *self < *other { *self } else { *other } } - #[inline(always)] + #[inline] fn max(&self, other: &$T) -> $T { if *self > *other { *self } else { *other } } - #[inline(always)] + #[inline] fn clamp(&self, mn: &$T, mx: &$T) -> $T { if *self > *mx { *mx } else if *self < *mn { *mn } else { *self } @@ -185,33 +185,33 @@ impl Orderable for $T { } impl Zero for $T { - #[inline(always)] + #[inline] fn zero() -> $T { 0 } - #[inline(always)] + #[inline] fn is_zero(&self) -> bool { *self == 0 } } impl One for $T { - #[inline(always)] + #[inline] fn one() -> $T { 1 } } #[cfg(not(test))] impl Add<$T,$T> for $T { - #[inline(always)] + #[inline] fn add(&self, other: &$T) -> $T { *self + *other } } #[cfg(not(test))] impl Sub<$T,$T> for $T { - #[inline(always)] + #[inline] fn sub(&self, other: &$T) -> $T { *self - *other } } #[cfg(not(test))] impl Mul<$T,$T> for $T { - #[inline(always)] + #[inline] fn mul(&self, other: &$T) -> $T { *self * *other } } @@ -235,7 +235,7 @@ impl Div<$T,$T> for $T { /// assert!(-1 / -2 == 0); /// ~~~ /// - #[inline(always)] + #[inline] fn div(&self, other: &$T) -> $T { *self / *other } } @@ -262,19 +262,19 @@ impl Rem<$T,$T> for $T { /// assert!(-1 % -2 == -1); /// ~~~ /// - #[inline(always)] + #[inline] fn rem(&self, other: &$T) -> $T { *self % *other } } #[cfg(not(test))] impl Neg<$T> for $T { - #[inline(always)] + #[inline] fn neg(&self) -> $T { -*self } } impl Signed for $T { /// Computes the absolute value - #[inline(always)] + #[inline] fn abs(&self) -> $T { if self.is_negative() { -*self } else { *self } } @@ -283,7 +283,7 @@ impl Signed for $T { /// The positive difference of two numbers. Returns `0` if the number is less than or /// equal to `other`, otherwise the difference between`self` and `other` is returned. /// - #[inline(always)] + #[inline] fn abs_sub(&self, other: &$T) -> $T { if *self <= *other { 0 } else { *self - *other } } @@ -295,7 +295,7 @@ impl Signed for $T { /// - `1` if the number is positive /// - `-1` if the number is negative /// - #[inline(always)] + #[inline] fn signum(&self) -> $T { match *self { n if n > 0 => 1, @@ -305,11 +305,11 @@ impl Signed for $T { } /// Returns true if the number is positive - #[inline(always)] + #[inline] fn is_positive(&self) -> bool { *self > 0 } /// Returns true if the number is negative - #[inline(always)] + #[inline] fn is_negative(&self) -> bool { *self < 0 } } @@ -331,7 +331,7 @@ impl Integer for $T { /// assert!((-1).div_floor(-2) == 0); /// ~~~ /// - #[inline(always)] + #[inline] fn div_floor(&self, other: &$T) -> $T { // Algorithm from [Daan Leijen. _Division and Modulus for Computer Scientists_, // December 2001](http://research.microsoft.com/pubs/151917/divmodnote-letter.pdf) @@ -363,7 +363,7 @@ impl Integer for $T { /// assert!((-1).mod_floor(-2) == -1); /// ~~~ /// - #[inline(always)] + #[inline] fn mod_floor(&self, other: &$T) -> $T { // Algorithm from [Daan Leijen. _Division and Modulus for Computer Scientists_, // December 2001](http://research.microsoft.com/pubs/151917/divmodnote-letter.pdf) @@ -375,7 +375,7 @@ impl Integer for $T { } /// Calculates `div_floor` and `mod_floor` simultaneously - #[inline(always)] + #[inline] fn div_mod_floor(&self, other: &$T) -> ($T,$T) { // Algorithm from [Daan Leijen. _Division and Modulus for Computer Scientists_, // December 2001](http://research.microsoft.com/pubs/151917/divmodnote-letter.pdf) @@ -387,7 +387,7 @@ impl Integer for $T { } /// Calculates `div` (`\`) and `rem` (`%`) simultaneously - #[inline(always)] + #[inline] fn div_rem(&self, other: &$T) -> ($T,$T) { (*self / *other, *self % *other) } @@ -397,7 +397,7 @@ impl Integer for $T { /// /// The result is always positive /// - #[inline(always)] + #[inline] fn gcd(&self, other: &$T) -> $T { // Use Euclid's algorithm let mut (m, n) = (*self, *other); @@ -412,21 +412,21 @@ impl Integer for $T { /// /// Calculates the Lowest Common Multiple (LCM) of the number and `other` /// - #[inline(always)] + #[inline] fn lcm(&self, other: &$T) -> $T { ((*self * *other) / self.gcd(other)).abs() // should not have to recaluculate abs } /// Returns `true` if the number can be divided by `other` without leaving a remainder - #[inline(always)] + #[inline] fn is_multiple_of(&self, other: &$T) -> bool { *self % *other == 0 } /// Returns `true` if the number is divisible by `2` - #[inline(always)] + #[inline] fn is_even(&self) -> bool { self.is_multiple_of(&2) } /// Returns `true` if the number is not divisible by `2` - #[inline(always)] + #[inline] fn is_odd(&self) -> bool { !self.is_even() } } @@ -434,90 +434,90 @@ impl Bitwise for $T {} #[cfg(not(test))] impl BitOr<$T,$T> for $T { - #[inline(always)] + #[inline] fn bitor(&self, other: &$T) -> $T { *self | *other } } #[cfg(not(test))] impl BitAnd<$T,$T> for $T { - #[inline(always)] + #[inline] fn bitand(&self, other: &$T) -> $T { *self & *other } } #[cfg(not(test))] impl BitXor<$T,$T> for $T { - #[inline(always)] + #[inline] fn bitxor(&self, other: &$T) -> $T { *self ^ *other } } #[cfg(not(test))] impl Shl<$T,$T> for $T { - #[inline(always)] + #[inline] fn shl(&self, other: &$T) -> $T { *self << *other } } #[cfg(not(test))] impl Shr<$T,$T> for $T { - #[inline(always)] + #[inline] fn shr(&self, other: &$T) -> $T { *self >> *other } } #[cfg(not(test))] impl Not<$T> for $T { - #[inline(always)] + #[inline] fn not(&self) -> $T { !*self } } impl Bounded for $T { - #[inline(always)] + #[inline] fn min_value() -> $T { min_value } - #[inline(always)] + #[inline] fn max_value() -> $T { max_value } } impl Int for $T {} impl Primitive for $T { - #[inline(always)] + #[inline] fn bits() -> uint { bits } - #[inline(always)] + #[inline] fn bytes() -> uint { bits / 8 } } // String conversion functions and impl str -> num /// Parse a string as a number in base 10. -#[inline(always)] +#[inline] pub fn from_str(s: &str) -> Option<$T> { strconv::from_str_common(s, 10u, true, false, false, strconv::ExpNone, false, false) } /// Parse a string as a number in the given base. -#[inline(always)] +#[inline] pub fn from_str_radix(s: &str, radix: uint) -> Option<$T> { strconv::from_str_common(s, radix, true, false, false, strconv::ExpNone, false, false) } /// Parse a byte slice as a number in the given base. -#[inline(always)] +#[inline] pub fn parse_bytes(buf: &[u8], radix: uint) -> Option<$T> { strconv::from_str_bytes_common(buf, radix, true, false, false, strconv::ExpNone, false, false) } impl FromStr for $T { - #[inline(always)] + #[inline] fn from_str(s: &str) -> Option<$T> { from_str(s) } } impl FromStrRadix for $T { - #[inline(always)] + #[inline] fn from_str_radix(s: &str, radix: uint) -> Option<$T> { from_str_radix(s, radix) } @@ -526,7 +526,7 @@ impl FromStrRadix for $T { // String conversion functions and impl num -> str /// Convert to a string as a byte slice in a given base. -#[inline(always)] +#[inline] pub fn to_str_bytes<U>(n: $T, radix: uint, f: &fn(v: &[u8]) -> U) -> U { let (buf, _) = strconv::to_str_bytes_common(&n, radix, false, strconv::SignNeg, strconv::DigAll); @@ -534,7 +534,7 @@ pub fn to_str_bytes<U>(n: $T, radix: uint, f: &fn(v: &[u8]) -> U) -> U { } /// Convert to a string in base 10. -#[inline(always)] +#[inline] pub fn to_str(num: $T) -> ~str { let (buf, _) = strconv::to_str_common(&num, 10u, false, strconv::SignNeg, strconv::DigAll); @@ -542,7 +542,7 @@ pub fn to_str(num: $T) -> ~str { } /// Convert to a string in a given base. -#[inline(always)] +#[inline] pub fn to_str_radix(num: $T, radix: uint) -> ~str { let (buf, _) = strconv::to_str_common(&num, radix, false, strconv::SignNeg, strconv::DigAll); @@ -550,14 +550,14 @@ pub fn to_str_radix(num: $T, radix: uint) -> ~str { } impl ToStr for $T { - #[inline(always)] + #[inline] fn to_str(&self) -> ~str { to_str(*self) } } impl ToStrRadix for $T { - #[inline(always)] + #[inline] fn to_str_radix(&self, radix: uint) -> ~str { to_str_radix(*self, radix) } diff --git a/src/libstd/num/num.rs b/src/libstd/num/num.rs index a9893579721..30a18a0587b 100644 --- a/src/libstd/num/num.rs +++ b/src/libstd/num/num.rs @@ -307,7 +307,7 @@ pub trait Float: Real /// assert_eq!(twenty, 20f32); /// ~~~ /// -#[inline(always)] +#[inline] pub fn cast<T:NumCast,U:NumCast>(n: T) -> U { NumCast::from(n) } @@ -338,28 +338,28 @@ pub trait NumCast { macro_rules! impl_num_cast( ($T:ty, $conv:ident) => ( impl NumCast for $T { - #[inline(always)] + #[inline] fn from<N:NumCast>(n: N) -> $T { // `$conv` could be generated using `concat_idents!`, but that // macro seems to be broken at the moment n.$conv() } - #[inline(always)] fn to_u8(&self) -> u8 { *self as u8 } - #[inline(always)] fn to_u16(&self) -> u16 { *self as u16 } - #[inline(always)] fn to_u32(&self) -> u32 { *self as u32 } - #[inline(always)] fn to_u64(&self) -> u64 { *self as u64 } - #[inline(always)] fn to_uint(&self) -> uint { *self as uint } - - #[inline(always)] fn to_i8(&self) -> i8 { *self as i8 } - #[inline(always)] fn to_i16(&self) -> i16 { *self as i16 } - #[inline(always)] fn to_i32(&self) -> i32 { *self as i32 } - #[inline(always)] fn to_i64(&self) -> i64 { *self as i64 } - #[inline(always)] fn to_int(&self) -> int { *self as int } - - #[inline(always)] fn to_f32(&self) -> f32 { *self as f32 } - #[inline(always)] fn to_f64(&self) -> f64 { *self as f64 } - #[inline(always)] fn to_float(&self) -> float { *self as float } + #[inline] fn to_u8(&self) -> u8 { *self as u8 } + #[inline] fn to_u16(&self) -> u16 { *self as u16 } + #[inline] fn to_u32(&self) -> u32 { *self as u32 } + #[inline] fn to_u64(&self) -> u64 { *self as u64 } + #[inline] fn to_uint(&self) -> uint { *self as uint } + + #[inline] fn to_i8(&self) -> i8 { *self as i8 } + #[inline] fn to_i16(&self) -> i16 { *self as i16 } + #[inline] fn to_i32(&self) -> i32 { *self as i32 } + #[inline] fn to_i64(&self) -> i64 { *self as i64 } + #[inline] fn to_int(&self) -> int { *self as int } + + #[inline] fn to_f32(&self) -> f32 { *self as f32 } + #[inline] fn to_f64(&self) -> f64 { *self as f64 } + #[inline] fn to_float(&self) -> float { *self as float } } ) ) @@ -410,14 +410,29 @@ pub fn pow_with_uint<T:NumCast+One+Zero+Copy+Div<T,T>+Mul<T,T>>(radix: uint, pow let mut multiplier = cast(radix); while (my_pow > 0u) { if my_pow % 2u == 1u { - total *= multiplier; + total = total * multiplier; } - my_pow /= 2u; - multiplier *= multiplier; + my_pow = my_pow / 2u; + multiplier = multiplier * multiplier; } total } +impl<T: Zero> Zero for @mut T { + fn zero() -> @mut T { @mut Zero::zero() } + fn is_zero(&self) -> bool { (**self).is_zero() } +} + +impl<T: Zero> Zero for @T { + fn zero() -> @T { @Zero::zero() } + fn is_zero(&self) -> bool { (**self).is_zero() } +} + +impl<T: Zero> Zero for ~T { + fn zero() -> ~T { ~Zero::zero() } + fn is_zero(&self) -> bool { (**self).is_zero() } +} + /// Helper function for testing numeric operations #[cfg(test)] pub fn test_num<T:Num + NumCast>(ten: T, two: T) { diff --git a/src/libstd/num/strconv.rs b/src/libstd/num/strconv.rs index 3905d82cd0f..a062838aacf 100644 --- a/src/libstd/num/strconv.rs +++ b/src/libstd/num/strconv.rs @@ -42,12 +42,12 @@ pub enum SignFormat { SignAll } -#[inline(always)] +#[inline] fn is_NaN<T:Eq>(num: &T) -> bool { *num != *num } -#[inline(always)] +#[inline] fn is_inf<T:Eq+NumStrConv>(num: &T) -> bool { match NumStrConv::inf() { None => false, @@ -55,7 +55,7 @@ fn is_inf<T:Eq+NumStrConv>(num: &T) -> bool { } } -#[inline(always)] +#[inline] fn is_neg_inf<T:Eq+NumStrConv>(num: &T) -> bool { match NumStrConv::neg_inf() { None => false, @@ -63,7 +63,7 @@ fn is_neg_inf<T:Eq+NumStrConv>(num: &T) -> bool { } } -#[inline(always)] +#[inline] fn is_neg_zero<T:Eq+One+Zero+NumStrConv+Div<T,T>>(num: &T) -> bool { let _0: T = Zero::zero(); let _1: T = One::one(); @@ -83,23 +83,23 @@ pub trait NumStrConv { macro_rules! impl_NumStrConv_Floating (($t:ty) => ( impl NumStrConv for $t { - #[inline(always)] + #[inline] fn NaN() -> Option<$t> { Some( 0.0 / 0.0) } - #[inline(always)] + #[inline] fn inf() -> Option<$t> { Some( 1.0 / 0.0) } - #[inline(always)] + #[inline] fn neg_inf() -> Option<$t> { Some(-1.0 / 0.0) } - #[inline(always)] + #[inline] fn neg_zero() -> Option<$t> { Some(-0.0 ) } - #[inline(always)] + #[inline] fn round_to_zero(&self) -> $t { ( if *self < 0.0 { f64::ceil(*self as f64) } else { f64::floor(*self as f64) } ) as $t } - #[inline(always)] + #[inline] fn fractional_part(&self) -> $t { *self - self.round_to_zero() } @@ -108,13 +108,13 @@ macro_rules! impl_NumStrConv_Floating (($t:ty) => ( macro_rules! impl_NumStrConv_Integer (($t:ty) => ( impl NumStrConv for $t { - #[inline(always)] fn NaN() -> Option<$t> { None } - #[inline(always)] fn inf() -> Option<$t> { None } - #[inline(always)] fn neg_inf() -> Option<$t> { None } - #[inline(always)] fn neg_zero() -> Option<$t> { None } + #[inline] fn NaN() -> Option<$t> { None } + #[inline] fn inf() -> Option<$t> { None } + #[inline] fn neg_inf() -> Option<$t> { None } + #[inline] fn neg_zero() -> Option<$t> { None } - #[inline(always)] fn round_to_zero(&self) -> $t { *self } - #[inline(always)] fn fractional_part(&self) -> $t { 0 } + #[inline] fn round_to_zero(&self) -> $t { *self } + #[inline] fn fractional_part(&self) -> $t { 0 } } )) @@ -229,7 +229,7 @@ pub fn to_str_bytes_common<T:NumCast+Zero+One+Eq+Ord+NumStrConv+Copy+ }; // Decrease the deccumulator one digit at a time - deccum /= radix_gen; + deccum = deccum / radix_gen; deccum = deccum.round_to_zero(); buf.push(char::from_digit(current_digit.to_int() as uint, radix) @@ -282,7 +282,7 @@ pub fn to_str_bytes_common<T:NumCast+Zero+One+Eq+Ord+NumStrConv+Copy+ ) ) { // Shift first fractional digit into the integer part - deccum *= radix_gen; + deccum = deccum * radix_gen; // Calculate the absolute value of each digit. // See note in first loop. @@ -381,7 +381,7 @@ pub fn to_str_bytes_common<T:NumCast+Zero+One+Eq+Ord+NumStrConv+Copy+ * Converts a number to its string representation. This is a wrapper for * `to_str_bytes_common()`, for details see there. */ -#[inline(always)] +#[inline] pub fn to_str_common<T:NumCast+Zero+One+Eq+Ord+NumStrConv+Copy+ Div<T,T>+Neg<T>+Rem<T,T>+Mul<T,T>>( num: &T, radix: uint, negative_zero: bool, @@ -499,8 +499,8 @@ pub fn from_str_bytes_common<T:NumCast+Zero+One+Eq+Ord+Copy+Div<T,T>+ // Initialize accumulator with signed zero for floating point parsing to // work - let mut accum = if accum_positive { _0 } else { -_1 * _0}; - let mut last_accum = accum; // Necessary to detect overflow + let mut accum = if accum_positive { copy _0 } else { -_1 * _0}; + let mut last_accum = copy accum; // Necessary to detect overflow let mut i = start; let mut exp_found = false; @@ -511,13 +511,13 @@ pub fn from_str_bytes_common<T:NumCast+Zero+One+Eq+Ord+Copy+Div<T,T>+ match char::to_digit(c, radix) { Some(digit) => { // shift accum one digit left - accum *= radix_gen; + accum = accum * copy radix_gen; // add/subtract current digit depending on sign if accum_positive { - accum += cast(digit as int); + accum = accum + cast(digit as int); } else { - accum -= cast(digit as int); + accum = accum - cast(digit as int); } // Detect overflow by comparing to last value, except @@ -526,7 +526,7 @@ pub fn from_str_bytes_common<T:NumCast+Zero+One+Eq+Ord+Copy+Div<T,T>+ if accum_positive && accum <= last_accum { return None; } if !accum_positive && accum >= last_accum { return None; } } - last_accum = accum; + last_accum = copy accum; } None => match c { '_' if ignore_underscores => {} @@ -548,7 +548,7 @@ pub fn from_str_bytes_common<T:NumCast+Zero+One+Eq+Ord+Copy+Div<T,T>+ // Parse fractional part of number // Skip if already reached start of exponent if !exp_found { - let mut power = _1; + let mut power = copy _1; while i < len { let c = buf[i] as char; @@ -556,21 +556,21 @@ pub fn from_str_bytes_common<T:NumCast+Zero+One+Eq+Ord+Copy+Div<T,T>+ match char::to_digit(c, radix) { Some(digit) => { // Decrease power one order of magnitude - power /= radix_gen; + power = power / radix_gen; let digit_t: T = cast(digit); // add/subtract current digit depending on sign if accum_positive { - accum += digit_t * power; + accum = accum + digit_t * power; } else { - accum -= digit_t * power; + accum = accum - digit_t * power; } // Detect overflow by comparing to last value if accum_positive && accum < last_accum { return None; } if !accum_positive && accum > last_accum { return None; } - last_accum = accum; + last_accum = copy accum; } None => match c { '_' if ignore_underscores => {} @@ -596,7 +596,7 @@ pub fn from_str_bytes_common<T:NumCast+Zero+One+Eq+Ord+Copy+Div<T,T>+ } } - let mut multiplier = _1; + let mut multiplier = copy _1; if exp_found { let c = buf[i] as char; @@ -632,7 +632,7 @@ pub fn from_str_bytes_common<T:NumCast+Zero+One+Eq+Ord+Copy+Div<T,T>+ * Parses a string as a number. This is a wrapper for * `from_str_bytes_common()`, for details see there. */ -#[inline(always)] +#[inline] pub fn from_str_common<T:NumCast+Zero+One+Eq+Ord+Copy+Div<T,T>+Mul<T,T>+ Sub<T,T>+Neg<T>+Add<T,T>+NumStrConv>( buf: &str, radix: uint, negative: bool, fractional: bool, diff --git a/src/libstd/num/uint.rs b/src/libstd/num/uint.rs index bcb97ff5a07..126150c0f1b 100644 --- a/src/libstd/num/uint.rs +++ b/src/libstd/num/uint.rs @@ -95,7 +95,7 @@ pub fn iterate(lo: uint, hi: uint, it: &fn(uint) -> bool) -> bool { } impl iter::Times for uint { - #[inline(always)] + #[inline] /// /// A convenience form for basic iteration. Given a uint `x`, /// `for x.times { ... }` executes the given block x times. @@ -117,7 +117,7 @@ impl iter::Times for uint { } /// Returns the smallest power of 2 greater than or equal to `n` -#[inline(always)] +#[inline] pub fn next_power_of_two(n: uint) -> uint { let halfbits: uint = sys::size_of::<uint>() * 4u; let mut tmp: uint = n - 1u; diff --git a/src/libstd/num/uint_macros.rs b/src/libstd/num/uint_macros.rs index 2bc1ca9c673..52f620f97ce 100644 --- a/src/libstd/num/uint_macros.rs +++ b/src/libstd/num/uint_macros.rs @@ -28,42 +28,42 @@ pub static min_value: $T = 0 as $T; pub static max_value: $T = 0 as $T - 1 as $T; /// Calculates the sum of two numbers -#[inline(always)] +#[inline] pub fn add(x: $T, y: $T) -> $T { x + y } /// Subtracts the second number from the first -#[inline(always)] +#[inline] pub fn sub(x: $T, y: $T) -> $T { x - y } /// Multiplies two numbers together -#[inline(always)] +#[inline] pub fn mul(x: $T, y: $T) -> $T { x * y } /// Divides the first argument by the second argument (using integer division) -#[inline(always)] +#[inline] pub fn div(x: $T, y: $T) -> $T { x / y } /// Calculates the integer remainder when x is divided by y (equivalent to the /// '%' operator) -#[inline(always)] +#[inline] pub fn rem(x: $T, y: $T) -> $T { x % y } /// Returns true iff `x < y` -#[inline(always)] +#[inline] pub fn lt(x: $T, y: $T) -> bool { x < y } /// Returns true iff `x <= y` -#[inline(always)] +#[inline] pub fn le(x: $T, y: $T) -> bool { x <= y } /// Returns true iff `x == y` -#[inline(always)] +#[inline] pub fn eq(x: $T, y: $T) -> bool { x == y } /// Returns true iff `x != y` -#[inline(always)] +#[inline] pub fn ne(x: $T, y: $T) -> bool { x != y } /// Returns true iff `x >= y` -#[inline(always)] +#[inline] pub fn ge(x: $T, y: $T) -> bool { x >= y } /// Returns true iff `x > y` -#[inline(always)] +#[inline] pub fn gt(x: $T, y: $T) -> bool { x > y } -#[inline(always)] +#[inline] /** * Iterate through a range with a given step value. * @@ -99,20 +99,20 @@ pub fn range_step(start: $T, stop: $T, step: $T_SIGNED, it: &fn($T) -> bool) -> return true; } -#[inline(always)] +#[inline] /// Iterate over the range [`lo`..`hi`) pub fn range(lo: $T, hi: $T, it: &fn($T) -> bool) -> bool { range_step(lo, hi, 1 as $T_SIGNED, it) } -#[inline(always)] +#[inline] /// Iterate over the range [`hi`..`lo`) pub fn range_rev(hi: $T, lo: $T, it: &fn($T) -> bool) -> bool { range_step(hi, lo, -1 as $T_SIGNED, it) } /// Computes the bitwise complement -#[inline(always)] +#[inline] pub fn compl(i: $T) -> $T { max_value ^ i } @@ -121,37 +121,37 @@ impl Num for $T {} #[cfg(not(test))] impl Ord for $T { - #[inline(always)] + #[inline] fn lt(&self, other: &$T) -> bool { (*self) < (*other) } - #[inline(always)] + #[inline] fn le(&self, other: &$T) -> bool { (*self) <= (*other) } - #[inline(always)] + #[inline] fn ge(&self, other: &$T) -> bool { (*self) >= (*other) } - #[inline(always)] + #[inline] fn gt(&self, other: &$T) -> bool { (*self) > (*other) } } #[cfg(not(test))] impl Eq for $T { - #[inline(always)] + #[inline] fn eq(&self, other: &$T) -> bool { return (*self) == (*other); } - #[inline(always)] + #[inline] fn ne(&self, other: &$T) -> bool { return (*self) != (*other); } } impl Orderable for $T { - #[inline(always)] + #[inline] fn min(&self, other: &$T) -> $T { if *self < *other { *self } else { *other } } - #[inline(always)] + #[inline] fn max(&self, other: &$T) -> $T { if *self > *other { *self } else { *other } } /// Returns the number constrained within the range `mn <= self <= mx`. - #[inline(always)] + #[inline] fn clamp(&self, mn: &$T, mx: &$T) -> $T { cond!( (*self > *mx) { *mx } @@ -162,51 +162,51 @@ impl Orderable for $T { } impl Zero for $T { - #[inline(always)] + #[inline] fn zero() -> $T { 0 } - #[inline(always)] + #[inline] fn is_zero(&self) -> bool { *self == 0 } } impl One for $T { - #[inline(always)] + #[inline] fn one() -> $T { 1 } } #[cfg(not(test))] impl Add<$T,$T> for $T { - #[inline(always)] + #[inline] fn add(&self, other: &$T) -> $T { *self + *other } } #[cfg(not(test))] impl Sub<$T,$T> for $T { - #[inline(always)] + #[inline] fn sub(&self, other: &$T) -> $T { *self - *other } } #[cfg(not(test))] impl Mul<$T,$T> for $T { - #[inline(always)] + #[inline] fn mul(&self, other: &$T) -> $T { *self * *other } } #[cfg(not(test))] impl Div<$T,$T> for $T { - #[inline(always)] + #[inline] fn div(&self, other: &$T) -> $T { *self / *other } } #[cfg(not(test))] impl Rem<$T,$T> for $T { - #[inline(always)] + #[inline] fn rem(&self, other: &$T) -> $T { *self % *other } } #[cfg(not(test))] impl Neg<$T> for $T { - #[inline(always)] + #[inline] fn neg(&self) -> $T { -*self } } @@ -214,27 +214,27 @@ impl Unsigned for $T {} impl Integer for $T { /// Calculates `div` (`\`) and `rem` (`%`) simultaneously - #[inline(always)] + #[inline] fn div_rem(&self, other: &$T) -> ($T,$T) { (*self / *other, *self % *other) } /// Unsigned integer division. Returns the same result as `div` (`/`). - #[inline(always)] + #[inline] fn div_floor(&self, other: &$T) -> $T { *self / *other } /// Unsigned integer modulo operation. Returns the same result as `rem` (`%`). - #[inline(always)] + #[inline] fn mod_floor(&self, other: &$T) -> $T { *self / *other } /// Calculates `div_floor` and `modulo_floor` simultaneously - #[inline(always)] + #[inline] fn div_mod_floor(&self, other: &$T) -> ($T,$T) { (*self / *other, *self % *other) } /// Calculates the Greatest Common Divisor (GCD) of the number and `other` - #[inline(always)] + #[inline] fn gcd(&self, other: &$T) -> $T { // Use Euclid's algorithm let mut (m, n) = (*self, *other); @@ -247,21 +247,21 @@ impl Integer for $T { } /// Calculates the Lowest Common Multiple (LCM) of the number and `other` - #[inline(always)] + #[inline] fn lcm(&self, other: &$T) -> $T { (*self * *other) / self.gcd(other) } /// Returns `true` if the number can be divided by `other` without leaving a remainder - #[inline(always)] + #[inline] fn is_multiple_of(&self, other: &$T) -> bool { *self % *other == 0 } /// Returns `true` if the number is divisible by `2` - #[inline(always)] + #[inline] fn is_even(&self) -> bool { self.is_multiple_of(&2) } /// Returns `true` if the number is not divisible by `2` - #[inline(always)] + #[inline] fn is_odd(&self) -> bool { !self.is_even() } } @@ -269,45 +269,45 @@ impl Bitwise for $T {} #[cfg(not(test))] impl BitOr<$T,$T> for $T { - #[inline(always)] + #[inline] fn bitor(&self, other: &$T) -> $T { *self | *other } } #[cfg(not(test))] impl BitAnd<$T,$T> for $T { - #[inline(always)] + #[inline] fn bitand(&self, other: &$T) -> $T { *self & *other } } #[cfg(not(test))] impl BitXor<$T,$T> for $T { - #[inline(always)] + #[inline] fn bitxor(&self, other: &$T) -> $T { *self ^ *other } } #[cfg(not(test))] impl Shl<$T,$T> for $T { - #[inline(always)] + #[inline] fn shl(&self, other: &$T) -> $T { *self << *other } } #[cfg(not(test))] impl Shr<$T,$T> for $T { - #[inline(always)] + #[inline] fn shr(&self, other: &$T) -> $T { *self >> *other } } #[cfg(not(test))] impl Not<$T> for $T { - #[inline(always)] + #[inline] fn not(&self) -> $T { !*self } } impl Bounded for $T { - #[inline(always)] + #[inline] fn min_value() -> $T { min_value } - #[inline(always)] + #[inline] fn max_value() -> $T { max_value } } @@ -316,35 +316,35 @@ impl Int for $T {} // String conversion functions and impl str -> num /// Parse a string as a number in base 10. -#[inline(always)] +#[inline] pub fn from_str(s: &str) -> Option<$T> { strconv::from_str_common(s, 10u, false, false, false, strconv::ExpNone, false, false) } /// Parse a string as a number in the given base. -#[inline(always)] +#[inline] pub fn from_str_radix(s: &str, radix: uint) -> Option<$T> { strconv::from_str_common(s, radix, false, false, false, strconv::ExpNone, false, false) } /// Parse a byte slice as a number in the given base. -#[inline(always)] +#[inline] pub fn parse_bytes(buf: &[u8], radix: uint) -> Option<$T> { strconv::from_str_bytes_common(buf, radix, false, false, false, strconv::ExpNone, false, false) } impl FromStr for $T { - #[inline(always)] + #[inline] fn from_str(s: &str) -> Option<$T> { from_str(s) } } impl FromStrRadix for $T { - #[inline(always)] + #[inline] fn from_str_radix(s: &str, radix: uint) -> Option<$T> { from_str_radix(s, radix) } @@ -353,7 +353,7 @@ impl FromStrRadix for $T { // String conversion functions and impl num -> str /// Convert to a string as a byte slice in a given base. -#[inline(always)] +#[inline] pub fn to_str_bytes<U>(n: $T, radix: uint, f: &fn(v: &[u8]) -> U) -> U { let (buf, _) = strconv::to_str_bytes_common(&n, radix, false, strconv::SignNeg, strconv::DigAll); @@ -361,7 +361,7 @@ pub fn to_str_bytes<U>(n: $T, radix: uint, f: &fn(v: &[u8]) -> U) -> U { } /// Convert to a string in base 10. -#[inline(always)] +#[inline] pub fn to_str(num: $T) -> ~str { let (buf, _) = strconv::to_str_common(&num, 10u, false, strconv::SignNeg, strconv::DigAll); @@ -369,7 +369,7 @@ pub fn to_str(num: $T) -> ~str { } /// Convert to a string in a given base. -#[inline(always)] +#[inline] pub fn to_str_radix(num: $T, radix: uint) -> ~str { let (buf, _) = strconv::to_str_common(&num, radix, false, strconv::SignNeg, strconv::DigAll); @@ -377,42 +377,42 @@ pub fn to_str_radix(num: $T, radix: uint) -> ~str { } impl ToStr for $T { - #[inline(always)] + #[inline] fn to_str(&self) -> ~str { to_str(*self) } } impl ToStrRadix for $T { - #[inline(always)] + #[inline] fn to_str_radix(&self, radix: uint) -> ~str { to_str_radix(*self, radix) } } impl Primitive for $T { - #[inline(always)] + #[inline] fn bits() -> uint { bits } - #[inline(always)] + #[inline] fn bytes() -> uint { bits / 8 } } impl BitCount for $T { /// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic. - #[inline(always)] + #[inline] fn population_count(&self) -> $T { (*self as $T_SIGNED).population_count() as $T } /// Counts the number of leading zeros. Wraps LLVM's `ctlz` intrinsic. - #[inline(always)] + #[inline] fn leading_zeros(&self) -> $T { (*self as $T_SIGNED).leading_zeros() as $T } /// Counts the number of trailing zeros. Wraps LLVM's `cttz` intrinsic. - #[inline(always)] + #[inline] fn trailing_zeros(&self) -> $T { (*self as $T_SIGNED).trailing_zeros() as $T } diff --git a/src/libstd/old_iter.rs b/src/libstd/old_iter.rs index 9fea4376816..83bb9eb0908 100644 --- a/src/libstd/old_iter.rs +++ b/src/libstd/old_iter.rs @@ -16,7 +16,7 @@ #[allow(missing_doc)]; -use cmp::{Eq, Ord}; +use cmp::{Eq}; use kinds::Copy; use option::{None, Option, Some}; use vec; @@ -54,11 +54,6 @@ pub trait CopyableIter<A:Copy> { fn find(&self, p: &fn(&A) -> bool) -> Option<A>; } -pub trait CopyableOrderedIter<A:Copy + Ord> { - fn min(&self) -> A; - fn max(&self) -> A; -} - // A trait for sequences that can be built by imperatively pushing elements // onto them. pub trait Buildable<A> { @@ -78,7 +73,7 @@ pub trait Buildable<A> { fn build_sized(size: uint, builder: &fn(push: &fn(A))) -> Self; } -#[inline(always)] +#[inline] pub fn _eachi<A,IA:BaseIter<A>>(this: &IA, blk: &fn(uint, &A) -> bool) -> bool { let mut i = 0; for this.each |a| { @@ -94,7 +89,7 @@ pub fn eachi<A,IA:BaseIter<A>>(this: &IA, blk: &fn(uint, &A) -> bool) -> bool { _eachi(this, blk) } -#[inline(always)] +#[inline] pub fn all<A,IA:BaseIter<A>>(this: &IA, blk: &fn(&A) -> bool) -> bool { for this.each |a| { if !blk(a) { @@ -104,7 +99,7 @@ pub fn all<A,IA:BaseIter<A>>(this: &IA, blk: &fn(&A) -> bool) -> bool { return true; } -#[inline(always)] +#[inline] pub fn any<A,IA:BaseIter<A>>(this: &IA, blk: &fn(&A) -> bool) -> bool { for this.each |a| { if blk(a) { @@ -114,18 +109,18 @@ pub fn any<A,IA:BaseIter<A>>(this: &IA, blk: &fn(&A) -> bool) -> bool { return false; } -#[inline(always)] +#[inline] pub fn filter_to_vec<A:Copy,IA:BaseIter<A>>(this: &IA, prd: &fn(&A) -> bool) -> ~[A] { do vec::build_sized_opt(this.size_hint()) |push| { for this.each |a| { - if prd(a) { push(*a); } + if prd(a) { push(copy *a); } } } } -#[inline(always)] +#[inline] pub fn map_to_vec<A,B,IA:BaseIter<A>>(this: &IA, op: &fn(&A) -> B) -> ~[B] { do vec::build_sized_opt(this.size_hint()) |push| { for this.each |a| { @@ -134,7 +129,7 @@ pub fn map_to_vec<A,B,IA:BaseIter<A>>(this: &IA, op: &fn(&A) -> B) -> ~[B] { } } -#[inline(always)] +#[inline] pub fn flat_map_to_vec<A,B,IA:BaseIter<A>,IB:BaseIter<B>>(this: &IA, op: &fn(&A) -> IB) -> ~[B] { @@ -147,7 +142,7 @@ pub fn flat_map_to_vec<A,B,IA:BaseIter<A>,IB:BaseIter<B>>(this: &IA, } } -#[inline(always)] +#[inline] pub fn foldl<A,B,IA:BaseIter<A>>(this: &IA, b0: B, blk: &fn(&B, &A) -> B) -> B { let mut b = b0; @@ -157,12 +152,12 @@ pub fn foldl<A,B,IA:BaseIter<A>>(this: &IA, b0: B, blk: &fn(&B, &A) -> B) b } -#[inline(always)] +#[inline] pub fn to_vec<A:Copy,IA:BaseIter<A>>(this: &IA) -> ~[A] { map_to_vec(this, |&x| x) } -#[inline(always)] +#[inline] pub fn contains<A:Eq,IA:BaseIter<A>>(this: &IA, x: &A) -> bool { for this.each |a| { if *a == *x { return true; } @@ -170,7 +165,7 @@ pub fn contains<A:Eq,IA:BaseIter<A>>(this: &IA, x: &A) -> bool { return false; } -#[inline(always)] +#[inline] pub fn count<A:Eq,IA:BaseIter<A>>(this: &IA, x: &A) -> uint { do foldl(this, 0) |count, value| { if *value == *x { @@ -181,7 +176,7 @@ pub fn count<A:Eq,IA:BaseIter<A>>(this: &IA, x: &A) -> uint { } } -#[inline(always)] +#[inline] pub fn position<A,IA:BaseIter<A>>(this: &IA, f: &fn(&A) -> bool) -> Option<uint> { let mut i = 0; @@ -192,45 +187,11 @@ pub fn position<A,IA:BaseIter<A>>(this: &IA, f: &fn(&A) -> bool) return None; } -// note: 'rposition' would only make sense to provide with a bidirectional -// iter interface, such as would provide "reach" in addition to "each". As is, -// it would have to be implemented with foldr, which is too inefficient. - -#[inline(always)] -pub fn min<A:Copy + Ord,IA:BaseIter<A>>(this: &IA) -> A { - match do foldl::<A,Option<A>,IA>(this, None) |a, b| { - match a { - &Some(ref a_) if *a_ < *b => { - *(a) - } - _ => Some(*b) - } - } { - Some(val) => val, - None => fail!("min called on empty iterator") - } -} - -#[inline(always)] -pub fn max<A:Copy + Ord,IA:BaseIter<A>>(this: &IA) -> A { - match do foldl::<A,Option<A>,IA>(this, None) |a, b| { - match a { - &Some(ref a_) if *a_ > *b => { - *(a) - } - _ => Some(*b) - } - } { - Some(val) => val, - None => fail!("max called on empty iterator") - } -} - -#[inline(always)] +#[inline] pub fn find<A:Copy,IA:BaseIter<A>>(this: &IA, f: &fn(&A) -> bool) -> Option<A> { for this.each |i| { - if f(i) { return Some(*i) } + if f(i) { return Some(copy *i) } } return None; } @@ -247,7 +208,7 @@ pub fn find<A:Copy,IA:BaseIter<A>>(this: &IA, f: &fn(&A) -> bool) * as an argument a function that will push an element * onto the sequence being constructed. */ -#[inline(always)] +#[inline] pub fn build<A,B: Buildable<A>>(builder: &fn(push: &fn(A))) -> B { Buildable::build_sized(4, builder) } @@ -265,7 +226,7 @@ pub fn build<A,B: Buildable<A>>(builder: &fn(push: &fn(A))) -> B { * as an argument a function that will push an element * onto the sequence being constructed. */ -#[inline(always)] +#[inline] pub fn build_sized_opt<A,B: Buildable<A>>(size: Option<uint>, builder: &fn(push: &fn(A))) -> B { Buildable::build_sized(size.get_or_default(4), builder) @@ -275,7 +236,7 @@ pub fn build_sized_opt<A,B: Buildable<A>>(size: Option<uint>, /// Applies a function to each element of an iterable and returns the results /// in a sequence built via `BU`. See also `map_to_vec`. -#[inline(always)] +#[inline] pub fn map<T,IT: BaseIter<T>,U,BU: Buildable<U>>(v: &IT, f: &fn(&T) -> U) -> BU { do build_sized_opt(v.size_hint()) |push| { @@ -291,7 +252,7 @@ pub fn map<T,IT: BaseIter<T>,U,BU: Buildable<U>>(v: &IT, f: &fn(&T) -> U) * Creates a generic sequence of size `n_elts` and initializes the elements * to the value returned by the function `op`. */ -#[inline(always)] +#[inline] pub fn from_fn<T,BT: Buildable<T>>(n_elts: uint, op: InitOp<T>) -> BT { do Buildable::build_sized(n_elts) |push| { let mut i: uint = 0u; @@ -305,31 +266,31 @@ pub fn from_fn<T,BT: Buildable<T>>(n_elts: uint, op: InitOp<T>) -> BT { * Creates an immutable vector of size `n_elts` and initializes the elements * to the value `t`. */ -#[inline(always)] +#[inline] pub fn from_elem<T:Copy,BT:Buildable<T>>(n_elts: uint, t: T) -> BT { do Buildable::build_sized(n_elts) |push| { let mut i: uint = 0; - while i < n_elts { push(t); i += 1; } + while i < n_elts { push(copy t); i += 1; } } } /// Appends two generic sequences. -#[inline(always)] +#[inline] pub fn append<T:Copy,IT:BaseIter<T>,BT:Buildable<T>>(lhs: &IT, rhs: &IT) -> BT { let size_opt = lhs.size_hint().chain_ref( |sz1| rhs.size_hint().map(|sz2| *sz1+*sz2)); do build_sized_opt(size_opt) |push| { - for lhs.each |x| { push(*x); } - for rhs.each |x| { push(*x); } + for lhs.each |x| { push(copy *x); } + for rhs.each |x| { push(copy *x); } } } /// Copies a generic sequence, possibly converting it to a different /// type of sequence. -#[inline(always)] +#[inline] pub fn copy_seq<T:Copy,IT:BaseIter<T>,BT:Buildable<T>>(v: &IT) -> BT { do build_sized_opt(v.size_hint()) |push| { - for v.each |x| { push(*x); } + for v.each |x| { push(copy *x); } } } diff --git a/src/libstd/option.rs b/src/libstd/option.rs index 80f4fb7643c..7dc6b7fe4b1 100644 --- a/src/libstd/option.rs +++ b/src/libstd/option.rs @@ -88,14 +88,14 @@ impl<T:Ord> Ord for Option<T> { } } -impl<T: Copy + Add<T,T>> Add<Option<T>, Option<T>> for Option<T> { - #[inline(always)] +impl<T: Copy+Add<T,T>> Add<Option<T>, Option<T>> for Option<T> { + #[inline] fn add(&self, other: &Option<T>) -> Option<T> { - match (*self, *other) { - (None, None) => None, - (_, None) => *self, - (None, _) => *other, - (Some(ref lhs), Some(ref rhs)) => Some(*lhs + *rhs) + match (&*self, &*other) { + (&None, &None) => None, + (_, &None) => copy *self, + (&None, _) => copy *other, + (&Some(ref lhs), &Some(ref rhs)) => Some(*lhs + *rhs) } } } @@ -126,12 +126,12 @@ impl<T> Option<T> { } /// Returns true if the option contains some value - #[inline(always)] + #[inline] pub fn is_some(&const self) -> bool { !self.is_none() } /// Update an optional value by optionally running its content through a /// function that returns an option. - #[inline(always)] + #[inline] pub fn chain<U>(self, f: &fn(t: T) -> Option<U>) -> Option<U> { match self { Some(t) => f(t), @@ -140,7 +140,7 @@ impl<T> Option<T> { } /// Returns the leftmost Some() value, or None if both are None. - #[inline(always)] + #[inline] pub fn or(self, optb: Option<T>) -> Option<T> { match self { Some(opta) => Some(opta), @@ -150,7 +150,7 @@ impl<T> Option<T> { /// Update an optional value by optionally running its content by reference /// through a function that returns an option. - #[inline(always)] + #[inline] pub fn chain_ref<'a, U>(&'a self, f: &fn(x: &'a T) -> Option<U>) -> Option<U> { match *self { @@ -160,27 +160,27 @@ impl<T> Option<T> { } /// Maps a `some` value from one type to another by reference - #[inline(always)] + #[inline] pub fn map<'a, U>(&self, f: &fn(&'a T) -> U) -> Option<U> { match *self { Some(ref x) => Some(f(x)), None => None } } /// As `map`, but consumes the option and gives `f` ownership to avoid /// copying. - #[inline(always)] + #[inline] pub fn map_consume<U>(self, f: &fn(v: T) -> U) -> Option<U> { match self { None => None, Some(v) => Some(f(v)) } } /// Applies a function to the contained value or returns a default - #[inline(always)] + #[inline] pub fn map_default<'a, U>(&'a self, def: U, f: &fn(&'a T) -> U) -> U { match *self { None => def, Some(ref t) => f(t) } } /// As `map_default`, but consumes the option and gives `f` /// ownership to avoid copying. - #[inline(always)] + #[inline] pub fn map_consume_default<U>(self, def: U, f: &fn(v: T) -> U) -> U { match self { None => def, Some(v) => f(v) } } @@ -215,7 +215,7 @@ impl<T> Option<T> { Instead, prefer to use pattern matching and handle the `None` case explicitly. */ - #[inline(always)] + #[inline] pub fn get_ref<'a>(&'a self) -> &'a T { match *self { Some(ref x) => x, @@ -237,7 +237,7 @@ impl<T> Option<T> { Instead, prefer to use pattern matching and handle the `None` case explicitly. */ - #[inline(always)] + #[inline] pub fn get_mut_ref<'a>(&'a mut self) -> &'a mut T { match *self { Some(ref mut x) => x, @@ -245,7 +245,7 @@ impl<T> Option<T> { } } - #[inline(always)] + #[inline] pub fn unwrap(self) -> T { /*! Moves a value out of an option type and returns it. @@ -277,7 +277,7 @@ impl<T> Option<T> { * * Fails if the value equals `None`. */ - #[inline(always)] + #[inline] pub fn swap_unwrap(&mut self) -> T { if self.is_none() { fail!("option::swap_unwrap none") } util::replace(self, None).unwrap() @@ -291,7 +291,7 @@ impl<T> Option<T> { * * Fails if the value equals `none` */ - #[inline(always)] + #[inline] pub fn expect(self, reason: &str) -> T { match self { Some(val) => val, @@ -315,7 +315,7 @@ impl<T:Copy> Option<T> { Instead, prefer to use pattern matching and handle the `None` case explicitly. */ - #[inline(always)] + #[inline] pub fn get(self) -> T { match self { Some(x) => return x, @@ -324,13 +324,13 @@ impl<T:Copy> Option<T> { } /// Returns the contained value or a default - #[inline(always)] + #[inline] pub fn get_or_default(self, def: T) -> T { match self { Some(x) => x, None => def } } /// Applies a function zero or more times until the result is none. - #[inline(always)] + #[inline] pub fn while_some(self, blk: &fn(v: T) -> Option<T>) { let mut opt = self; while opt.is_some() { @@ -341,7 +341,7 @@ impl<T:Copy> Option<T> { impl<T:Copy + Zero> Option<T> { /// Returns the contained value or zero (for this type) - #[inline(always)] + #[inline] pub fn get_or_zero(self) -> T { match self { Some(x) => x, @@ -350,6 +350,11 @@ impl<T:Copy + Zero> Option<T> { } } +impl<T> Zero for Option<T> { + fn zero() -> Option<T> { None } + fn is_zero(&self) -> bool { self.is_none() } +} + /// Immutable iterator over an `Option<A>` pub struct OptionIterator<'self, A> { priv opt: Option<&'self A> diff --git a/src/libstd/os.rs b/src/libstd/os.rs index 044b305a0dd..765dd30febc 100644 --- a/src/libstd/os.rs +++ b/src/libstd/os.rs @@ -40,6 +40,8 @@ use option::{Some, None}; use os; use prelude::*; use ptr; +use rt; +use rt::TaskContext; use str; use uint; use unstable::finally::Finally; @@ -144,7 +146,7 @@ pub mod win32 { } pub fn as_utf16_p<T>(s: &str, f: &fn(*u16) -> T) -> T { - let mut t = str::to_utf16(s); + let mut t = s.to_utf16(); // Null terminate before passing on. t += [0u16]; vec::as_imm_buf(t, |buf, _len| f(buf)) @@ -959,12 +961,10 @@ pub fn copy_file(from: &Path, to: &Path) -> bool { fclose(ostream); // Give the new file the old file's permissions - unsafe { - if do str::as_c_str(to.to_str()) |to_buf| { - libc::chmod(to_buf, from_mode as mode_t) - } != 0 { - return false; // should be a condition... - } + if do str::as_c_str(to.to_str()) |to_buf| { + libc::chmod(to_buf, from_mode as mode_t) + } != 0 { + return false; // should be a condition... } return ok; } @@ -1169,10 +1169,17 @@ pub fn real_args() -> ~[~str] { #[cfg(target_os = "android")] #[cfg(target_os = "freebsd")] pub fn real_args() -> ~[~str] { - unsafe { - let argc = rustrt::rust_get_argc(); - let argv = rustrt::rust_get_argv(); - load_argc_and_argv(argc, argv) + if rt::context() == TaskContext { + match rt::args::clone() { + Some(args) => args, + None => fail!("process arguments not initialized") + } + } else { + unsafe { + let argc = rustrt::rust_get_argc(); + let argv = rustrt::rust_get_argv(); + load_argc_and_argv(argc, argv) + } } } @@ -1685,10 +1692,11 @@ mod tests { assert!((ostream as uint != 0u)); let s = ~"hello"; let mut buf = s.as_bytes_with_null().to_owned(); + let len = buf.len(); do vec::as_mut_buf(buf) |b, _len| { - assert!((libc::fwrite(b as *c_void, 1u as size_t, - (s.len() + 1u) as size_t, ostream) - == buf.len() as size_t)) + assert_eq!(libc::fwrite(b as *c_void, 1u as size_t, + (s.len() + 1u) as size_t, ostream), + len as size_t) } assert_eq!(libc::fclose(ostream), (0u as c_int)); let in_mode = in.get_mode(); diff --git a/src/libstd/owned.rs b/src/libstd/owned.rs index 3262fb4afdc..e7a6e38fdb0 100644 --- a/src/libstd/owned.rs +++ b/src/libstd/owned.rs @@ -14,20 +14,20 @@ #[cfg(not(test))] impl<T:Eq> Eq for ~T { - #[inline(always)] + #[inline] fn eq(&self, other: &~T) -> bool { *(*self) == *(*other) } - #[inline(always)] + #[inline] fn ne(&self, other: &~T) -> bool { *(*self) != *(*other) } } #[cfg(not(test))] impl<T:Ord> Ord for ~T { - #[inline(always)] + #[inline] fn lt(&self, other: &~T) -> bool { *(*self) < *(*other) } - #[inline(always)] + #[inline] fn le(&self, other: &~T) -> bool { *(*self) <= *(*other) } - #[inline(always)] + #[inline] fn ge(&self, other: &~T) -> bool { *(*self) >= *(*other) } - #[inline(always)] + #[inline] fn gt(&self, other: &~T) -> bool { *(*self) > *(*other) } } diff --git a/src/libstd/path.rs b/src/libstd/path.rs index 400657d0c25..9c51526aa7f 100644 --- a/src/libstd/path.rs +++ b/src/libstd/path.rs @@ -515,7 +515,7 @@ impl GenericPath for PosixPath { fn with_filestem(&self, s: &str) -> PosixPath { match self.filetype() { None => self.with_filename(s), - Some(ref t) => self.with_filename(str::to_owned(s) + *t), + Some(ref t) => self.with_filename(s.to_owned() + *t), } } @@ -657,7 +657,7 @@ impl GenericPath for WindowsPath { (None, None) => { host = None; device = None; - rest = str::to_owned(s); + rest = s.to_owned(); } } @@ -729,7 +729,7 @@ impl GenericPath for WindowsPath { fn with_filestem(&self, s: &str) -> WindowsPath { match self.filetype() { None => self.with_filename(s), - Some(ref t) => self.with_filename(str::to_owned(s) + *t), + Some(ref t) => self.with_filename(s.to_owned() + *t), } } @@ -904,7 +904,7 @@ pub mod windows { use libc; use option::{None, Option, Some}; - #[inline(always)] + #[inline] pub fn is_sep(u: char) -> bool { u == '/' || u == '\\' } @@ -947,7 +947,6 @@ pub mod windows { mod tests { use option::{None, Some}; use path::{PosixPath, WindowsPath, windows}; - use str; #[test] fn test_double_slash_collapsing() { @@ -984,7 +983,7 @@ mod tests { fn test_posix_paths() { fn t(wp: &PosixPath, s: &str) { let ss = wp.to_str(); - let sss = str::to_owned(s); + let sss = s.to_owned(); if (ss != sss) { debug!("got %s", ss); debug!("expected %s", sss); @@ -1042,7 +1041,7 @@ mod tests { fn test_normalize() { fn t(wp: &PosixPath, s: &str) { let ss = wp.to_str(); - let sss = str::to_owned(s); + let sss = s.to_owned(); if (ss != sss) { debug!("got %s", ss); debug!("expected %s", sss); @@ -1105,7 +1104,7 @@ mod tests { fn test_windows_paths() { fn t(wp: &WindowsPath, s: &str) { let ss = wp.to_str(); - let sss = str::to_owned(s); + let sss = s.to_owned(); if (ss != sss) { debug!("got %s", ss); debug!("expected %s", sss); diff --git a/src/libstd/pipes.rs b/src/libstd/pipes.rs index 012ad0ed80d..26dd4af45d6 100644 --- a/src/libstd/pipes.rs +++ b/src/libstd/pipes.rs @@ -85,7 +85,7 @@ bounded and unbounded protocols allows for less code duplication. #[allow(missing_doc)]; use container::Container; -use cast::{forget, transmute, transmute_copy}; +use cast::{forget, transmute, transmute_copy, transmute_mut}; use either::{Either, Left, Right}; use iterator::IteratorUtil; use kinds::Owned; @@ -102,10 +102,6 @@ use util::replace; static SPIN_COUNT: uint = 0; -macro_rules! move_it ( - { $x:expr } => ( unsafe { let y = *ptr::to_unsafe_ptr(&($x)); y } ) -) - #[deriving(Eq)] enum State { Empty, @@ -316,9 +312,11 @@ impl<T> Drop for BufferResource<T> { fn finalize(&self) { unsafe { // FIXME(#4330) Need self by value to get mutability. - let this: &mut BufferResource<T> = transmute(self); + let this: &mut BufferResource<T> = transmute_mut(self); + + let null_buffer: ~Buffer<T> = transmute(ptr::null::<Buffer<T>>()); + let mut b = replace(&mut this.buffer, null_buffer); - let mut b = move_it!(this.buffer); //let p = ptr::to_unsafe_ptr(*b); //error!("drop %?", p); let old_count = intrinsics::atomic_xsub_rel( diff --git a/src/libstd/prelude.rs b/src/libstd/prelude.rs index 61b8d36266e..309df27e151 100644 --- a/src/libstd/prelude.rs +++ b/src/libstd/prelude.rs @@ -47,9 +47,9 @@ pub use char::Char; pub use container::{Container, Mutable, Map, Set}; pub use hash::Hash; pub use old_iter::{BaseIter, ReverseIter, ExtendedIter, EqIter}; -pub use old_iter::{CopyableIter, CopyableOrderedIter}; +pub use old_iter::CopyableIter; pub use iter::{Times, FromIter}; -pub use iterator::{Iterator, IteratorUtil}; +pub use iterator::{Iterator, IteratorUtil, OrdIterator}; pub use num::{Num, NumCast}; pub use num::{Orderable, Signed, Unsigned, Round}; pub use num::{Algebraic, Trigonometric, Exponential, Hyperbolic}; @@ -61,7 +61,7 @@ pub use path::Path; pub use path::PosixPath; pub use path::WindowsPath; pub use ptr::RawPtr; -pub use ascii::{Ascii, AsciiCast, OwnedAsciiCast, AsciiStr}; +pub use ascii::{Ascii, AsciiCast, OwnedAsciiCast, AsciiStr, ToBytesConsume}; pub use str::{Str, StrVector, StrSlice, OwnedStr, StrUtil, NullTerminatedStr}; pub use from_str::{FromStr}; pub use to_bytes::IterBytes; diff --git a/src/libstd/ptr.rs b/src/libstd/ptr.rs index cd5a3182f6b..7f89d454be1 100644 --- a/src/libstd/ptr.rs +++ b/src/libstd/ptr.rs @@ -19,31 +19,31 @@ use unstable::intrinsics; use uint; /// Calculate the offset from a pointer -#[inline(always)] +#[inline] pub fn offset<T>(ptr: *T, count: uint) -> *T { (ptr as uint + count * sys::size_of::<T>()) as *T } /// Calculate the offset from a const pointer -#[inline(always)] +#[inline] pub fn const_offset<T>(ptr: *const T, count: uint) -> *const T { (ptr as uint + count * sys::size_of::<T>()) as *T } /// Calculate the offset from a mut pointer -#[inline(always)] +#[inline] pub fn mut_offset<T>(ptr: *mut T, count: uint) -> *mut T { (ptr as uint + count * sys::size_of::<T>()) as *mut T } /// Return the offset of the first null pointer in `buf`. -#[inline(always)] +#[inline] pub unsafe fn buf_len<T>(buf: **T) -> uint { position(buf, |i| *i == null()) } /// Return the first offset `i` such that `f(buf[i]) == true`. -#[inline(always)] +#[inline] pub unsafe fn position<T>(buf: *T, f: &fn(&T) -> bool) -> uint { let mut i = 0; loop { @@ -53,19 +53,19 @@ pub unsafe fn position<T>(buf: *T, f: &fn(&T) -> bool) -> uint { } /// Create an unsafe null pointer -#[inline(always)] +#[inline] pub fn null<T>() -> *T { 0 as *T } /// Create an unsafe mutable null pointer -#[inline(always)] +#[inline] pub fn mut_null<T>() -> *mut T { 0 as *mut T } /// Returns true if the pointer is equal to the null pointer. -#[inline(always)] +#[inline] pub fn is_null<T>(ptr: *const T) -> bool { ptr == null() } /// Returns true if the pointer is not equal to the null pointer. -#[inline(always)] +#[inline] pub fn is_not_null<T>(ptr: *const T) -> bool { !is_null(ptr) } /** @@ -74,22 +74,8 @@ pub fn is_not_null<T>(ptr: *const T) -> bool { !is_null(ptr) } * Copies `count` elements (not bytes) from `src` to `dst`. The source * and destination may overlap. */ -#[inline(always)] -#[cfg(target_word_size = "32", stage0)] -pub unsafe fn copy_memory<T>(dst: *mut T, src: *const T, count: uint) { - use unstable::intrinsics::memmove32; - let n = count * sys::size_of::<T>(); - memmove32(dst as *mut u8, src as *u8, n as u32); -} - -/** - * Copies data from one location to another. - * - * Copies `count` elements (not bytes) from `src` to `dst`. The source - * and destination may overlap. - */ -#[inline(always)] -#[cfg(target_word_size = "32", not(stage0))] +#[inline] +#[cfg(target_word_size = "32")] pub unsafe fn copy_memory<T>(dst: *mut T, src: *const T, count: uint) { use unstable::intrinsics::memmove32; memmove32(dst, src as *T, count as u32); @@ -101,22 +87,8 @@ pub unsafe fn copy_memory<T>(dst: *mut T, src: *const T, count: uint) { * Copies `count` elements (not bytes) from `src` to `dst`. The source * and destination may overlap. */ -#[inline(always)] -#[cfg(target_word_size = "64", stage0)] -pub unsafe fn copy_memory<T>(dst: *mut T, src: *const T, count: uint) { - use unstable::intrinsics::memmove64; - let n = count * sys::size_of::<T>(); - memmove64(dst as *mut u8, src as *u8, n as u64); -} - -/** - * Copies data from one location to another. - * - * Copies `count` elements (not bytes) from `src` to `dst`. The source - * and destination may overlap. - */ -#[inline(always)] -#[cfg(target_word_size = "64", not(stage0))] +#[inline] +#[cfg(target_word_size = "64")] pub unsafe fn copy_memory<T>(dst: *mut T, src: *const T, count: uint) { use unstable::intrinsics::memmove64; memmove64(dst, src as *T, count as u64); @@ -128,22 +100,8 @@ pub unsafe fn copy_memory<T>(dst: *mut T, src: *const T, count: uint) { * Copies `count` elements (not bytes) from `src` to `dst`. The source * and destination may *not* overlap. */ -#[inline(always)] -#[cfg(target_word_size = "32", stage0)] -pub unsafe fn copy_nonoverlapping_memory<T>(dst: *mut T, src: *const T, count: uint) { - use unstable::intrinsics::memmove32; - let n = count * sys::size_of::<T>(); - memmove32(dst as *mut u8, src as *u8, n as u32); -} - -/** - * Copies data from one location to another. - * - * Copies `count` elements (not bytes) from `src` to `dst`. The source - * and destination may *not* overlap. - */ -#[inline(always)] -#[cfg(target_word_size = "32", not(stage0))] +#[inline] +#[cfg(target_word_size = "32")] pub unsafe fn copy_nonoverlapping_memory<T>(dst: *mut T, src: *const T, count: uint) { use unstable::intrinsics::memcpy32; memcpy32(dst, src as *T, count as u32); @@ -155,22 +113,8 @@ pub unsafe fn copy_nonoverlapping_memory<T>(dst: *mut T, src: *const T, count: u * Copies `count` elements (not bytes) from `src` to `dst`. The source * and destination may *not* overlap. */ -#[inline(always)] -#[cfg(target_word_size = "64", stage0)] -pub unsafe fn copy_nonoverlapping_memory<T>(dst: *mut T, src: *const T, count: uint) { - use unstable::intrinsics::memmove64; - let n = count * sys::size_of::<T>(); - memmove64(dst as *mut u8, src as *u8, n as u64); -} - -/** - * Copies data from one location to another. - * - * Copies `count` elements (not bytes) from `src` to `dst`. The source - * and destination may *not* overlap. - */ -#[inline(always)] -#[cfg(target_word_size = "64", not(stage0))] +#[inline] +#[cfg(target_word_size = "64")] pub unsafe fn copy_nonoverlapping_memory<T>(dst: *mut T, src: *const T, count: uint) { use unstable::intrinsics::memcpy64; memcpy64(dst, src as *T, count as u64); @@ -180,8 +124,8 @@ pub unsafe fn copy_nonoverlapping_memory<T>(dst: *mut T, src: *const T, count: u * Invokes memset on the specified pointer, setting `count * size_of::<T>()` * bytes of memory starting at `dst` to `c`. */ -#[inline(always)] -#[cfg(target_word_size = "32", not(stage0))] +#[inline] +#[cfg(target_word_size = "32")] pub unsafe fn set_memory<T>(dst: *mut T, c: u8, count: uint) { use unstable::intrinsics::memset32; memset32(dst, c, count as u32); @@ -191,8 +135,8 @@ pub unsafe fn set_memory<T>(dst: *mut T, c: u8, count: uint) { * Invokes memset on the specified pointer, setting `count * size_of::<T>()` * bytes of memory starting at `dst` to `c`. */ -#[inline(always)] -#[cfg(target_word_size = "64", not(stage0))] +#[inline] +#[cfg(target_word_size = "64")] pub unsafe fn set_memory<T>(dst: *mut T, c: u8, count: uint) { use unstable::intrinsics::memset64; memset64(dst, c, count as u64); @@ -222,26 +166,26 @@ pub unsafe fn swap_ptr<T>(x: *mut T, y: *mut T) { * Replace the value at a mutable location with a new one, returning the old * value, without deinitialising or copying either one. */ -#[inline(always)] +#[inline] pub unsafe fn replace_ptr<T>(dest: *mut T, mut src: T) -> T { swap_ptr(dest, &mut src); src } /// Transform a region pointer - &T - to an unsafe pointer - *T. -#[inline(always)] +#[inline] pub fn to_unsafe_ptr<T>(thing: &T) -> *T { thing as *T } /// Transform a const region pointer - &const T - to a const unsafe pointer - *const T. -#[inline(always)] +#[inline] pub fn to_const_unsafe_ptr<T>(thing: &const T) -> *const T { thing as *const T } /// Transform a mutable region pointer - &mut T - to a mutable unsafe pointer - *mut T. -#[inline(always)] +#[inline] pub fn to_mut_unsafe_ptr<T>(thing: &mut T) -> *mut T { thing as *mut T } @@ -297,11 +241,11 @@ pub trait RawPtr<T> { /// Extension methods for immutable pointers impl<T> RawPtr<T> for *T { /// Returns true if the pointer is equal to the null pointer. - #[inline(always)] + #[inline] fn is_null(&const self) -> bool { is_null(*self) } /// Returns true if the pointer is not equal to the null pointer. - #[inline(always)] + #[inline] fn is_not_null(&const self) -> bool { is_not_null(*self) } /// @@ -314,7 +258,7 @@ impl<T> RawPtr<T> for *T { /// that this is still an unsafe operation because the returned value could /// be pointing to invalid memory. /// - #[inline(always)] + #[inline] unsafe fn to_option(&const self) -> Option<&T> { if self.is_null() { None } else { Some(cast::transmute(*self)) @@ -322,18 +266,18 @@ impl<T> RawPtr<T> for *T { } /// Calculates the offset from a pointer. - #[inline(always)] + #[inline] fn offset(&self, count: uint) -> *T { offset(*self, count) } } /// Extension methods for mutable pointers impl<T> RawPtr<T> for *mut T { /// Returns true if the pointer is equal to the null pointer. - #[inline(always)] + #[inline] fn is_null(&const self) -> bool { is_null(*self) } /// Returns true if the pointer is not equal to the null pointer. - #[inline(always)] + #[inline] fn is_not_null(&const self) -> bool { is_not_null(*self) } /// @@ -346,7 +290,7 @@ impl<T> RawPtr<T> for *mut T { /// that this is still an unsafe operation because the returned value could /// be pointing to invalid memory. /// - #[inline(always)] + #[inline] unsafe fn to_option(&const self) -> Option<&T> { if self.is_null() { None } else { Some(cast::transmute(*self)) @@ -354,37 +298,37 @@ impl<T> RawPtr<T> for *mut T { } /// Calculates the offset from a mutable pointer. - #[inline(always)] + #[inline] fn offset(&self, count: uint) -> *mut T { mut_offset(*self, count) } } // Equality for pointers #[cfg(not(test))] impl<T> Eq for *const T { - #[inline(always)] + #[inline] fn eq(&self, other: &*const T) -> bool { (*self as uint) == (*other as uint) } - #[inline(always)] + #[inline] fn ne(&self, other: &*const T) -> bool { !self.eq(other) } } // Comparison for pointers #[cfg(not(test))] impl<T> Ord for *const T { - #[inline(always)] + #[inline] fn lt(&self, other: &*const T) -> bool { (*self as uint) < (*other as uint) } - #[inline(always)] + #[inline] fn le(&self, other: &*const T) -> bool { (*self as uint) <= (*other as uint) } - #[inline(always)] + #[inline] fn ge(&self, other: &*const T) -> bool { (*self as uint) >= (*other as uint) } - #[inline(always)] + #[inline] fn gt(&self, other: &*const T) -> bool { (*self as uint) > (*other as uint) } @@ -592,7 +536,6 @@ pub mod ptr_tests { } #[test] - #[cfg(not(stage0))] fn test_set_memory() { let mut xs = [0u8, ..20]; let ptr = vec::raw::to_mut_ptr(xs); diff --git a/src/libstd/rand.rs b/src/libstd/rand.rs index 7946f7e4f13..739e3dfedc7 100644 --- a/src/libstd/rand.rs +++ b/src/libstd/rand.rs @@ -451,7 +451,7 @@ pub trait RngUtil { /// Extension methods for random number generators impl<R: Rng> RngUtil for R { /// Return a random value for a Rand type - #[inline(always)] + #[inline] fn gen<T: Rand>(&mut self) -> T { Rand::rand(self) } @@ -526,7 +526,7 @@ impl<R: Rng> RngUtil for R { if values.is_empty() { None } else { - Some(values[self.gen_uint_range(0u, values.len())]) + Some(copy values[self.gen_uint_range(0u, values.len())]) } } /** @@ -555,7 +555,7 @@ impl<R: Rng> RngUtil for R { for v.each |item| { so_far += item.weight; if so_far > chosen { - return Some(item.item); + return Some(copy item.item); } } util::unreachable(); @@ -569,7 +569,7 @@ impl<R: Rng> RngUtil for R { let mut r = ~[]; for v.each |item| { for uint::range(0u, item.weight) |_i| { - r.push(item.item); + r.push(copy item.item); } } r @@ -762,7 +762,7 @@ impl IsaacRng { } impl Rng for IsaacRng { - #[inline(always)] + #[inline] fn next(&mut self) -> u32 { if self.cnt == 0 { // make some more numbers @@ -862,7 +862,7 @@ pub fn task_rng() -> @@mut IsaacRng { // Allow direct chaining with `task_rng` impl<R: Rng> Rng for @@mut R { - #[inline(always)] + #[inline] fn next(&mut self) -> u32 { match *self { @@ref mut r => r.next() diff --git a/src/libstd/rand/distributions.rs b/src/libstd/rand/distributions.rs index f08d967cbe0..6f4f1a34977 100644 --- a/src/libstd/rand/distributions.rs +++ b/src/libstd/rand/distributions.rs @@ -26,7 +26,7 @@ use rand::{Rng,Rand}; mod ziggurat_tables; // inlining should mean there is no performance penalty for this -#[inline(always)] +#[inline] fn ziggurat<R:Rng>(rng: &mut R, center_u: bool, X: ziggurat_tables::ZigTable, @@ -77,11 +77,11 @@ pub struct StandardNormal(f64); impl Rand for StandardNormal { fn rand<R:Rng>(rng: &mut R) -> StandardNormal { - #[inline(always)] + #[inline] fn pdf(x: f64) -> f64 { f64::exp((-x*x/2.0) as f64) as f64 } - #[inline(always)] + #[inline] fn zero_case<R:Rng>(rng: &mut R, u: f64) -> f64 { // compute a random number in the tail by hand @@ -131,11 +131,11 @@ pub struct Exp1(f64); impl Rand for Exp1 { #[inline] fn rand<R:Rng>(rng: &mut R) -> Exp1 { - #[inline(always)] + #[inline] fn pdf(x: f64) -> f64 { f64::exp(-x) } - #[inline(always)] + #[inline] fn zero_case<R:Rng>(rng: &mut R, _u: f64) -> f64 { ziggurat_tables::ZIG_EXP_R - f64::ln(rng.gen()) } diff --git a/src/libstd/reflect.rs b/src/libstd/reflect.rs index 1eb3d3a0daa..d276abf0c8b 100644 --- a/src/libstd/reflect.rs +++ b/src/libstd/reflect.rs @@ -35,7 +35,7 @@ pub trait MovePtr { } /// Helper function for alignment calculation. -#[inline(always)] +#[inline] pub fn align(size: uint, align: uint) -> uint { ((size + align) - 1u) & !(align - 1u) } @@ -49,26 +49,26 @@ pub fn MovePtrAdaptor<V:TyVisitor + MovePtr>(v: V) -> MovePtrAdaptor<V> { } impl<V:TyVisitor + MovePtr> MovePtrAdaptor<V> { - #[inline(always)] + #[inline] pub fn bump(&self, sz: uint) { do self.inner.move_ptr() |p| { ((p as uint) + sz) as *c_void }; } - #[inline(always)] + #[inline] pub fn align(&self, a: uint) { do self.inner.move_ptr() |p| { align(p as uint, a) as *c_void }; } - #[inline(always)] + #[inline] pub fn align_to<T>(&self) { self.align(sys::min_align_of::<T>()); } - #[inline(always)] + #[inline] pub fn bump_past<T>(&self) { self.bump(sys::size_of::<T>()); } diff --git a/src/libstd/repr.rs b/src/libstd/repr.rs index 46f69d020d1..ab3f83d34d5 100644 --- a/src/libstd/repr.rs +++ b/src/libstd/repr.rs @@ -18,6 +18,7 @@ More runtime type reflection use cast::transmute; use char; +use container::Container; use intrinsic; use intrinsic::{TyDesc, TyVisitor, visit_tydesc}; use intrinsic::Opaque; @@ -163,7 +164,7 @@ pub fn ReprVisitor(ptr: *c_void, writer: @Writer) -> ReprVisitor { } impl MovePtr for ReprVisitor { - #[inline(always)] + #[inline] fn move_ptr(&self, adjustment: &fn(*c_void) -> *c_void) { *self.ptr = adjustment(*self.ptr); } @@ -178,7 +179,7 @@ impl MovePtr for ReprVisitor { impl ReprVisitor { // Various helpers for the TyVisitor impl - #[inline(always)] + #[inline] pub fn get<T>(&self, f: &fn(&T)) -> bool { unsafe { f(transmute::<*c_void,&T>(*self.ptr)); @@ -186,12 +187,12 @@ impl ReprVisitor { true } - #[inline(always)] + #[inline] pub fn visit_inner(&self, inner: *TyDesc) -> bool { self.visit_ptr_inner(*self.ptr, inner) } - #[inline(always)] + #[inline] pub fn visit_ptr_inner(&self, ptr: *c_void, inner: *TyDesc) -> bool { unsafe { let u = ReprVisitor(ptr, self.writer); @@ -201,7 +202,7 @@ impl ReprVisitor { } } - #[inline(always)] + #[inline] pub fn write<T:Repr>(&self) -> bool { do self.get |v:&T| { v.write_repr(self.writer); @@ -502,7 +503,7 @@ impl TyVisitor for ReprVisitor { _offset: uint, inner: *TyDesc) -> bool { - match self.var_stk[vec::uniq_len(&const *self.var_stk) - 1] { + match self.var_stk[self.var_stk.len() - 1] { Matched => { if i != 0 { self.writer.write_str(", "); @@ -520,7 +521,7 @@ impl TyVisitor for ReprVisitor { _disr_val: int, n_fields: uint, _name: &str) -> bool { - match self.var_stk[vec::uniq_len(&const *self.var_stk) - 1] { + match self.var_stk[self.var_stk.len() - 1] { Matched => { if n_fields > 0 { self.writer.write_char(')'); diff --git a/src/libstd/result.rs b/src/libstd/result.rs index 24751b66925..6cef5c33de0 100644 --- a/src/libstd/result.rs +++ b/src/libstd/result.rs @@ -38,7 +38,7 @@ pub enum Result<T, U> { * * If the result is an error */ -#[inline(always)] +#[inline] pub fn get<T:Copy,U>(res: &Result<T, U>) -> T { match *res { Ok(ref t) => copy *t, @@ -54,7 +54,7 @@ pub fn get<T:Copy,U>(res: &Result<T, U>) -> T { * * If the result is an error */ -#[inline(always)] +#[inline] pub fn get_ref<'a, T, U>(res: &'a Result<T, U>) -> &'a T { match *res { Ok(ref t) => t, @@ -70,7 +70,7 @@ pub fn get_ref<'a, T, U>(res: &'a Result<T, U>) -> &'a T { * * If the result is not an error */ -#[inline(always)] +#[inline] pub fn get_err<T, U: Copy>(res: &Result<T, U>) -> U { match *res { Err(ref u) => copy *u, @@ -79,7 +79,7 @@ pub fn get_err<T, U: Copy>(res: &Result<T, U>) -> U { } /// Returns true if the result is `ok` -#[inline(always)] +#[inline] pub fn is_ok<T, U>(res: &Result<T, U>) -> bool { match *res { Ok(_) => true, @@ -88,7 +88,7 @@ pub fn is_ok<T, U>(res: &Result<T, U>) -> bool { } /// Returns true if the result is `err` -#[inline(always)] +#[inline] pub fn is_err<T, U>(res: &Result<T, U>) -> bool { !is_ok(res) } @@ -99,7 +99,7 @@ pub fn is_err<T, U>(res: &Result<T, U>) -> bool { * `ok` result variants are converted to `either::right` variants, `err` * result variants are converted to `either::left`. */ -#[inline(always)] +#[inline] pub fn to_either<T:Copy,U:Copy>(res: &Result<U, T>) -> Either<T, U> { match *res { @@ -122,7 +122,7 @@ pub fn to_either<T:Copy,U:Copy>(res: &Result<U, T>) * ok(parse_bytes(buf)) * } */ -#[inline(always)] +#[inline] pub fn chain<T, U, V>(res: Result<T, V>, op: &fn(T) -> Result<U, V>) -> Result<U, V> { match res { @@ -139,7 +139,7 @@ pub fn chain<T, U, V>(res: Result<T, V>, op: &fn(T) * immediately returned. This function can be used to pass through a * successful result while handling an error. */ -#[inline(always)] +#[inline] pub fn chain_err<T, U, V>( res: Result<T, V>, op: &fn(t: V) -> Result<T, U>) @@ -164,7 +164,7 @@ pub fn chain_err<T, U, V>( * print_buf(buf) * } */ -#[inline(always)] +#[inline] pub fn iter<T, E>(res: &Result<T, E>, f: &fn(&T)) { match *res { Ok(ref t) => f(t), @@ -180,7 +180,7 @@ pub fn iter<T, E>(res: &Result<T, E>, f: &fn(&T)) { * This function can be used to pass through a successful result while * handling an error. */ -#[inline(always)] +#[inline] pub fn iter_err<T, E>(res: &Result<T, E>, f: &fn(&E)) { match *res { Ok(_) => (), @@ -202,7 +202,7 @@ pub fn iter_err<T, E>(res: &Result<T, E>, f: &fn(&E)) { * parse_bytes(buf) * } */ -#[inline(always)] +#[inline] pub fn map<T, E: Copy, U: Copy>(res: &Result<T, E>, op: &fn(&T) -> U) -> Result<U, E> { match *res { @@ -219,7 +219,7 @@ pub fn map<T, E: Copy, U: Copy>(res: &Result<T, E>, op: &fn(&T) -> U) * is immediately returned. This function can be used to pass through a * successful result while handling an error. */ -#[inline(always)] +#[inline] pub fn map_err<T:Copy,E,F:Copy>(res: &Result<T, E>, op: &fn(&E) -> F) -> Result<T, F> { match *res { @@ -229,53 +229,53 @@ pub fn map_err<T:Copy,E,F:Copy>(res: &Result<T, E>, op: &fn(&E) -> F) } impl<T, E> Result<T, E> { - #[inline(always)] + #[inline] pub fn get_ref<'a>(&'a self) -> &'a T { get_ref(self) } - #[inline(always)] + #[inline] pub fn is_ok(&self) -> bool { is_ok(self) } - #[inline(always)] + #[inline] pub fn is_err(&self) -> bool { is_err(self) } - #[inline(always)] + #[inline] pub fn iter(&self, f: &fn(&T)) { iter(self, f) } - #[inline(always)] + #[inline] pub fn iter_err(&self, f: &fn(&E)) { iter_err(self, f) } - #[inline(always)] + #[inline] pub fn unwrap(self) -> T { unwrap(self) } - #[inline(always)] + #[inline] pub fn unwrap_err(self) -> E { unwrap_err(self) } - #[inline(always)] + #[inline] pub fn chain<U>(self, op: &fn(T) -> Result<U,E>) -> Result<U,E> { chain(self, op) } - #[inline(always)] + #[inline] pub fn chain_err<F>(self, op: &fn(E) -> Result<T,F>) -> Result<T,F> { chain_err(self, op) } } impl<T:Copy,E> Result<T, E> { - #[inline(always)] + #[inline] pub fn get(&self) -> T { get(self) } - #[inline(always)] + #[inline] pub fn map_err<F:Copy>(&self, op: &fn(&E) -> F) -> Result<T,F> { map_err(self, op) } } impl<T, E: Copy> Result<T, E> { - #[inline(always)] + #[inline] pub fn get_err(&self) -> E { get_err(self) } - #[inline(always)] + #[inline] pub fn map<U:Copy>(&self, op: &fn(&T) -> U) -> Result<U,E> { map(self, op) } @@ -298,7 +298,7 @@ impl<T, E: Copy> Result<T, E> { * assert!(incd == ~[2u, 3u, 4u]); * } */ -#[inline(always)] +#[inline] pub fn map_vec<T,U:Copy,V:Copy>( ts: &[T], op: &fn(&T) -> Result<V,U>) -> Result<~[V],U> { @@ -312,7 +312,7 @@ pub fn map_vec<T,U:Copy,V:Copy>( return Ok(vs); } -#[inline(always)] +#[inline] #[allow(missing_doc)] pub fn map_opt<T,U:Copy,V:Copy>( o_t: &Option<T>, op: &fn(&T) -> Result<V,U>) -> Result<Option<V>,U> { @@ -335,7 +335,7 @@ pub fn map_opt<T,U:Copy,V:Copy>( * used in 'careful' code contexts where it is both appropriate and easy * to accommodate an error like the vectors being of different lengths. */ -#[inline(always)] +#[inline] pub fn map_vec2<S,T,U:Copy,V:Copy>(ss: &[S], ts: &[T], op: &fn(&S,&T) -> Result<V,U>) -> Result<~[V],U> { @@ -358,7 +358,7 @@ pub fn map_vec2<S,T,U:Copy,V:Copy>(ss: &[S], ts: &[T], * error. This could be implemented using `map_zip()` but it is more efficient * on its own as no result vector is built. */ -#[inline(always)] +#[inline] pub fn iter_vec2<S,T,U:Copy>(ss: &[S], ts: &[T], op: &fn(&S,&T) -> Result<(),U>) -> Result<(),U> { @@ -376,7 +376,7 @@ pub fn iter_vec2<S,T,U:Copy>(ss: &[S], ts: &[T], } /// Unwraps a result, assuming it is an `ok(T)` -#[inline(always)] +#[inline] pub fn unwrap<T, U>(res: Result<T, U>) -> T { match res { Ok(t) => t, @@ -385,7 +385,7 @@ pub fn unwrap<T, U>(res: Result<T, U>) -> T { } /// Unwraps a result, assuming it is an `err(U)` -#[inline(always)] +#[inline] pub fn unwrap_err<T, U>(res: Result<T, U>) -> U { match res { Err(u) => u, diff --git a/src/libstd/rt/args.rs b/src/libstd/rt/args.rs new file mode 100644 index 00000000000..75ee4f381f6 --- /dev/null +++ b/src/libstd/rt/args.rs @@ -0,0 +1,125 @@ +// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Global storage for command line arguments +//! +//! The current incarnation of the Rust runtime expects for +//! the processes `argc` and `argv` arguments to be stored +//! in a globally-accessible location for use by the `os` module. +//! +//! XXX: Would be nice for this to not exist. +//! XXX: This has a lot of C glue for lack of globals. + +use libc; +use option::{Option, Some, None}; +use str; +use uint; +use unstable::finally::Finally; +use util; + +/// One-time global initialization. +pub unsafe fn init(argc: int, argv: **u8) { + let args = load_argc_and_argv(argc, argv); + put(args); +} + +/// One-time global cleanup. +pub fn cleanup() { + rtassert!(take().is_some()); +} + +/// Take the global arguments from global storage. +pub fn take() -> Option<~[~str]> { + with_lock(|| unsafe { + let ptr = get_global_ptr(); + let val = util::replace(&mut *ptr, None); + val.map(|s: &~~[~str]| (**s).clone()) + }) +} + +/// Give the global arguments to global storage. +/// +/// It is an error if the arguments already exist. +pub fn put(args: ~[~str]) { + with_lock(|| unsafe { + let ptr = get_global_ptr(); + rtassert!((*ptr).is_none()); + (*ptr) = Some(~args.clone()); + }) +} + +/// Make a clone of the global arguments. +pub fn clone() -> Option<~[~str]> { + with_lock(|| unsafe { + let ptr = get_global_ptr(); + (*ptr).map(|s: &~~[~str]| (**s).clone()) + }) +} + +fn with_lock<T>(f: &fn() -> T) -> T { + do (|| { + unsafe { + rust_take_global_args_lock(); + f() + } + }).finally { + unsafe { + rust_drop_global_args_lock(); + } + } +} + +fn get_global_ptr() -> *mut Option<~~[~str]> { + unsafe { rust_get_global_args_ptr() } +} + +// Copied from `os`. +unsafe fn load_argc_and_argv(argc: int, argv: **u8) -> ~[~str] { + let mut args = ~[]; + for uint::range(0, argc as uint) |i| { + args.push(str::raw::from_c_str(*(argv as **libc::c_char).offset(i))); + } + return args; +} + +extern { + fn rust_take_global_args_lock(); + fn rust_drop_global_args_lock(); + fn rust_get_global_args_ptr() -> *mut Option<~~[~str]>; +} + +#[cfg(test)] +mod tests { + use option::{Some, None}; + use super::*; + use unstable::finally::Finally; + + #[test] + fn smoke_test() { + // Preserve the actual global state. + let saved_value = take(); + + let expected = ~[~"happy", ~"today?"]; + + put(expected.clone()); + assert!(clone() == Some(expected.clone())); + assert!(take() == Some(expected.clone())); + assert!(take() == None); + + do (|| { + }).finally { + // Restore the actual global state. + match saved_value { + Some(ref args) => put(args.clone()), + None => () + } + } + } +} diff --git a/src/libstd/rt/borrowck.rs b/src/libstd/rt/borrowck.rs new file mode 100644 index 00000000000..e057f6e9637 --- /dev/null +++ b/src/libstd/rt/borrowck.rs @@ -0,0 +1,283 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use cast::transmute; +use libc::{c_char, c_void, size_t, STDERR_FILENO}; +use io; +use io::{Writer, WriterUtil}; +use managed::raw::BoxRepr; +use option::{Option, None, Some}; +use uint; +use str; +use str::OwnedStr; +use sys; +use vec::ImmutableVector; + +#[allow(non_camel_case_types)] +type rust_task = c_void; + +pub static FROZEN_BIT: uint = 1 << (uint::bits - 1); +pub static MUT_BIT: uint = 1 << (uint::bits - 2); +static ALL_BITS: uint = FROZEN_BIT | MUT_BIT; + +#[deriving(Eq)] +struct BorrowRecord { + box: *mut BoxRepr, + file: *c_char, + line: size_t +} + +fn try_take_task_borrow_list() -> Option<~[BorrowRecord]> { + unsafe { + let cur_task: *rust_task = rust_try_get_task(); + if cur_task.is_not_null() { + let ptr = rust_take_task_borrow_list(cur_task); + if ptr.is_null() { + None + } else { + let v: ~[BorrowRecord] = transmute(ptr); + Some(v) + } + } else { + None + } + } +} + +fn swap_task_borrow_list(f: &fn(~[BorrowRecord]) -> ~[BorrowRecord]) { + unsafe { + let cur_task: *rust_task = rust_try_get_task(); + if cur_task.is_not_null() { + let mut borrow_list: ~[BorrowRecord] = { + let ptr = rust_take_task_borrow_list(cur_task); + if ptr.is_null() { ~[] } else { transmute(ptr) } + }; + borrow_list = f(borrow_list); + rust_set_task_borrow_list(cur_task, transmute(borrow_list)); + } + } +} + +pub unsafe fn clear_task_borrow_list() { + // pub because it is used by the box annihilator. + let _ = try_take_task_borrow_list(); +} + +unsafe fn fail_borrowed(box: *mut BoxRepr, file: *c_char, line: size_t) { + debug_borrow("fail_borrowed: ", box, 0, 0, file, line); + + match try_take_task_borrow_list() { + None => { // not recording borrows + let msg = "borrowed"; + do str::as_buf(msg) |msg_p, _| { + sys::begin_unwind_(msg_p as *c_char, file, line); + } + } + Some(borrow_list) => { // recording borrows + let mut msg = ~"borrowed"; + let mut sep = " at "; + for borrow_list.rev_iter().advance |entry| { + if entry.box == box { + msg.push_str(sep); + let filename = str::raw::from_c_str(entry.file); + msg.push_str(filename); + msg.push_str(fmt!(":%u", entry.line as uint)); + sep = " and at "; + } + } + do str::as_buf(msg) |msg_p, _| { + sys::begin_unwind_(msg_p as *c_char, file, line) + } + } + } +} + +/// Because this code is so perf. sensitive, use a static constant so that +/// debug printouts are compiled out most of the time. +static ENABLE_DEBUG: bool = false; + +#[inline] +unsafe fn debug_borrow<T>(tag: &'static str, + p: *const T, + old_bits: uint, + new_bits: uint, + filename: *c_char, + line: size_t) { + //! A useful debugging function that prints a pointer + tag + newline + //! without allocating memory. + + if ENABLE_DEBUG && ::rt::env::get().debug_borrow { + debug_borrow_slow(tag, p, old_bits, new_bits, filename, line); + } + + unsafe fn debug_borrow_slow<T>(tag: &'static str, + p: *const T, + old_bits: uint, + new_bits: uint, + filename: *c_char, + line: size_t) { + let dbg = STDERR_FILENO as io::fd_t; + dbg.write_str(tag); + dbg.write_hex(p as uint); + dbg.write_str(" "); + dbg.write_hex(old_bits); + dbg.write_str(" "); + dbg.write_hex(new_bits); + dbg.write_str(" "); + dbg.write_cstr(filename); + dbg.write_str(":"); + dbg.write_hex(line as uint); + dbg.write_str("\n"); + } +} + +trait DebugPrints { + fn write_hex(&self, val: uint); + unsafe fn write_cstr(&self, str: *c_char); +} + +impl DebugPrints for io::fd_t { + fn write_hex(&self, mut i: uint) { + let letters = ['0', '1', '2', '3', '4', '5', '6', '7', '8', + '9', 'a', 'b', 'c', 'd', 'e', 'f']; + static uint_nibbles: uint = ::uint::bytes << 1; + let mut buffer = [0_u8, ..uint_nibbles+1]; + let mut c = uint_nibbles; + while c > 0 { + c -= 1; + buffer[c] = letters[i & 0xF] as u8; + i >>= 4; + } + self.write(buffer.slice(0, uint_nibbles)); + } + + unsafe fn write_cstr(&self, p: *c_char) { + use libc::strlen; + use vec; + + let len = strlen(p); + let p: *u8 = transmute(p); + do vec::raw::buf_as_slice(p, len as uint) |s| { + self.write(s); + } + } +} + +#[inline] +pub unsafe fn borrow_as_imm(a: *u8, file: *c_char, line: size_t) -> uint { + let a: *mut BoxRepr = transmute(a); + let old_ref_count = (*a).header.ref_count; + let new_ref_count = old_ref_count | FROZEN_BIT; + + debug_borrow("borrow_as_imm:", a, old_ref_count, new_ref_count, file, line); + + if (old_ref_count & MUT_BIT) != 0 { + fail_borrowed(a, file, line); + } + + (*a).header.ref_count = new_ref_count; + + old_ref_count +} + +#[inline] +pub unsafe fn borrow_as_mut(a: *u8, file: *c_char, line: size_t) -> uint { + let a: *mut BoxRepr = transmute(a); + let old_ref_count = (*a).header.ref_count; + let new_ref_count = old_ref_count | MUT_BIT | FROZEN_BIT; + + debug_borrow("borrow_as_mut:", a, old_ref_count, new_ref_count, file, line); + + if (old_ref_count & (MUT_BIT|FROZEN_BIT)) != 0 { + fail_borrowed(a, file, line); + } + + (*a).header.ref_count = new_ref_count; + + old_ref_count +} + +pub unsafe fn record_borrow(a: *u8, old_ref_count: uint, + file: *c_char, line: size_t) { + if (old_ref_count & ALL_BITS) == 0 { + // was not borrowed before + let a: *mut BoxRepr = transmute(a); + debug_borrow("record_borrow:", a, old_ref_count, 0, file, line); + do swap_task_borrow_list |borrow_list| { + let mut borrow_list = borrow_list; + borrow_list.push(BorrowRecord {box: a, file: file, line: line}); + borrow_list + } + } +} + +pub unsafe fn unrecord_borrow(a: *u8, old_ref_count: uint, + file: *c_char, line: size_t) { + if (old_ref_count & ALL_BITS) == 0 { + // was not borrowed before, so we should find the record at + // the end of the list + let a: *mut BoxRepr = transmute(a); + debug_borrow("unrecord_borrow:", a, old_ref_count, 0, file, line); + do swap_task_borrow_list |borrow_list| { + let mut borrow_list = borrow_list; + assert!(!borrow_list.is_empty()); + let br = borrow_list.pop(); + if br.box != a || br.file != file || br.line != line { + let err = fmt!("wrong borrow found, br=%?", br); + do str::as_buf(err) |msg_p, _| { + sys::begin_unwind_(msg_p as *c_char, file, line) + } + } + borrow_list + } + } +} + +#[inline] +pub unsafe fn return_to_mut(a: *u8, orig_ref_count: uint, + file: *c_char, line: size_t) { + // Sometimes the box is null, if it is conditionally frozen. + // See e.g. #4904. + if !a.is_null() { + let a: *mut BoxRepr = transmute(a); + let old_ref_count = (*a).header.ref_count; + let new_ref_count = + (old_ref_count & !ALL_BITS) | (orig_ref_count & ALL_BITS); + + debug_borrow("return_to_mut:", + a, old_ref_count, new_ref_count, file, line); + + (*a).header.ref_count = new_ref_count; + } +} + +#[inline] +pub unsafe fn check_not_borrowed(a: *u8, + file: *c_char, + line: size_t) { + let a: *mut BoxRepr = transmute(a); + let ref_count = (*a).header.ref_count; + debug_borrow("check_not_borrowed:", a, ref_count, 0, file, line); + if (ref_count & FROZEN_BIT) != 0 { + fail_borrowed(a, file, line); + } +} + + +extern { + #[rust_stack] + pub fn rust_take_task_borrow_list(task: *rust_task) -> *c_void; + + #[rust_stack] + pub fn rust_set_task_borrow_list(task: *rust_task, map: *c_void); + + #[rust_stack] + pub fn rust_try_get_task() -> *rust_task; +} diff --git a/src/libstd/rt/comm.rs b/src/libstd/rt/comm.rs index 82e6d44fe62..dd27c03ff51 100644 --- a/src/libstd/rt/comm.rs +++ b/src/libstd/rt/comm.rs @@ -399,12 +399,6 @@ impl<T: Owned> GenericChan<T> for SharedChan<T> { } impl<T: Owned> GenericSmartChan<T> for SharedChan<T> { - #[cfg(stage0)] // odd type checking errors - fn try_send(&self, _val: T) -> bool { - fail!() - } - - #[cfg(not(stage0))] fn try_send(&self, val: T) -> bool { unsafe { let (next_pone, next_cone) = oneshot(); @@ -448,12 +442,6 @@ impl<T: Owned> GenericPort<T> for SharedPort<T> { } } - #[cfg(stage0)] // odd type checking errors - fn try_recv(&self) -> Option<T> { - fail!() - } - - #[cfg(not(stage0))] fn try_recv(&self) -> Option<T> { unsafe { let (next_link_port, next_link_chan) = oneshot(); diff --git a/src/libstd/rt/context.rs b/src/libstd/rt/context.rs index d5ca8473cee..09ba869549f 100644 --- a/src/libstd/rt/context.rs +++ b/src/libstd/rt/context.rs @@ -207,7 +207,7 @@ fn align_down(sp: *mut uint) -> *mut uint { } // XXX: ptr::offset is positive ints only -#[inline(always)] +#[inline] pub fn mut_offset<T>(ptr: *mut T, count: int) -> *mut T { use core::sys::size_of; (ptr as int + count * (size_of::<T>() as int)) as *mut T diff --git a/src/libstd/rt/io/extensions.rs b/src/libstd/rt/io/extensions.rs index c7c3eadbe21..55861f127bb 100644 --- a/src/libstd/rt/io/extensions.rs +++ b/src/libstd/rt/io/extensions.rs @@ -297,7 +297,8 @@ impl<T: Reader> ReaderUtil for T { do (|| { while total_read < len { - let slice = vec::mut_slice(*buf, start_len + total_read, buf.len()); + let len = buf.len(); + let slice = vec::mut_slice(*buf, start_len + total_read, len); match self.read(slice) { Some(nread) => { total_read += nread; diff --git a/src/libstd/rt/local_heap.rs b/src/libstd/rt/local_heap.rs index 6bf228a1b22..f62c9fb2c66 100644 --- a/src/libstd/rt/local_heap.rs +++ b/src/libstd/rt/local_heap.rs @@ -10,11 +10,24 @@ //! The local, garbage collected heap +use libc; use libc::{c_void, uintptr_t, size_t}; use ops::Drop; +use repr::BoxRepr; +use rt; +use rt::OldTaskContext; +use rt::local::Local; +use rt::task::Task; type MemoryRegion = c_void; -type BoxedRegion = c_void; + +struct Env { priv opaque: () } + +struct BoxedRegion { + env: *Env, + backing_region: *MemoryRegion, + live_allocs: *BoxRepr +} pub type OpaqueBox = c_void; pub type TypeDesc = c_void; @@ -49,6 +62,12 @@ impl LocalHeap { } } + pub fn realloc(&mut self, ptr: *OpaqueBox, size: uint) -> *OpaqueBox { + unsafe { + return rust_boxed_region_realloc(self.boxed_region, ptr, size as size_t); + } + } + pub fn free(&mut self, box: *OpaqueBox) { unsafe { return rust_boxed_region_free(self.boxed_region, box); @@ -65,6 +84,40 @@ impl Drop for LocalHeap { } } +// A little compatibility function +pub unsafe fn local_free(ptr: *libc::c_char) { + match rt::context() { + OldTaskContext => { + rust_upcall_free_noswitch(ptr); + + extern { + #[fast_ffi] + unsafe fn rust_upcall_free_noswitch(ptr: *libc::c_char); + } + } + _ => { + do Local::borrow::<Task,()> |task| { + task.heap.free(ptr as *libc::c_void); + } + } + } +} + +pub fn live_allocs() -> *BoxRepr { + let region = match rt::context() { + OldTaskContext => { + unsafe { rust_current_boxed_region() } + } + _ => { + do Local::borrow::<Task, *BoxedRegion> |task| { + task.heap.boxed_region + } + } + }; + + return unsafe { (*region).live_allocs }; +} + extern { fn rust_new_memory_region(synchronized: uintptr_t, detailed_leaks: uintptr_t, @@ -76,5 +129,9 @@ extern { fn rust_boxed_region_malloc(region: *BoxedRegion, td: *TypeDesc, size: size_t) -> *OpaqueBox; + fn rust_boxed_region_realloc(region: *BoxedRegion, + ptr: *OpaqueBox, + size: size_t) -> *OpaqueBox; fn rust_boxed_region_free(region: *BoxedRegion, box: *OpaqueBox); + fn rust_current_boxed_region() -> *BoxedRegion; } diff --git a/src/libstd/rt/logging.rs b/src/libstd/rt/logging.rs index a0d05397689..84186180aa6 100644 --- a/src/libstd/rt/logging.rs +++ b/src/libstd/rt/logging.rs @@ -9,6 +9,7 @@ // except according to those terms. use either::*; +use libc; pub trait Logger { fn log(&mut self, msg: Either<~str, &'static str>); @@ -20,6 +21,10 @@ impl Logger for StdErrLogger { fn log(&mut self, msg: Either<~str, &'static str>) { use io::{Writer, WriterUtil}; + if !should_log_console() { + return; + } + let s: &str = match msg { Left(ref s) => { let s: &str = *s; @@ -44,7 +49,6 @@ pub fn init(crate_map: *u8) { use str; use ptr; use option::{Some, None}; - use libc::c_char; let log_spec = os::getenv("RUST_LOG"); match log_spec { @@ -61,8 +65,16 @@ pub fn init(crate_map: *u8) { } } } +} - extern { - fn rust_update_log_settings(crate_map: *u8, settings: *c_char); - } +pub fn console_on() { unsafe { rust_log_console_on() } } +pub fn console_off() { unsafe { rust_log_console_off() } } +fn should_log_console() -> bool { unsafe { rust_should_log_console() != 0 } } + +extern { + fn rust_update_log_settings(crate_map: *u8, settings: *libc::c_char); + fn rust_log_console_on(); + fn rust_log_console_off(); + fn rust_should_log_console() -> libc::uintptr_t; } + diff --git a/src/libstd/rt/mod.rs b/src/libstd/rt/mod.rs index 581e3addff0..bbf1cf0d9b7 100644 --- a/src/libstd/rt/mod.rs +++ b/src/libstd/rt/mod.rs @@ -58,22 +58,23 @@ Several modules in `core` are clients of `rt`: #[deny(unused_imports)]; #[deny(unused_mut)]; #[deny(unused_variable)]; +#[deny(unused_unsafe)]; use cell::Cell; use clone::Clone; use container::Container; -use from_str::FromStr; +use iter::Times; use iterator::IteratorUtil; -use option::{Some, None}; -use os; +use option::Some; use ptr::RawPtr; -use uint; use rt::sched::{Scheduler, Coroutine, Shutdown}; use rt::sleeper_list::SleeperList; use rt::task::Task; use rt::thread::Thread; use rt::work_queue::WorkQueue; use rt::uv::uvio::UvEventLoop; +use unstable::atomics::{AtomicInt, SeqCst}; +use unstable::sync::UnsafeAtomicRcBox; use vec::{OwnedVector, MutableVector}; /// The global (exchange) heap. @@ -122,7 +123,7 @@ mod thread; pub mod env; /// The local, managed heap -mod local_heap; +pub mod local_heap; /// The Logger trait and implementations pub mod logging; @@ -148,7 +149,7 @@ pub mod local_ptr; /// Bindings to pthread/windows thread-local storage. pub mod thread_local_storage; -/// A concurrent data structure with which parent tasks wait on child tasks. +/// For waiting on child tasks. pub mod join_latch; pub mod metrics; @@ -157,6 +158,12 @@ pub mod metrics; /// Just stuff pub mod util; +// Global command line argument storage +pub mod args; + +// Support for dynamic borrowck +pub mod borrowck; + /// Set up a default runtime configuration, given compiler-supplied arguments. /// /// This is invoked by the `start` _language item_ (unstable::lang) to @@ -171,71 +178,104 @@ pub mod util; /// # Return value /// /// The return value is used as the process return code. 0 on success, 101 on error. -pub fn start(_argc: int, _argv: **u8, crate_map: *u8, main: ~fn()) -> int { +pub fn start(argc: int, argv: **u8, crate_map: *u8, main: ~fn()) -> int { - init(crate_map); - run(main); + init(argc, argv, crate_map); + let exit_code = run(main); cleanup(); - return 0; + return exit_code; } -/// One-time runtime initialization. Currently all this does is set up logging -/// based on the RUST_LOG environment variable. -pub fn init(crate_map: *u8) { - logging::init(crate_map); +/// One-time runtime initialization. +/// +/// Initializes global state, including frobbing +/// the crate's logging flags, registering GC +/// metadata, and storing the process arguments. +pub fn init(argc: int, argv: **u8, crate_map: *u8) { + // XXX: Derefing these pointers is not safe. + // Need to propagate the unsafety to `start`. + unsafe { + args::init(argc, argv); + logging::init(crate_map); + rust_update_gc_metadata(crate_map); + } + + extern { + fn rust_update_gc_metadata(crate_map: *u8); + } } +/// One-time runtime cleanup. pub fn cleanup() { + args::cleanup(); global_heap::cleanup(); } -pub fn run(main: ~fn()) { - let nthreads = match os::getenv("RUST_THREADS") { - Some(nstr) => FromStr::from_str(nstr).get(), - None => unsafe { - // Using more threads than cores in test code - // to force the OS to preempt them frequently. - // Assuming that this help stress test concurrent types. - util::num_cpus() * 2 - } - }; +/// Execute the main function in a scheduler. +/// +/// Configures the runtime according to the environment, by default +/// using a task scheduler with the same number of threads as cores. +/// Returns a process exit code. +pub fn run(main: ~fn()) -> int { + + static DEFAULT_ERROR_CODE: int = 101; + let nthreads = util::default_sched_threads(); + + // The shared list of sleeping schedulers. Schedulers wake each other + // occassionally to do new work. let sleepers = SleeperList::new(); + // The shared work queue. Temporary until work stealing is implemented. let work_queue = WorkQueue::new(); - let mut handles = ~[]; + // The schedulers. let mut scheds = ~[]; + // Handles to the schedulers. When the main task ends these will be + // sent the Shutdown message to terminate the schedulers. + let mut handles = ~[]; - for uint::range(0, nthreads) |_| { + for nthreads.times { + // Every scheduler is driven by an I/O event loop. let loop_ = ~UvEventLoop::new(); let mut sched = ~Scheduler::new(loop_, work_queue.clone(), sleepers.clone()); let handle = sched.make_handle(); - handles.push(handle); scheds.push(sched); + handles.push(handle); } - let main_cell = Cell::new(main); + // Create a shared cell for transmitting the process exit + // code from the main task to this function. + let exit_code = UnsafeAtomicRcBox::new(AtomicInt::new(0)); + let exit_code_clone = exit_code.clone(); + + // When the main task exits, after all the tasks in the main + // task tree, shut down the schedulers and set the exit code. let handles = Cell::new(handles); - let mut new_task = ~Task::new_root(); - let on_exit: ~fn(bool) = |exit_status| { + let on_exit: ~fn(bool) = |exit_success| { let mut handles = handles.take(); - // Tell schedulers to exit for handles.mut_iter().advance |handle| { handle.send(Shutdown); } - rtassert!(exit_status); + unsafe { + let exit_code = if exit_success { 0 } else { DEFAULT_ERROR_CODE }; + (*exit_code_clone.get()).store(exit_code, SeqCst); + } }; + + // Create and enqueue the main task. + let main_cell = Cell::new(main); + let mut new_task = ~Task::new_root(); new_task.on_exit = Some(on_exit); let main_task = ~Coroutine::with_task(&mut scheds[0].stack_pool, new_task, main_cell.take()); scheds[0].enqueue_task(main_task); + // Run each scheduler in a thread. let mut threads = ~[]; - while !scheds.is_empty() { let sched = scheds.pop(); let sched_cell = Cell::new(sched); @@ -248,7 +288,12 @@ pub fn run(main: ~fn()) { } // Wait for schedulers - let _threads = threads; + { let _threads = threads; } + + // Return the exit code + unsafe { + (*exit_code.get()).load(SeqCst) + } } /// Possible contexts in which Rust code may be executing. diff --git a/src/libstd/rt/sched.rs b/src/libstd/rt/sched.rs index 453d3303db6..bbe4aa25e29 100644 --- a/src/libstd/rt/sched.rs +++ b/src/libstd/rt/sched.rs @@ -646,12 +646,12 @@ impl Scheduler { } } -// The cases for the below function. +// The cases for the below function. enum ResumeAction { SendHome, Requeue, ResumeNow, - Homeless + Homeless } impl SchedHandle { diff --git a/src/libstd/rt/task.rs b/src/libstd/rt/task.rs index e7f87906fe5..97c3b6a749b 100644 --- a/src/libstd/rt/task.rs +++ b/src/libstd/rt/task.rs @@ -15,6 +15,7 @@ use borrow; use cast::transmute; +use cleanup; use libc::{c_void, uintptr_t}; use ptr; use prelude::*; @@ -118,6 +119,10 @@ impl Task { } _ => () } + + // Destroy remaining boxes + unsafe { cleanup::annihilate(); } + self.destroyed = true; } } @@ -249,6 +254,18 @@ mod test { } #[test] + fn comm_shared_chan() { + use comm::*; + + do run_in_newsched_task() { + let (port, chan) = stream(); + let chan = SharedChan::new(chan); + chan.send(10); + assert!(port.recv() == 10); + } + } + + #[test] fn linked_failure() { do run_in_newsched_task() { let res = do spawntask_try { @@ -257,4 +274,45 @@ mod test { assert!(res.is_err()); } } + + #[test] + fn heap_cycles() { + use option::{Option, Some, None}; + + do run_in_newsched_task { + struct List { + next: Option<@mut List>, + } + + let a = @mut List { next: None }; + let b = @mut List { next: Some(a) }; + + a.next = Some(b); + } + } + + // XXX: This is a copy of test_future_result in std::task. + // It can be removed once the scheduler is turned on by default. + #[test] + fn future_result() { + do run_in_newsched_task { + use option::{Some, None}; + use task::*; + + let mut result = None; + let mut builder = task(); + builder.future_result(|r| result = Some(r)); + do builder.spawn {} + assert_eq!(result.unwrap().recv(), Success); + + result = None; + let mut builder = task(); + builder.future_result(|r| result = Some(r)); + builder.unlinked(); + do builder.spawn { + fail!(); + } + assert_eq!(result.unwrap().recv(), Failure); + } + } } diff --git a/src/libstd/rt/test.rs b/src/libstd/rt/test.rs index 36efcd91834..b0e49684014 100644 --- a/src/libstd/rt/test.rs +++ b/src/libstd/rt/test.rs @@ -74,7 +74,7 @@ pub fn run_in_mt_newsched_task(f: ~fn()) { do run_in_bare_thread { let nthreads = match os::getenv("RUST_TEST_THREADS") { Some(nstr) => FromStr::from_str(nstr).get(), - None => unsafe { + None => { // Using more threads than cores in test code // to force the OS to preempt them frequently. // Assuming that this help stress test concurrent types. diff --git a/src/libstd/rt/util.rs b/src/libstd/rt/util.rs index 904b2f8bbb9..5219ae1d540 100644 --- a/src/libstd/rt/util.rs +++ b/src/libstd/rt/util.rs @@ -9,8 +9,11 @@ // except according to those terms. use container::Container; +use from_str::FromStr; use iterator::IteratorUtil; use libc; +use option::{Some, None}; +use os; use str::StrSlice; /// Get the number of cores available @@ -24,6 +27,15 @@ pub fn num_cpus() -> uint { } } +/// Get's the number of scheduler threads requested by the environment +/// either `RUST_THREADS` or `num_cpus`. +pub fn default_sched_threads() -> uint { + match os::getenv("RUST_THREADS") { + Some(nstr) => FromStr::from_str(nstr).get(), + None => num_cpus() + } +} + pub fn dumb_println(s: &str) { use io::WriterUtil; let dbg = ::libc::STDERR_FILENO as ::io::fd_t; diff --git a/src/libstd/rt/uv/timer.rs b/src/libstd/rt/uv/timer.rs index 5557a580987..14465eb7dfd 100644 --- a/src/libstd/rt/uv/timer.rs +++ b/src/libstd/rt/uv/timer.rs @@ -143,7 +143,7 @@ mod test { let count_ptr: *mut int = &mut count; let mut loop_ = Loop::new(); let mut timer = TimerWatcher::new(&mut loop_); - do timer.start(10, 20) |timer, status| { + do timer.start(1, 2) |timer, status| { assert!(status.is_none()); unsafe { *count_ptr += 1; @@ -160,14 +160,14 @@ mod test { let mut timer2 = TimerWatcher::new(&mut loop_); do timer2.start(10, 0) |timer2, _| { - unsafe { *count_ptr += 1; } + *count_ptr += 1; timer2.close(||()); // Restart the original timer let mut timer = timer; - do timer.start(10, 0) |timer, _| { - unsafe { *count_ptr += 1; } + do timer.start(1, 0) |timer, _| { + *count_ptr += 1; timer.close(||()); } } diff --git a/src/libstd/run.rs b/src/libstd/run.rs index b204cf6cfb0..060de3f4d5d 100644 --- a/src/libstd/run.rs +++ b/src/libstd/run.rs @@ -915,7 +915,7 @@ priv fn waitpid(pid: pid_t) -> int { #[cfg(test)] mod tests { use io; - use libc::{c_int}; + use libc::{c_int, uintptr_t}; use option::{Option, None, Some}; use os; use path::Path; @@ -958,7 +958,10 @@ mod tests { assert_eq!(status, 0); assert_eq!(output_str.trim().to_owned(), ~"hello"); - assert_eq!(error, ~[]); + // FIXME #7224 + if !running_on_valgrind() { + assert_eq!(error, ~[]); + } } #[test] @@ -1043,7 +1046,10 @@ mod tests { assert_eq!(status, 0); assert_eq!(output_str.trim().to_owned(), ~"hello"); - assert_eq!(error, ~[]); + // FIXME #7224 + if !running_on_valgrind() { + assert_eq!(error, ~[]); + } } #[test] @@ -1057,14 +1063,20 @@ mod tests { assert_eq!(status, 0); assert_eq!(output_str.trim().to_owned(), ~"hello"); - assert_eq!(error, ~[]); + // FIXME #7224 + if !running_on_valgrind() { + assert_eq!(error, ~[]); + } let run::ProcessOutput {status, output, error} = prog.finish_with_output(); assert_eq!(status, 0); assert_eq!(output, ~[]); - assert_eq!(error, ~[]); + // FIXME #7224 + if !running_on_valgrind() { + assert_eq!(error, ~[]); + } } #[test] @@ -1148,6 +1160,7 @@ mod tests { #[test] fn test_inherit_env() { + if running_on_valgrind() { return; } let mut prog = run_env(None); let output = str::from_bytes(prog.finish_with_output().output); @@ -1169,4 +1182,12 @@ mod tests { assert!(output.contains("RUN_TEST_NEW_ENV=123")); } + + fn running_on_valgrind() -> bool { + unsafe { rust_running_on_valgrind() != 0 } + } + + extern { + fn rust_running_on_valgrind() -> uintptr_t; + } } diff --git a/src/libstd/str.rs b/src/libstd/str.rs index 1086fcaa75c..04f5247782b 100644 --- a/src/libstd/str.rs +++ b/src/libstd/str.rs @@ -23,11 +23,11 @@ use cast; use char; use char::Char; use clone::Clone; -use cmp::{TotalOrd, Ordering, Less, Equal, Greater}; use container::Container; use iter::Times; -use iterator::{Iterator, IteratorUtil, FilterIterator, AdditiveIterator}; +use iterator::{Iterator, IteratorUtil, FilterIterator, AdditiveIterator, MapIterator}; use libc; +use num::Zero; use option::{None, Option, Some}; use old_iter::{BaseIter, EqIter}; use ptr; @@ -37,8 +37,6 @@ use uint; use vec; use vec::{OwnedVector, OwnedCopyableVector, ImmutableVector}; -#[cfg(not(test))] use cmp::{Eq, Ord, Equiv, TotalEq}; - /* Section: Conditions */ @@ -108,21 +106,21 @@ pub fn from_bytes_slice<'a>(vector: &'a [u8]) -> &'a str { } /// Copy a slice into a new unique str -#[inline(always)] +#[inline] pub fn to_owned(s: &str) -> ~str { unsafe { raw::slice_bytes_owned(s, 0, s.len()) } } impl ToStr for ~str { - #[inline(always)] + #[inline] fn to_str(&self) -> ~str { to_owned(*self) } } impl<'self> ToStr for &'self str { - #[inline(always)] + #[inline] fn to_str(&self) -> ~str { to_owned(*self) } } impl ToStr for @str { - #[inline(always)] + #[inline] fn to_str(&self) -> ~str { to_owned(*self) } } @@ -243,26 +241,26 @@ pub trait CharEq { fn only_ascii(&self) -> bool; } impl CharEq for char { - #[inline(always)] + #[inline] fn matches(&self, c: char) -> bool { *self == c } fn only_ascii(&self) -> bool { (*self as uint) < 128 } } impl<'self> CharEq for &'self fn(char) -> bool { - #[inline(always)] + #[inline] fn matches(&self, c: char) -> bool { (*self)(c) } fn only_ascii(&self) -> bool { false } } impl CharEq for extern "Rust" fn(char) -> bool { - #[inline(always)] + #[inline] fn matches(&self, c: char) -> bool { (*self)(c) } fn only_ascii(&self) -> bool { false } } impl<'self, C: CharEq> CharEq for &'self [C] { - #[inline(always)] + #[inline] fn matches(&self, c: char) -> bool { self.iter().any_(|m| m.matches(c)) } @@ -291,6 +289,10 @@ pub type WordIterator<'self> = FilterIterator<'self, &'self str, StrCharSplitIterator<'self, extern "Rust" fn(char) -> bool>>; +/// An iterator over the lines of a string, separated by either `\n` or (`\r\n`). +pub type AnyLineIterator<'self> = + MapIterator<'self, &'self str, &'self str, StrCharSplitIterator<'self, char>>; + impl<'self, Sep: CharEq> Iterator<&'self str> for StrCharSplitIterator<'self, Sep> { #[inline] fn next(&mut self) -> Option<&'self str> { @@ -400,56 +402,6 @@ impl<'self> Iterator<&'self str> for StrStrSplitIterator<'self> { } } -/// Levenshtein Distance between two strings -pub fn levdistance(s: &str, t: &str) -> uint { - - let slen = s.len(); - let tlen = t.len(); - - if slen == 0 { return tlen; } - if tlen == 0 { return slen; } - - let mut dcol = vec::from_fn(tlen + 1, |x| x); - - for s.iter().enumerate().advance |(i, sc)| { - - let mut current = i; - dcol[0] = current + 1; - - for t.iter().enumerate().advance |(j, tc)| { - - let next = dcol[j + 1]; - - if sc == tc { - dcol[j + 1] = current; - } else { - dcol[j + 1] = ::cmp::min(current, next); - dcol[j + 1] = ::cmp::min(dcol[j + 1], dcol[j]) + 1; - } - - current = next; - } - } - - return dcol[tlen]; -} - -/** - * Splits a string into substrings separated by LF ('\n') - * and/or CR LF ("\r\n") - */ -pub fn each_line_any<'a>(s: &'a str, it: &fn(&'a str) -> bool) -> bool { - for s.line_iter().advance |s| { - let l = s.len(); - if l > 0u && s[l - 1u] == '\r' as u8 { - if !it( unsafe { raw::slice_bytes(s, 0, l - 1) } ) { return false; } - } else { - if !it( s ) { return false; } - } - } - return true; -} - /** Splits a string into substrings with possibly internal whitespace, * each of them at most `lim` bytes long. The substrings have leading and trailing * whitespace removed, and are only cut at whitespace boundaries. @@ -576,196 +528,6 @@ pub fn eq(a: &~str, b: &~str) -> bool { eq_slice(*a, *b) } -#[inline] -fn cmp(a: &str, b: &str) -> Ordering { - let low = uint::min(a.len(), b.len()); - - for uint::range(0, low) |idx| { - match a[idx].cmp(&b[idx]) { - Greater => return Greater, - Less => return Less, - Equal => () - } - } - - a.len().cmp(&b.len()) -} - -#[cfg(not(test))] -impl<'self> TotalOrd for &'self str { - #[inline] - fn cmp(&self, other: & &'self str) -> Ordering { cmp(*self, *other) } -} - -#[cfg(not(test))] -impl TotalOrd for ~str { - #[inline] - fn cmp(&self, other: &~str) -> Ordering { cmp(*self, *other) } -} - -#[cfg(not(test))] -impl TotalOrd for @str { - #[inline] - fn cmp(&self, other: &@str) -> Ordering { cmp(*self, *other) } -} - -/// Bytewise slice less than -#[inline] -fn lt(a: &str, b: &str) -> bool { - let (a_len, b_len) = (a.len(), b.len()); - let end = uint::min(a_len, b_len); - - let mut i = 0; - while i < end { - let (c_a, c_b) = (a[i], b[i]); - if c_a < c_b { return true; } - if c_a > c_b { return false; } - i += 1; - } - - return a_len < b_len; -} - -/// Bytewise less than or equal -#[inline] -pub fn le(a: &str, b: &str) -> bool { - !lt(b, a) -} - -/// Bytewise greater than or equal -#[inline] -fn ge(a: &str, b: &str) -> bool { - !lt(a, b) -} - -/// Bytewise greater than -#[inline] -fn gt(a: &str, b: &str) -> bool { - !le(a, b) -} - -#[cfg(not(test))] -impl<'self> Eq for &'self str { - #[inline(always)] - fn eq(&self, other: & &'self str) -> bool { - eq_slice((*self), (*other)) - } - #[inline(always)] - fn ne(&self, other: & &'self str) -> bool { !(*self).eq(other) } -} - -#[cfg(not(test))] -impl Eq for ~str { - #[inline(always)] - fn eq(&self, other: &~str) -> bool { - eq_slice((*self), (*other)) - } - #[inline(always)] - fn ne(&self, other: &~str) -> bool { !(*self).eq(other) } -} - -#[cfg(not(test))] -impl Eq for @str { - #[inline(always)] - fn eq(&self, other: &@str) -> bool { - eq_slice((*self), (*other)) - } - #[inline(always)] - fn ne(&self, other: &@str) -> bool { !(*self).eq(other) } -} - -#[cfg(not(test))] -impl<'self> TotalEq for &'self str { - #[inline(always)] - fn equals(&self, other: & &'self str) -> bool { - eq_slice((*self), (*other)) - } -} - -#[cfg(not(test))] -impl TotalEq for ~str { - #[inline(always)] - fn equals(&self, other: &~str) -> bool { - eq_slice((*self), (*other)) - } -} - -#[cfg(not(test))] -impl TotalEq for @str { - #[inline(always)] - fn equals(&self, other: &@str) -> bool { - eq_slice((*self), (*other)) - } -} - -#[cfg(not(test))] -impl Ord for ~str { - #[inline(always)] - fn lt(&self, other: &~str) -> bool { lt((*self), (*other)) } - #[inline(always)] - fn le(&self, other: &~str) -> bool { le((*self), (*other)) } - #[inline(always)] - fn ge(&self, other: &~str) -> bool { ge((*self), (*other)) } - #[inline(always)] - fn gt(&self, other: &~str) -> bool { gt((*self), (*other)) } -} - -#[cfg(not(test))] -impl<'self> Ord for &'self str { - #[inline(always)] - fn lt(&self, other: & &'self str) -> bool { lt((*self), (*other)) } - #[inline(always)] - fn le(&self, other: & &'self str) -> bool { le((*self), (*other)) } - #[inline(always)] - fn ge(&self, other: & &'self str) -> bool { ge((*self), (*other)) } - #[inline(always)] - fn gt(&self, other: & &'self str) -> bool { gt((*self), (*other)) } -} - -#[cfg(not(test))] -impl Ord for @str { - #[inline(always)] - fn lt(&self, other: &@str) -> bool { lt((*self), (*other)) } - #[inline(always)] - fn le(&self, other: &@str) -> bool { le((*self), (*other)) } - #[inline(always)] - fn ge(&self, other: &@str) -> bool { ge((*self), (*other)) } - #[inline(always)] - fn gt(&self, other: &@str) -> bool { gt((*self), (*other)) } -} - -#[cfg(not(test))] -impl<'self, S: Str> Equiv<S> for &'self str { - #[inline(always)] - fn equiv(&self, other: &S) -> bool { eq_slice(*self, other.as_slice()) } -} -#[cfg(not(test))] -impl<'self, S: Str> Equiv<S> for @str { - #[inline(always)] - fn equiv(&self, other: &S) -> bool { eq_slice(*self, other.as_slice()) } -} - -#[cfg(not(test))] -impl<'self, S: Str> Equiv<S> for ~str { - #[inline(always)] - fn equiv(&self, other: &S) -> bool { eq_slice(*self, other.as_slice()) } -} - - -/* -Section: Iterating through strings -*/ - -/// Apply a function to each character -pub fn map(ss: &str, ff: &fn(char) -> char) -> ~str { - let mut result = ~""; - result.reserve(ss.len()); - for ss.iter().advance |cc| { - result.push_char(ff(cc)); - } - result -} - /* Section: Searching */ @@ -820,30 +582,6 @@ pub fn is_utf16(v: &[u16]) -> bool { return true; } -/// Converts to a vector of `u16` encoded as UTF-16 -pub fn to_utf16(s: &str) -> ~[u16] { - let mut u = ~[]; - for s.iter().advance |ch| { - // Arithmetic with u32 literals is easier on the eyes than chars. - let mut ch = ch as u32; - - if (ch & 0xFFFF_u32) == ch { - // The BMP falls through (assuming non-surrogate, as it - // should) - assert!(ch <= 0xD7FF_u32 || ch >= 0xE000_u32); - u.push(ch as u16) - } else { - // Supplementary planes break into surrogates. - assert!(ch >= 0x1_0000_u32 && ch <= 0x10_FFFF_u32); - ch -= 0x1_0000_u32; - let w1 = 0xD800_u16 | ((ch >> 10) as u16); - let w2 = 0xDC00_u16 | ((ch as u16) & 0x3FF_u16); - u.push_all([w1, w2]) - } - } - u -} - /// Iterates over the utf-16 characters in the specified slice, yielding each /// decoded unicode character to the function provided. /// @@ -967,7 +705,7 @@ impl<'self> StrUtil for &'self str { /** * Deprecated. Use the `as_c_str` method on strings instead. */ -#[inline(always)] +#[inline] pub fn as_c_str<T>(s: &str, f: &fn(*libc::c_char) -> T) -> T { s.as_c_str(f) } @@ -980,7 +718,7 @@ pub fn as_c_str<T>(s: &str, f: &fn(*libc::c_char) -> T) -> T { * indexable area for a null byte, as is the case in slices pointing * to full strings, or suffixes of them. */ -#[inline(always)] +#[inline] pub fn as_buf<T>(s: &str, f: &fn(*u8, uint) -> T) -> T { unsafe { let v : *(*u8,uint) = transmute(&s); @@ -989,40 +727,6 @@ pub fn as_buf<T>(s: &str, f: &fn(*u8, uint) -> T) -> T { } } -/** - * Returns the byte offset of an inner slice relative to an enclosing outer slice - * - * # Example - * - * ~~~ {.rust} - * let string = "a\nb\nc"; - * let mut lines = ~[]; - * for string.line_iter().advance |line| { lines.push(line) } - * - * assert!(subslice_offset(string, lines[0]) == 0); // &"a" - * assert!(subslice_offset(string, lines[1]) == 2); // &"b" - * assert!(subslice_offset(string, lines[2]) == 4); // &"c" - * ~~~ - */ -#[inline(always)] -pub fn subslice_offset(outer: &str, inner: &str) -> uint { - do as_buf(outer) |a, a_len| { - do as_buf(inner) |b, b_len| { - let a_start: uint; - let a_end: uint; - let b_start: uint; - let b_end: uint; - unsafe { - a_start = cast::transmute(a); a_end = a_len + cast::transmute(a); - b_start = cast::transmute(b); b_end = b_len + cast::transmute(b); - } - assert!(a_start <= b_start); - assert!(b_end <= a_end); - b_start - a_start - } - } -} - /// Unsafe operations pub mod raw { use cast; @@ -1207,12 +911,138 @@ pub mod raw { #[cfg(not(test))] pub mod traits { use ops::Add; - impl<'self> Add<&'self str,~str> for ~str { - #[inline(always)] + use cmp::{TotalOrd, Ordering, Less, Equal, Greater, Eq, Ord, Equiv, TotalEq}; + use super::{Str, eq_slice}; + + impl<'self> Add<&'self str,~str> for &'self str { + #[inline] fn add(&self, rhs: & &'self str) -> ~str { - self.append((*rhs)) + let mut ret = self.to_owned(); + ret.push_str(*rhs); + ret + } + } + + impl<'self> TotalOrd for &'self str { + #[inline] + fn cmp(&self, other: & &'self str) -> Ordering { + for self.bytes_iter().zip(other.bytes_iter()).advance |(s_b, o_b)| { + match s_b.cmp(&o_b) { + Greater => return Greater, + Less => return Less, + Equal => () + } + } + + self.len().cmp(&other.len()) + } + } + + impl TotalOrd for ~str { + #[inline] + fn cmp(&self, other: &~str) -> Ordering { self.as_slice().cmp(&other.as_slice()) } + } + + impl TotalOrd for @str { + #[inline] + fn cmp(&self, other: &@str) -> Ordering { self.as_slice().cmp(&other.as_slice()) } + } + + impl<'self> Eq for &'self str { + #[inline] + fn eq(&self, other: & &'self str) -> bool { + eq_slice((*self), (*other)) + } + #[inline] + fn ne(&self, other: & &'self str) -> bool { !(*self).eq(other) } + } + + impl Eq for ~str { + #[inline] + fn eq(&self, other: &~str) -> bool { + eq_slice((*self), (*other)) + } + #[inline] + fn ne(&self, other: &~str) -> bool { !(*self).eq(other) } + } + + impl Eq for @str { + #[inline] + fn eq(&self, other: &@str) -> bool { + eq_slice((*self), (*other)) + } + #[inline] + fn ne(&self, other: &@str) -> bool { !(*self).eq(other) } + } + + impl<'self> TotalEq for &'self str { + #[inline] + fn equals(&self, other: & &'self str) -> bool { + eq_slice((*self), (*other)) + } + } + + impl TotalEq for ~str { + #[inline] + fn equals(&self, other: &~str) -> bool { + eq_slice((*self), (*other)) + } + } + + impl TotalEq for @str { + #[inline] + fn equals(&self, other: &@str) -> bool { + eq_slice((*self), (*other)) } } + + impl<'self> Ord for &'self str { + #[inline] + fn lt(&self, other: & &'self str) -> bool { self.cmp(other) == Less } + #[inline] + fn le(&self, other: & &'self str) -> bool { self.cmp(other) != Greater } + #[inline] + fn ge(&self, other: & &'self str) -> bool { self.cmp(other) != Less } + #[inline] + fn gt(&self, other: & &'self str) -> bool { self.cmp(other) == Greater } + } + + impl Ord for ~str { + #[inline] + fn lt(&self, other: &~str) -> bool { self.cmp(other) == Less } + #[inline] + fn le(&self, other: &~str) -> bool { self.cmp(other) != Greater } + #[inline] + fn ge(&self, other: &~str) -> bool { self.cmp(other) != Less } + #[inline] + fn gt(&self, other: &~str) -> bool { self.cmp(other) == Greater } + } + + impl Ord for @str { + #[inline] + fn lt(&self, other: &@str) -> bool { self.cmp(other) == Less } + #[inline] + fn le(&self, other: &@str) -> bool { self.cmp(other) != Greater } + #[inline] + fn ge(&self, other: &@str) -> bool { self.cmp(other) != Less } + #[inline] + fn gt(&self, other: &@str) -> bool { self.cmp(other) == Greater } + } + + impl<'self, S: Str> Equiv<S> for &'self str { + #[inline] + fn equiv(&self, other: &S) -> bool { eq_slice(*self, other.as_slice()) } + } + + impl<'self, S: Str> Equiv<S> for @str { + #[inline] + fn equiv(&self, other: &S) -> bool { eq_slice(*self, other.as_slice()) } + } + + impl<'self, S: Str> Equiv<S> for ~str { + #[inline] + fn equiv(&self, other: &S) -> bool { eq_slice(*self, other.as_slice()) } + } } #[cfg(test)] @@ -1225,17 +1055,17 @@ pub trait Str { } impl<'self> Str for &'self str { - #[inline(always)] + #[inline] fn as_slice<'a>(&'a self) -> &'a str { *self } } impl<'self> Str for ~str { - #[inline(always)] + #[inline] fn as_slice<'a>(&'a self) -> &'a str { let s: &'a str = *self; s } } impl<'self> Str for @str { - #[inline(always)] + #[inline] fn as_slice<'a>(&'a self) -> &'a str { let s: &'a str = *self; s } @@ -1256,6 +1086,7 @@ pub trait StrSlice<'self> { fn matches_index_iter(&self, sep: &'self str) -> StrMatchesIndexIterator<'self>; fn split_str_iter(&self, &'self str) -> StrStrSplitIterator<'self>; fn line_iter(&self) -> StrCharSplitIterator<'self, char>; + fn any_line_iter(&self) -> AnyLineIterator<'self>; fn word_iter(&self) -> WordIterator<'self>; fn ends_with(&self, needle: &str) -> bool; fn is_empty(&self) -> bool; @@ -1282,6 +1113,7 @@ pub trait StrSlice<'self> { fn replace(&self, from: &str, to: &str) -> ~str; fn to_owned(&self) -> ~str; fn to_managed(&self) -> @str; + fn to_utf16(&self) -> ~[u16]; fn is_char_boundary(&self, index: uint) -> bool; fn char_range_at(&self, start: uint) -> CharRange; fn char_at(&self, i: uint) -> char; @@ -1296,6 +1128,12 @@ pub trait StrSlice<'self> { fn repeat(&self, nn: uint) -> ~str; fn slice_shift_char(&self) -> (char, &'self str); + + fn map_chars(&self, ff: &fn(char) -> char) -> ~str; + + fn lev_distance(&self, t: &str) -> uint; + + fn subslice_offset(&self, inner: &str) -> uint; } /// Extension methods for strings @@ -1437,6 +1275,17 @@ impl<'self> StrSlice<'self> for &'self str { fn line_iter(&self) -> StrCharSplitIterator<'self, char> { self.split_options_iter('\n', self.len(), false) } + + /// An iterator over the lines of a string, separated by either + /// `\n` or (`\r\n`). + fn any_line_iter(&self) -> AnyLineIterator<'self> { + do self.line_iter().transform |line| { + let l = line.len(); + if l > 0 && line[l - 1] == '\r' as u8 { line.slice(0, l - 1) } + else { line } + } + } + /// An iterator over the words of a string (subsequences separated /// by any sequence of whitespace). #[inline] @@ -1462,7 +1311,7 @@ impl<'self> StrSlice<'self> for &'self str { #[inline] fn is_alphanumeric(&self) -> bool { self.iter().all(char::is_alphanumeric) } /// Returns the size in bytes not counting the null terminator - #[inline(always)] + #[inline] fn len(&self) -> uint { do as_buf(*self) |_p, n| { n - 1u } } @@ -1586,7 +1435,7 @@ impl<'self> StrSlice<'self> for &'self str { * * # Example * - * ~~~ + * ~~~ {.rust} * assert_eq!("11foo1bar11".trim_chars(&'1'), "foo1bar") * assert_eq!("12foo1bar12".trim_chars(& &['1', '2']), "foo1bar") * assert_eq!("123foo1bar123".trim_chars(&|c: char| c.is_digit()), "foo1bar") @@ -1605,7 +1454,7 @@ impl<'self> StrSlice<'self> for &'self str { * * # Example * - * ~~~ + * ~~~ {.rust} * assert_eq!("11foo1bar11".trim_left_chars(&'1'), "foo1bar11") * assert_eq!("12foo1bar12".trim_left_chars(& &['1', '2']), "foo1bar12") * assert_eq!("123foo1bar123".trim_left_chars(&|c: char| c.is_digit()), "foo1bar123") @@ -1627,7 +1476,7 @@ impl<'self> StrSlice<'self> for &'self str { * * # Example * - * ~~~ + * ~~~ {.rust} * assert_eq!("11foo1bar11".trim_right_chars(&'1'), "11foo1bar") * assert_eq!("12foo1bar12".trim_right_chars(& &['1', '2']), "12foo1bar") * assert_eq!("123foo1bar123".trim_right_chars(&|c: char| c.is_digit()), "123foo1bar") @@ -1679,6 +1528,30 @@ impl<'self> StrSlice<'self> for &'self str { unsafe { ::cast::transmute(v) } } + /// Converts to a vector of `u16` encoded as UTF-16. + fn to_utf16(&self) -> ~[u16] { + let mut u = ~[]; + for self.iter().advance |ch| { + // Arithmetic with u32 literals is easier on the eyes than chars. + let mut ch = ch as u32; + + if (ch & 0xFFFF_u32) == ch { + // The BMP falls through (assuming non-surrogate, as it + // should) + assert!(ch <= 0xD7FF_u32 || ch >= 0xE000_u32); + u.push(ch as u16) + } else { + // Supplementary planes break into surrogates. + assert!(ch >= 0x1_0000_u32 && ch <= 0x10_FFFF_u32); + ch -= 0x1_0000_u32; + let w1 = 0xD800_u16 | ((ch >> 10) as u16); + let w2 = 0xDC00_u16 | ((ch as u16) & 0x3FF_u16); + u.push_all([w1, w2]) + } + } + u + } + /** * Returns false if the index points into the middle of a multi-byte * character sequence. @@ -1921,6 +1794,85 @@ impl<'self> StrSlice<'self> for &'self str { } + /// Apply a function to each character. + fn map_chars(&self, ff: &fn(char) -> char) -> ~str { + let mut result = with_capacity(self.len()); + for self.iter().advance |cc| { + result.push_char(ff(cc)); + } + result + } + + /// Levenshtein Distance between two strings. + fn lev_distance(&self, t: &str) -> uint { + let slen = self.len(); + let tlen = t.len(); + + if slen == 0 { return tlen; } + if tlen == 0 { return slen; } + + let mut dcol = vec::from_fn(tlen + 1, |x| x); + + for self.iter().enumerate().advance |(i, sc)| { + + let mut current = i; + dcol[0] = current + 1; + + for t.iter().enumerate().advance |(j, tc)| { + + let next = dcol[j + 1]; + + if sc == tc { + dcol[j + 1] = current; + } else { + dcol[j + 1] = ::cmp::min(current, next); + dcol[j + 1] = ::cmp::min(dcol[j + 1], dcol[j]) + 1; + } + + current = next; + } + } + + return dcol[tlen]; + } + + + /** + * Returns the byte offset of an inner slice relative to an enclosing outer slice. + * + * Fails if `inner` is not a direct slice contained within self. + * + * # Example + * + * ~~~ {.rust} + * let string = "a\nb\nc"; + * let mut lines = ~[]; + * for string.line_iter().advance |line| { lines.push(line) } + * + * assert!(string.subslice_offset(lines[0]) == 0); // &"a" + * assert!(string.subslice_offset(lines[1]) == 2); // &"b" + * assert!(string.subslice_offset(lines[2]) == 4); // &"c" + * ~~~ + */ + #[inline] + fn subslice_offset(&self, inner: &str) -> uint { + do as_buf(*self) |a, a_len| { + do as_buf(inner) |b, b_len| { + let a_start: uint; + let a_end: uint; + let b_start: uint; + let b_end: uint; + unsafe { + a_start = cast::transmute(a); a_end = a_len + cast::transmute(a); + b_start = cast::transmute(b); b_end = b_len + cast::transmute(b); + } + assert!(a_start <= b_start); + assert!(b_end <= a_end); + b_start - a_start + } + } + } + } #[allow(missing_doc)] @@ -1973,7 +1925,7 @@ pub trait OwnedStr { impl OwnedStr for ~str { /// Appends a string slice to the back of a string, without overallocating - #[inline(always)] + #[inline] fn push_str_no_overallocate(&mut self, rhs: &str) { unsafe { let llen = self.len(); @@ -2126,7 +2078,7 @@ impl OwnedStr for ~str { * * s - A string * * n - The number of bytes to reserve space for */ - #[inline(always)] + #[inline] pub fn reserve(&mut self, n: uint) { unsafe { let v: *mut ~[u8] = cast::transmute(self); @@ -2154,7 +2106,7 @@ impl OwnedStr for ~str { * * s - A string * * n - The number of bytes to reserve space for */ - #[inline(always)] + #[inline] fn reserve_at_least(&mut self, n: uint) { self.reserve(uint::next_power_of_two(n + 1u) - 1u) } @@ -2179,7 +2131,7 @@ impl OwnedStr for ~str { } impl Clone for ~str { - #[inline(always)] + #[inline] fn clone(&self) -> ~str { to_owned(*self) } @@ -2250,6 +2202,22 @@ impl<'self> Iterator<u8> for StrBytesRevIterator<'self> { } } +// This works because every lifetime is a sub-lifetime of 'static +impl<'self> Zero for &'self str { + fn zero() -> &'self str { "" } + fn is_zero(&self) -> bool { self.is_empty() } +} + +impl Zero for ~str { + fn zero() -> ~str { ~"" } + fn is_zero(&self) -> bool { self.len() == 0 } +} + +impl Zero for @str { + fn zero() -> @str { @"" } + fn is_zero(&self) -> bool { self.len() == 0 } +} + #[cfg(test)] mod tests { use iterator::IteratorUtil; @@ -2280,10 +2248,10 @@ mod tests { #[test] fn test_le() { - assert!((le(&"", &""))); - assert!((le(&"", &"foo"))); - assert!((le(&"foo", &"foo"))); - assert!((!eq(&~"foo", &~"bar"))); + assert!("" <= ""); + assert!("" <= "foo"); + assert!("foo" <= "foo"); + assert!("foo" != ~"bar"); } #[test] @@ -3003,15 +2971,15 @@ mod tests { let a = "kernelsprite"; let b = a.slice(7, a.len()); let c = a.slice(0, a.len() - 6); - assert_eq!(subslice_offset(a, b), 7); - assert_eq!(subslice_offset(a, c), 0); + assert_eq!(a.subslice_offset(b), 7); + assert_eq!(a.subslice_offset(c), 0); let string = "a\nb\nc"; let mut lines = ~[]; for string.line_iter().advance |line| { lines.push(line) } - assert_eq!(subslice_offset(string, lines[0]), 0); - assert_eq!(subslice_offset(string, lines[1]), 2); - assert_eq!(subslice_offset(string, lines[2]), 4); + assert_eq!(string.subslice_offset(lines[0]), 0); + assert_eq!(string.subslice_offset(lines[1]), 2); + assert_eq!(string.subslice_offset(lines[2]), 4); } #[test] @@ -3019,7 +2987,7 @@ mod tests { fn test_subslice_offset_2() { let a = "alchemiter"; let b = "cruxtruder"; - subslice_offset(a, b); + a.subslice_offset(b); } #[test] @@ -3069,8 +3037,8 @@ mod tests { #[test] fn test_map() { - assert_eq!(~"", map("", |c| unsafe {libc::toupper(c as c_char)} as char)); - assert_eq!(~"YMCA", map("ymca", |c| unsafe {libc::toupper(c as c_char)} as char)); + assert_eq!(~"", "".map_chars(|c| unsafe {libc::toupper(c as c_char)} as char)); + assert_eq!(~"YMCA", "ymca".map_chars(|c| unsafe {libc::toupper(c as c_char)} as char)); } #[test] @@ -3114,10 +3082,10 @@ mod tests { for pairs.each |p| { let (s, u) = copy *p; - assert!(to_utf16(s) == u); + assert!(s.to_utf16() == u); assert!(from_utf16(u) == s); - assert!(from_utf16(to_utf16(s)) == s); - assert!(to_utf16(from_utf16(u)) == u); + assert!(from_utf16(s.to_utf16()) == s); + assert!(from_utf16(u).to_utf16() == u); } } @@ -3189,6 +3157,24 @@ mod tests { } #[test] + fn test_add() { + macro_rules! t ( + ($s1:expr, $s2:expr, $e:expr) => { + assert_eq!($s1 + $s2, $e); + assert_eq!($s1.to_owned() + $s2, $e); + assert_eq!($s1.to_managed() + $s2, $e); + } + ); + + t!("foo", "bar", ~"foobar"); + t!("foo", @"bar", ~"foobar"); + t!("foo", ~"bar", ~"foobar"); + t!("ศไทย中", "华Việt Nam", ~"ศไทย中华Việt Nam"); + t!("ศไทย中", @"华Việt Nam", ~"ศไทย中华Việt Nam"); + t!("ศไทย中", ~"华Việt Nam", ~"ศไทย中华Việt Nam"); + } + + #[test] fn test_iterator() { use iterator::*; let s = ~"ศไทย中华Việt Nam"; @@ -3337,4 +3323,18 @@ mod tests { t("zzz", "zz", ~["","z"]); t("zzzzz", "zz", ~["","","z"]); } + + #[test] + fn test_str_zero() { + use num::Zero; + fn t<S: Zero + Str>() { + let s: S = Zero::zero(); + assert_eq!(s.as_slice(), ""); + assert!(s.is_zero()); + } + + t::<&str>(); + t::<@str>(); + t::<~str>(); + } } diff --git a/src/libstd/str/ascii.rs b/src/libstd/str/ascii.rs index 618d5095777..c71765f911a 100644 --- a/src/libstd/str/ascii.rs +++ b/src/libstd/str/ascii.rs @@ -17,26 +17,27 @@ use cast; use old_iter::BaseIter; use iterator::IteratorUtil; use vec::{CopyableVector, ImmutableVector, OwnedVector}; +use to_bytes::IterBytes; -/// Datatype to hold one ascii character. It is 8 bit long. +/// Datatype to hold one ascii character. It wraps a `u8`, with the highest bit always zero. #[deriving(Clone, Eq)] pub struct Ascii { priv chr: u8 } impl Ascii { /// Converts a ascii character into a `u8`. - #[inline(always)] + #[inline] pub fn to_byte(self) -> u8 { self.chr } /// Converts a ascii character into a `char`. - #[inline(always)] + #[inline] pub fn to_char(self) -> char { self.chr as char } /// Convert to lowercase. - #[inline(always)] + #[inline] pub fn to_lower(self) -> Ascii { if self.chr >= 65 && self.chr <= 90 { Ascii{chr: self.chr | 0x20 } @@ -46,7 +47,7 @@ impl Ascii { } /// Convert to uppercase. - #[inline(always)] + #[inline] pub fn to_upper(self) -> Ascii { if self.chr >= 97 && self.chr <= 122 { Ascii{chr: self.chr & !0x20 } @@ -56,14 +57,14 @@ impl Ascii { } /// Compares two ascii characters of equality, ignoring case. - #[inline(always)] + #[inline] pub fn eq_ignore_case(self, other: Ascii) -> bool { self.to_lower().chr == other.to_lower().chr } } impl ToStr for Ascii { - #[inline(always)] + #[inline] fn to_str(&self) -> ~str { str::from_bytes(['\'' as u8, self.chr, '\'' as u8]) } } @@ -72,18 +73,26 @@ pub trait AsciiCast<T> { /// Convert to an ascii type fn to_ascii(&self) -> T; + /// Convert to an ascii type, not doing any range asserts + unsafe fn to_ascii_nocheck(&self) -> T; + /// Check if convertible to ascii fn is_ascii(&self) -> bool; } impl<'self> AsciiCast<&'self[Ascii]> for &'self [u8] { - #[inline(always)] + #[inline] fn to_ascii(&self) -> &'self[Ascii] { assert!(self.is_ascii()); - unsafe{ cast::transmute(*self) } + unsafe {self.to_ascii_nocheck()} + } + + #[inline] + unsafe fn to_ascii_nocheck(&self) -> &'self[Ascii] { + cast::transmute(*self) } - #[inline(always)] + #[inline] fn is_ascii(&self) -> bool { for self.each |b| { if !b.is_ascii() { return false; } @@ -93,40 +102,55 @@ impl<'self> AsciiCast<&'self[Ascii]> for &'self [u8] { } impl<'self> AsciiCast<&'self[Ascii]> for &'self str { - #[inline(always)] + #[inline] fn to_ascii(&self) -> &'self[Ascii] { assert!(self.is_ascii()); - let (p,len): (*u8, uint) = unsafe{ cast::transmute(*self) }; - unsafe{ cast::transmute((p, len - 1))} + unsafe {self.to_ascii_nocheck()} + } + + #[inline] + unsafe fn to_ascii_nocheck(&self) -> &'self[Ascii] { + let (p,len): (*u8, uint) = cast::transmute(*self); + cast::transmute((p, len - 1)) } - #[inline(always)] + #[inline] fn is_ascii(&self) -> bool { self.bytes_iter().all(|b| b.is_ascii()) } } impl AsciiCast<Ascii> for u8 { - #[inline(always)] + #[inline] fn to_ascii(&self) -> Ascii { assert!(self.is_ascii()); + unsafe {self.to_ascii_nocheck()} + } + + #[inline] + unsafe fn to_ascii_nocheck(&self) -> Ascii { Ascii{ chr: *self } } - #[inline(always)] + #[inline] fn is_ascii(&self) -> bool { *self & 128 == 0u8 } } impl AsciiCast<Ascii> for char { - #[inline(always)] + #[inline] fn to_ascii(&self) -> Ascii { assert!(self.is_ascii()); + unsafe {self.to_ascii_nocheck()} + } + + #[inline] + unsafe fn to_ascii_nocheck(&self) -> Ascii { Ascii{ chr: *self as u8 } } - #[inline(always)] + #[inline] fn is_ascii(&self) -> bool { *self - ('\x7F' & *self) == '\x00' } @@ -135,26 +159,38 @@ impl AsciiCast<Ascii> for char { /// Trait for copyless casting to an ascii vector. pub trait OwnedAsciiCast { /// Take ownership and cast to an ascii vector without trailing zero element. - fn to_ascii_consume(self) -> ~[Ascii]; + fn into_ascii(self) -> ~[Ascii]; + + /// Take ownership and cast to an ascii vector without trailing zero element. + /// Does not perform validation checks. + unsafe fn into_ascii_nocheck(self) -> ~[Ascii]; } impl OwnedAsciiCast for ~[u8] { - #[inline(always)] - fn to_ascii_consume(self) -> ~[Ascii] { + #[inline] + fn into_ascii(self) -> ~[Ascii] { assert!(self.is_ascii()); - unsafe {cast::transmute(self)} + unsafe {self.into_ascii_nocheck()} + } + + #[inline] + unsafe fn into_ascii_nocheck(self) -> ~[Ascii] { + cast::transmute(self) } } impl OwnedAsciiCast for ~str { - #[inline(always)] - fn to_ascii_consume(self) -> ~[Ascii] { + #[inline] + fn into_ascii(self) -> ~[Ascii] { assert!(self.is_ascii()); - let mut s = self; - unsafe { - str::raw::pop_byte(&mut s); - cast::transmute(s) - } + unsafe {self.into_ascii_nocheck()} + } + + #[inline] + unsafe fn into_ascii_nocheck(self) -> ~[Ascii] { + let mut r: ~[Ascii] = cast::transmute(self); + r.pop(); + r } } @@ -169,39 +205,66 @@ pub trait AsciiStr { /// Convert to vector representing a upper cased ascii string. fn to_upper(&self) -> ~[Ascii]; + /// Compares two Ascii strings ignoring case + fn eq_ignore_case(self, other: &[Ascii]) -> bool; } impl<'self> AsciiStr for &'self [Ascii] { - #[inline(always)] + #[inline] fn to_str_ascii(&self) -> ~str { let mut cpy = self.to_owned(); cpy.push(0u8.to_ascii()); unsafe {cast::transmute(cpy)} } - #[inline(always)] + #[inline] fn to_lower(&self) -> ~[Ascii] { self.map(|a| a.to_lower()) } - #[inline(always)] + #[inline] fn to_upper(&self) -> ~[Ascii] { self.map(|a| a.to_upper()) } + + #[inline] + fn eq_ignore_case(self, other: &[Ascii]) -> bool { + do self.iter().zip(other.iter()).all |(&a, &b)| { a.eq_ignore_case(b) } + } } impl ToStrConsume for ~[Ascii] { - #[inline(always)] - fn to_str_consume(self) -> ~str { + #[inline] + fn into_str(self) -> ~str { let mut cpy = self; cpy.push(0u8.to_ascii()); unsafe {cast::transmute(cpy)} } } +impl IterBytes for Ascii { + #[inline] + fn iter_bytes(&self, _lsb0: bool, f: &fn(buf: &[u8]) -> bool) -> bool { + f([self.to_byte()]) + } +} + +/// Trait to convert to a owned byte array by consuming self +pub trait ToBytesConsume { + /// Converts to a owned byte array by consuming self + fn into_bytes(self) -> ~[u8]; +} + +impl ToBytesConsume for ~[Ascii] { + fn into_bytes(self) -> ~[u8] { + unsafe {cast::transmute(self)} + } +} + #[cfg(test)] mod tests { use super::*; + use to_bytes::ToBytes; macro_rules! v2ascii ( ( [$($e:expr),*]) => ( [$(Ascii{chr:$e}),*]); @@ -245,6 +308,8 @@ mod tests { assert_eq!("YMCA".to_ascii().to_lower().to_str_ascii(), ~"ymca"); assert_eq!("abcDEFxyz:.;".to_ascii().to_upper().to_str_ascii(), ~"ABCDEFXYZ:.;"); + assert!("aBcDeF&?#".to_ascii().eq_ignore_case("AbCdEf&?#".to_ascii())); + assert!("".is_ascii()); assert!("a".is_ascii()); assert!(!"\u2009".is_ascii()); @@ -253,21 +318,22 @@ mod tests { #[test] fn test_owned_ascii_vec() { - // FIXME: #4318 Compiler crashes on moving self - //assert_eq!(~"( ;".to_ascii_consume(), v2ascii!(~[40, 32, 59])); - //assert_eq!(~[40u8, 32u8, 59u8].to_ascii_consume(), v2ascii!(~[40, 32, 59])); - //assert_eq!(~"( ;".to_ascii_consume_with_null(), v2ascii!(~[40, 32, 59, 0])); - //assert_eq!(~[40u8, 32u8, 59u8].to_ascii_consume_with_null(), - // v2ascii!(~[40, 32, 59, 0])); + assert_eq!((~"( ;").into_ascii(), v2ascii!(~[40, 32, 59])); + assert_eq!((~[40u8, 32u8, 59u8]).into_ascii(), v2ascii!(~[40, 32, 59])); } #[test] fn test_ascii_to_str() { assert_eq!(v2ascii!([40, 32, 59]).to_str_ascii(), ~"( ;"); } #[test] - fn test_ascii_to_str_consume() { - // FIXME: #4318 Compiler crashes on moving self - //assert_eq!(v2ascii!(~[40, 32, 59]).to_str_consume(), ~"( ;"); + fn test_ascii_into_str() { + assert_eq!(v2ascii!(~[40, 32, 59]).into_str(), ~"( ;"); + } + + #[test] + fn test_ascii_to_bytes() { + assert_eq!(v2ascii!(~[40, 32, 59]).to_bytes(false), ~[40u8, 32u8, 59u8]); + assert_eq!(v2ascii!(~[40, 32, 59]).into_bytes(), ~[40u8, 32u8, 59u8]); } #[test] #[should_fail] diff --git a/src/libstd/sys.rs b/src/libstd/sys.rs index e49ad348542..523c5d633cf 100644 --- a/src/libstd/sys.rs +++ b/src/libstd/sys.rs @@ -57,25 +57,25 @@ pub mod rustrt { * Useful for calling certain function in the Rust runtime or otherwise * performing dark magick. */ -#[inline(always)] +#[inline] pub fn get_type_desc<T>() -> *TypeDesc { unsafe { intrinsics::get_tydesc::<T>() as *TypeDesc } } /// Returns a pointer to a type descriptor. -#[inline(always)] +#[inline] pub fn get_type_desc_val<T>(_val: &T) -> *TypeDesc { get_type_desc::<T>() } /// Returns the size of a type -#[inline(always)] +#[inline] pub fn size_of<T>() -> uint { unsafe { intrinsics::size_of::<T>() } } /// Returns the size of the type that `_val` points to -#[inline(always)] +#[inline] pub fn size_of_val<T>(_val: &T) -> uint { size_of::<T>() } @@ -85,14 +85,14 @@ pub fn size_of_val<T>(_val: &T) -> uint { * * Useful for building structures containing variable-length arrays. */ -#[inline(always)] +#[inline] pub fn nonzero_size_of<T>() -> uint { let s = size_of::<T>(); if s == 0 { 1 } else { s } } /// Returns the size of the type of the value that `_val` points to -#[inline(always)] +#[inline] pub fn nonzero_size_of_val<T>(_val: &T) -> uint { nonzero_size_of::<T>() } @@ -104,33 +104,33 @@ pub fn nonzero_size_of_val<T>(_val: &T) -> uint { * This is the alignment used for struct fields. It may be smaller * than the preferred alignment. */ -#[inline(always)] +#[inline] pub fn min_align_of<T>() -> uint { unsafe { intrinsics::min_align_of::<T>() } } /// Returns the ABI-required minimum alignment of the type of the value that /// `_val` points to -#[inline(always)] +#[inline] pub fn min_align_of_val<T>(_val: &T) -> uint { min_align_of::<T>() } /// Returns the preferred alignment of a type -#[inline(always)] +#[inline] pub fn pref_align_of<T>() -> uint { unsafe { intrinsics::pref_align_of::<T>() } } /// Returns the preferred alignment of the type of the value that /// `_val` points to -#[inline(always)] +#[inline] pub fn pref_align_of_val<T>(_val: &T) -> uint { pref_align_of::<T>() } /// Returns the refcount of a shared box (as just before calling this) -#[inline(always)] +#[inline] pub fn refcount<T>(t: @T) -> uint { unsafe { let ref_ptr: *uint = cast::transmute_copy(&t); @@ -180,10 +180,13 @@ impl FailWithCause for &'static str { // FIXME #4427: Temporary until rt::rt_fail_ goes away pub fn begin_unwind_(msg: *c_char, file: *c_char, line: size_t) -> ! { + use cell::Cell; use option::Option; + use either::Left; use rt::{context, OldTaskContext, TaskContext}; use rt::task::{Task, Unwinder}; use rt::local::Local; + use rt::logging::Logger; let context = context(); match context { @@ -200,19 +203,28 @@ pub fn begin_unwind_(msg: *c_char, file: *c_char, line: size_t) -> ! { let msg = str::raw::from_c_str(msg); let file = str::raw::from_c_str(file); - let outmsg = fmt!("%s at line %i of file %s", msg, line as int, file); + let outmsg = fmt!("task failed: '%s' at line %i of file %s", + msg, line as int, file); // XXX: Logging doesn't work correctly in non-task context because it // invokes the local heap if context == TaskContext { - error!(outmsg); + // XXX: Logging doesn't work here - the check to call the log + // function never passes - so calling the log function directly. + let outmsg = Cell::new(outmsg); + do Local::borrow::<Task, ()> |task| { + task.logger.log(Left(outmsg.take())); + } } else { - rtdebug!("%s", outmsg); + rterrln!("%s", outmsg); } gc::cleanup_stack_for_failure(); let task = Local::unsafe_borrow::<Task>(); + if (*task).unwinder.unwinding { + rtabort!("unwinding again"); + } (*task).unwinder.begin_unwind(); } } diff --git a/src/libstd/task/spawn.rs b/src/libstd/task/spawn.rs index 9df93d19d21..63eb768d1c9 100644 --- a/src/libstd/task/spawn.rs +++ b/src/libstd/task/spawn.rs @@ -79,7 +79,6 @@ use cast; use cell::Cell; use container::Map; use comm::{Chan, GenericChan}; -use ptr; use hashmap::HashSet; use task::local_data_priv::{local_get, local_set, OldHandle}; use task::rt::rust_task; @@ -99,10 +98,6 @@ use rt::task::Task; #[cfg(test)] use comm; #[cfg(test)] use task; -macro_rules! move_it ( - { $x:expr } => ( unsafe { let y = *ptr::to_unsafe_ptr(&($x)); y } ) -) - type TaskSet = HashSet<*rust_task>; fn new_taskset() -> TaskSet { @@ -162,14 +157,14 @@ struct AncestorNode { struct AncestorList(Option<Exclusive<AncestorNode>>); // Accessors for taskgroup arcs and ancestor arcs that wrap the unsafety. -#[inline(always)] +#[inline] fn access_group<U>(x: &TaskGroupArc, blk: &fn(TaskGroupInner) -> U) -> U { unsafe { x.with(blk) } } -#[inline(always)] +#[inline] fn access_ancestors<U>(x: &Exclusive<AncestorNode>, blk: &fn(x: &mut AncestorNode) -> U) -> U { unsafe { @@ -583,13 +578,29 @@ pub fn spawn_raw(opts: TaskOpts, f: ~fn()) { } } -fn spawn_raw_newsched(_opts: TaskOpts, f: ~fn()) { +fn spawn_raw_newsched(mut opts: TaskOpts, f: ~fn()) { use rt::sched::*; - let task = do Local::borrow::<Task, ~Task>() |running_task| { - ~running_task.new_child() + let mut task = if opts.linked { + do Local::borrow::<Task, ~Task>() |running_task| { + ~running_task.new_child() + } + } else { + // An unlinked task is a new root in the task tree + ~Task::new_root() }; + if opts.notify_chan.is_some() { + let notify_chan = opts.notify_chan.swap_unwrap(); + let notify_chan = Cell::new(notify_chan); + let on_exit: ~fn(bool) = |success| { + notify_chan.take().send( + if success { Success } else { Failure } + ) + }; + task.on_exit = Some(on_exit); + } + let mut sched = Local::take::<Scheduler>(); let task = ~Coroutine::with_task(&mut sched.stack_pool, task, f); @@ -644,23 +655,16 @@ fn spawn_raw_oldsched(mut opts: TaskOpts, f: ~fn()) { notify_chan: Option<Chan<TaskResult>>, f: ~fn()) -> ~fn() { - let child_data = Cell::new((child_arc, ancestors)); + let child_data = Cell::new((notify_chan, child_arc, ancestors)); let result: ~fn() = || { // Agh. Get move-mode items into the closure. FIXME (#2829) - let mut (child_arc, ancestors) = child_data.take(); + let mut (notify_chan, child_arc, ancestors) = child_data.take(); // Child task runs this code. // Even if the below code fails to kick the child off, we must // send Something on the notify channel. - //let mut notifier = None;//notify_chan.map(|c| AutoNotify(c)); - let notifier = match notify_chan { - Some(ref notify_chan_value) => { - let moved_ncv = move_it!(*notify_chan_value); - Some(AutoNotify(moved_ncv)) - } - _ => None - }; + let notifier = notify_chan.map_consume(|c| AutoNotify(c)); if enlist_many(child, &child_arc, &mut ancestors) { let group = @@mut TCB(child, diff --git a/src/libstd/to_bytes.rs b/src/libstd/to_bytes.rs index c0c8b729f9e..822aab0a027 100644 --- a/src/libstd/to_bytes.rs +++ b/src/libstd/to_bytes.rs @@ -14,6 +14,7 @@ The `ToBytes` and `IterBytes` traits */ +use cast; use io; use io::Writer; use option::{None, Option, Some}; @@ -48,7 +49,7 @@ pub trait IterBytes { } impl IterBytes for bool { - #[inline(always)] + #[inline] fn iter_bytes(&self, _lsb0: bool, f: Cb) -> bool { f([ *self as u8 @@ -57,7 +58,7 @@ impl IterBytes for bool { } impl IterBytes for u8 { - #[inline(always)] + #[inline] fn iter_bytes(&self, _lsb0: bool, f: Cb) -> bool { f([ *self @@ -66,7 +67,7 @@ impl IterBytes for u8 { } impl IterBytes for u16 { - #[inline(always)] + #[inline] fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { if lsb0 { f([ @@ -83,7 +84,7 @@ impl IterBytes for u16 { } impl IterBytes for u32 { - #[inline(always)] + #[inline] fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { if lsb0 { f([ @@ -104,7 +105,7 @@ impl IterBytes for u32 { } impl IterBytes for u64 { - #[inline(always)] + #[inline] fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { if lsb0 { f([ @@ -133,35 +134,35 @@ impl IterBytes for u64 { } impl IterBytes for i8 { - #[inline(always)] + #[inline] fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { (*self as u8).iter_bytes(lsb0, f) } } impl IterBytes for i16 { - #[inline(always)] + #[inline] fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { (*self as u16).iter_bytes(lsb0, f) } } impl IterBytes for i32 { - #[inline(always)] + #[inline] fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { (*self as u32).iter_bytes(lsb0, f) } } impl IterBytes for i64 { - #[inline(always)] + #[inline] fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { (*self as u64).iter_bytes(lsb0, f) } } impl IterBytes for char { - #[inline(always)] + #[inline] fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { (*self as u32).iter_bytes(lsb0, f) } @@ -169,7 +170,7 @@ impl IterBytes for char { #[cfg(target_word_size = "32")] impl IterBytes for uint { - #[inline(always)] + #[inline] fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { (*self as u32).iter_bytes(lsb0, f) } @@ -177,28 +178,57 @@ impl IterBytes for uint { #[cfg(target_word_size = "64")] impl IterBytes for uint { - #[inline(always)] + #[inline] fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { (*self as u64).iter_bytes(lsb0, f) } } impl IterBytes for int { - #[inline(always)] + #[inline] fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { (*self as uint).iter_bytes(lsb0, f) } } +impl IterBytes for float { + #[inline] + fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { + (*self as f64).iter_bytes(lsb0, f) + } +} + +impl IterBytes for f32 { + #[inline] + fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { + let i: u32 = unsafe { + // 0.0 == -0.0 so they should also have the same hashcode + cast::transmute(if *self == -0.0 { 0.0 } else { *self }) + }; + i.iter_bytes(lsb0, f) + } +} + +impl IterBytes for f64 { + #[inline] + fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { + let i: u64 = unsafe { + // 0.0 == -0.0 so they should also have the same hashcode + cast::transmute(if *self == -0.0 { 0.0 } else { *self }) + }; + i.iter_bytes(lsb0, f) + } +} + impl<'self,A:IterBytes> IterBytes for &'self [A] { - #[inline(always)] + #[inline] fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { self.each(|elt| elt.iter_bytes(lsb0, |b| f(b))) } } impl<A:IterBytes,B:IterBytes> IterBytes for (A,B) { - #[inline(always)] + #[inline] fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { match *self { (ref a, ref b) => { a.iter_bytes(lsb0, f) && b.iter_bytes(lsb0, f) } @@ -207,7 +237,7 @@ impl<A:IterBytes,B:IterBytes> IterBytes for (A,B) { } impl<A:IterBytes,B:IterBytes,C:IterBytes> IterBytes for (A,B,C) { - #[inline(always)] + #[inline] fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { match *self { (ref a, ref b, ref c) => { @@ -223,28 +253,28 @@ fn borrow<'x,A>(a: &'x [A]) -> &'x [A] { } impl<A:IterBytes> IterBytes for ~[A] { - #[inline(always)] + #[inline] fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { borrow(*self).iter_bytes(lsb0, f) } } impl<A:IterBytes> IterBytes for @[A] { - #[inline(always)] + #[inline] fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { borrow(*self).iter_bytes(lsb0, f) } } impl<'self> IterBytes for &'self str { - #[inline(always)] + #[inline] fn iter_bytes(&self, _lsb0: bool, f: Cb) -> bool { f(self.as_bytes()) } } impl IterBytes for ~str { - #[inline(always)] + #[inline] fn iter_bytes(&self, _lsb0: bool, f: Cb) -> bool { // this should possibly include the null terminator, but that // breaks .find_equiv on hashmaps. @@ -253,7 +283,7 @@ impl IterBytes for ~str { } impl IterBytes for @str { - #[inline(always)] + #[inline] fn iter_bytes(&self, _lsb0: bool, f: Cb) -> bool { // this should possibly include the null terminator, but that // breaks .find_equiv on hashmaps. @@ -262,7 +292,7 @@ impl IterBytes for @str { } impl<A:IterBytes> IterBytes for Option<A> { - #[inline(always)] + #[inline] fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { match *self { Some(ref a) => 0u8.iter_bytes(lsb0, f) && a.iter_bytes(lsb0, f), @@ -272,21 +302,21 @@ impl<A:IterBytes> IterBytes for Option<A> { } impl<'self,A:IterBytes> IterBytes for &'self A { - #[inline(always)] + #[inline] fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { (**self).iter_bytes(lsb0, f) } } impl<A:IterBytes> IterBytes for @A { - #[inline(always)] + #[inline] fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { (**self).iter_bytes(lsb0, f) } } impl<A:IterBytes> IterBytes for ~A { - #[inline(always)] + #[inline] fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { (**self).iter_bytes(lsb0, f) } @@ -295,7 +325,7 @@ impl<A:IterBytes> IterBytes for ~A { // NB: raw-pointer IterBytes does _not_ dereference // to the target; it just gives you the pointer-bytes. impl<A> IterBytes for *const A { - #[inline(always)] + #[inline] fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { (*self as uint).iter_bytes(lsb0, f) } diff --git a/src/libstd/to_str.rs b/src/libstd/to_str.rs index bfda92d46a2..3e782e728fe 100644 --- a/src/libstd/to_str.rs +++ b/src/libstd/to_str.rs @@ -31,16 +31,16 @@ pub trait ToStr { /// Trait for converting a type to a string, consuming it in the process. pub trait ToStrConsume { /// Cosume and convert to a string. - fn to_str_consume(self) -> ~str; + fn into_str(self) -> ~str; } impl ToStr for () { - #[inline(always)] + #[inline] fn to_str(&self) -> ~str { ~"()" } } impl<A:ToStr> ToStr for (A,) { - #[inline(always)] + #[inline] fn to_str(&self) -> ~str { match *self { (ref a,) => { @@ -51,7 +51,7 @@ impl<A:ToStr> ToStr for (A,) { } impl<A:ToStr+Hash+Eq, B:ToStr+Hash+Eq> ToStr for HashMap<A, B> { - #[inline(always)] + #[inline] fn to_str(&self) -> ~str { let mut (acc, first) = (~"{", true); for self.each |key, value| { @@ -71,7 +71,7 @@ impl<A:ToStr+Hash+Eq, B:ToStr+Hash+Eq> ToStr for HashMap<A, B> { } impl<A:ToStr+Hash+Eq> ToStr for HashSet<A> { - #[inline(always)] + #[inline] fn to_str(&self) -> ~str { let mut (acc, first) = (~"{", true); for self.each |element| { @@ -89,7 +89,7 @@ impl<A:ToStr+Hash+Eq> ToStr for HashSet<A> { } impl<A:ToStr,B:ToStr> ToStr for (A, B) { - #[inline(always)] + #[inline] fn to_str(&self) -> ~str { // FIXME(#4653): this causes an llvm assertion //let &(ref a, ref b) = self; @@ -102,7 +102,7 @@ impl<A:ToStr,B:ToStr> ToStr for (A, B) { } impl<A:ToStr,B:ToStr,C:ToStr> ToStr for (A, B, C) { - #[inline(always)] + #[inline] fn to_str(&self) -> ~str { // FIXME(#4653): this causes an llvm assertion //let &(ref a, ref b, ref c) = self; @@ -119,7 +119,7 @@ impl<A:ToStr,B:ToStr,C:ToStr> ToStr for (A, B, C) { } impl<'self,A:ToStr> ToStr for &'self [A] { - #[inline(always)] + #[inline] fn to_str(&self) -> ~str { let mut (acc, first) = (~"[", true); for self.each |elt| { @@ -137,7 +137,7 @@ impl<'self,A:ToStr> ToStr for &'self [A] { } impl<A:ToStr> ToStr for ~[A] { - #[inline(always)] + #[inline] fn to_str(&self) -> ~str { let mut (acc, first) = (~"[", true); for self.each |elt| { @@ -155,7 +155,7 @@ impl<A:ToStr> ToStr for ~[A] { } impl<A:ToStr> ToStr for @[A] { - #[inline(always)] + #[inline] fn to_str(&self) -> ~str { let mut (acc, first) = (~"[", true); for self.each |elt| { diff --git a/src/libstd/trie.rs b/src/libstd/trie.rs index 4bd3946f885..aaeaa489834 100644 --- a/src/libstd/trie.rs +++ b/src/libstd/trie.rs @@ -34,17 +34,17 @@ pub struct TrieMap<T> { impl<T> Container for TrieMap<T> { /// Return the number of elements in the map - #[inline(always)] + #[inline] fn len(&const self) -> uint { self.length } /// Return true if the map contains no elements - #[inline(always)] + #[inline] fn is_empty(&const self) -> bool { self.len() == 0 } } impl<T> Mutable for TrieMap<T> { /// Clear the map, removing all values. - #[inline(always)] + #[inline] fn clear(&mut self) { self.root = TrieNode::new(); self.length = 0; @@ -53,37 +53,37 @@ impl<T> Mutable for TrieMap<T> { impl<T> Map<uint, T> for TrieMap<T> { /// Return true if the map contains a value for the specified key - #[inline(always)] + #[inline] fn contains_key(&self, key: &uint) -> bool { self.find(key).is_some() } /// Visit all key-value pairs in order - #[inline(always)] + #[inline] fn each<'a>(&'a self, f: &fn(&uint, &'a T) -> bool) -> bool { self.root.each(f) } /// Visit all keys in order - #[inline(always)] + #[inline] fn each_key(&self, f: &fn(&uint) -> bool) -> bool { self.each(|k, _| f(k)) } /// Visit all values in order - #[inline(always)] + #[inline] fn each_value<'a>(&'a self, f: &fn(&'a T) -> bool) -> bool { self.each(|_, v| f(v)) } /// Iterate over the map and mutate the contained values - #[inline(always)] + #[inline] fn mutate_values(&mut self, f: &fn(&uint, &mut T) -> bool) -> bool { self.root.mutate_values(f) } /// Return a reference to the value corresponding to the key - #[inline(hint)] + #[inline] fn find<'a>(&'a self, key: &uint) -> Option<&'a T> { let mut node: &'a TrieNode<T> = &self.root; let mut idx = 0; @@ -104,7 +104,7 @@ impl<T> Map<uint, T> for TrieMap<T> { } /// Return a mutable reference to the value corresponding to the key - #[inline(always)] + #[inline] fn find_mut<'a>(&'a mut self, key: &uint) -> Option<&'a mut T> { find_mut(&mut self.root.children[chunk(*key, 0)], *key, 1) } @@ -112,14 +112,14 @@ impl<T> Map<uint, T> for TrieMap<T> { /// Insert a key-value pair into the map. An existing value for a /// key is replaced by the new value. Return true if the key did /// not already exist in the map. - #[inline(always)] + #[inline] fn insert(&mut self, key: uint, value: T) -> bool { self.swap(key, value).is_none() } /// Remove a key-value pair from the map. Return true if the key /// was present in the map, otherwise false. - #[inline(always)] + #[inline] fn remove(&mut self, key: &uint) -> bool { self.pop(key).is_some() } @@ -147,25 +147,25 @@ impl<T> Map<uint, T> for TrieMap<T> { impl<T> TrieMap<T> { /// Create an empty TrieMap - #[inline(always)] + #[inline] pub fn new() -> TrieMap<T> { TrieMap{root: TrieNode::new(), length: 0} } /// Visit all key-value pairs in reverse order - #[inline(always)] + #[inline] pub fn each_reverse<'a>(&'a self, f: &fn(&uint, &'a T) -> bool) -> bool { self.root.each_reverse(f) } /// Visit all keys in reverse order - #[inline(always)] + #[inline] pub fn each_key_reverse(&self, f: &fn(&uint) -> bool) -> bool { self.each_reverse(|k, _| f(k)) } /// Visit all values in reverse order - #[inline(always)] + #[inline] pub fn each_value_reverse(&self, f: &fn(&T) -> bool) -> bool { self.each_reverse(|_, v| f(v)) } @@ -178,15 +178,15 @@ pub struct TrieSet { impl BaseIter<uint> for TrieSet { /// Visit all values in order - #[inline(always)] + #[inline] fn each(&self, f: &fn(&uint) -> bool) -> bool { self.map.each_key(f) } - #[inline(always)] + #[inline] fn size_hint(&self) -> Option<uint> { Some(self.len()) } } impl ReverseIter<uint> for TrieSet { /// Visit all values in reverse order - #[inline(always)] + #[inline] fn each_reverse(&self, f: &fn(&uint) -> bool) -> bool { self.map.each_key_reverse(f) } @@ -194,43 +194,43 @@ impl ReverseIter<uint> for TrieSet { impl Container for TrieSet { /// Return the number of elements in the set - #[inline(always)] + #[inline] fn len(&const self) -> uint { self.map.len() } /// Return true if the set contains no elements - #[inline(always)] + #[inline] fn is_empty(&const self) -> bool { self.map.is_empty() } } impl Mutable for TrieSet { /// Clear the set, removing all values. - #[inline(always)] + #[inline] fn clear(&mut self) { self.map.clear() } } impl TrieSet { /// Create an empty TrieSet - #[inline(always)] + #[inline] pub fn new() -> TrieSet { TrieSet{map: TrieMap::new()} } /// Return true if the set contains a value - #[inline(always)] + #[inline] pub fn contains(&self, value: &uint) -> bool { self.map.contains_key(value) } /// Add a value to the set. Return true if the value was not already /// present in the set. - #[inline(always)] + #[inline] pub fn insert(&mut self, value: uint) -> bool { self.map.insert(value, ()) } /// Remove a value from the set. Return true if the value was /// present in the set. - #[inline(always)] + #[inline] pub fn remove(&mut self, value: &uint) -> bool { self.map.remove(value) } @@ -242,7 +242,7 @@ struct TrieNode<T> { } impl<T> TrieNode<T> { - #[inline(always)] + #[inline] fn new() -> TrieNode<T> { // FIXME: #5244: [Nothing, ..SIZE] should be possible without Copy TrieNode{count: 0, @@ -291,7 +291,7 @@ impl<T> TrieNode<T> { } // if this was done via a trait, the key could be generic -#[inline(always)] +#[inline] fn chunk(n: uint, idx: uint) -> uint { let sh = uint::bits - (SHIFT * (idx + 1)); (n >> sh) & MASK diff --git a/src/libstd/tuple.rs b/src/libstd/tuple.rs index 589c18de0ab..fefd55c3541 100644 --- a/src/libstd/tuple.rs +++ b/src/libstd/tuple.rs @@ -29,25 +29,25 @@ pub trait CopyableTuple<T, U> { impl<T:Copy,U:Copy> CopyableTuple<T, U> for (T, U) { /// Return the first element of self - #[inline(always)] + #[inline] fn first(&self) -> T { match *self { - (t, _) => t, + (ref t, _) => copy *t, } } /// Return the second element of self - #[inline(always)] + #[inline] fn second(&self) -> U { match *self { - (_, u) => u, + (_, ref u) => copy *u, } } /// Return the results of swapping the two elements of self - #[inline(always)] + #[inline] fn swap(&self) -> (U, T) { - match *self { + match copy *self { (t, u) => (u, t), } } @@ -63,13 +63,13 @@ pub trait ImmutableTuple<T, U> { } impl<T, U> ImmutableTuple<T, U> for (T, U) { - #[inline(always)] + #[inline] fn first_ref<'a>(&'a self) -> &'a T { match *self { (ref t, _) => t, } } - #[inline(always)] + #[inline] fn second_ref<'a>(&'a self) -> &'a U { match *self { (_, ref u) => u, @@ -83,7 +83,7 @@ pub trait ExtendedTupleOps<A,B> { } impl<'self,A:Copy,B:Copy> ExtendedTupleOps<A,B> for (&'self [A], &'self [B]) { - #[inline(always)] + #[inline] fn zip(&self) -> ~[(A, B)] { match *self { (ref a, ref b) => { @@ -92,7 +92,7 @@ impl<'self,A:Copy,B:Copy> ExtendedTupleOps<A,B> for (&'self [A], &'self [B]) { } } - #[inline(always)] + #[inline] fn map<C>(&self, f: &fn(a: &A, b: &B) -> C) -> ~[C] { match *self { (ref a, ref b) => { @@ -103,7 +103,7 @@ impl<'self,A:Copy,B:Copy> ExtendedTupleOps<A,B> for (&'self [A], &'self [B]) { } impl<A:Copy,B:Copy> ExtendedTupleOps<A,B> for (~[A], ~[B]) { - #[inline(always)] + #[inline] fn zip(&self) -> ~[(A, B)] { match *self { (ref a, ref b) => { @@ -112,7 +112,7 @@ impl<A:Copy,B:Copy> ExtendedTupleOps<A,B> for (~[A], ~[B]) { } } - #[inline(always)] + #[inline] fn map<C>(&self, f: &fn(a: &A, b: &B) -> C) -> ~[C] { match *self { (ref a, ref b) => { @@ -135,6 +135,7 @@ macro_rules! tuple_impls { pub mod inner { use clone::Clone; #[cfg(not(test))] use cmp::*; + #[cfg(not(test))] use num::Zero; $( pub trait $cloneable_trait<$($T),+> { @@ -143,7 +144,7 @@ macro_rules! tuple_impls { impl<$($T:Clone),+> $cloneable_trait<$($T),+> for ($($T),+) { $( - #[inline(always)] + #[inline] fn $get_fn(&self) -> $T { self.$get_ref_fn().clone() } @@ -156,7 +157,7 @@ macro_rules! tuple_impls { impl<$($T),+> $immutable_trait<$($T),+> for ($($T),+) { $( - #[inline(always)] + #[inline] fn $get_ref_fn<'a>(&'a self) -> &'a $T { match *self { $get_pattern => $ret } } @@ -171,11 +172,11 @@ macro_rules! tuple_impls { #[cfg(not(test))] impl<$($T:Eq),+> Eq for ($($T),+) { - #[inline(always)] + #[inline] fn eq(&self, other: &($($T),+)) -> bool { $(*self.$get_ref_fn() == *other.$get_ref_fn())&&+ } - #[inline(always)] + #[inline] fn ne(&self, other: &($($T),+)) -> bool { !(*self == *other) } @@ -183,7 +184,7 @@ macro_rules! tuple_impls { #[cfg(not(test))] impl<$($T:TotalEq),+> TotalEq for ($($T),+) { - #[inline(always)] + #[inline] fn equals(&self, other: &($($T),+)) -> bool { $(self.$get_ref_fn().equals(other.$get_ref_fn()))&&+ } @@ -191,15 +192,15 @@ macro_rules! tuple_impls { #[cfg(not(test))] impl<$($T:Ord),+> Ord for ($($T),+) { - #[inline(always)] + #[inline] fn lt(&self, other: &($($T),+)) -> bool { lexical_lt!($(self.$get_ref_fn(), other.$get_ref_fn()),+) } - #[inline(always)] + #[inline] fn le(&self, other: &($($T),+)) -> bool { !(*other).lt(&(*self)) } - #[inline(always)] + #[inline] fn ge(&self, other: &($($T),+)) -> bool { !(*self).lt(other) } - #[inline(always)] + #[inline] fn gt(&self, other: &($($T),+)) -> bool { (*other).lt(&(*self)) } } @@ -210,6 +211,18 @@ macro_rules! tuple_impls { lexical_cmp!($(self.$get_ref_fn(), other.$get_ref_fn()),+) } } + + #[cfg(not(test))] + impl<$($T:Zero),+> Zero for ($($T),+) { + #[inline] + fn zero() -> ($($T),+) { + ($(Zero::zero::<$T>()),+) + } + #[inline] + fn is_zero(&self) -> bool { + $(self.$get_ref_fn().is_zero())&&+ + } + } )+ } } diff --git a/src/libstd/unstable/atomics.rs b/src/libstd/unstable/atomics.rs index aa70897ad48..6e7a7e2b129 100644 --- a/src/libstd/unstable/atomics.rs +++ b/src/libstd/unstable/atomics.rs @@ -82,7 +82,7 @@ impl AtomicFlag { /** * Clears the atomic flag */ - #[inline(always)] + #[inline] pub fn clear(&mut self, order: Ordering) { unsafe {atomic_store(&mut self.v, 0, order)} } @@ -91,7 +91,7 @@ impl AtomicFlag { * Sets the flag if it was previously unset, returns the previous value of the * flag. */ - #[inline(always)] + #[inline] pub fn test_and_set(&mut self, order: Ordering) -> bool { unsafe {atomic_compare_and_swap(&mut self.v, 0, 1, order) > 0} } @@ -102,26 +102,26 @@ impl AtomicBool { AtomicBool { v: if v { 1 } else { 0 } } } - #[inline(always)] + #[inline] pub fn load(&self, order: Ordering) -> bool { unsafe { atomic_load(&self.v, order) > 0 } } - #[inline(always)] + #[inline] pub fn store(&mut self, val: bool, order: Ordering) { let val = if val { 1 } else { 0 }; unsafe { atomic_store(&mut self.v, val, order); } } - #[inline(always)] + #[inline] pub fn swap(&mut self, val: bool, order: Ordering) -> bool { let val = if val { 1 } else { 0 }; unsafe { atomic_swap(&mut self.v, val, order) > 0} } - #[inline(always)] + #[inline] pub fn compare_and_swap(&mut self, old: bool, new: bool, order: Ordering) -> bool { let old = if old { 1 } else { 0 }; let new = if new { 1 } else { 0 }; @@ -135,34 +135,34 @@ impl AtomicInt { AtomicInt { v:v } } - #[inline(always)] + #[inline] pub fn load(&self, order: Ordering) -> int { unsafe { atomic_load(&self.v, order) } } - #[inline(always)] + #[inline] pub fn store(&mut self, val: int, order: Ordering) { unsafe { atomic_store(&mut self.v, val, order); } } - #[inline(always)] + #[inline] pub fn swap(&mut self, val: int, order: Ordering) -> int { unsafe { atomic_swap(&mut self.v, val, order) } } - #[inline(always)] + #[inline] pub fn compare_and_swap(&mut self, old: int, new: int, order: Ordering) -> int { unsafe { atomic_compare_and_swap(&mut self.v, old, new, order) } } /// Returns the old value (like __sync_fetch_and_add). - #[inline(always)] + #[inline] pub fn fetch_add(&mut self, val: int, order: Ordering) -> int { unsafe { atomic_add(&mut self.v, val, order) } } /// Returns the old value (like __sync_fetch_and_sub). - #[inline(always)] + #[inline] pub fn fetch_sub(&mut self, val: int, order: Ordering) -> int { unsafe { atomic_sub(&mut self.v, val, order) } } @@ -173,34 +173,34 @@ impl AtomicUint { AtomicUint { v:v } } - #[inline(always)] + #[inline] pub fn load(&self, order: Ordering) -> uint { unsafe { atomic_load(&self.v, order) } } - #[inline(always)] + #[inline] pub fn store(&mut self, val: uint, order: Ordering) { unsafe { atomic_store(&mut self.v, val, order); } } - #[inline(always)] + #[inline] pub fn swap(&mut self, val: uint, order: Ordering) -> uint { unsafe { atomic_swap(&mut self.v, val, order) } } - #[inline(always)] + #[inline] pub fn compare_and_swap(&mut self, old: uint, new: uint, order: Ordering) -> uint { unsafe { atomic_compare_and_swap(&mut self.v, old, new, order) } } /// Returns the old value (like __sync_fetch_and_add). - #[inline(always)] + #[inline] pub fn fetch_add(&mut self, val: uint, order: Ordering) -> uint { unsafe { atomic_add(&mut self.v, val, order) } } /// Returns the old value (like __sync_fetch_and_sub).. - #[inline(always)] + #[inline] pub fn fetch_sub(&mut self, val: uint, order: Ordering) -> uint { unsafe { atomic_sub(&mut self.v, val, order) } } @@ -211,22 +211,22 @@ impl<T> AtomicPtr<T> { AtomicPtr { p:p } } - #[inline(always)] + #[inline] pub fn load(&self, order: Ordering) -> *mut T { unsafe { atomic_load(&self.p, order) } } - #[inline(always)] + #[inline] pub fn store(&mut self, ptr: *mut T, order: Ordering) { unsafe { atomic_store(&mut self.p, ptr, order); } } - #[inline(always)] + #[inline] pub fn swap(&mut self, ptr: *mut T, order: Ordering) -> *mut T { unsafe { atomic_swap(&mut self.p, ptr, order) } } - #[inline(always)] + #[inline] pub fn compare_and_swap(&mut self, old: *mut T, new: *mut T, order: Ordering) -> *mut T { unsafe { atomic_compare_and_swap(&mut self.p, old, new, order) } } @@ -249,7 +249,7 @@ impl<T> AtomicOption<T> { } } - #[inline(always)] + #[inline] pub fn swap(&mut self, val: ~T, order: Ordering) -> Option<~T> { unsafe { let val = cast::transmute(val); @@ -265,7 +265,7 @@ impl<T> AtomicOption<T> { } } - #[inline(always)] + #[inline] pub fn take(&mut self, order: Ordering) -> Option<~T> { unsafe { self.swap(cast::transmute(0), order) @@ -286,7 +286,7 @@ impl<T> Drop for AtomicOption<T> { } } -#[inline(always)] +#[inline] pub unsafe fn atomic_store<T>(dst: &mut T, val: T, order:Ordering) { let dst = cast::transmute(dst); let val = cast::transmute(val); @@ -297,7 +297,7 @@ pub unsafe fn atomic_store<T>(dst: &mut T, val: T, order:Ordering) { } } -#[inline(always)] +#[inline] pub unsafe fn atomic_load<T>(dst: &T, order:Ordering) -> T { let dst = cast::transmute(dst); @@ -307,7 +307,7 @@ pub unsafe fn atomic_load<T>(dst: &T, order:Ordering) -> T { }) } -#[inline(always)] +#[inline] pub unsafe fn atomic_swap<T>(dst: &mut T, val: T, order: Ordering) -> T { let dst = cast::transmute(dst); let val = cast::transmute(val); @@ -320,7 +320,7 @@ pub unsafe fn atomic_swap<T>(dst: &mut T, val: T, order: Ordering) -> T { } /// Returns the old value (like __sync_fetch_and_add). -#[inline(always)] +#[inline] pub unsafe fn atomic_add<T>(dst: &mut T, val: T, order: Ordering) -> T { let dst = cast::transmute(dst); let val = cast::transmute(val); @@ -333,7 +333,7 @@ pub unsafe fn atomic_add<T>(dst: &mut T, val: T, order: Ordering) -> T { } /// Returns the old value (like __sync_fetch_and_sub). -#[inline(always)] +#[inline] pub unsafe fn atomic_sub<T>(dst: &mut T, val: T, order: Ordering) -> T { let dst = cast::transmute(dst); let val = cast::transmute(val); @@ -345,7 +345,7 @@ pub unsafe fn atomic_sub<T>(dst: &mut T, val: T, order: Ordering) -> T { }) } -#[inline(always)] +#[inline] pub unsafe fn atomic_compare_and_swap<T>(dst:&mut T, old:T, new:T, order: Ordering) -> T { let dst = cast::transmute(dst); let old = cast::transmute(old); diff --git a/src/libstd/unstable/dynamic_lib.rs b/src/libstd/unstable/dynamic_lib.rs index 96aba1d2971..64dd5bba6bc 100644 --- a/src/libstd/unstable/dynamic_lib.rs +++ b/src/libstd/unstable/dynamic_lib.rs @@ -15,7 +15,6 @@ Dynamic library facilities. A simple wrapper over the platforms dynamic library facilities */ -use ptr; use cast; use path; use libc; @@ -42,19 +41,15 @@ impl DynamicLibrary { /// Lazily open a dynamic library. When passed None it gives a /// handle to the calling process pub fn open(filename: Option<&path::Path>) -> Result<DynamicLibrary, ~str> { - let open_wrapper = |raw_ptr| { - do dl::check_for_errors_in { - unsafe { - DynamicLibrary { handle: dl::open(raw_ptr) } + do dl::check_for_errors_in { + unsafe { + DynamicLibrary { handle: + match filename { + Some(name) => dl::open_external(name), + None => dl::open_internal() + } } } - }; - - match filename { - Some(name) => do name.to_str().as_c_str |raw_name| { - open_wrapper(raw_name) - }, - None => open_wrapper(ptr::null()) } } @@ -74,6 +69,7 @@ impl DynamicLibrary { } #[test] +#[ignore(cfg(windows))] priv fn test_loading_cosine () { // The math library does not need to be loaded since it is already // statically linked in @@ -106,13 +102,20 @@ priv fn test_loading_cosine () { #[cfg(target_os = "freebsd")] mod dl { use libc; + use path; use ptr; use str; use task; use result::*; - pub unsafe fn open(filename: *libc::c_char) -> *libc::c_void { - dlopen(filename, Lazy as libc::c_int) + pub unsafe fn open_external(filename: &path::Path) -> *libc::c_void { + do filename.to_str().as_c_str |raw_name| { + dlopen(raw_name, Lazy as libc::c_int) + } + } + + pub unsafe fn open_internal() -> *libc::c_void { + dlopen(ptr::null(), Lazy as libc::c_int) } pub fn check_for_errors_in<T>(f: &fn()->T) -> Result<T, ~str> { @@ -159,11 +162,22 @@ mod dl { mod dl { use os; use libc; + use path; + use ptr; + use str; use task; use result::*; - pub unsafe fn open(filename: *libc::c_char) -> *libc::c_void { - LoadLibrary(filename) + pub unsafe fn open_external(filename: &path::Path) -> *libc::c_void { + do os::win32::as_utf16_p(filename.to_str()) |raw_name| { + LoadLibraryW(raw_name) + } + } + + pub unsafe fn open_internal() -> *libc::c_void { + let mut handle = ptr::null(); + GetModuleHandleExW(0 as libc::DWORD, ptr::null(), &handle as **libc::c_void); + handle } pub fn check_for_errors_in<T>(f: &fn()->T) -> Result<T, ~str> { @@ -192,7 +206,9 @@ mod dl { #[link_name = "kernel32"] extern "stdcall" { fn SetLastError(error: u32); - fn LoadLibrary(name: *libc::c_char) -> *libc::c_void; + fn LoadLibraryW(name: *u16) -> *libc::c_void; + fn GetModuleHandleExW(dwFlags: libc::DWORD, name: *u16, + handle: **libc::c_void) -> *libc::c_void; fn GetProcAddress(handle: *libc::c_void, name: *libc::c_char) -> *libc::c_void; fn FreeLibrary(handle: *libc::c_void); } diff --git a/src/libstd/unstable/extfmt.rs b/src/libstd/unstable/extfmt.rs index 7d9ce585d7c..d466488ce5e 100644 --- a/src/libstd/unstable/extfmt.rs +++ b/src/libstd/unstable/extfmt.rs @@ -673,7 +673,7 @@ pub mod rt { } buf.push_str(s); } - #[inline(always)] + #[inline] pub fn have_flag(flags: u32, f: u32) -> bool { flags & f != 0 } diff --git a/src/libstd/unstable/global.rs b/src/libstd/unstable/global.rs index 96549a83a8c..f81252274c4 100644 --- a/src/libstd/unstable/global.rs +++ b/src/libstd/unstable/global.rs @@ -105,7 +105,7 @@ unsafe fn global_data_modify_<T:Owned>( let dtor: ~fn() = match maybe_dtor { Some(dtor) => dtor, None => { - let dtor: ~fn() = || unsafe { + let dtor: ~fn() = || { let _destroy_value: ~T = transmute(data); }; dtor diff --git a/src/libstd/unstable/intrinsics.rs b/src/libstd/unstable/intrinsics.rs index 908c5e23ab0..13425007785 100644 --- a/src/libstd/unstable/intrinsics.rs +++ b/src/libstd/unstable/intrinsics.rs @@ -130,36 +130,23 @@ pub extern "rust-intrinsic" { /// Equivalent to the `llvm.memcpy.p0i8.0i8.i32` intrinsic, with a size of /// `count` * `size_of::<T>()` and an alignment of `min_align_of::<T>()` - #[cfg(not(stage0))] pub fn memcpy32<T>(dst: *mut T, src: *T, count: u32); /// Equivalent to the `llvm.memcpy.p0i8.0i8.i64` intrinsic, with a size of /// `count` * `size_of::<T>()` and an alignment of `min_align_of::<T>()` - #[cfg(not(stage0))] pub fn memcpy64<T>(dst: *mut T, src: *T, count: u64); - /// Equivalent to the `llvm.memmove.p0i8.0i8.i32` intrinsic. - #[cfg(stage0)] - pub fn memmove32(dst: *mut u8, src: *u8, size: u32); - /// Equivalent to the `llvm.memmove.p0i8.0i8.i64` intrinsic. - #[cfg(stage0)] - pub fn memmove64(dst: *mut u8, src: *u8, size: u64); - /// Equivalent to the `llvm.memmove.p0i8.0i8.i32` intrinsic, with a size of /// `count` * `size_of::<T>()` and an alignment of `min_align_of::<T>()` - #[cfg(not(stage0))] pub fn memmove32<T>(dst: *mut T, src: *T, count: u32); /// Equivalent to the `llvm.memmove.p0i8.0i8.i64` intrinsic, with a size of /// `count` * `size_of::<T>()` and an alignment of `min_align_of::<T>()` - #[cfg(not(stage0))] pub fn memmove64<T>(dst: *mut T, src: *T, count: u64); /// Equivalent to the `llvm.memset.p0i8.i32` intrinsic, with a size of /// `count` * `size_of::<T>()` and an alignment of `min_align_of::<T>()` - #[cfg(not(stage0))] pub fn memset32<T>(dst: *mut T, val: u8, count: u32); /// Equivalent to the `llvm.memset.p0i8.i64` intrinsic, with a size of /// `count` * `size_of::<T>()` and an alignment of `min_align_of::<T>()` - #[cfg(not(stage0))] pub fn memset64<T>(dst: *mut T, val: u8, count: u64); pub fn sqrtf32(x: f32) -> f32; diff --git a/src/libstd/unstable/lang.rs b/src/libstd/unstable/lang.rs index 3d61c1fe144..f750b31a466 100644 --- a/src/libstd/unstable/lang.rs +++ b/src/libstd/unstable/lang.rs @@ -14,7 +14,6 @@ use iterator::IteratorUtil; use uint; use cast::transmute; use libc::{c_char, c_uchar, c_void, size_t, uintptr_t, c_int, STDERR_FILENO}; -use managed::raw::BoxRepr; use str; use sys; use rt::{context, OldTaskContext}; @@ -23,14 +22,11 @@ use rt::local::Local; use option::{Option, Some, None}; use io; use rt::global_heap; +use rt::borrowck; #[allow(non_camel_case_types)] pub type rust_task = c_void; -pub static FROZEN_BIT: uint = 1 << (uint::bits - 1); -pub static MUT_BIT: uint = 1 << (uint::bits - 2); -static ALL_BITS: uint = FROZEN_BIT | MUT_BIT; - pub mod rustrt { use unstable::lang::rust_task; use libc::{c_void, c_char, uintptr_t}; @@ -47,15 +43,6 @@ pub mod rustrt { size: uintptr_t) -> *c_char; - #[fast_ffi] - unsafe fn rust_upcall_free_noswitch(ptr: *c_char); - - #[rust_stack] - fn rust_take_task_borrow_list(task: *rust_task) -> *c_void; - - #[rust_stack] - fn rust_set_task_borrow_list(task: *rust_task, map: *c_void); - #[rust_stack] fn rust_try_get_task() -> *rust_task; @@ -78,161 +65,18 @@ pub fn fail_bounds_check(file: *c_char, line: size_t, } } -#[deriving(Eq)] -struct BorrowRecord { - box: *mut BoxRepr, - file: *c_char, - line: size_t -} - -fn try_take_task_borrow_list() -> Option<~[BorrowRecord]> { - unsafe { - let cur_task: *rust_task = rustrt::rust_try_get_task(); - if cur_task.is_not_null() { - let ptr = rustrt::rust_take_task_borrow_list(cur_task); - if ptr.is_null() { - None - } else { - let v: ~[BorrowRecord] = transmute(ptr); - Some(v) - } - } else { - None - } - } -} - -fn swap_task_borrow_list(f: &fn(~[BorrowRecord]) -> ~[BorrowRecord]) { - unsafe { - let cur_task: *rust_task = rustrt::rust_try_get_task(); - if cur_task.is_not_null() { - let mut borrow_list: ~[BorrowRecord] = { - let ptr = rustrt::rust_take_task_borrow_list(cur_task); - if ptr.is_null() { ~[] } else { transmute(ptr) } - }; - borrow_list = f(borrow_list); - rustrt::rust_set_task_borrow_list(cur_task, transmute(borrow_list)); - } - } -} - -pub unsafe fn clear_task_borrow_list() { - // pub because it is used by the box annihilator. - let _ = try_take_task_borrow_list(); -} - -unsafe fn fail_borrowed(box: *mut BoxRepr, file: *c_char, line: size_t) { - debug_borrow("fail_borrowed: ", box, 0, 0, file, line); - - match try_take_task_borrow_list() { - None => { // not recording borrows - let msg = "borrowed"; - do str::as_buf(msg) |msg_p, _| { - fail_(msg_p as *c_char, file, line); - } - } - Some(borrow_list) => { // recording borrows - let mut msg = ~"borrowed"; - let mut sep = " at "; - for borrow_list.rev_iter().advance |entry| { - if entry.box == box { - msg.push_str(sep); - let filename = str::raw::from_c_str(entry.file); - msg.push_str(filename); - msg.push_str(fmt!(":%u", entry.line as uint)); - sep = " and at "; - } - } - do str::as_buf(msg) |msg_p, _| { - fail_(msg_p as *c_char, file, line) - } - } - } -} - // FIXME #4942: Make these signatures agree with exchange_alloc's signatures #[lang="exchange_malloc"] -#[inline(always)] +#[inline] pub unsafe fn exchange_malloc(td: *c_char, size: uintptr_t) -> *c_char { transmute(global_heap::malloc(transmute(td), transmute(size))) } -/// Because this code is so perf. sensitive, use a static constant so that -/// debug printouts are compiled out most of the time. -static ENABLE_DEBUG: bool = false; - -#[inline] -unsafe fn debug_borrow<T>(tag: &'static str, - p: *const T, - old_bits: uint, - new_bits: uint, - filename: *c_char, - line: size_t) { - //! A useful debugging function that prints a pointer + tag + newline - //! without allocating memory. - - if ENABLE_DEBUG && ::rt::env::get().debug_borrow { - debug_borrow_slow(tag, p, old_bits, new_bits, filename, line); - } - - unsafe fn debug_borrow_slow<T>(tag: &'static str, - p: *const T, - old_bits: uint, - new_bits: uint, - filename: *c_char, - line: size_t) { - let dbg = STDERR_FILENO as io::fd_t; - dbg.write_str(tag); - dbg.write_hex(p as uint); - dbg.write_str(" "); - dbg.write_hex(old_bits); - dbg.write_str(" "); - dbg.write_hex(new_bits); - dbg.write_str(" "); - dbg.write_cstr(filename); - dbg.write_str(":"); - dbg.write_hex(line as uint); - dbg.write_str("\n"); - } -} - -trait DebugPrints { - fn write_hex(&self, val: uint); - unsafe fn write_cstr(&self, str: *c_char); -} - -impl DebugPrints for io::fd_t { - fn write_hex(&self, mut i: uint) { - let letters = ['0', '1', '2', '3', '4', '5', '6', '7', '8', - '9', 'a', 'b', 'c', 'd', 'e', 'f']; - static uint_nibbles: uint = ::uint::bytes << 1; - let mut buffer = [0_u8, ..uint_nibbles+1]; - let mut c = uint_nibbles; - while c > 0 { - c -= 1; - buffer[c] = letters[i & 0xF] as u8; - i >>= 4; - } - self.write(buffer.slice(0, uint_nibbles)); - } - - unsafe fn write_cstr(&self, p: *c_char) { - use libc::strlen; - use vec; - - let len = strlen(p); - let p: *u8 = transmute(p); - do vec::raw::buf_as_slice(p, len as uint) |s| { - self.write(s); - } - } -} - // NB: Calls to free CANNOT be allowed to fail, as throwing an exception from // inside a landing pad may corrupt the state of the exception handler. If a // problem occurs, call exit instead. #[lang="exchange_free"] -#[inline(always)] +#[inline] pub unsafe fn exchange_free(ptr: *c_char) { global_heap::free(transmute(ptr)) } @@ -258,138 +102,63 @@ pub unsafe fn local_malloc(td: *c_char, size: uintptr_t) -> *c_char { // problem occurs, call exit instead. #[lang="free"] pub unsafe fn local_free(ptr: *c_char) { - match context() { - OldTaskContext => { - rustrt::rust_upcall_free_noswitch(ptr); - } - _ => { - do Local::borrow::<Task,()> |task| { - task.heap.free(ptr as *c_void); - } - } - } + ::rt::local_heap::local_free(ptr); } #[lang="borrow_as_imm"] -#[inline(always)] +#[inline] pub unsafe fn borrow_as_imm(a: *u8, file: *c_char, line: size_t) -> uint { - let a: *mut BoxRepr = transmute(a); - let old_ref_count = (*a).header.ref_count; - let new_ref_count = old_ref_count | FROZEN_BIT; - - debug_borrow("borrow_as_imm:", a, old_ref_count, new_ref_count, file, line); - - if (old_ref_count & MUT_BIT) != 0 { - fail_borrowed(a, file, line); - } - - (*a).header.ref_count = new_ref_count; - - old_ref_count + borrowck::borrow_as_imm(a, file, line) } #[lang="borrow_as_mut"] -#[inline(always)] +#[inline] pub unsafe fn borrow_as_mut(a: *u8, file: *c_char, line: size_t) -> uint { - let a: *mut BoxRepr = transmute(a); - let old_ref_count = (*a).header.ref_count; - let new_ref_count = old_ref_count | MUT_BIT | FROZEN_BIT; - - debug_borrow("borrow_as_mut:", a, old_ref_count, new_ref_count, file, line); - - if (old_ref_count & (MUT_BIT|FROZEN_BIT)) != 0 { - fail_borrowed(a, file, line); - } - - (*a).header.ref_count = new_ref_count; - - old_ref_count + borrowck::borrow_as_mut(a, file, line) } - #[lang="record_borrow"] pub unsafe fn record_borrow(a: *u8, old_ref_count: uint, file: *c_char, line: size_t) { - if (old_ref_count & ALL_BITS) == 0 { - // was not borrowed before - let a: *mut BoxRepr = transmute(a); - debug_borrow("record_borrow:", a, old_ref_count, 0, file, line); - do swap_task_borrow_list |borrow_list| { - let mut borrow_list = borrow_list; - borrow_list.push(BorrowRecord {box: a, file: file, line: line}); - borrow_list - } - } + borrowck::record_borrow(a, old_ref_count, file, line) } #[lang="unrecord_borrow"] pub unsafe fn unrecord_borrow(a: *u8, old_ref_count: uint, file: *c_char, line: size_t) { - if (old_ref_count & ALL_BITS) == 0 { - // was not borrowed before, so we should find the record at - // the end of the list - let a: *mut BoxRepr = transmute(a); - debug_borrow("unrecord_borrow:", a, old_ref_count, 0, file, line); - do swap_task_borrow_list |borrow_list| { - let mut borrow_list = borrow_list; - assert!(!borrow_list.is_empty()); - let br = borrow_list.pop(); - if br.box != a || br.file != file || br.line != line { - let err = fmt!("wrong borrow found, br=%?", br); - do str::as_buf(err) |msg_p, _| { - fail_(msg_p as *c_char, file, line) - } - } - borrow_list - } - } + borrowck::unrecord_borrow(a, old_ref_count, file, line) } #[lang="return_to_mut"] -#[inline(always)] +#[inline] pub unsafe fn return_to_mut(a: *u8, orig_ref_count: uint, file: *c_char, line: size_t) { - // Sometimes the box is null, if it is conditionally frozen. - // See e.g. #4904. - if !a.is_null() { - let a: *mut BoxRepr = transmute(a); - let old_ref_count = (*a).header.ref_count; - let new_ref_count = - (old_ref_count & !ALL_BITS) | (orig_ref_count & ALL_BITS); - - debug_borrow("return_to_mut:", - a, old_ref_count, new_ref_count, file, line); - - (*a).header.ref_count = new_ref_count; - } + borrowck::return_to_mut(a, orig_ref_count, file, line) } #[lang="check_not_borrowed"] -#[inline(always)] +#[inline] pub unsafe fn check_not_borrowed(a: *u8, file: *c_char, line: size_t) { - let a: *mut BoxRepr = transmute(a); - let ref_count = (*a).header.ref_count; - debug_borrow("check_not_borrowed:", a, ref_count, 0, file, line); - if (ref_count & FROZEN_BIT) != 0 { - fail_borrowed(a, file, line); - } + borrowck::check_not_borrowed(a, file, line) } #[lang="strdup_uniq"] -#[inline(always)] +#[inline] pub unsafe fn strdup_uniq(ptr: *c_uchar, len: uint) -> ~str { str::raw::from_buf_len(ptr, len) } +#[lang="annihilate"] +pub unsafe fn annihilate() { + ::cleanup::annihilate() +} + #[lang="start"] pub fn start(main: *u8, argc: int, argv: **c_char, crate_map: *u8) -> int { use rt; - use sys::Closure; - use ptr; - use cast; use os; unsafe { @@ -399,17 +168,8 @@ pub fn start(main: *u8, argc: int, argv: **c_char, crate_map as *c_void) as int; } else { return do rt::start(argc, argv as **u8, crate_map) { - unsafe { - // `main` is an `fn() -> ()` that doesn't take an environment - // XXX: Could also call this as an `extern "Rust" fn` once they work - let main = Closure { - code: main as *(), - env: ptr::null(), - }; - let mainfn: &fn() = cast::transmute(main); - - mainfn(); - } + let main: extern "Rust" fn() = transmute(main); + main(); }; } } diff --git a/src/libstd/unstable/mod.rs b/src/libstd/unstable/mod.rs index ae878050142..0a46ef619af 100644 --- a/src/libstd/unstable/mod.rs +++ b/src/libstd/unstable/mod.rs @@ -18,11 +18,6 @@ use task; pub mod at_exit; -// Currently only works for *NIXes -#[cfg(target_os = "linux")] -#[cfg(target_os = "android")] -#[cfg(target_os = "macos")] -#[cfg(target_os = "freebsd")] pub mod dynamic_lib; pub mod global; diff --git a/src/libstd/unstable/sync.rs b/src/libstd/unstable/sync.rs index 3cf46bec41a..162891124f6 100644 --- a/src/libstd/unstable/sync.rs +++ b/src/libstd/unstable/sync.rs @@ -40,7 +40,7 @@ impl<T: Owned> UnsafeAtomicRcBox<T> { } } - #[inline(always)] + #[inline] pub unsafe fn get(&self) -> *mut T { let mut data: ~AtomicRcBoxData<T> = cast::transmute(self.data); @@ -50,7 +50,7 @@ impl<T: Owned> UnsafeAtomicRcBox<T> { return r; } - #[inline(always)] + #[inline] pub unsafe fn get_immut(&self) -> *T { let mut data: ~AtomicRcBoxData<T> = cast::transmute(self.data); @@ -118,7 +118,7 @@ fn LittleLock() -> LittleLock { } impl LittleLock { - #[inline(always)] + #[inline] pub unsafe fn lock<T>(&self, f: &fn() -> T) -> T { do atomically { rust_lock_little_lock(self.l); @@ -169,7 +169,7 @@ impl<T:Owned> Exclusive<T> { // Currently, scheduling operations (i.e., yielding, receiving on a pipe, // accessing the provided condition variable) are prohibited while inside // the exclusive. Supporting that is a work in progress. - #[inline(always)] + #[inline] pub unsafe fn with<U>(&self, f: &fn(x: &mut T) -> U) -> U { let rec = self.x.get(); do (*rec).lock.lock { @@ -183,7 +183,7 @@ impl<T:Owned> Exclusive<T> { } } - #[inline(always)] + #[inline] pub unsafe fn with_imm<U>(&self, f: &fn(x: &T) -> U) -> U { do self.with |x| { f(cast::transmute_immut(x)) diff --git a/src/libstd/util.rs b/src/libstd/util.rs index 61c284f580c..2a5d44c9ce2 100644 --- a/src/libstd/util.rs +++ b/src/libstd/util.rs @@ -16,11 +16,11 @@ use prelude::*; use unstable::intrinsics; /// The identity function. -#[inline(always)] +#[inline] pub fn id<T>(x: T) -> T { x } /// Ignores a value. -#[inline(always)] +#[inline] pub fn ignore<T>(_x: T) { } /// Sets `*ptr` to `new_value`, invokes `op()`, and then restores the @@ -30,7 +30,7 @@ pub fn ignore<T>(_x: T) { } /// an obvious borrowck hazard. Typically passing in `&mut T` will /// cause borrow check errors because it freezes whatever location /// that `&mut T` is stored in (either statically or dynamically). -#[inline(always)] +#[inline] pub fn with<T,R>( ptr: @mut T, value: T, @@ -46,7 +46,7 @@ pub fn with<T,R>( * Swap the values at two mutable locations of the same type, without * deinitialising or copying either one. */ -#[inline(always)] +#[inline] pub fn swap<T>(x: &mut T, y: &mut T) { unsafe { // Give ourselves some scratch space to work with @@ -68,7 +68,7 @@ pub fn swap<T>(x: &mut T, y: &mut T) { * Replace the value at a mutable location with a new one, returning the old * value, without deinitialising or copying either one. */ -#[inline(always)] +#[inline] pub fn replace<T>(dest: &mut T, mut src: T) -> T { swap(dest, &mut src); src diff --git a/src/libstd/vec.rs b/src/libstd/vec.rs index 211ee12c291..4339153c43e 100644 --- a/src/libstd/vec.rs +++ b/src/libstd/vec.rs @@ -19,10 +19,11 @@ use cmp::{Eq, Ord, TotalEq, TotalOrd, Ordering, Less, Equal, Greater}; use clone::Clone; use old_iter::BaseIter; use old_iter; -use iterator::{Iterator, IteratorUtil}; +use iterator::{Iterator}; use iter::FromIter; use kinds::Copy; use libc; +use num::Zero; use old_iter::CopyableIter; use option::{None, Option, Some}; use ptr::to_unsafe_ptr; @@ -47,12 +48,8 @@ pub mod rustrt { // to ~[] and reserve_shared_actual applies to @[]. #[fast_ffi] unsafe fn vec_reserve_shared(t: *sys::TypeDesc, - v: **raw::VecRepr, + v: *mut *mut raw::VecRepr, n: libc::size_t); - #[fast_ffi] - unsafe fn vec_reserve_shared_actual(t: *sys::TypeDesc, - v: **raw::VecRepr, - n: libc::size_t); } } @@ -78,11 +75,11 @@ pub fn reserve<T>(v: &mut ~[T], n: uint) { use managed; if capacity(v) < n { unsafe { - let ptr: **raw::VecRepr = cast::transmute(v); + let ptr: *mut *mut raw::VecRepr = cast::transmute(v); let td = sys::get_type_desc::<T>(); if ((**ptr).box_header.ref_count == managed::raw::RC_MANAGED_UNIQUE) { - rustrt::vec_reserve_shared_actual(td, ptr, n as libc::size_t); + ::at_vec::raw::reserve_raw(td, ptr, n); } else { rustrt::vec_reserve_shared(td, ptr, n as libc::size_t); } @@ -110,7 +107,7 @@ pub fn reserve_at_least<T>(v: &mut ~[T], n: uint) { } /// Returns the number of elements the vector can hold without reallocating -#[inline(always)] +#[inline] pub fn capacity<T>(v: &const ~[T]) -> uint { unsafe { let repr: **raw::VecRepr = transmute(v); @@ -118,15 +115,6 @@ pub fn capacity<T>(v: &const ~[T]) -> uint { } } -// A botch to tide us over until core and std are fully demuted. -#[allow(missing_doc)] -pub fn uniq_len<T>(v: &const ~[T]) -> uint { - unsafe { - let v: &~[T] = transmute(v); - as_const_buf(*v, |_p, len| len) - } -} - /** * Creates and initializes an owned vector. * @@ -155,8 +143,10 @@ pub fn from_fn<T>(n_elts: uint, op: old_iter::InitOp<T>) -> ~[T] { * to the value `t`. */ pub fn from_elem<T:Copy>(n_elts: uint, t: T) -> ~[T] { - // hack: manually inline from_fn for 2x plus speedup (sadly very important, from_elem is a - // bottleneck in borrowck!) + // FIXME (#7136): manually inline from_fn for 2x plus speedup (sadly very + // important, from_elem is a bottleneck in borrowck!). Unfortunately it + // still is substantially slower than using the unsafe + // vec::with_capacity/ptr::set_memory for primitive types. unsafe { let mut v = with_capacity(n_elts); do as_mut_buf(v) |p, _len| { @@ -173,7 +163,7 @@ pub fn from_elem<T:Copy>(n_elts: uint, t: T) -> ~[T] { /// Creates a new unique vector with the same contents as the slice pub fn to_owned<T:Copy>(t: &[T]) -> ~[T] { - from_fn(t.len(), |i| t[i]) + from_fn(t.len(), |i| copy t[i]) } /// Creates a new vector with a capacity of `capacity` @@ -195,7 +185,7 @@ pub fn with_capacity<T>(capacity: uint) -> ~[T] { * as an argument a function that will push an element * onto the vector being constructed. */ -#[inline(always)] +#[inline] pub fn build_sized<A>(size: uint, builder: &fn(push: &fn(v: A))) -> ~[A] { let mut vec = with_capacity(size); builder(|x| vec.push(x)); @@ -212,7 +202,7 @@ pub fn build_sized<A>(size: uint, builder: &fn(push: &fn(v: A))) -> ~[A] { * as an argument a function that will push an element * onto the vector being constructed. */ -#[inline(always)] +#[inline] pub fn build<A>(builder: &fn(push: &fn(v: A))) -> ~[A] { build_sized(4, builder) } @@ -229,7 +219,7 @@ pub fn build<A>(builder: &fn(push: &fn(v: A))) -> ~[A] { * as an argument a function that will push an element * onto the vector being constructed. */ -#[inline(always)] +#[inline] pub fn build_sized_opt<A>(size: Option<uint>, builder: &fn(push: &fn(v: A))) -> ~[A] { @@ -277,7 +267,7 @@ pub fn last_opt<'r,T>(v: &'r [T]) -> Option<&'r T> { } /// Return a slice that points into another slice. -#[inline(always)] +#[inline] pub fn slice<'r,T>(v: &'r [T], start: uint, end: uint) -> &'r [T] { assert!(start <= end); assert!(end <= v.len()); @@ -290,7 +280,7 @@ pub fn slice<'r,T>(v: &'r [T], start: uint, end: uint) -> &'r [T] { } /// Return a slice that points into another slice. -#[inline(always)] +#[inline] pub fn mut_slice<'r,T>(v: &'r mut [T], start: uint, end: uint) -> &'r mut [T] { assert!(start <= end); @@ -304,7 +294,7 @@ pub fn mut_slice<'r,T>(v: &'r mut [T], start: uint, end: uint) } /// Return a slice that points into another slice. -#[inline(always)] +#[inline] pub fn const_slice<'r,T>(v: &'r const [T], start: uint, end: uint) -> &'r const [T] { assert!(start <= end); @@ -447,9 +437,9 @@ pub fn partitioned<T:Copy>(v: &[T], f: &fn(&T) -> bool) -> (~[T], ~[T]) { for each(v) |elt| { if f(elt) { - lefts.push(*elt); + lefts.push(copy *elt); } else { - rights.push(*elt); + rights.push(copy *elt); } } @@ -639,7 +629,7 @@ pub fn swap_remove<T>(v: &mut ~[T], index: uint) -> T { } /// Append an element to a vector -#[inline(always)] +#[inline] pub fn push<T>(v: &mut ~[T], initval: T) { unsafe { let repr: **raw::VecRepr = transmute(&mut *v); @@ -654,7 +644,7 @@ pub fn push<T>(v: &mut ~[T], initval: T) { } // This doesn't bother to make sure we have space. -#[inline(always)] // really pretty please +#[inline] // really pretty please unsafe fn push_fast<T>(v: &mut ~[T], initval: T) { let repr: **mut raw::VecRepr = transmute(v); let fill = (**repr).unboxed.fill; @@ -681,7 +671,7 @@ fn push_slow<T>(v: &mut ~[T], initval: T) { /// vec::push_all(&mut a, [2, 3, 4]); /// assert!(a == ~[1, 2, 3, 4]); /// ~~~ -#[inline(always)] +#[inline] pub fn push_all<T:Copy>(v: &mut ~[T], rhs: &const [T]) { let new_len = v.len() + rhs.len(); reserve(&mut *v, new_len); @@ -702,7 +692,7 @@ pub fn push_all<T:Copy>(v: &mut ~[T], rhs: &const [T]) { /// vec::push_all_move(&mut a, ~[~2, ~3, ~4]); /// assert!(a == ~[~1, ~2, ~3, ~4]); /// ~~~ -#[inline(always)] +#[inline] pub fn push_all_move<T>(v: &mut ~[T], mut rhs: ~[T]) { let new_len = v.len() + rhs.len(); reserve(&mut *v, new_len); @@ -773,7 +763,7 @@ pub fn dedup<T:Eq>(v: &mut ~[T]) { /// Iterates over the `rhs` vector, copying each element and appending it to the /// `lhs`. Afterwards, the `lhs` is then returned for use again. -#[inline(always)] +#[inline] pub fn append<T:Copy>(lhs: ~[T], rhs: &const [T]) -> ~[T] { let mut v = lhs; v.push_all(rhs); @@ -782,7 +772,7 @@ pub fn append<T:Copy>(lhs: ~[T], rhs: &const [T]) -> ~[T] { /// Appends one element to the vector provided. The vector itself is then /// returned for use again. -#[inline(always)] +#[inline] pub fn append_one<T>(lhs: ~[T], x: T) -> ~[T] { let mut v = lhs; v.push(x); @@ -804,7 +794,7 @@ pub fn grow<T:Copy>(v: &mut ~[T], n: uint, initval: &T) { let mut i: uint = 0u; while i < n { - v.push(*initval); + v.push(copy *initval); i += 1u; } } @@ -976,7 +966,7 @@ pub fn filter<T>(v: ~[T], f: &fn(t: &T) -> bool) -> ~[T] { pub fn filtered<T:Copy>(v: &[T], f: &fn(t: &T) -> bool) -> ~[T] { let mut result = ~[]; for each(v) |elem| { - if f(elem) { result.push(*elem); } + if f(elem) { result.push(copy *elem); } } result } @@ -1032,7 +1022,7 @@ impl<'self, T:Copy> VectorVector<T> for &'self [~[T]] { let mut r = ~[]; let mut first = true; for self.each |&inner| { - if first { first = false; } else { r.push(*sep); } + if first { first = false; } else { r.push(copy *sep); } r.push_all(inner); } r @@ -1050,7 +1040,7 @@ impl<'self, T:Copy> VectorVector<T> for &'self [&'self [T]] { let mut r = ~[]; let mut first = true; for self.each |&inner| { - if first { first = false; } else { r.push(*sep); } + if first { first = false; } else { r.push(copy *sep); } r.push_all(inner); } r @@ -1083,7 +1073,7 @@ pub fn find<T:Copy>(v: &[T], f: &fn(t: &T) -> bool) -> Option<T> { */ pub fn find_between<T:Copy>(v: &[T], start: uint, end: uint, f: &fn(t: &T) -> bool) -> Option<T> { - position_between(v, start, end, f).map(|i| v[*i]) + position_between(v, start, end, f).map(|i| copy v[*i]) } /** @@ -1109,7 +1099,7 @@ pub fn rfind_between<T:Copy>(v: &[T], end: uint, f: &fn(t: &T) -> bool) -> Option<T> { - rposition_between(v, start, end, f).map(|i| v[*i]) + rposition_between(v, start, end, f).map(|i| copy v[*i]) } /// Find the first index containing a matching value @@ -1233,7 +1223,7 @@ pub fn bsearch_elem<T:TotalOrd>(v: &[T], x: &T) -> Option<uint> { pub fn unzip_slice<T:Copy,U:Copy>(v: &[(T, U)]) -> (~[T], ~[U]) { let mut (ts, us) = (~[], ~[]); for each(v) |p| { - let (t, u) = *p; + let (t, u) = copy *p; ts.push(t); us.push(u); } @@ -1268,7 +1258,7 @@ pub fn zip_slice<T:Copy,U:Copy>(v: &const [T], u: &const [U]) let mut i = 0u; assert_eq!(sz, u.len()); while i < sz { - zipped.push((v[i], u[i])); + zipped.push((copy v[i], copy u[i])); i += 1u; } zipped @@ -1301,7 +1291,7 @@ pub fn zip<T, U>(mut v: ~[T], mut u: ~[U]) -> ~[(T, U)] { * * a - The index of the first element * * b - The index of the second element */ -#[inline(always)] +#[inline] pub fn swap<T>(v: &mut [T], a: uint, b: uint) { unsafe { // Can't take two mutable loans from one vector, so instead just cast @@ -1365,8 +1355,8 @@ pub fn reversed<T:Copy>(v: &const [T]) -> ~[T] { let mut rs: ~[T] = ~[]; let mut i = v.len(); if i == 0 { return (rs); } else { i -= 1; } - while i != 0 { rs.push(v[i]); i -= 1; } - rs.push(v[0]); + while i != 0 { rs.push(copy v[i]); i -= 1; } + rs.push(copy v[0]); rs } @@ -1409,7 +1399,7 @@ pub fn reversed<T:Copy>(v: &const [T]) -> ~[T] { * } * ~~~ */ -#[inline(always)] +#[inline] pub fn each<'r,T>(v: &'r [T], f: &fn(&'r T) -> bool) -> bool { // ^^^^ // NB---this CANNOT be &const [T]! The reason @@ -1435,7 +1425,7 @@ pub fn each<'r,T>(v: &'r [T], f: &fn(&'r T) -> bool) -> bool { /// Like `each()`, but for the case where you have a vector that *may or may /// not* have mutable contents. -#[inline(always)] +#[inline] pub fn each_const<T>(v: &const [T], f: &fn(elem: &const T) -> bool) -> bool { let mut i = 0; let n = v.len(); @@ -1453,7 +1443,7 @@ pub fn each_const<T>(v: &const [T], f: &fn(elem: &const T) -> bool) -> bool { * * Return true to continue, false to break. */ -#[inline(always)] +#[inline] pub fn eachi<'r,T>(v: &'r [T], f: &fn(uint, v: &'r T) -> bool) -> bool { let mut i = 0; for each(v) |p| { @@ -1485,7 +1475,7 @@ pub fn eachi<'r,T>(v: &'r [T], f: &fn(uint, v: &'r T) -> bool) -> bool { */ pub fn each_permutation<T:Copy>(values: &[T], fun: &fn(perm : &[T]) -> bool) -> bool { let length = values.len(); - let mut permutation = vec::from_fn(length, |i| values[i]); + let mut permutation = vec::from_fn(length, |i| copy values[i]); if length <= 1 { fun(permutation); return true; @@ -1512,7 +1502,7 @@ pub fn each_permutation<T:Copy>(values: &[T], fun: &fn(perm : &[T]) -> bool) -> reverse_part(indices, k+1, length); // fixup permutation based on indices for uint::range(k, length) |i| { - permutation[i] = values[indices[i]]; + permutation[i] = copy values[indices[i]]; } } } @@ -1546,7 +1536,7 @@ pub fn windowed<'r, T>(n: uint, v: &'r [T], it: &fn(&'r [T]) -> bool) -> bool { * Allows for unsafe manipulation of vector contents, which is useful for * foreign interop. */ -#[inline(always)] +#[inline] pub fn as_imm_buf<T,U>(s: &[T], /* NB---this CANNOT be const, see below */ f: &fn(*T, uint) -> U) -> U { @@ -1565,7 +1555,7 @@ pub fn as_imm_buf<T,U>(s: &[T], } /// Similar to `as_imm_buf` but passing a `*const T` -#[inline(always)] +#[inline] pub fn as_const_buf<T,U>(s: &const [T], f: &fn(*const T, uint) -> U) -> U { unsafe { let v : *(*const T,uint) = transmute(&s); @@ -1575,7 +1565,7 @@ pub fn as_const_buf<T,U>(s: &const [T], f: &fn(*const T, uint) -> U) -> U { } /// Similar to `as_imm_buf` but passing a `*mut T` -#[inline(always)] +#[inline] pub fn as_mut_buf<T,U>(s: &mut [T], f: &fn(*mut T, uint) -> U) -> U { unsafe { let v : *(*mut T,uint) = transmute(&s); @@ -1618,49 +1608,49 @@ fn equals<T: TotalEq>(a: &[T], b: &[T]) -> bool { #[cfg(not(test))] impl<'self,T:Eq> Eq for &'self [T] { - #[inline(always)] + #[inline] fn eq(&self, other: & &'self [T]) -> bool { eq(*self, *other) } - #[inline(always)] + #[inline] fn ne(&self, other: & &'self [T]) -> bool { !self.eq(other) } } #[cfg(not(test))] impl<T:Eq> Eq for ~[T] { - #[inline(always)] + #[inline] fn eq(&self, other: &~[T]) -> bool { eq(*self, *other) } - #[inline(always)] + #[inline] fn ne(&self, other: &~[T]) -> bool { !self.eq(other) } } #[cfg(not(test))] impl<T:Eq> Eq for @[T] { - #[inline(always)] + #[inline] fn eq(&self, other: &@[T]) -> bool { eq(*self, *other) } - #[inline(always)] + #[inline] fn ne(&self, other: &@[T]) -> bool { !self.eq(other) } } #[cfg(not(test))] impl<'self,T:TotalEq> TotalEq for &'self [T] { - #[inline(always)] + #[inline] fn equals(&self, other: & &'self [T]) -> bool { equals(*self, *other) } } #[cfg(not(test))] impl<T:TotalEq> TotalEq for ~[T] { - #[inline(always)] + #[inline] fn equals(&self, other: &~[T]) -> bool { equals(*self, *other) } } #[cfg(not(test))] impl<T:TotalEq> TotalEq for @[T] { - #[inline(always)] + #[inline] fn equals(&self, other: &@[T]) -> bool { equals(*self, *other) } } #[cfg(not(test))] impl<'self,T:Eq> Equiv<~[T]> for &'self [T] { - #[inline(always)] + #[inline] fn equiv(&self, other: &~[T]) -> bool { eq(*self, *other) } } @@ -1682,19 +1672,19 @@ fn cmp<T: TotalOrd>(a: &[T], b: &[T]) -> Ordering { #[cfg(not(test))] impl<'self,T:TotalOrd> TotalOrd for &'self [T] { - #[inline(always)] + #[inline] fn cmp(&self, other: & &'self [T]) -> Ordering { cmp(*self, *other) } } #[cfg(not(test))] impl<T: TotalOrd> TotalOrd for ~[T] { - #[inline(always)] + #[inline] fn cmp(&self, other: &~[T]) -> Ordering { cmp(*self, *other) } } #[cfg(not(test))] impl<T: TotalOrd> TotalOrd for @[T] { - #[inline(always)] + #[inline] fn cmp(&self, other: &@[T]) -> Ordering { cmp(*self, *other) } } @@ -1719,37 +1709,37 @@ fn gt<T:Ord>(a: &[T], b: &[T]) -> bool { lt(b, a) } #[cfg(not(test))] impl<'self,T:Ord> Ord for &'self [T] { - #[inline(always)] + #[inline] fn lt(&self, other: & &'self [T]) -> bool { lt((*self), (*other)) } - #[inline(always)] + #[inline] fn le(&self, other: & &'self [T]) -> bool { le((*self), (*other)) } - #[inline(always)] + #[inline] fn ge(&self, other: & &'self [T]) -> bool { ge((*self), (*other)) } - #[inline(always)] + #[inline] fn gt(&self, other: & &'self [T]) -> bool { gt((*self), (*other)) } } #[cfg(not(test))] impl<T:Ord> Ord for ~[T] { - #[inline(always)] + #[inline] fn lt(&self, other: &~[T]) -> bool { lt((*self), (*other)) } - #[inline(always)] + #[inline] fn le(&self, other: &~[T]) -> bool { le((*self), (*other)) } - #[inline(always)] + #[inline] fn ge(&self, other: &~[T]) -> bool { ge((*self), (*other)) } - #[inline(always)] + #[inline] fn gt(&self, other: &~[T]) -> bool { gt((*self), (*other)) } } #[cfg(not(test))] impl<T:Ord> Ord for @[T] { - #[inline(always)] + #[inline] fn lt(&self, other: &@[T]) -> bool { lt((*self), (*other)) } - #[inline(always)] + #[inline] fn le(&self, other: &@[T]) -> bool { le((*self), (*other)) } - #[inline(always)] + #[inline] fn ge(&self, other: &@[T]) -> bool { ge((*self), (*other)) } - #[inline(always)] + #[inline] fn gt(&self, other: &@[T]) -> bool { gt((*self), (*other)) } } @@ -1760,26 +1750,39 @@ pub mod traits { use vec::append; impl<'self,T:Copy> Add<&'self const [T],~[T]> for ~[T] { - #[inline(always)] + #[inline] fn add(&self, rhs: & &'self const [T]) -> ~[T] { append(copy *self, (*rhs)) } } } -impl<'self,T> Container for &'self const [T] { +impl<'self, T> Container for &'self const [T] { /// Returns true if a vector contains no elements #[inline] - fn is_empty(&const self) -> bool { + fn is_empty(&self) -> bool { as_const_buf(*self, |_p, len| len == 0u) } /// Returns the length of a vector #[inline] - fn len(&const self) -> uint { + fn len(&self) -> uint { as_const_buf(*self, |_p, len| len) } +} +impl<T> Container for ~[T] { + /// Returns true if a vector contains no elements + #[inline] + fn is_empty(&self) -> bool { + as_const_buf(*self, |_p, len| len == 0u) + } + + /// Returns the length of a vector + #[inline] + fn len(&self) -> uint { + as_const_buf(*self, |_p, len| len) + } } #[allow(missing_doc)] @@ -1951,7 +1954,7 @@ impl<'self,T> ImmutableVector<'self, T> for &'self [T] { /// Returns a pointer to the element at the given index, without doing /// bounds checking. - #[inline(always)] + #[inline] unsafe fn unsafe_ref(&self, index: uint) -> *T { let (ptr, _): (*T, uint) = transmute(*self); ptr.offset(index) @@ -2022,9 +2025,9 @@ impl<'self,T:Copy> ImmutableCopyableVector<T> for &'self [T] { } /// Returns the element at the given index, without doing bounds checking. - #[inline(always)] + #[inline] unsafe fn unsafe_get(&self, index: uint) -> T { - *self.unsafe_ref(index) + copy *self.unsafe_ref(index) } } @@ -2203,14 +2206,14 @@ impl<'self,T> MutableVector<'self, T> for &'self mut [T] { } } - #[inline(always)] + #[inline] unsafe fn unsafe_mut_ref(&self, index: uint) -> *mut T { let pair_ptr: &(*mut T, uint) = transmute(self); let (ptr, _) = *pair_ptr; ptr.offset(index) } - #[inline(always)] + #[inline] unsafe fn unsafe_set(&self, index: uint, val: T) { *self.unsafe_mut_ref(index) = val; } @@ -2271,7 +2274,7 @@ pub mod raw { * modifing its buffers, so it is up to the caller to ensure that * the vector is actually the specified size. */ - #[inline(always)] + #[inline] pub unsafe fn set_len<T>(v: &mut ~[T], new_len: uint) { let repr: **mut VecRepr = transmute(v); (**repr).unboxed.fill = new_len * sys::nonzero_size_of::<T>(); @@ -2286,7 +2289,7 @@ pub mod raw { * Modifying the vector may cause its buffer to be reallocated, which * would also make any pointers to it invalid. */ - #[inline(always)] + #[inline] pub fn to_ptr<T>(v: &[T]) -> *T { unsafe { let repr: **SliceRepr = transmute(&v); @@ -2295,7 +2298,7 @@ pub mod raw { } /** see `to_ptr()` */ - #[inline(always)] + #[inline] pub fn to_const_ptr<T>(v: &const [T]) -> *const T { unsafe { let repr: **SliceRepr = transmute(&v); @@ -2304,7 +2307,7 @@ pub mod raw { } /** see `to_ptr()` */ - #[inline(always)] + #[inline] pub fn to_mut_ptr<T>(v: &mut [T]) -> *mut T { unsafe { let repr: **SliceRepr = transmute(&v); @@ -2316,7 +2319,7 @@ pub mod raw { * Form a slice from a pointer and length (as a number of units, * not bytes). */ - #[inline(always)] + #[inline] pub unsafe fn buf_as_slice<T,U>(p: *T, len: uint, f: &fn(v: &[T]) -> U) -> U { @@ -2329,7 +2332,7 @@ pub mod raw { * Form a slice from a pointer and length (as a number of units, * not bytes). */ - #[inline(always)] + #[inline] pub unsafe fn mut_buf_as_slice<T,U>(p: *mut T, len: uint, f: &fn(v: &mut [T]) -> U) -> U { @@ -2341,9 +2344,9 @@ pub mod raw { /** * Unchecked vector indexing. */ - #[inline(always)] + #[inline] pub unsafe fn get<T:Copy>(v: &const [T], i: uint) -> T { - as_const_buf(v, |p, _len| *ptr::const_offset(p, i)) + as_const_buf(v, |p, _len| copy *ptr::const_offset(p, i)) } /** @@ -2351,7 +2354,7 @@ pub mod raw { * old value and hence is only suitable when the vector * is newly allocated. */ - #[inline(always)] + #[inline] pub unsafe fn init_elem<T>(v: &mut [T], i: uint, val: T) { let mut box = Some(val); do as_mut_buf(v) |p, _len| { @@ -2370,7 +2373,7 @@ pub mod raw { * * elts - The number of elements in the buffer */ // Was in raw, but needs to be called by net_tcp::on_tcp_read_cb - #[inline(always)] + #[inline] pub unsafe fn from_buf_raw<T>(ptr: *T, elts: uint) -> ~[T] { let mut dst = with_capacity(elts); set_len(&mut dst, elts); @@ -2384,7 +2387,7 @@ pub mod raw { * Copies `count` bytes from `src` to `dst`. The source and destination * may overlap. */ - #[inline(always)] + #[inline] pub unsafe fn copy_memory<T>(dst: &mut [T], src: &const [T], count: uint) { assert!(dst.len() >= count); @@ -2450,7 +2453,7 @@ pub mod bytes { * Copies `count` bytes from `src` to `dst`. The source and destination * may overlap. */ - #[inline(always)] + #[inline] pub fn copy_memory(dst: &mut [u8], src: &const [u8], count: uint) { // Bound checks are done at vec::raw::copy_memory. unsafe { vec::raw::copy_memory(dst, src, count) } @@ -2461,31 +2464,31 @@ pub mod bytes { // ITERATION TRAIT METHODS impl<'self,A> old_iter::BaseIter<A> for &'self [A] { - #[inline(always)] + #[inline] fn each<'a>(&'a self, blk: &fn(v: &'a A) -> bool) -> bool { each(*self, blk) } - #[inline(always)] + #[inline] fn size_hint(&self) -> Option<uint> { Some(self.len()) } } // FIXME(#4148): This should be redundant impl<A> old_iter::BaseIter<A> for ~[A] { - #[inline(always)] + #[inline] fn each<'a>(&'a self, blk: &fn(v: &'a A) -> bool) -> bool { each(*self, blk) } - #[inline(always)] + #[inline] fn size_hint(&self) -> Option<uint> { Some(self.len()) } } // FIXME(#4148): This should be redundant impl<A> old_iter::BaseIter<A> for @[A] { - #[inline(always)] + #[inline] fn each<'a>(&'a self, blk: &fn(v: &'a A) -> bool) -> bool { each(*self, blk) } - #[inline(always)] + #[inline] fn size_hint(&self) -> Option<uint> { Some(self.len()) } } @@ -2615,28 +2618,27 @@ impl<A:Copy> old_iter::CopyableIter<A> for @[A] { } } -impl<'self,A:Copy + Ord> old_iter::CopyableOrderedIter<A> for &'self [A] { - fn min(&self) -> A { old_iter::min(self) } - fn max(&self) -> A { old_iter::max(self) } +impl<A:Clone> Clone for ~[A] { + #[inline] + fn clone(&self) -> ~[A] { + self.map(|item| item.clone()) + } } -// FIXME(#4148): This should be redundant -impl<A:Copy + Ord> old_iter::CopyableOrderedIter<A> for ~[A] { - fn min(&self) -> A { old_iter::min(self) } - fn max(&self) -> A { old_iter::max(self) } +// This works because every lifetime is a sub-lifetime of 'static +impl<'self, A> Zero for &'self [A] { + fn zero() -> &'self [A] { &'self [] } + fn is_zero(&self) -> bool { self.is_empty() } } -// FIXME(#4148): This should be redundant -impl<A:Copy + Ord> old_iter::CopyableOrderedIter<A> for @[A] { - fn min(&self) -> A { old_iter::min(self) } - fn max(&self) -> A { old_iter::max(self) } +impl<A> Zero for ~[A] { + fn zero() -> ~[A] { ~[] } + fn is_zero(&self) -> bool { self.len() == 0 } } -impl<A:Clone> Clone for ~[A] { - #[inline] - fn clone(&self) -> ~[A] { - self.map(|item| item.clone()) - } +impl<A> Zero for @[A] { + fn zero() -> @[A] { @[] } + fn is_zero(&self) -> bool { self.len() == 0 } } macro_rules! iterator { @@ -2704,7 +2706,7 @@ pub struct VecMutRevIterator<'self, T> { iterator!{impl VecMutRevIterator -> &'self mut T, -1} impl<T> FromIter<T> for ~[T]{ - #[inline(always)] + #[inline] pub fn from_iter(iter: &fn(f: &fn(T) -> bool) -> bool) -> ~[T] { let mut v = ~[]; for iter |x| { v.push(x) } @@ -4293,4 +4295,20 @@ mod tests { } assert_eq!(v, ~[~[1,2,3],~[1,3,2],~[2,1,3],~[2,3,1],~[3,1,2],~[3,2,1]]); } + + #[test] + fn test_vec_zero() { + use num::Zero; + macro_rules! t ( + ($ty:ty) => { + let v: $ty = Zero::zero(); + assert!(v.is_empty()); + assert!(v.is_zero()); + } + ); + + t!(&[int]); + t!(@[int]); + t!(~[int]); + } } |
