diff --git a/src/compiletest/common.rs b/src/compiletest/common.rs index 2c917f7aefeb9..b7d4596b0febf 100644 --- a/src/compiletest/common.rs +++ b/src/compiletest/common.rs @@ -8,8 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::from_str::FromStr; use std::fmt; +use std::str::FromStr; use regex::Regex; #[deriving(Clone, PartialEq)] diff --git a/src/compiletest/compiletest.rs b/src/compiletest/compiletest.rs index caf1c8c314dbb..d49ff0258ab02 100644 --- a/src/compiletest/compiletest.rs +++ b/src/compiletest/compiletest.rs @@ -22,7 +22,7 @@ extern crate regex; use std::os; use std::io; use std::io::fs; -use std::from_str::FromStr; +use std::str::FromStr; use getopts::{optopt, optflag, reqopt}; use common::Config; use common::{Pretty, DebugInfoGdb, DebugInfoLldb, Codegen}; diff --git a/src/compiletest/header.rs b/src/compiletest/header.rs index b7b94ca6d0df5..60ef76528e849 100644 --- a/src/compiletest/header.rs +++ b/src/compiletest/header.rs @@ -12,8 +12,6 @@ use common::Config; use common; use util; -use std::from_str::FromStr; - pub struct TestProps { // Lines that should be expected, in order, on standard out pub error_patterns: Vec , @@ -353,8 +351,8 @@ pub fn gdb_version_to_int(version_string: &str) -> int { panic!("{}", error_string); } - let major: int = FromStr::from_str(components[0]).expect(error_string); - let minor: int = FromStr::from_str(components[1]).expect(error_string); + let major: int = from_str(components[0]).expect(error_string); + let minor: int = from_str(components[1]).expect(error_string); return major * 1000 + minor; } @@ -364,6 +362,6 @@ pub fn lldb_version_to_int(version_string: &str) -> int { "Encountered LLDB version string with unexpected format: {}", version_string); let error_string = error_string.as_slice(); - let major: int = FromStr::from_str(version_string).expect(error_string); + let major: int = from_str(version_string).expect(error_string); return major; } diff --git a/src/doc/complement-design-faq.md b/src/doc/complement-design-faq.md index 9a2531f094c17..e57953db3a256 100644 --- a/src/doc/complement-design-faq.md +++ b/src/doc/complement-design-faq.md @@ -95,7 +95,7 @@ code should need to run is a stack. `match` being exhaustive has some useful properties. First, if every possibility is covered by the `match`, adding further variants to the `enum` in the future will prompt a compilation failure, rather than runtime panic. -Second, it makes cost explicit. In general, only safe way to have a +Second, it makes cost explicit. In general, the only safe way to have a non-exhaustive match would be to panic the task if nothing is matched, though it could fall through if the type of the `match` expression is `()`. This sort of hidden cost and special casing is against the language's philosophy. It's diff --git a/src/doc/guide-pointers.md b/src/doc/guide-pointers.md index 87eb91d3ec7ff..2c6388a618052 100644 --- a/src/doc/guide-pointers.md +++ b/src/doc/guide-pointers.md @@ -133,11 +133,11 @@ pass-by-reference. Basically, languages can make two choices (this is made up syntax, it's not Rust): ```{notrust,ignore} -fn foo(x) { +func foo(x) { x = 5 } -fn main() { +func main() { i = 1 foo(i) // what is the value of i here? @@ -153,11 +153,11 @@ So what do pointers have to do with this? Well, since pointers point to a location in memory... ```{notrust,ignore} -fn foo(&int x) { +func foo(&int x) { *x = 5 } -fn main() { +func main() { i = 1 foo(&i) // what is the value of i here? @@ -192,13 +192,13 @@ When you combine pointers and functions, it's easy to accidentally invalidate the memory the pointer is pointing to. For example: ```{notrust,ignore} -fn make_pointer(): &int { +func make_pointer(): &int { x = 5; return &x; } -fn main() { +func main() { &int i = make_pointer(); *i = 5; // uh oh! } @@ -214,11 +214,11 @@ issue. Two pointers are said to alias when they point at the same location in memory. Like this: ```{notrust,ignore} -fn mutate(&int i, int j) { +func mutate(&int i, int j) { *i = j; } -fn main() { +func main() { x = 5; y = &x; z = &x; //y and z are aliased diff --git a/src/doc/guide-strings.md b/src/doc/guide-strings.md index 1c7cb1a3b4eb9..071c9ff013c59 100644 --- a/src/doc/guide-strings.md +++ b/src/doc/guide-strings.md @@ -155,7 +155,7 @@ println!("{}", s[0]); This does not compile. This is on purpose. In the world of UTF-8, direct indexing is basically never what you want to do. The reason is that each character can be a variable number of bytes. This means that you have to iterate -through the characters anyway, which is a O(n) operation. +through the characters anyway, which is an O(n) operation. There's 3 basic levels of unicode (and its encodings): diff --git a/src/doc/reference.md b/src/doc/reference.md index d05705562d27a..5d1401e27ba4a 100644 --- a/src/doc/reference.md +++ b/src/doc/reference.md @@ -2526,7 +2526,7 @@ The currently implemented features of the reference compiler are: * `plugin_registrar` - Indicates that a crate has [compiler plugins][plugin] that it wants to load. As with `phase`, the implementation is - in need of a overhaul, and it is not clear that plugins + in need of an overhaul, and it is not clear that plugins defined using this will continue to work. * `quote` - Allows use of the `quote_*!` family of macros, which are @@ -2583,7 +2583,7 @@ there isn't a parser error first). The directive in this case is no longer necessary, and it's likely that existing code will break if the feature isn't removed. -If a unknown feature is found in a directive, it results in a compiler error. +If an unknown feature is found in a directive, it results in a compiler error. An unknown feature is one which has never been recognized by the compiler. # Statements and expressions @@ -2685,7 +2685,7 @@ When an lvalue is evaluated in an _lvalue context_, it denotes a memory location; when evaluated in an _rvalue context_, it denotes the value held _in_ that memory location. -When an rvalue is used in lvalue context, a temporary un-named lvalue is +When an rvalue is used in an lvalue context, a temporary un-named lvalue is created and used instead. A temporary's lifetime equals the largest lifetime of any reference that points to it. @@ -2833,7 +2833,7 @@ foo().x; ``` A field access is an [lvalue](#lvalues,-rvalues-and-temporaries) referring to -the value of that field. When the type providing the field inherits mutabilty, +the value of that field. When the type providing the field inherits mutability, it can be [assigned](#assignment-expressions) to. Also, if the type of the expression to the left of the dot is a pointer, it is @@ -3108,11 +3108,10 @@ then the expression completes. Some examples of call expressions: ``` -# use std::from_str::FromStr; # fn add(x: int, y: int) -> int { 0 } let x: int = add(1, 2); -let pi: Option = FromStr::from_str("3.14"); +let pi: Option = from_str("3.14"); ``` ### Lambda expressions @@ -3321,7 +3320,7 @@ between `_` and `..` is that the pattern `C(_)` is only type-correct if `C` has exactly one argument, while the pattern `C(..)` is type-correct for any enum variant `C`, regardless of how many arguments `C` has. -Used inside a array pattern, `..` stands for any number of elements, when the +Used inside an array pattern, `..` stands for any number of elements, when the `advanced_slice_patterns` feature gate is turned on. This wildcard can be used at most once for a given array, which implies that it cannot be used to specifically match elements that are at an unknown distance from both ends of a @@ -3584,7 +3583,7 @@ is not a surrogate), represented as a 32-bit unsigned word in the 0x0000 to 0xD7FF or 0xE000 to 0x10FFFF range. A `[char]` array is effectively an UCS-4 / UTF-32 string. -A value of type `str` is a Unicode string, represented as a array of 8-bit +A value of type `str` is a Unicode string, represented as an array of 8-bit unsigned bytes holding a sequence of UTF-8 codepoints. Since `str` is of unknown size, it is not a _first class_ type, but can only be instantiated through a pointer type, such as `&str` or `String`. diff --git a/src/etc/snapshot.py b/src/etc/snapshot.py index e0610bfbdfe28..cb99da8092df0 100644 --- a/src/etc/snapshot.py +++ b/src/etc/snapshot.py @@ -75,7 +75,11 @@ def full_snapshot_name(date, rev, platform, hsh): def get_kernel(triple): - os_name = triple.split('-')[2] + t = triple.split('-') + if len(t) == 2: + os_name = t[1] + else: + os_name = t[2] if os_name == "windows": return "winnt" if os_name == "darwin": diff --git a/src/etc/vim/syntax/rust.vim b/src/etc/vim/syntax/rust.vim index 710092a3e5f37..1b1b65bd560e1 100644 --- a/src/etc/vim/syntax/rust.vim +++ b/src/etc/vim/syntax/rust.vim @@ -105,7 +105,7 @@ syn keyword rustTrait RawPtr syn keyword rustTrait Buffer Writer Reader Seek syn keyword rustTrait Str StrVector StrSlice syn keyword rustTrait IntoMaybeOwned StrAllocating UnicodeStrSlice -syn keyword rustTrait ToString IntoStr +syn keyword rustTrait ToString IntoString syn keyword rustTrait Tuple1 Tuple2 Tuple3 Tuple4 syn keyword rustTrait Tuple5 Tuple6 Tuple7 Tuple8 syn keyword rustTrait Tuple9 Tuple10 Tuple11 Tuple12 diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index 049bf4eb1b02d..501f915461a27 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -179,9 +179,9 @@ pub struct Rc { _noshare: marker::NoSync } -#[stable] impl Rc { /// Constructs a new reference-counted pointer. + #[stable] pub fn new(value: T) -> Rc { unsafe { Rc { @@ -200,9 +200,7 @@ impl Rc { } } } -} -impl Rc { /// Downgrades the reference-counted pointer to a weak reference. #[experimental = "Weak pointers may not belong in this module"] pub fn downgrade(&self) -> Weak { diff --git a/src/libcollections/str.rs b/src/libcollections/str.rs index 20aa29fbb3dcc..a2f89dfecbc13 100644 --- a/src/libcollections/str.rs +++ b/src/libcollections/str.rs @@ -73,6 +73,7 @@ pub use core::str::{CharSplitsN, AnyLines, MatchIndices, StrSplits}; pub use core::str::{Utf16CodeUnits, eq_slice, is_utf8, is_utf16, Utf16Items}; pub use core::str::{Utf16Item, ScalarValue, LoneSurrogate, utf16_items}; pub use core::str::{truncate_utf16_at_nul, utf8_char_width, CharRange}; +pub use core::str::{FromStr, from_str}; pub use core::str::{Str, StrPrelude}; pub use unicode::str::{UnicodeStrPrelude, Words, Graphemes, GraphemeIndices}; diff --git a/src/libcollections/string.rs b/src/libcollections/string.rs index 5872afc6fde5f..3c75198a368bf 100644 --- a/src/libcollections/string.rs +++ b/src/libcollections/string.rs @@ -25,7 +25,7 @@ use core::raw::Slice as RawSlice; use hash; use slice::CloneSliceAllocPrelude; use str; -use str::{CharRange, StrAllocating, MaybeOwned, Owned}; +use str::{CharRange, FromStr, StrAllocating, MaybeOwned, Owned}; use str::Slice as MaybeOwnedSlice; // So many `Slice`s... use vec::{DerefVec, Vec, as_vec}; @@ -795,6 +795,33 @@ pub fn as_string<'a>(x: &'a str) -> DerefString<'a> { DerefString { x: as_vec(x.as_bytes()) } } +impl FromStr for String { + #[inline] + fn from_str(s: &str) -> Option { + Some(String::from_str(s)) + } +} + +/// Trait for converting a type to a string, consuming it in the process. +pub trait IntoString { + /// Consume and convert to a string. + fn into_string(self) -> String; +} + +/// A generic trait for converting a value to a string +pub trait ToString { + /// Converts the value of `self` to an owned string + fn to_string(&self) -> String; +} + +impl ToString for T { + fn to_string(&self) -> String { + let mut buf = Vec::::new(); + let _ = format_args!(|args| fmt::write(&mut buf, args), "{}", self); + String::from_utf8(buf).unwrap() + } +} + /// Unsafe operations #[unstable = "waiting on raw module conventions"] pub mod raw { @@ -860,7 +887,7 @@ mod tests { use str; use str::{Str, StrPrelude, Owned}; - use super::{as_string, String}; + use super::{as_string, String, ToString}; use vec::Vec; use slice::CloneSliceAllocPrelude; @@ -1164,6 +1191,28 @@ mod tests { assert_eq!("oob", s[1..4]); } + #[test] + fn test_simple_types() { + assert_eq!(1i.to_string(), "1".to_string()); + assert_eq!((-1i).to_string(), "-1".to_string()); + assert_eq!(200u.to_string(), "200".to_string()); + assert_eq!(2u8.to_string(), "2".to_string()); + assert_eq!(true.to_string(), "true".to_string()); + assert_eq!(false.to_string(), "false".to_string()); + assert_eq!(().to_string(), "()".to_string()); + assert_eq!(("hi".to_string()).to_string(), "hi".to_string()); + } + + #[test] + fn test_vectors() { + let x: Vec = vec![]; + assert_eq!(x.to_string(), "[]".to_string()); + assert_eq!((vec![1i]).to_string(), "[1]".to_string()); + assert_eq!((vec![1i, 2, 3]).to_string(), "[1, 2, 3]".to_string()); + assert!((vec![vec![], vec![1i], vec![1i, 1]]).to_string() == + "[[], [1], [1, 1]]".to_string()); + } + #[bench] fn bench_with_capacity(b: &mut Bencher) { b.iter(|| { diff --git a/src/libcollections/tree/set.rs b/src/libcollections/tree/set.rs index 45904259c6614..1005732a1e24f 100644 --- a/src/libcollections/tree/set.rs +++ b/src/libcollections/tree/set.rs @@ -504,9 +504,9 @@ impl TreeSet { /// # Example /// /// ``` - /// use std::collections::BTreeSet; + /// use std::collections::TreeSet; /// - /// let mut set = BTreeSet::new(); + /// let mut set = TreeSet::new(); /// /// assert_eq!(set.insert(2i), true); /// assert_eq!(set.insert(2i), false); @@ -522,9 +522,9 @@ impl TreeSet { /// # Example /// /// ``` - /// use std::collections::BTreeSet; + /// use std::collections::TreeSet; /// - /// let mut set = BTreeSet::new(); + /// let mut set = TreeSet::new(); /// /// set.insert(2i); /// assert_eq!(set.remove(&2), true); diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index 2b68de932d2b7..fdee089380bbb 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -645,7 +645,6 @@ impl Vec { /// assert!(vec.capacity() >= 3); /// ``` #[stable] - #[unstable = "matches collection reform specification, waiting for dust to settle"] pub fn shrink_to_fit(&mut self) { if mem::size_of::() == 0 { return } @@ -1653,6 +1652,13 @@ impl Vec { } } +impl<'a> fmt::FormatWriter for Vec { + fn write(&mut self, buf: &[u8]) -> fmt::Result { + self.push_all(buf); + Ok(()) + } +} + #[cfg(test)] mod tests { extern crate test; diff --git a/src/libcore/any.rs b/src/libcore/any.rs index 021f575b0acea..5511266b4cd22 100644 --- a/src/libcore/any.rs +++ b/src/libcore/any.rs @@ -88,6 +88,7 @@ use intrinsics::TypeId; #[stable] pub trait Any: 'static { /// Get the `TypeId` of `self` + #[stable] fn get_type_id(&self) -> TypeId; } @@ -117,7 +118,6 @@ pub trait AnyRefExt<'a> { #[stable] impl<'a> AnyRefExt<'a> for &'a Any { #[inline] - #[stable] fn is(self) -> bool { // Get TypeId of the type this function is instantiated with let t = TypeId::of::(); @@ -130,7 +130,6 @@ impl<'a> AnyRefExt<'a> for &'a Any { } #[inline] - #[unstable = "naming conventions around acquiring references may change"] fn downcast_ref(self) -> Option<&'a T> { if self.is::() { unsafe { @@ -159,7 +158,6 @@ pub trait AnyMutRefExt<'a> { #[stable] impl<'a> AnyMutRefExt<'a> for &'a mut Any { #[inline] - #[unstable = "naming conventions around acquiring references may change"] fn downcast_mut(self) -> Option<&'a mut T> { if self.is::() { unsafe { diff --git a/src/libcore/atomic.rs b/src/libcore/atomic.rs index 352beeb473a86..d84a7875df1aa 100644 --- a/src/libcore/atomic.rs +++ b/src/libcore/atomic.rs @@ -58,20 +58,25 @@ pub struct AtomicPtr { #[stable] pub enum Ordering { /// No ordering constraints, only atomic operations + #[stable] Relaxed, /// When coupled with a store, all previous writes become visible /// to another thread that performs a load with `Acquire` ordering /// on the same value + #[stable] Release, /// When coupled with a load, all subsequent loads will see data /// written before a store with `Release` ordering on the same value /// in another thread + #[stable] Acquire, /// When coupled with a load, uses `Acquire` ordering, and with a store /// `Release` ordering + #[stable] AcqRel, /// Like `AcqRel` with the additional guarantee that all threads see all /// sequentially consistent operations in the same order. + #[stable] SeqCst } @@ -91,10 +96,10 @@ pub const INIT_ATOMIC_UINT: AtomicUint = // NB: Needs to be -1 (0b11111111...) to make fetch_nand work correctly const UINT_TRUE: uint = -1; -#[stable] impl AtomicBool { /// Create a new `AtomicBool` #[inline] + #[stable] pub fn new(v: bool) -> AtomicBool { let val = if v { UINT_TRUE } else { 0 }; AtomicBool { v: UnsafeCell::new(val), nocopy: marker::NoCopy } @@ -106,6 +111,7 @@ impl AtomicBool { /// /// Panics if `order` is `Release` or `AcqRel`. #[inline] + #[stable] pub fn load(&self, order: Ordering) -> bool { unsafe { atomic_load(self.v.get() as *const uint, order) > 0 } } @@ -116,6 +122,7 @@ impl AtomicBool { /// /// Panics if `order` is `Acquire` or `AcqRel`. #[inline] + #[stable] pub fn store(&self, val: bool, order: Ordering) { let val = if val { UINT_TRUE } else { 0 }; @@ -124,6 +131,7 @@ impl AtomicBool { /// Store a value, returning the old value #[inline] + #[stable] pub fn swap(&self, val: bool, order: Ordering) -> bool { let val = if val { UINT_TRUE } else { 0 }; @@ -174,6 +182,7 @@ impl AtomicBool { /// } /// ``` #[inline] + #[stable] pub fn compare_and_swap(&self, old: bool, new: bool, order: Ordering) -> bool { let old = if old { UINT_TRUE } else { 0 }; let new = if new { UINT_TRUE } else { 0 }; @@ -205,6 +214,7 @@ impl AtomicBool { /// assert_eq!(false, foo.load(SeqCst)); /// ``` #[inline] + #[stable] pub fn fetch_and(&self, val: bool, order: Ordering) -> bool { let val = if val { UINT_TRUE } else { 0 }; @@ -236,6 +246,7 @@ impl AtomicBool { /// assert_eq!(true, foo.load(SeqCst)); /// ``` #[inline] + #[stable] pub fn fetch_nand(&self, val: bool, order: Ordering) -> bool { let val = if val { UINT_TRUE } else { 0 }; @@ -266,6 +277,7 @@ impl AtomicBool { /// assert_eq!(false, foo.load(SeqCst)); /// ``` #[inline] + #[stable] pub fn fetch_or(&self, val: bool, order: Ordering) -> bool { let val = if val { UINT_TRUE } else { 0 }; @@ -296,6 +308,7 @@ impl AtomicBool { /// assert_eq!(false, foo.load(SeqCst)); /// ``` #[inline] + #[stable] pub fn fetch_xor(&self, val: bool, order: Ordering) -> bool { let val = if val { UINT_TRUE } else { 0 }; @@ -303,10 +316,10 @@ impl AtomicBool { } } -#[stable] impl AtomicInt { /// Create a new `AtomicInt` #[inline] + #[stable] pub fn new(v: int) -> AtomicInt { AtomicInt {v: UnsafeCell::new(v), nocopy: marker::NoCopy} } @@ -317,6 +330,7 @@ impl AtomicInt { /// /// Panics if `order` is `Release` or `AcqRel`. #[inline] + #[stable] pub fn load(&self, order: Ordering) -> int { unsafe { atomic_load(self.v.get() as *const int, order) } } @@ -327,12 +341,14 @@ impl AtomicInt { /// /// Panics if `order` is `Acquire` or `AcqRel`. #[inline] + #[stable] pub fn store(&self, val: int, order: Ordering) { unsafe { atomic_store(self.v.get(), val, order); } } /// Store a value, returning the old value #[inline] + #[stable] pub fn swap(&self, val: int, order: Ordering) -> int { unsafe { atomic_swap(self.v.get(), val, order) } } @@ -343,6 +359,7 @@ impl AtomicInt { /// replace the current value with `new`. Return the previous value. /// If the return value is equal to `old` then the value was updated. #[inline] + #[stable] pub fn compare_and_swap(&self, old: int, new: int, order: Ordering) -> int { unsafe { atomic_compare_and_swap(self.v.get(), old, new, order) } } @@ -359,6 +376,7 @@ impl AtomicInt { /// assert_eq!(10, foo.load(SeqCst)); /// ``` #[inline] + #[stable] pub fn fetch_add(&self, val: int, order: Ordering) -> int { unsafe { atomic_add(self.v.get(), val, order) } } @@ -375,6 +393,7 @@ impl AtomicInt { /// assert_eq!(-10, foo.load(SeqCst)); /// ``` #[inline] + #[stable] pub fn fetch_sub(&self, val: int, order: Ordering) -> int { unsafe { atomic_sub(self.v.get(), val, order) } } @@ -390,6 +409,7 @@ impl AtomicInt { /// assert_eq!(0b101101, foo.fetch_and(0b110011, SeqCst)); /// assert_eq!(0b100001, foo.load(SeqCst)); #[inline] + #[stable] pub fn fetch_and(&self, val: int, order: Ordering) -> int { unsafe { atomic_and(self.v.get(), val, order) } } @@ -405,6 +425,7 @@ impl AtomicInt { /// assert_eq!(0b101101, foo.fetch_or(0b110011, SeqCst)); /// assert_eq!(0b111111, foo.load(SeqCst)); #[inline] + #[stable] pub fn fetch_or(&self, val: int, order: Ordering) -> int { unsafe { atomic_or(self.v.get(), val, order) } } @@ -420,15 +441,16 @@ impl AtomicInt { /// assert_eq!(0b101101, foo.fetch_xor(0b110011, SeqCst)); /// assert_eq!(0b011110, foo.load(SeqCst)); #[inline] + #[stable] pub fn fetch_xor(&self, val: int, order: Ordering) -> int { unsafe { atomic_xor(self.v.get(), val, order) } } } -#[stable] impl AtomicUint { /// Create a new `AtomicUint` #[inline] + #[stable] pub fn new(v: uint) -> AtomicUint { AtomicUint { v: UnsafeCell::new(v), nocopy: marker::NoCopy } } @@ -439,6 +461,7 @@ impl AtomicUint { /// /// Panics if `order` is `Release` or `AcqRel`. #[inline] + #[stable] pub fn load(&self, order: Ordering) -> uint { unsafe { atomic_load(self.v.get() as *const uint, order) } } @@ -449,12 +472,14 @@ impl AtomicUint { /// /// Panics if `order` is `Acquire` or `AcqRel`. #[inline] + #[stable] pub fn store(&self, val: uint, order: Ordering) { unsafe { atomic_store(self.v.get(), val, order); } } /// Store a value, returning the old value #[inline] + #[stable] pub fn swap(&self, val: uint, order: Ordering) -> uint { unsafe { atomic_swap(self.v.get(), val, order) } } @@ -465,6 +490,7 @@ impl AtomicUint { /// replace the current value with `new`. Return the previous value. /// If the return value is equal to `old` then the value was updated. #[inline] + #[stable] pub fn compare_and_swap(&self, old: uint, new: uint, order: Ordering) -> uint { unsafe { atomic_compare_and_swap(self.v.get(), old, new, order) } } @@ -481,6 +507,7 @@ impl AtomicUint { /// assert_eq!(10, foo.load(SeqCst)); /// ``` #[inline] + #[stable] pub fn fetch_add(&self, val: uint, order: Ordering) -> uint { unsafe { atomic_add(self.v.get(), val, order) } } @@ -497,6 +524,7 @@ impl AtomicUint { /// assert_eq!(0, foo.load(SeqCst)); /// ``` #[inline] + #[stable] pub fn fetch_sub(&self, val: uint, order: Ordering) -> uint { unsafe { atomic_sub(self.v.get(), val, order) } } @@ -512,6 +540,7 @@ impl AtomicUint { /// assert_eq!(0b101101, foo.fetch_and(0b110011, SeqCst)); /// assert_eq!(0b100001, foo.load(SeqCst)); #[inline] + #[stable] pub fn fetch_and(&self, val: uint, order: Ordering) -> uint { unsafe { atomic_and(self.v.get(), val, order) } } @@ -527,6 +556,7 @@ impl AtomicUint { /// assert_eq!(0b101101, foo.fetch_or(0b110011, SeqCst)); /// assert_eq!(0b111111, foo.load(SeqCst)); #[inline] + #[stable] pub fn fetch_or(&self, val: uint, order: Ordering) -> uint { unsafe { atomic_or(self.v.get(), val, order) } } @@ -542,15 +572,16 @@ impl AtomicUint { /// assert_eq!(0b101101, foo.fetch_xor(0b110011, SeqCst)); /// assert_eq!(0b011110, foo.load(SeqCst)); #[inline] + #[stable] pub fn fetch_xor(&self, val: uint, order: Ordering) -> uint { unsafe { atomic_xor(self.v.get(), val, order) } } } -#[stable] impl AtomicPtr { /// Create a new `AtomicPtr` #[inline] + #[stable] pub fn new(p: *mut T) -> AtomicPtr { AtomicPtr { p: UnsafeCell::new(p as uint), nocopy: marker::NoCopy } } @@ -561,6 +592,7 @@ impl AtomicPtr { /// /// Panics if `order` is `Release` or `AcqRel`. #[inline] + #[stable] pub fn load(&self, order: Ordering) -> *mut T { unsafe { atomic_load(self.p.get() as *const *mut T, order) as *mut T @@ -573,12 +605,14 @@ impl AtomicPtr { /// /// Panics if `order` is `Acquire` or `AcqRel`. #[inline] + #[stable] pub fn store(&self, ptr: *mut T, order: Ordering) { unsafe { atomic_store(self.p.get(), ptr as uint, order); } } /// Store a value, returning the old value #[inline] + #[stable] pub fn swap(&self, ptr: *mut T, order: Ordering) -> *mut T { unsafe { atomic_swap(self.p.get(), ptr as uint, order) as *mut T } } @@ -589,6 +623,7 @@ impl AtomicPtr { /// replace the current value with `new`. Return the previous value. /// If the return value is equal to `old` then the value was updated. #[inline] + #[stable] pub fn compare_and_swap(&self, old: *mut T, new: *mut T, order: Ordering) -> *mut T { unsafe { atomic_compare_and_swap(self.p.get(), old as uint, @@ -609,6 +644,7 @@ unsafe fn atomic_store(dst: *mut T, val: T, order:Ordering) { } #[inline] +#[stable] unsafe fn atomic_load(dst: *const T, order:Ordering) -> T { match order { Acquire => intrinsics::atomic_load_acq(dst), @@ -620,6 +656,7 @@ unsafe fn atomic_load(dst: *const T, order:Ordering) -> T { } #[inline] +#[stable] unsafe fn atomic_swap(dst: *mut T, val: T, order: Ordering) -> T { match order { Acquire => intrinsics::atomic_xchg_acq(dst, val), @@ -632,6 +669,7 @@ unsafe fn atomic_swap(dst: *mut T, val: T, order: Ordering) -> T { /// Returns the old value (like __sync_fetch_and_add). #[inline] +#[stable] unsafe fn atomic_add(dst: *mut T, val: T, order: Ordering) -> T { match order { Acquire => intrinsics::atomic_xadd_acq(dst, val), @@ -644,6 +682,7 @@ unsafe fn atomic_add(dst: *mut T, val: T, order: Ordering) -> T { /// Returns the old value (like __sync_fetch_and_sub). #[inline] +#[stable] unsafe fn atomic_sub(dst: *mut T, val: T, order: Ordering) -> T { match order { Acquire => intrinsics::atomic_xsub_acq(dst, val), @@ -655,6 +694,7 @@ unsafe fn atomic_sub(dst: *mut T, val: T, order: Ordering) -> T { } #[inline] +#[stable] unsafe fn atomic_compare_and_swap(dst: *mut T, old:T, new:T, order: Ordering) -> T { match order { Acquire => intrinsics::atomic_cxchg_acq(dst, old, new), @@ -666,6 +706,7 @@ unsafe fn atomic_compare_and_swap(dst: *mut T, old:T, new:T, order: Ordering) } #[inline] +#[stable] unsafe fn atomic_and(dst: *mut T, val: T, order: Ordering) -> T { match order { Acquire => intrinsics::atomic_and_acq(dst, val), @@ -677,6 +718,7 @@ unsafe fn atomic_and(dst: *mut T, val: T, order: Ordering) -> T { } #[inline] +#[stable] unsafe fn atomic_nand(dst: *mut T, val: T, order: Ordering) -> T { match order { Acquire => intrinsics::atomic_nand_acq(dst, val), @@ -689,6 +731,7 @@ unsafe fn atomic_nand(dst: *mut T, val: T, order: Ordering) -> T { #[inline] +#[stable] unsafe fn atomic_or(dst: *mut T, val: T, order: Ordering) -> T { match order { Acquire => intrinsics::atomic_or_acq(dst, val), @@ -701,6 +744,7 @@ unsafe fn atomic_or(dst: *mut T, val: T, order: Ordering) -> T { #[inline] +#[stable] unsafe fn atomic_xor(dst: *mut T, val: T, order: Ordering) -> T { match order { Acquire => intrinsics::atomic_xor_acq(dst, val), diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs index 6f87ff52662b6..0b7389b20190c 100644 --- a/src/libcore/cell.rs +++ b/src/libcore/cell.rs @@ -157,6 +157,7 @@ use clone::Clone; use cmp::PartialEq; +use default::Default; use kinds::{marker, Copy}; use ops::{Deref, DerefMut, Drop}; use option::{None, Option, Some}; @@ -168,9 +169,9 @@ pub struct Cell { noshare: marker::NoSync, } -#[stable] impl Cell { /// Creates a new `Cell` containing the given value. + #[stable] pub fn new(value: T) -> Cell { Cell { value: UnsafeCell::new(value), @@ -180,12 +181,14 @@ impl Cell { /// Returns a copy of the contained value. #[inline] + #[stable] pub fn get(&self) -> T { unsafe{ *self.value.get() } } /// Sets the contained value. #[inline] + #[stable] pub fn set(&self, value: T) { unsafe { *self.value.get() = value; @@ -211,6 +214,13 @@ impl Clone for Cell { } } +#[unstable] +impl Default for Cell { + fn default() -> Cell { + Cell::new(Default::default()) + } +} + #[unstable = "waiting for `PartialEq` trait to become stable"] impl PartialEq for Cell { fn eq(&self, other: &Cell) -> bool { @@ -337,6 +347,13 @@ impl Clone for RefCell { } } +#[unstable] +impl Default for RefCell { + fn default() -> RefCell { + RefCell::new(Default::default()) + } +} + #[unstable = "waiting for `PartialEq` to become stable"] impl PartialEq for RefCell { fn eq(&self, other: &RefCell) -> bool { diff --git a/src/libcore/num/f32.rs b/src/libcore/num/f32.rs index ba03bb8f3d5c1..e7b0f626bf872 100644 --- a/src/libcore/num/f32.rs +++ b/src/libcore/num/f32.rs @@ -16,8 +16,8 @@ use intrinsics; use mem; -use num::{FPNormal, FPCategory, FPZero, FPSubnormal, FPInfinite, FPNaN}; -use num::Float; +use num::{Float, FPNormal, FPCategory, FPZero, FPSubnormal, FPInfinite, FPNaN}; +use num::from_str_radix; use option::Option; pub const RADIX: uint = 2u; @@ -424,3 +424,10 @@ impl Float for f32 { self * (value / 180.0f32) } } + +#[inline] +#[allow(missing_docs)] +#[deprecated="Use `FromStrRadix::from_str_radix(src, 16)`"] +pub fn from_str_hex(src: &str) -> Option { + from_str_radix(src, 16) +} diff --git a/src/libcore/num/f64.rs b/src/libcore/num/f64.rs index f1af4f0272c6b..e82be19011073 100644 --- a/src/libcore/num/f64.rs +++ b/src/libcore/num/f64.rs @@ -16,8 +16,8 @@ use intrinsics; use mem; -use num::{FPNormal, FPCategory, FPZero, FPSubnormal, FPInfinite, FPNaN}; -use num::Float; +use num::{Float, FPNormal, FPCategory, FPZero, FPSubnormal, FPInfinite, FPNaN}; +use num::from_str_radix; use option::Option; // FIXME(#5527): These constants should be deprecated once associated @@ -430,3 +430,10 @@ impl Float for f64 { self * (value / 180.0) } } + +#[inline] +#[allow(missing_docs)] +#[deprecated="Use `FromStrRadix::from_str_radix(src, 16)`"] +pub fn from_str_hex(src: &str) -> Option { + from_str_radix(src, 16) +} diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index 216d140ac4897..f5505ff8e7625 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -14,18 +14,21 @@ #![allow(missing_docs)] -use intrinsics; use {int, i8, i16, i32, i64}; use {uint, u8, u16, u32, u64}; use {f32, f64}; +use char::Char; use clone::Clone; use cmp::{PartialEq, Eq}; use cmp::{PartialOrd, Ord}; +use intrinsics; +use iter::Iterator; use kinds::Copy; use mem::size_of; use ops::{Add, Sub, Mul, Div, Rem, Neg}; use ops::{Not, BitAnd, BitOr, BitXor, Shl, Shr}; use option::{Option, Some, None}; +use str::{FromStr, from_str, StrPrelude}; /// Simultaneous division and remainder #[inline] @@ -1372,6 +1375,290 @@ pub trait Float fn to_radians(self) -> Self; } +/// A generic trait for converting a string with a radix (base) to a value +#[experimental = "might need to return Result"] +pub trait FromStrRadix { + fn from_str_radix(str: &str, radix: uint) -> Option; +} + +/// A utility function that just calls FromStrRadix::from_str_radix. +#[experimental = "might need to return Result"] +pub fn from_str_radix(str: &str, radix: uint) -> Option { + FromStrRadix::from_str_radix(str, radix) +} + +macro_rules! from_str_radix_float_impl { + ($T:ty) => { + #[experimental = "might need to return Result"] + impl FromStr for $T { + /// Convert a string in base 10 to a float. + /// Accepts an optional decimal exponent. + /// + /// This function accepts strings such as + /// + /// * '3.14' + /// * '+3.14', equivalent to '3.14' + /// * '-3.14' + /// * '2.5E10', or equivalently, '2.5e10' + /// * '2.5E-10' + /// * '.' (understood as 0) + /// * '5.' + /// * '.5', or, equivalently, '0.5' + /// * '+inf', 'inf', '-inf', 'NaN' + /// + /// Leading and trailing whitespace represent an error. + /// + /// # Arguments + /// + /// * src - A string + /// + /// # Return value + /// + /// `None` if the string did not represent a valid number. Otherwise, + /// `Some(n)` where `n` is the floating-point number represented by `src`. + #[inline] + fn from_str(src: &str) -> Option<$T> { + from_str_radix(src, 10) + } + } + + #[experimental = "might need to return Result"] + impl FromStrRadix for $T { + /// Convert a string in a given base to a float. + /// + /// Due to possible conflicts, this function does **not** accept + /// the special values `inf`, `-inf`, `+inf` and `NaN`, **nor** + /// does it recognize exponents of any kind. + /// + /// Leading and trailing whitespace represent an error. + /// + /// # Arguments + /// + /// * src - A string + /// * radix - The base to use. Must lie in the range [2 .. 36] + /// + /// # Return value + /// + /// `None` if the string did not represent a valid number. Otherwise, + /// `Some(n)` where `n` is the floating-point number represented by `src`. + fn from_str_radix(src: &str, radix: uint) -> Option<$T> { + assert!(radix >= 2 && radix <= 36, + "from_str_radix_float: must lie in the range `[2, 36]` - found {}", + radix); + + // Special values + match src { + "inf" => return Some(Float::infinity()), + "-inf" => return Some(Float::neg_infinity()), + "NaN" => return Some(Float::nan()), + _ => {}, + } + + let (is_positive, src) = match src.slice_shift_char() { + (None, _) => return None, + (Some('-'), "") => return None, + (Some('-'), src) => (false, src), + (Some(_), _) => (true, src), + }; + + // The significand to accumulate + let mut sig = if is_positive { 0.0 } else { -0.0 }; + // Necessary to detect overflow + let mut prev_sig = sig; + let mut cs = src.chars().enumerate(); + // Exponent prefix and exponent index offset + let mut exp_info = None::<(char, uint)>; + + // Parse the integer part of the significand + for (i, c) in cs { + match c.to_digit(radix) { + Some(digit) => { + // shift significand one digit left + sig = sig * (radix as $T); + + // add/subtract current digit depending on sign + if is_positive { + sig = sig + ((digit as int) as $T); + } else { + sig = sig - ((digit as int) as $T); + } + + // Detect overflow by comparing to last value, except + // if we've not seen any non-zero digits. + if prev_sig != 0.0 { + if is_positive && sig <= prev_sig + { return Some(Float::infinity()); } + if !is_positive && sig >= prev_sig + { return Some(Float::neg_infinity()); } + + // Detect overflow by reversing the shift-and-add process + if is_positive && (prev_sig != (sig - digit as $T) / radix as $T) + { return Some(Float::infinity()); } + if !is_positive && (prev_sig != (sig + digit as $T) / radix as $T) + { return Some(Float::neg_infinity()); } + } + prev_sig = sig; + }, + None => match c { + 'e' | 'E' | 'p' | 'P' => { + exp_info = Some((c, i + 1)); + break; // start of exponent + }, + '.' => { + break; // start of fractional part + }, + _ => { + return None; + }, + }, + } + } + + // If we are not yet at the exponent parse the fractional + // part of the significand + if exp_info.is_none() { + let mut power = 1.0; + for (i, c) in cs { + match c.to_digit(radix) { + Some(digit) => { + // Decrease power one order of magnitude + power = power / (radix as $T); + // add/subtract current digit depending on sign + sig = if is_positive { + sig + (digit as $T) * power + } else { + sig - (digit as $T) * power + }; + // Detect overflow by comparing to last value + if is_positive && sig < prev_sig + { return Some(Float::infinity()); } + if !is_positive && sig > prev_sig + { return Some(Float::neg_infinity()); } + prev_sig = sig; + }, + None => match c { + 'e' | 'E' | 'p' | 'P' => { + exp_info = Some((c, i + 1)); + break; // start of exponent + }, + _ => { + return None; // invalid number + }, + }, + } + } + } + + // Parse and calculate the exponent + let exp = match exp_info { + Some((c, offset)) => { + let base = match c { + 'E' | 'e' if radix == 10 => 10u as $T, + 'P' | 'p' if radix == 16 => 2u as $T, + _ => return None, + }; + + // Parse the exponent as decimal integer + let src = src[offset..]; + let (is_positive, exp) = match src.slice_shift_char() { + (Some('-'), src) => (false, from_str::(src)), + (Some('+'), src) => (true, from_str::(src)), + (Some(_), _) => (true, from_str::(src)), + (None, _) => return None, + }; + + match (is_positive, exp) { + (true, Some(exp)) => base.powi(exp as i32), + (false, Some(exp)) => 1.0 / base.powi(exp as i32), + (_, None) => return None, + } + }, + None => 1.0, // no exponent + }; + + Some(sig * exp) + } + } + } +} +from_str_radix_float_impl!(f32) +from_str_radix_float_impl!(f64) + +macro_rules! from_str_radix_int_impl { + ($T:ty) => { + #[experimental = "might need to return Result"] + impl FromStr for $T { + #[inline] + fn from_str(src: &str) -> Option<$T> { + from_str_radix(src, 10) + } + } + + #[experimental = "might need to return Result"] + impl FromStrRadix for $T { + fn from_str_radix(src: &str, radix: uint) -> Option<$T> { + assert!(radix >= 2 && radix <= 36, + "from_str_radix_int: must lie in the range `[2, 36]` - found {}", + radix); + + let is_signed_ty = (0 as $T) > Int::min_value(); + + match src.slice_shift_char() { + (Some('-'), src) if is_signed_ty => { + // The number is negative + let mut result = 0; + for c in src.chars() { + let x = match c.to_digit(radix) { + Some(x) => x, + None => return None, + }; + result = match result.checked_mul(radix as $T) { + Some(result) => result, + None => return None, + }; + result = match result.checked_sub(x as $T) { + Some(result) => result, + None => return None, + }; + } + Some(result) + }, + (Some(_), _) => { + // The number is signed + let mut result = 0; + for c in src.chars() { + let x = match c.to_digit(radix) { + Some(x) => x, + None => return None, + }; + result = match result.checked_mul(radix as $T) { + Some(result) => result, + None => return None, + }; + result = match result.checked_add(x as $T) { + Some(result) => result, + None => return None, + }; + } + Some(result) + }, + (None, _) => None, + } + } + } + } +} +from_str_radix_int_impl!(int) +from_str_radix_int_impl!(i8) +from_str_radix_int_impl!(i16) +from_str_radix_int_impl!(i32) +from_str_radix_int_impl!(i64) +from_str_radix_int_impl!(uint) +from_str_radix_int_impl!(u8) +from_str_radix_int_impl!(u16) +from_str_radix_int_impl!(u32) +from_str_radix_int_impl!(u64) + // DEPRECATED macro_rules! trait_impl { diff --git a/src/libcore/option.rs b/src/libcore/option.rs index 2964a6b68534e..d41dbb11adb19 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -716,7 +716,6 @@ impl Option { impl AsSlice for Option { /// Convert from `Option` to `&[T]` (without copying) #[inline] - #[stable] fn as_slice<'a>(&'a self) -> &'a [T] { match *self { Some(ref x) => slice::ref_slice(x), @@ -728,6 +727,7 @@ impl AsSlice for Option { } } +#[stable] impl Default for Option { #[inline] fn default() -> Option { None } @@ -772,9 +772,10 @@ impl DoubleEndedIterator for Item { impl ExactSize for Item {} ///////////////////////////////////////////////////////////////////////////// -// Free functions +// FromIterator ///////////////////////////////////////////////////////////////////////////// +#[stable] impl> FromIterator> for Option { /// Takes each element in the `Iterator`: if it is `None`, no further /// elements are taken, and the `None` is returned. Should no `None` occur, a diff --git a/src/libcore/prelude.rs b/src/libcore/prelude.rs index 60012ab149f2a..101eb7ac74cdb 100644 --- a/src/libcore/prelude.rs +++ b/src/libcore/prelude.rs @@ -41,6 +41,7 @@ pub use ops::{Fn, FnMut, FnOnce}; // Reexported functions pub use iter::{range, repeat}; pub use mem::drop; +pub use str::from_str; // Reexported types and traits diff --git a/src/libcore/result.rs b/src/libcore/result.rs index 69802aef4c28d..5a6d0917af2c4 100644 --- a/src/libcore/result.rs +++ b/src/libcore/result.rs @@ -878,9 +878,10 @@ impl DoubleEndedIterator for Item { impl ExactSize for Item {} ///////////////////////////////////////////////////////////////////////////// -// Free functions +// FromIterator ///////////////////////////////////////////////////////////////////////////// +#[stable] impl> FromIterator> for Result { /// Takes each element in the `Iterator`: if it is an `Err`, no further /// elements are taken, and the `Err` is returned. Should no `Err` occur, a @@ -933,6 +934,10 @@ impl> FromIterator> for Result { } } +///////////////////////////////////////////////////////////////////////////// +// FromIterator +///////////////////////////////////////////////////////////////////////////// + /// Perform a fold operation over the result values from an iterator. /// /// If an `Err` is encountered, it is immediately returned. diff --git a/src/libcore/str.rs b/src/libcore/str.rs index 745de5f179e7c..ab4e50c58d9a4 100644 --- a/src/libcore/str.rs +++ b/src/libcore/str.rs @@ -31,6 +31,42 @@ use raw::Repr; use slice::{mod, SlicePrelude}; use uint; +/// A trait to abstract the idea of creating a new instance of a type from a +/// string. +#[experimental = "might need to return Result"] +pub trait FromStr { + /// Parses a string `s` to return an optional value of this type. If the + /// string is ill-formatted, the None is returned. + fn from_str(s: &str) -> Option; +} + +/// A utility function that just calls FromStr::from_str +pub fn from_str(s: &str) -> Option { + FromStr::from_str(s) +} + +impl FromStr for bool { + /// Parse a `bool` from a string. + /// + /// Yields an `Option`, because `s` may or may not actually be parseable. + /// + /// # Examples + /// + /// ```rust + /// assert_eq!(from_str::("true"), Some(true)); + /// assert_eq!(from_str::("false"), Some(false)); + /// assert_eq!(from_str::("not even a boolean"), None); + /// ``` + #[inline] + fn from_str(s: &str) -> Option { + match s { + "true" => Some(true), + "false" => Some(false), + _ => None, + } + } +} + /* Section: Creating a string */ diff --git a/src/libcoretest/cell.rs b/src/libcoretest/cell.rs index 59365045f4380..6444cf7ee0ebf 100644 --- a/src/libcoretest/cell.rs +++ b/src/libcoretest/cell.rs @@ -9,6 +9,7 @@ // except according to those terms. use core::cell::*; +use core::default::Default; use std::mem::drop; #[test] @@ -146,3 +147,15 @@ fn as_unsafe_cell() { unsafe { *r2.as_unsafe_cell().get() = 1u; } assert_eq!(1u, *r2.borrow()); } + +#[test] +fn cell_default() { + let cell: Cell = Default::default(); + assert_eq!(0, cell.get()); +} + +#[test] +fn refcell_default() { + let cell: RefCell = Default::default(); + assert_eq!(0, *cell.borrow()); +} diff --git a/src/libcoretest/num/int_macros.rs b/src/libcoretest/num/int_macros.rs index 5e2530ef2a92b..e25f10bd0dad5 100644 --- a/src/libcoretest/num/int_macros.rs +++ b/src/libcoretest/num/int_macros.rs @@ -15,7 +15,8 @@ macro_rules! int_module (($T:ty, $T_i:ident) => ( mod tests { use core::$T_i::*; use core::int; - use core::num::{Int, SignedInt}; + use core::num::{FromStrRadix, Int, SignedInt}; + use core::str::from_str; use num; #[test] @@ -156,6 +157,49 @@ mod tests { assert!(5i.checked_div(0) == None); assert!(int::MIN.checked_div(-1) == None); } + + #[test] + fn test_from_str() { + assert_eq!(from_str::<$T>("0"), Some(0 as $T)); + assert_eq!(from_str::<$T>("3"), Some(3 as $T)); + assert_eq!(from_str::<$T>("10"), Some(10 as $T)); + assert_eq!(from_str::("123456789"), Some(123456789 as i32)); + assert_eq!(from_str::<$T>("00100"), Some(100 as $T)); + + assert_eq!(from_str::<$T>("-1"), Some(-1 as $T)); + assert_eq!(from_str::<$T>("-3"), Some(-3 as $T)); + assert_eq!(from_str::<$T>("-10"), Some(-10 as $T)); + assert_eq!(from_str::("-123456789"), Some(-123456789 as i32)); + assert_eq!(from_str::<$T>("-00100"), Some(-100 as $T)); + + assert_eq!(from_str::<$T>(""), None); + assert_eq!(from_str::<$T>(" "), None); + assert_eq!(from_str::<$T>("x"), None); + } + + #[test] + fn test_from_str_radix() { + assert_eq!(FromStrRadix::from_str_radix("123", 10), Some(123 as $T)); + assert_eq!(FromStrRadix::from_str_radix("1001", 2), Some(9 as $T)); + assert_eq!(FromStrRadix::from_str_radix("123", 8), Some(83 as $T)); + assert_eq!(FromStrRadix::from_str_radix("123", 16), Some(291 as i32)); + assert_eq!(FromStrRadix::from_str_radix("ffff", 16), Some(65535 as i32)); + assert_eq!(FromStrRadix::from_str_radix("FFFF", 16), Some(65535 as i32)); + assert_eq!(FromStrRadix::from_str_radix("z", 36), Some(35 as $T)); + assert_eq!(FromStrRadix::from_str_radix("Z", 36), Some(35 as $T)); + + assert_eq!(FromStrRadix::from_str_radix("-123", 10), Some(-123 as $T)); + assert_eq!(FromStrRadix::from_str_radix("-1001", 2), Some(-9 as $T)); + assert_eq!(FromStrRadix::from_str_radix("-123", 8), Some(-83 as $T)); + assert_eq!(FromStrRadix::from_str_radix("-123", 16), Some(-291 as i32)); + assert_eq!(FromStrRadix::from_str_radix("-ffff", 16), Some(-65535 as i32)); + assert_eq!(FromStrRadix::from_str_radix("-FFFF", 16), Some(-65535 as i32)); + assert_eq!(FromStrRadix::from_str_radix("-z", 36), Some(-35 as $T)); + assert_eq!(FromStrRadix::from_str_radix("-Z", 36), Some(-35 as $T)); + + assert_eq!(FromStrRadix::from_str_radix("Z", 35), None::<$T>); + assert_eq!(FromStrRadix::from_str_radix("-9", 2), None::<$T>); + } } )) diff --git a/src/libcoretest/num/mod.rs b/src/libcoretest/num/mod.rs index 38502321c1d21..0cd1ded21d6c6 100644 --- a/src/libcoretest/num/mod.rs +++ b/src/libcoretest/num/mod.rs @@ -45,3 +45,73 @@ pub fn test_num(ten: T, two: T) where assert_eq!(ten.div(&two), ten / two); assert_eq!(ten.rem(&two), ten % two); } + +#[cfg(test)] +mod test { + use core::option::{Option, Some, None}; + use core::num::Float; + use core::num::from_str_radix; + + #[test] + fn from_str_issue7588() { + let u : Option = from_str_radix("1000", 10); + assert_eq!(u, None); + let s : Option = from_str_radix("80000", 10); + assert_eq!(s, None); + let f : Option = from_str_radix("10000000000000000000000000000000000000000", 10); + assert_eq!(f, Some(Float::infinity())) + let fe : Option = from_str_radix("1e40", 10); + assert_eq!(fe, Some(Float::infinity())) + } + + #[test] + fn test_from_str_radix_float() { + let x1 : Option = from_str_radix("-123.456", 10); + assert_eq!(x1, Some(-123.456)); + let x2 : Option = from_str_radix("123.456", 10); + assert_eq!(x2, Some(123.456)); + let x3 : Option = from_str_radix("-0.0", 10); + assert_eq!(x3, Some(-0.0)); + let x4 : Option = from_str_radix("0.0", 10); + assert_eq!(x4, Some(0.0)); + let x4 : Option = from_str_radix("1.0", 10); + assert_eq!(x4, Some(1.0)); + let x5 : Option = from_str_radix("-1.0", 10); + assert_eq!(x5, Some(-1.0)); + } + + #[test] + fn test_int_from_str_overflow() { + let mut i8_val: i8 = 127_i8; + assert_eq!(from_str::("127"), Some(i8_val)); + assert_eq!(from_str::("128"), None); + + i8_val += 1 as i8; + assert_eq!(from_str::("-128"), Some(i8_val)); + assert_eq!(from_str::("-129"), None); + + let mut i16_val: i16 = 32_767_i16; + assert_eq!(from_str::("32767"), Some(i16_val)); + assert_eq!(from_str::("32768"), None); + + i16_val += 1 as i16; + assert_eq!(from_str::("-32768"), Some(i16_val)); + assert_eq!(from_str::("-32769"), None); + + let mut i32_val: i32 = 2_147_483_647_i32; + assert_eq!(from_str::("2147483647"), Some(i32_val)); + assert_eq!(from_str::("2147483648"), None); + + i32_val += 1 as i32; + assert_eq!(from_str::("-2147483648"), Some(i32_val)); + assert_eq!(from_str::("-2147483649"), None); + + let mut i64_val: i64 = 9_223_372_036_854_775_807_i64; + assert_eq!(from_str::("9223372036854775807"), Some(i64_val)); + assert_eq!(from_str::("9223372036854775808"), None); + + i64_val += 1 as i64; + assert_eq!(from_str::("-9223372036854775808"), Some(i64_val)); + assert_eq!(from_str::("-9223372036854775809"), None); + } +} diff --git a/src/libcoretest/str.rs b/src/libcoretest/str.rs index d3f77c47c44bc..5f44fd807ccae 100644 --- a/src/libcoretest/str.rs +++ b/src/libcoretest/str.rs @@ -8,6 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#[test] +fn test_bool_from_str() { + assert_eq!(from_str::("true"), Some(true)); + assert_eq!(from_str::("false"), Some(false)); + assert_eq!(from_str::("not even a boolean"), None); +} + fn check_contains_all_substrings(s: &str) { assert!(s.contains("")); for i in range(0, s.len()) { diff --git a/src/libregex/re.rs b/src/libregex/re.rs index df5bfccd18d63..c7540852970d8 100644 --- a/src/libregex/re.rs +++ b/src/libregex/re.rs @@ -10,7 +10,6 @@ use std::collections::HashMap; use std::fmt; -use std::from_str::from_str; use std::str::{MaybeOwned, Owned, Slice}; use compile::Program; diff --git a/src/librustc/driver/config.rs b/src/librustc/driver/config.rs index 8c1d7c839acd0..9768b3ce1aba6 100644 --- a/src/librustc/driver/config.rs +++ b/src/librustc/driver/config.rs @@ -268,8 +268,21 @@ macro_rules! cgoptions( pub type CodegenSetter = fn(&mut CodegenOptions, v: Option<&str>) -> bool; pub const CG_OPTIONS: &'static [(&'static str, CodegenSetter, - &'static str)] = - &[ $( (stringify!($opt), cgsetters::$opt, $desc) ),* ]; + Option<&'static str>, &'static str)] = + &[ $( (stringify!($opt), cgsetters::$opt, cg_type_descs::$parse, $desc) ),* ]; + + #[allow(non_upper_case_globals)] + mod cg_type_descs { + pub const parse_bool: Option<&'static str> = None; + pub const parse_opt_bool: Option<&'static str> = None; + pub const parse_string: Option<&'static str> = Some("a string"); + pub const parse_opt_string: Option<&'static str> = Some("a string"); + pub const parse_list: Option<&'static str> = Some("a space-separated list of strings"); + pub const parse_opt_list: Option<&'static str> = Some("a space-separated list of strings"); + pub const parse_uint: Option<&'static str> = Some("a number"); + pub const parse_passes: Option<&'static str> = + Some("a space-separated list of passes, or `all`"); + } mod cgsetters { use super::{CodegenOptions, Passes, SomePasses, AllPasses}; @@ -334,8 +347,7 @@ macro_rules! cgoptions( } fn parse_uint(slot: &mut uint, v: Option<&str>) -> bool { - use std::from_str::FromStr; - match v.and_then(FromStr::from_str) { + match v.and_then(from_str) { Some(i) => { *slot = i; true }, None => false } @@ -421,19 +433,25 @@ pub fn build_codegen_options(matches: &getopts::Matches) -> CodegenOptions let value = iter.next(); let option_to_lookup = key.replace("-", "_"); let mut found = false; - for &(candidate, setter, _) in CG_OPTIONS.iter() { + for &(candidate, setter, opt_type_desc, _) in CG_OPTIONS.iter() { if option_to_lookup.as_slice() != candidate { continue } if !setter(&mut cg, value) { - match value { - Some(..) => { + match (value, opt_type_desc) { + (Some(..), None) => { early_error(format!("codegen option `{}` takes no \ value", key).as_slice()) } - None => { + (None, Some(type_desc)) => { early_error(format!("codegen option `{0}` requires \ - a value (-C {0}=)", - key).as_slice()) + {1} (-C {0}=)", + key, type_desc).as_slice()) + } + (Some(value), Some(type_desc)) => { + early_error(format!("incorrect value `{}` for codegen \ + option `{}` - {} was expected", + value, key, type_desc).as_slice()) } + (None, None) => unreachable!() } } found = true; diff --git a/src/librustc/driver/mod.rs b/src/librustc/driver/mod.rs index edd82b42876aa..546469c3c0e5d 100644 --- a/src/librustc/driver/mod.rs +++ b/src/librustc/driver/mod.rs @@ -299,14 +299,10 @@ fn describe_debug_flags() { fn describe_codegen_flags() { println!("\nAvailable codegen options:\n"); - let mut cg = config::basic_codegen_options(); - for &(name, parser, desc) in config::CG_OPTIONS.iter() { - // we invoke the parser function on `None` to see if this option needs - // an argument or not. - let (width, extra) = if parser(&mut cg, None) { - (25, "") - } else { - (21, "=val") + for &(name, _, opt_type_desc, desc) in config::CG_OPTIONS.iter() { + let (width, extra) = match opt_type_desc { + Some(..) => (21, "=val"), + None => (25, "") }; println!(" -C {:>width$s}{} -- {}", name.replace("_", "-"), extra, desc, width=width); diff --git a/src/librustc/driver/pretty.rs b/src/librustc/driver/pretty.rs index 0a7cfdeeadc2a..7b6de088319f4 100644 --- a/src/librustc/driver/pretty.rs +++ b/src/librustc/driver/pretty.rs @@ -31,8 +31,8 @@ use syntax::print::{pp, pprust}; use graphviz as dot; use std::io::{mod, MemReader}; -use std::from_str::FromStr; use std::option; +use std::str::FromStr; use arena::TypedArena; #[deriving(PartialEq, Show)] diff --git a/src/librustc/middle/trans/type_of.rs b/src/librustc/middle/trans/type_of.rs index a597325015c70..9530c86a94c11 100644 --- a/src/librustc/middle/trans/type_of.rs +++ b/src/librustc/middle/trans/type_of.rs @@ -455,7 +455,12 @@ pub fn llvm_type_name(cx: &CrateContext, let base = ty::item_path_str(cx.tcx(), did); let strings: Vec = tps.iter().map(|t| t.repr(cx.tcx())).collect(); - let tstr = format!("{}<{}>", base, strings); + let tstr = if strings.is_empty() { + base + } else { + format!("{}<{}>", base, strings) + }; + if did.krate == 0 { format!("{}.{}", name, tstr) } else { diff --git a/src/librustdoc/html/static/main.css b/src/librustdoc/html/static/main.css index 7cc34798f9904..b28da098a5783 100644 --- a/src/librustdoc/html/static/main.css +++ b/src/librustdoc/html/static/main.css @@ -584,3 +584,9 @@ pre.rust { position: relative; } height: 1.5em; } } + +@media print { + nav.sub, .content .out-of-band, .collapse-toggle { + display: none; + } +} diff --git a/src/librustdoc/stability_summary.rs b/src/librustdoc/stability_summary.rs index b0e1aeea3a182..7ec59f0139d98 100644 --- a/src/librustdoc/stability_summary.rs +++ b/src/librustdoc/stability_summary.rs @@ -19,7 +19,7 @@ use std::num::Zero; use syntax::attr::{Deprecated, Experimental, Unstable, Stable, Frozen, Locked}; use syntax::ast::Public; -use clean::{Crate, Item, ModuleItem, Module, StructItem, Struct, EnumItem, Enum}; +use clean::{Crate, Item, ModuleItem, Module, EnumItem, Enum}; use clean::{ImplItem, Impl, Trait, TraitItem, TraitMethod, ProvidedMethod, RequiredMethod}; use clean::{TypeTraitItem, ViewItemItem, PrimitiveItem, Stability}; @@ -146,13 +146,12 @@ fn summarize_item(item: &Item) -> (Counts, Option) { // considered to have no children. match item.inner { // Require explicit `pub` to be visible - StructItem(Struct { fields: ref subitems, .. }) | ImplItem(Impl { items: ref subitems, trait_: None, .. }) => { let subcounts = subitems.iter().filter(|i| visible(*i)) .map(summarize_item) .map(|s| s.val0()) .fold(Counts::zero(), |acc, x| acc + x); - (item_counts + subcounts, None) + (subcounts, None) } // `pub` automatically EnumItem(Enum { variants: ref subitems, .. }) => { diff --git a/src/libserialize/json.rs b/src/libserialize/json.rs index 524638155ac16..a074d6f43b97b 100644 --- a/src/libserialize/json.rs +++ b/src/libserialize/json.rs @@ -200,7 +200,7 @@ use std::{char, f64, fmt, io, num, str}; use std::io::MemWriter; use std::mem::{swap, transmute}; use std::num::{Float, FPNaN, FPInfinite, Int}; -use std::str::ScalarValue; +use std::str::{FromStr, ScalarValue}; use std::string; use std::vec::Vec; use std::ops; @@ -1988,7 +1988,7 @@ macro_rules! read_primitive { String(s) => { // re: #12967.. a type w/ numeric keys (ie HashMap etc) // is going to have a string here, as per JSON spec. - match std::from_str::from_str(s.as_slice()) { + match std::str::from_str(s.as_slice()) { Some(f) => Ok(f), None => Err(ExpectedError("Number".to_string(), s)), } @@ -2027,7 +2027,7 @@ impl ::Decoder for Decoder { String(s) => { // re: #12967.. a type w/ numeric keys (ie HashMap etc) // is going to have a string here, as per JSON spec. - match std::from_str::from_str(s.as_slice()) { + match std::str::from_str(s.as_slice()) { Some(f) => Ok(f), None => Err(ExpectedError("Number".to_string(), s)), } @@ -2315,6 +2315,10 @@ impl ToJson for bool { fn to_json(&self) -> Json { Boolean(*self) } } +impl ToJson for str { + fn to_json(&self) -> Json { String(self.into_string()) } +} + impl ToJson for string::String { fn to_json(&self) -> Json { String((*self).clone()) } } @@ -2395,7 +2399,7 @@ impl fmt::Show for Json { } } -impl std::from_str::FromStr for Json { +impl FromStr for Json { fn from_str(s: &str) -> Option { from_str(s).ok() } @@ -2480,7 +2484,7 @@ mod tests { #[test] fn test_from_str_trait() { let s = "null"; - assert!(::std::from_str::from_str::(s).unwrap() == from_str(s).unwrap()); + assert!(::std::str::from_str::(s).unwrap() == from_str(s).unwrap()); } #[test] @@ -3714,7 +3718,8 @@ mod tests { assert_eq!(f64::NAN.to_json(), Null); assert_eq!(true.to_json(), Boolean(true)); assert_eq!(false.to_json(), Boolean(false)); - assert_eq!("abc".to_string().to_json(), String("abc".to_string())); + assert_eq!("abc".to_json(), String("abc".into_string())); + assert_eq!("abc".into_string().to_json(), String("abc".into_string())); assert_eq!((1u, 2u).to_json(), list2); assert_eq!((1u, 2u, 3u).to_json(), list3); assert_eq!([1u, 2].to_json(), list2); diff --git a/src/libstd/ascii.rs b/src/libstd/ascii.rs index ff83027d28008..923349b1bf740 100644 --- a/src/libstd/ascii.rs +++ b/src/libstd/ascii.rs @@ -21,8 +21,7 @@ use mem; use option::{Option, Some, None}; use slice::{SlicePrelude, AsSlice}; use str::{Str, StrPrelude}; -use string::{mod, String}; -use to_string::IntoStr; +use string::{mod, String, IntoString}; use vec::Vec; /// Datatype to hold one ascii character. It wraps a `u8`, with the highest bit always zero. @@ -326,7 +325,7 @@ impl AsciiStr for [Ascii] { } } -impl IntoStr for Vec { +impl IntoString for Vec { #[inline] fn into_string(self) -> String { unsafe { diff --git a/src/libstd/from_str.rs b/src/libstd/from_str.rs deleted file mode 100644 index 21b1e0560a5db..0000000000000 --- a/src/libstd/from_str.rs +++ /dev/null @@ -1,71 +0,0 @@ -// 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! The `FromStr` trait for types that can be created from strings - -#![experimental] - -use option::{Option, Some, None}; -use string::String; - -/// A trait to abstract the idea of creating a new instance of a type from a -/// string. -#[experimental = "might need to return Result"] -pub trait FromStr { - /// Parses a string `s` to return an optional value of this type. If the - /// string is ill-formatted, the None is returned. - fn from_str(s: &str) -> Option; -} - -/// A utility function that just calls FromStr::from_str -pub fn from_str(s: &str) -> Option { - FromStr::from_str(s) -} - -impl FromStr for bool { - /// Parse a `bool` from a string. - /// - /// Yields an `Option`, because `s` may or may not actually be parseable. - /// - /// # Examples - /// - /// ```rust - /// assert_eq!(from_str::("true"), Some(true)); - /// assert_eq!(from_str::("false"), Some(false)); - /// assert_eq!(from_str::("not even a boolean"), None); - /// ``` - #[inline] - fn from_str(s: &str) -> Option { - match s { - "true" => Some(true), - "false" => Some(false), - _ => None, - } - } -} - -impl FromStr for String { - #[inline] - fn from_str(s: &str) -> Option { - Some(String::from_str(s)) - } -} - -#[cfg(test)] -mod test { - use prelude::*; - - #[test] - fn test_bool_from_str() { - assert_eq!(from_str::("true"), Some(true)); - assert_eq!(from_str::("false"), Some(false)); - assert_eq!(from_str::("not even a boolean"), None); - } -} diff --git a/src/libstd/io/net/ip.rs b/src/libstd/io/net/ip.rs index 2a2d978ef495b..7ba5e173182e1 100644 --- a/src/libstd/io/net/ip.rs +++ b/src/libstd/io/net/ip.rs @@ -16,13 +16,12 @@ #![allow(missing_docs)] use fmt; -use from_str::FromStr; use io::{mod, IoResult, IoError}; use io::net; use iter::Iterator; use option::{Option, None, Some}; use result::{Ok, Err}; -use str::StrPrelude; +use str::{FromStr, StrPrelude}; use slice::{CloneSlicePrelude, SlicePrelude}; use vec::Vec; @@ -540,7 +539,7 @@ impl<'a> ToSocketAddr for &'a str { mod test { use prelude::*; use super::*; - use from_str::FromStr; + use str::FromStr; #[test] fn test_from_str_ipv4() { diff --git a/src/libstd/io/net/tcp.rs b/src/libstd/io/net/tcp.rs index 2545e07cbb5c2..24fc2998ee696 100644 --- a/src/libstd/io/net/tcp.rs +++ b/src/libstd/io/net/tcp.rs @@ -661,23 +661,22 @@ mod test { let addr = next_test_ip4(); let mut acceptor = TcpListener::bind(addr).listen(); + let (tx, rx) = channel(); spawn(proc() { - let _stream = TcpStream::connect(addr); - // Close + drop(TcpStream::connect(addr)); + tx.send(()); }); let mut stream = acceptor.accept(); + rx.recv(); let buf = [0]; - loop { - match stream.write(buf) { - Ok(..) => {} - Err(e) => { - assert!(e.kind == ConnectionReset || - e.kind == BrokenPipe || - e.kind == ConnectionAborted, - "unknown error: {}", e); - break; - } + match stream.write(buf) { + Ok(..) => {} + Err(e) => { + assert!(e.kind == ConnectionReset || + e.kind == BrokenPipe || + e.kind == ConnectionAborted, + "unknown error: {}", e); } } } @@ -687,23 +686,22 @@ mod test { let addr = next_test_ip6(); let mut acceptor = TcpListener::bind(addr).listen(); + let (tx, rx) = channel(); spawn(proc() { - let _stream = TcpStream::connect(addr); - // Close + drop(TcpStream::connect(addr)); + tx.send(()); }); let mut stream = acceptor.accept(); + rx.recv(); let buf = [0]; - loop { - match stream.write(buf) { - Ok(..) => {} - Err(e) => { - assert!(e.kind == ConnectionReset || - e.kind == BrokenPipe || - e.kind == ConnectionAborted, - "unknown error: {}", e); - break; - } + match stream.write(buf) { + Ok(..) => {} + Err(e) => { + assert!(e.kind == ConnectionReset || + e.kind == BrokenPipe || + e.kind == ConnectionAborted, + "unknown error: {}", e); } } } diff --git a/src/libstd/io/process.rs b/src/libstd/io/process.rs index d71bab0b48f90..5b5bb61815165 100644 --- a/src/libstd/io/process.rs +++ b/src/libstd/io/process.rs @@ -1190,7 +1190,7 @@ mod tests { Path::new("/dev/null") }; - let mut fdes = match fs::open(&path, Truncate, Write) { + let fdes = match fs::open(&path, Truncate, Write) { Ok(f) => f, Err(_) => panic!("failed to open file descriptor"), }; diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 3940d7db66e4b..612613134d448 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -54,7 +54,7 @@ //! //! For converting to strings use the [`format!`](fmt/index.html) //! macro, and for converting from strings use the -//! [`FromStr`](from_str/index.html) trait. +//! [`FromStr`](str/trait.FromStr.html) trait. //! //! ## Platform abstractions //! @@ -219,9 +219,7 @@ pub mod time; /* Common traits */ pub mod error; -pub mod from_str; pub mod num; -pub mod to_string; /* Common data structures */ diff --git a/src/libstd/num/f32.rs b/src/libstd/num/f32.rs index 3f46cc8af50b1..207fa6499309c 100644 --- a/src/libstd/num/f32.rs +++ b/src/libstd/num/f32.rs @@ -17,12 +17,10 @@ use prelude::*; -use from_str::FromStr; use intrinsics; use libc::c_int; use num::{Float, FloatMath}; use num::strconv; -use num; pub use core::f32::{RADIX, MANTISSA_DIGITS, DIGITS, EPSILON, MIN_VALUE}; pub use core::f32::{MIN_POS_VALUE, MAX_VALUE, MIN_EXP, MAX_EXP, MIN_10_EXP}; @@ -339,68 +337,6 @@ pub fn to_str_exp_digits(num: f32, dig: uint, upper: bool) -> String { r } -#[inline] -#[deprecated="Use `FromStrRadix::from_str_radix(src, 16)`"] -pub fn from_str_hex(src: &str) -> Option { - strconv::from_str_radix_float(src, 16) -} - -impl FromStr for f32 { - /// Convert a string in base 10 to a float. - /// Accepts an optional decimal exponent. - /// - /// This function accepts strings such as - /// - /// * '3.14' - /// * '+3.14', equivalent to '3.14' - /// * '-3.14' - /// * '2.5E10', or equivalently, '2.5e10' - /// * '2.5E-10' - /// * '.' (understood as 0) - /// * '5.' - /// * '.5', or, equivalently, '0.5' - /// * '+inf', 'inf', '-inf', 'NaN' - /// - /// Leading and trailing whitespace represent an error. - /// - /// # Arguments - /// - /// * src - A string - /// - /// # Return value - /// - /// `None` if the string did not represent a valid number. Otherwise, - /// `Some(n)` where `n` is the floating-point number represented by `src`. - #[inline] - fn from_str(src: &str) -> Option { - strconv::from_str_radix_float(src, 10u) - } -} - -impl num::FromStrRadix for f32 { - /// Convert a string in a given base to a float. - /// - /// Due to possible conflicts, this function does **not** accept - /// the special values `inf`, `-inf`, `+inf` and `NaN`, **nor** - /// does it recognize exponents of any kind. - /// - /// Leading and trailing whitespace represent an error. - /// - /// # Arguments - /// - /// * src - A string - /// * radix - The base to use. Must lie in the range [2 .. 36] - /// - /// # Return value - /// - /// `None` if the string did not represent a valid number. Otherwise, - /// `Some(n)` where `n` is the floating-point number represented by `src`. - #[inline] - fn from_str_radix(src: &str, radix: uint) -> Option { - strconv::from_str_radix_float(src, radix) - } -} - #[cfg(test)] mod tests { use f32::*; diff --git a/src/libstd/num/f64.rs b/src/libstd/num/f64.rs index 4d691fc967698..543d50596e8ce 100644 --- a/src/libstd/num/f64.rs +++ b/src/libstd/num/f64.rs @@ -16,12 +16,10 @@ use prelude::*; -use from_str::FromStr; use intrinsics; use libc::c_int; use num::{Float, FloatMath}; use num::strconv; -use num; pub use core::f64::{RADIX, MANTISSA_DIGITS, DIGITS, EPSILON, MIN_VALUE}; pub use core::f64::{MIN_POS_VALUE, MAX_VALUE, MIN_EXP, MAX_EXP, MIN_10_EXP}; @@ -347,63 +345,6 @@ pub fn to_str_exp_digits(num: f64, dig: uint, upper: bool) -> String { r } -#[inline] -#[deprecated="Use `FromStrRadix::from_str_radix(src, 16)`"] -pub fn from_str_hex(src: &str) -> Option { - strconv::from_str_radix_float(src, 16) -} - -impl FromStr for f64 { - /// Convert a string in base 10 to a float. - /// Accepts an optional decimal exponent. - /// - /// This function accepts strings such as: - /// - /// * '3.14' - /// * '-3.14' - /// * '2.5E10', or equivalently, '2.5e10' - /// * '2.5E-10' - /// * '.' (understood as 0) - /// * '5.' - /// * '.5', or, equivalently, '0.5' - /// * inf', '-inf', 'NaN' - /// - /// Leading and trailing whitespace represent an error. - /// - /// # Arguments - /// - /// * src - A string - /// - /// # Return value - /// - /// `none` if the string did not represent a valid number. Otherwise, - /// `Some(n)` where `n` is the floating-point number represented by `src`. - #[inline] - fn from_str(src: &str) -> Option { - strconv::from_str_radix_float(src, 10u) - } -} - -impl num::FromStrRadix for f64 { - /// Convert a string in a given base to a float. - /// - /// Leading and trailing whitespace represent an error. - /// - /// # Arguments - /// - /// * src - A string - /// * radix - The base to use. Must lie in the range [2 .. 36] - /// - /// # Return value - /// - /// `None` if the string did not represent a valid number. Otherwise, - /// `Some(n)` where `n` is the floating-point number represented by `src`. - #[inline] - fn from_str_radix(src: &str, radix: uint) -> Option { - strconv::from_str_radix_float(src, radix) - } -} - #[cfg(test)] mod tests { use f64::*; diff --git a/src/libstd/num/i16.rs b/src/libstd/num/i16.rs index d7732b474dba8..6455c10736a3f 100644 --- a/src/libstd/num/i16.rs +++ b/src/libstd/num/i16.rs @@ -13,11 +13,6 @@ #![unstable] #![doc(primitive = "i16")] -use from_str::FromStr; -use num::FromStrRadix; -use num::strconv; -use option::Option; - pub use core::i16::{BITS, BYTES, MIN, MAX}; int_module!(i16) diff --git a/src/libstd/num/i32.rs b/src/libstd/num/i32.rs index 778f1c6748c26..39b179c8274eb 100644 --- a/src/libstd/num/i32.rs +++ b/src/libstd/num/i32.rs @@ -13,11 +13,6 @@ #![unstable] #![doc(primitive = "i32")] -use from_str::FromStr; -use num::FromStrRadix; -use num::strconv; -use option::Option; - pub use core::i32::{BITS, BYTES, MIN, MAX}; int_module!(i32) diff --git a/src/libstd/num/i64.rs b/src/libstd/num/i64.rs index ae3d57eeac65d..a0c474c479ae4 100644 --- a/src/libstd/num/i64.rs +++ b/src/libstd/num/i64.rs @@ -13,11 +13,6 @@ #![unstable] #![doc(primitive = "i64")] -use from_str::FromStr; -use num::FromStrRadix; -use num::strconv; -use option::Option; - pub use core::i64::{BITS, BYTES, MIN, MAX}; int_module!(i64) diff --git a/src/libstd/num/i8.rs b/src/libstd/num/i8.rs index 8a3f379893c24..e911ed1de9ac4 100644 --- a/src/libstd/num/i8.rs +++ b/src/libstd/num/i8.rs @@ -13,11 +13,6 @@ #![unstable] #![doc(primitive = "i8")] -use from_str::FromStr; -use num::FromStrRadix; -use num::strconv; -use option::Option; - pub use core::i8::{BITS, BYTES, MIN, MAX}; int_module!(i8) diff --git a/src/libstd/num/int.rs b/src/libstd/num/int.rs index 51af04b32d4fb..36c021efe0a39 100644 --- a/src/libstd/num/int.rs +++ b/src/libstd/num/int.rs @@ -13,11 +13,6 @@ #![unstable] #![doc(primitive = "int")] -use from_str::FromStr; -use num::FromStrRadix; -use num::strconv; -use option::Option; - pub use core::int::{BITS, BYTES, MIN, MAX}; int_module!(int) diff --git a/src/libstd/num/int_macros.rs b/src/libstd/num/int_macros.rs index 9ae146c840ae8..2f1162d28e558 100644 --- a/src/libstd/num/int_macros.rs +++ b/src/libstd/num/int_macros.rs @@ -14,131 +14,4 @@ macro_rules! int_module (($T:ty) => ( -#[experimental = "might need to return Result"] -impl FromStr for $T { - #[inline] - fn from_str(s: &str) -> Option<$T> { - strconv::from_str_radix_int(s, 10) - } -} - -#[experimental = "might need to return Result"] -impl FromStrRadix for $T { - #[inline] - fn from_str_radix(s: &str, radix: uint) -> Option<$T> { - strconv::from_str_radix_int(s, radix) - } -} - -#[cfg(test)] -mod tests { - use prelude::*; - use num::FromStrRadix; - - #[test] - fn test_from_str() { - assert_eq!(from_str::<$T>("0"), Some(0 as $T)); - assert_eq!(from_str::<$T>("3"), Some(3 as $T)); - assert_eq!(from_str::<$T>("10"), Some(10 as $T)); - assert_eq!(from_str::("123456789"), Some(123456789 as i32)); - assert_eq!(from_str::<$T>("00100"), Some(100 as $T)); - - assert_eq!(from_str::<$T>("-1"), Some(-1 as $T)); - assert_eq!(from_str::<$T>("-3"), Some(-3 as $T)); - assert_eq!(from_str::<$T>("-10"), Some(-10 as $T)); - assert_eq!(from_str::("-123456789"), Some(-123456789 as i32)); - assert_eq!(from_str::<$T>("-00100"), Some(-100 as $T)); - - assert_eq!(from_str::<$T>(""), None); - assert_eq!(from_str::<$T>(" "), None); - assert_eq!(from_str::<$T>("x"), None); - } - - #[test] - fn test_from_str_radix() { - assert_eq!(FromStrRadix::from_str_radix("123", 10), Some(123 as $T)); - assert_eq!(FromStrRadix::from_str_radix("1001", 2), Some(9 as $T)); - assert_eq!(FromStrRadix::from_str_radix("123", 8), Some(83 as $T)); - assert_eq!(FromStrRadix::from_str_radix("123", 16), Some(291 as i32)); - assert_eq!(FromStrRadix::from_str_radix("ffff", 16), Some(65535 as i32)); - assert_eq!(FromStrRadix::from_str_radix("FFFF", 16), Some(65535 as i32)); - assert_eq!(FromStrRadix::from_str_radix("z", 36), Some(35 as $T)); - assert_eq!(FromStrRadix::from_str_radix("Z", 36), Some(35 as $T)); - - assert_eq!(FromStrRadix::from_str_radix("-123", 10), Some(-123 as $T)); - assert_eq!(FromStrRadix::from_str_radix("-1001", 2), Some(-9 as $T)); - assert_eq!(FromStrRadix::from_str_radix("-123", 8), Some(-83 as $T)); - assert_eq!(FromStrRadix::from_str_radix("-123", 16), Some(-291 as i32)); - assert_eq!(FromStrRadix::from_str_radix("-ffff", 16), Some(-65535 as i32)); - assert_eq!(FromStrRadix::from_str_radix("-FFFF", 16), Some(-65535 as i32)); - assert_eq!(FromStrRadix::from_str_radix("-z", 36), Some(-35 as $T)); - assert_eq!(FromStrRadix::from_str_radix("-Z", 36), Some(-35 as $T)); - - assert_eq!(FromStrRadix::from_str_radix("Z", 35), None::<$T>); - assert_eq!(FromStrRadix::from_str_radix("-9", 2), None::<$T>); - } - - #[test] - fn test_int_to_str_overflow() { - let mut i8_val: i8 = 127_i8; - assert_eq!(i8_val.to_string(), "127".to_string()); - - i8_val += 1 as i8; - assert_eq!(i8_val.to_string(), "-128".to_string()); - - let mut i16_val: i16 = 32_767_i16; - assert_eq!(i16_val.to_string(), "32767".to_string()); - - i16_val += 1 as i16; - assert_eq!(i16_val.to_string(), "-32768".to_string()); - - let mut i32_val: i32 = 2_147_483_647_i32; - assert_eq!(i32_val.to_string(), "2147483647".to_string()); - - i32_val += 1 as i32; - assert_eq!(i32_val.to_string(), "-2147483648".to_string()); - - let mut i64_val: i64 = 9_223_372_036_854_775_807_i64; - assert_eq!(i64_val.to_string(), "9223372036854775807".to_string()); - - i64_val += 1 as i64; - assert_eq!(i64_val.to_string(), "-9223372036854775808".to_string()); - } - - #[test] - fn test_int_from_str_overflow() { - let mut i8_val: i8 = 127_i8; - assert_eq!(from_str::("127"), Some(i8_val)); - assert_eq!(from_str::("128"), None); - - i8_val += 1 as i8; - assert_eq!(from_str::("-128"), Some(i8_val)); - assert_eq!(from_str::("-129"), None); - - let mut i16_val: i16 = 32_767_i16; - assert_eq!(from_str::("32767"), Some(i16_val)); - assert_eq!(from_str::("32768"), None); - - i16_val += 1 as i16; - assert_eq!(from_str::("-32768"), Some(i16_val)); - assert_eq!(from_str::("-32769"), None); - - let mut i32_val: i32 = 2_147_483_647_i32; - assert_eq!(from_str::("2147483647"), Some(i32_val)); - assert_eq!(from_str::("2147483648"), None); - - i32_val += 1 as i32; - assert_eq!(from_str::("-2147483648"), Some(i32_val)); - assert_eq!(from_str::("-2147483649"), None); - - let mut i64_val: i64 = 9_223_372_036_854_775_807_i64; - assert_eq!(from_str::("9223372036854775807"), Some(i64_val)); - assert_eq!(from_str::("9223372036854775808"), None); - - i64_val += 1 as i64; - assert_eq!(from_str::("-9223372036854775808"), Some(i64_val)); - assert_eq!(from_str::("-9223372036854775809"), None); - } -} - )) diff --git a/src/libstd/num/mod.rs b/src/libstd/num/mod.rs index 0afc8ce0452c8..2ce6c0e6e71cd 100644 --- a/src/libstd/num/mod.rs +++ b/src/libstd/num/mod.rs @@ -16,8 +16,6 @@ #![experimental] #![allow(missing_docs)] -use option::Option; - #[cfg(test)] use cmp::PartialEq; #[cfg(test)] use fmt::Show; #[cfg(test)] use ops::{Add, Sub, Mul, Div, Rem}; @@ -31,6 +29,7 @@ pub use core::num::{checked_next_power_of_two}; pub use core::num::{from_int, from_i8, from_i16, from_i32, from_i64}; pub use core::num::{from_uint, from_u8, from_u16, from_u32, from_u64}; pub use core::num::{from_f32, from_f64}; +pub use core::num::{FromStrRadix, from_str_radix}; pub use core::num::{FPCategory, FPNaN, FPInfinite, FPZero, FPSubnormal}; pub use core::num::{FPNormal, Float}; @@ -115,18 +114,6 @@ pub trait FloatMath: Float { fn atanh(self) -> Self; } -/// A generic trait for converting a string with a radix (base) to a value -#[experimental = "might need to return Result"] -pub trait FromStrRadix { - fn from_str_radix(str: &str, radix: uint) -> Option; -} - -/// A utility function that just calls FromStrRadix::from_str_radix. -#[experimental = "might need to return Result"] -pub fn from_str_radix(str: &str, radix: uint) -> Option { - FromStrRadix::from_str_radix(str, radix) -} - // DEPRECATED #[deprecated = "Use `FloatMath::abs_sub`"] @@ -764,8 +751,9 @@ mod tests { #[test] fn test_pow() { - fn naive_pow>(base: T, exp: uint) -> T { - range(0, exp).fold(one::(), |acc, _| acc * base) + fn naive_pow(base: T, exp: uint) -> T { + let one: T = Int::one(); + range(0, exp).fold(one, |acc, _| acc * base) } macro_rules! assert_pow( (($num:expr, $exp:expr) => $expected:expr) => {{ diff --git a/src/libstd/num/strconv.rs b/src/libstd/num/strconv.rs index fff31b332e179..d1a89d72621a7 100644 --- a/src/libstd/num/strconv.rs +++ b/src/libstd/num/strconv.rs @@ -13,12 +13,8 @@ #![allow(missing_docs)] use char; -use char::Char; -use from_str::from_str; -use iter::Iterator; use num; use num::{Int, Float, FPNaN, FPInfinite, ToPrimitive}; -use option::{None, Option, Some}; use slice::{SlicePrelude, CloneSliceAllocPrelude}; use str::StrPrelude; use string::String; @@ -425,242 +421,35 @@ pub fn float_to_str_common( static DIGIT_P_RADIX: uint = ('p' as uint) - ('a' as uint) + 11u; static DIGIT_E_RADIX: uint = ('e' as uint) - ('a' as uint) + 11u; -pub fn from_str_radix_float(src: &str, radix: uint) -> Option { - assert!(radix >= 2 && radix <= 36, - "from_str_radix_float: must lie in the range `[2, 36]` - found {}", - radix); - - let _0: T = Float::zero(); - let _1: T = Float::one(); - let radix_t: T = num::cast(radix as int).unwrap(); - - // Special values - match src { - "inf" => return Some(Float::infinity()), - "-inf" => return Some(Float::neg_infinity()), - "NaN" => return Some(Float::nan()), - _ => {}, - } - - let (is_positive, src) = match src.slice_shift_char() { - (None, _) => return None, - (Some('-'), "") => return None, - (Some('-'), src) => (false, src), - (Some(_), _) => (true, src), - }; - - // The significand to accumulate - let mut sig = if is_positive { _0 } else { -_0 }; - // Necessary to detect overflow - let mut prev_sig = sig; - let mut cs = src.chars().enumerate(); - // Exponent prefix and exponent index offset - let mut exp_info = None::<(char, uint)>; - - // Parse the integer part of the significand - for (i, c) in cs { - match c.to_digit(radix) { - Some(digit) => { - // shift significand one digit left - sig = sig * radix_t; - - // add/subtract current digit depending on sign - if is_positive { - sig = sig + num::cast(digit as int).unwrap(); - } else { - sig = sig - num::cast(digit as int).unwrap(); - } - - // Detect overflow by comparing to last value, except - // if we've not seen any non-zero digits. - if prev_sig != _0 { - if is_positive && sig <= prev_sig - { return Some(Float::infinity()); } - if !is_positive && sig >= prev_sig - { return Some(Float::neg_infinity()); } - - // Detect overflow by reversing the shift-and-add process - let digit: T = num::cast(digit as int).unwrap(); - if is_positive && (prev_sig != ((sig - digit) / radix_t)) - { return Some(Float::infinity()); } - if !is_positive && (prev_sig != ((sig + digit) / radix_t)) - { return Some(Float::neg_infinity()); } - } - prev_sig = sig; - }, - None => match c { - 'e' | 'E' | 'p' | 'P' => { - exp_info = Some((c, i + 1)); - break; // start of exponent - }, - '.' => { - break; // start of fractional part - }, - _ => { - return None; - }, - }, - } - } - - // If we are not yet at the exponent parse the fractional - // part of the significand - if exp_info.is_none() { - let mut power = _1; - for (i, c) in cs { - match c.to_digit(radix) { - Some(digit) => { - let digit: T = num::cast(digit).unwrap(); - // Decrease power one order of magnitude - power = power / radix_t; - // add/subtract current digit depending on sign - sig = if is_positive { - sig + digit * power - } else { - sig - digit * power - }; - // Detect overflow by comparing to last value - if is_positive && sig < prev_sig - { return Some(Float::infinity()); } - if !is_positive && sig > prev_sig - { return Some(Float::neg_infinity()); } - prev_sig = sig; - }, - None => match c { - 'e' | 'E' | 'p' | 'P' => { - exp_info = Some((c, i + 1)); - break; // start of exponent - }, - _ => { - return None; // invalid number - }, - }, - } - } - } - - // Parse and calculate the exponent - let exp = match exp_info { - Some((c, offset)) => { - let base: T = match c { - 'E' | 'e' if radix == 10 => num::cast(10u).unwrap(), - 'P' | 'p' if radix == 16 => num::cast(2u).unwrap(), - _ => return None, - }; - - // Parse the exponent as decimal integer - let src = src[offset..]; - let (is_positive, exp) = match src.slice_shift_char() { - (Some('-'), src) => (false, from_str::(src)), - (Some('+'), src) => (true, from_str::(src)), - (Some(_), _) => (true, from_str::(src)), - (None, _) => return None, - }; - - match (is_positive, exp) { - (true, Some(exp)) => base.powi(exp as i32), - (false, Some(exp)) => _1 / base.powi(exp as i32), - (_, None) => return None, - } - }, - None => _1, // no exponent - }; +#[cfg(test)] +mod tests { + use string::ToString; - Some(sig * exp) -} + #[test] + fn test_int_to_str_overflow() { + let mut i8_val: i8 = 127_i8; + assert_eq!(i8_val.to_string(), "127".to_string()); -pub fn from_str_radix_int(src: &str, radix: uint) -> Option { - assert!(radix >= 2 && radix <= 36, - "from_str_radix_int: must lie in the range `[2, 36]` - found {}", - radix); + i8_val += 1 as i8; + assert_eq!(i8_val.to_string(), "-128".to_string()); - fn cast(x: uint) -> T { - num::cast(x).unwrap() - } + let mut i16_val: i16 = 32_767_i16; + assert_eq!(i16_val.to_string(), "32767".to_string()); - let _0: T = Int::zero(); - let _1: T = Int::one(); - let is_signed = _0 > Int::min_value(); + i16_val += 1 as i16; + assert_eq!(i16_val.to_string(), "-32768".to_string()); - let (is_positive, src) = match src.slice_shift_char() { - (Some('-'), src) if is_signed => (false, src), - (Some(_), _) => (true, src), - (None, _) => return None, - }; + let mut i32_val: i32 = 2_147_483_647_i32; + assert_eq!(i32_val.to_string(), "2147483647".to_string()); - let mut xs = src.chars().map(|c| { - c.to_digit(radix).map(cast) - }); - let radix = cast(radix); - let mut result = _0; - - if is_positive { - for x in xs { - let x = match x { - Some(x) => x, - None => return None, - }; - result = match result.checked_mul(radix) { - Some(result) => result, - None => return None, - }; - result = match result.checked_add(x) { - Some(result) => result, - None => return None, - }; - } - } else { - for x in xs { - let x = match x { - Some(x) => x, - None => return None, - }; - result = match result.checked_mul(radix) { - Some(result) => result, - None => return None, - }; - result = match result.checked_sub(x) { - Some(result) => result, - None => return None, - }; - } - } + i32_val += 1 as i32; + assert_eq!(i32_val.to_string(), "-2147483648".to_string()); - Some(result) -} + let mut i64_val: i64 = 9_223_372_036_854_775_807_i64; + assert_eq!(i64_val.to_string(), "9223372036854775807".to_string()); -#[cfg(test)] -mod test { - use super::*; - use option::*; - use num::Float; - - #[test] - fn from_str_issue7588() { - let u : Option = from_str_radix_int("1000", 10); - assert_eq!(u, None); - let s : Option = from_str_radix_int("80000", 10); - assert_eq!(s, None); - let f : Option = from_str_radix_float("10000000000000000000000000000000000000000", 10); - assert_eq!(f, Some(Float::infinity())) - let fe : Option = from_str_radix_float("1e40", 10); - assert_eq!(fe, Some(Float::infinity())) - } - - #[test] - fn test_from_str_radix_float() { - let x1 : Option = from_str_radix_float("-123.456", 10); - assert_eq!(x1, Some(-123.456)); - let x2 : Option = from_str_radix_float("123.456", 10); - assert_eq!(x2, Some(123.456)); - let x3 : Option = from_str_radix_float("-0.0", 10); - assert_eq!(x3, Some(-0.0)); - let x4 : Option = from_str_radix_float("0.0", 10); - assert_eq!(x4, Some(0.0)); - let x4 : Option = from_str_radix_float("1.0", 10); - assert_eq!(x4, Some(1.0)); - let x5 : Option = from_str_radix_float("-1.0", 10); - assert_eq!(x5, Some(-1.0)); + i64_val += 1 as i64; + assert_eq!(i64_val.to_string(), "-9223372036854775808".to_string()); } } diff --git a/src/libstd/num/u16.rs b/src/libstd/num/u16.rs index bb619b5b2f595..246224ddb2b4e 100644 --- a/src/libstd/num/u16.rs +++ b/src/libstd/num/u16.rs @@ -13,11 +13,6 @@ #![unstable] #![doc(primitive = "u16")] -use from_str::FromStr; -use num::FromStrRadix; -use num::strconv; -use option::Option; - pub use core::u16::{BITS, BYTES, MIN, MAX}; uint_module!(u16) diff --git a/src/libstd/num/u32.rs b/src/libstd/num/u32.rs index 754103ba5dab2..143b45010c254 100644 --- a/src/libstd/num/u32.rs +++ b/src/libstd/num/u32.rs @@ -13,11 +13,6 @@ #![unstable] #![doc(primitive = "u32")] -use from_str::FromStr; -use num::FromStrRadix; -use num::strconv; -use option::Option; - pub use core::u32::{BITS, BYTES, MIN, MAX}; uint_module!(u32) diff --git a/src/libstd/num/u64.rs b/src/libstd/num/u64.rs index da497d2cbe470..92c5380f980ea 100644 --- a/src/libstd/num/u64.rs +++ b/src/libstd/num/u64.rs @@ -13,11 +13,6 @@ #![unstable] #![doc(primitive = "u64")] -use from_str::FromStr; -use num::FromStrRadix; -use num::strconv; -use option::Option; - pub use core::u64::{BITS, BYTES, MIN, MAX}; uint_module!(u64) diff --git a/src/libstd/num/u8.rs b/src/libstd/num/u8.rs index bdfcdb2c5a5bc..faa6d167065ce 100644 --- a/src/libstd/num/u8.rs +++ b/src/libstd/num/u8.rs @@ -13,11 +13,6 @@ #![unstable] #![doc(primitive = "u8")] -use from_str::FromStr; -use num::FromStrRadix; -use num::strconv; -use option::Option; - pub use core::u8::{BITS, BYTES, MIN, MAX}; uint_module!(u8) diff --git a/src/libstd/num/uint.rs b/src/libstd/num/uint.rs index 5090219d3de65..a425aab3aa10c 100644 --- a/src/libstd/num/uint.rs +++ b/src/libstd/num/uint.rs @@ -13,11 +13,6 @@ #![unstable] #![doc(primitive = "uint")] -use from_str::FromStr; -use num::FromStrRadix; -use num::strconv; -use option::Option; - pub use core::uint::{BITS, BYTES, MIN, MAX}; uint_module!(uint) diff --git a/src/libstd/num/uint_macros.rs b/src/libstd/num/uint_macros.rs index aa8e58bab0286..ef9e809ed2bcc 100644 --- a/src/libstd/num/uint_macros.rs +++ b/src/libstd/num/uint_macros.rs @@ -15,22 +15,6 @@ macro_rules! uint_module (($T:ty) => ( -#[experimental = "might need to return Result"] -impl FromStr for $T { - #[inline] - fn from_str(s: &str) -> Option<$T> { - strconv::from_str_radix_int(s, 10) - } -} - -#[experimental = "might need to return Result"] -impl FromStrRadix for $T { - #[inline] - fn from_str_radix(s: &str, radix: uint) -> Option<$T> { - strconv::from_str_radix_int(s, radix) - } -} - // String conversion functions and impl num -> str /// Convert to a string as a byte slice in a given base. diff --git a/src/libstd/os.rs b/src/libstd/os.rs index 1402d3a355905..23e57a028de27 100644 --- a/src/libstd/os.rs +++ b/src/libstd/os.rs @@ -51,8 +51,7 @@ use result::{Err, Ok, Result}; use slice::{AsSlice, SlicePrelude, PartialEqSlicePrelude}; use slice::CloneSliceAllocPrelude; use str::{Str, StrPrelude, StrAllocating}; -use string::String; -use to_string::ToString; +use string::{String, ToString}; use sync::atomic::{AtomicInt, INIT_ATOMIC_INT, SeqCst}; use vec::Vec; diff --git a/src/libstd/path/posix.rs b/src/libstd/path/posix.rs index 794f6978642cf..e2ff824a7c98f 100644 --- a/src/libstd/path/posix.rs +++ b/src/libstd/path/posix.rs @@ -13,12 +13,11 @@ use c_str::{CString, ToCStr}; use clone::Clone; use cmp::{PartialEq, Eq, PartialOrd, Ord, Ordering}; -use from_str::FromStr; use hash; use io::Writer; use iter::{DoubleEndedIterator, AdditiveIterator, Extend, Iterator, Map}; use option::{Option, None, Some}; -use str::Str; +use str::{FromStr, Str}; use str; use slice::{CloneSliceAllocPrelude, Splits, AsSlice, VectorVector, PartialEqSlicePrelude, SlicePrelude}; diff --git a/src/libstd/path/windows.rs b/src/libstd/path/windows.rs index 2da2159653e9a..b8016e3e8f453 100644 --- a/src/libstd/path/windows.rs +++ b/src/libstd/path/windows.rs @@ -16,14 +16,13 @@ use ascii::AsciiCast; use c_str::{CString, ToCStr}; use clone::Clone; use cmp::{PartialEq, Eq, PartialOrd, Ord, Ordering}; -use from_str::FromStr; use hash; use io::Writer; use iter::{AdditiveIterator, DoubleEndedIterator, Extend, Iterator, Map}; use mem; use option::{Option, Some, None}; use slice::{AsSlice, SlicePrelude}; -use str::{CharSplits, Str, StrAllocating, StrVector, StrPrelude}; +use str::{CharSplits, FromStr, Str, StrAllocating, StrVector, StrPrelude}; use string::String; use unicode::char::UnicodeChar; use vec::Vec; diff --git a/src/libstd/prelude.rs b/src/libstd/prelude.rs index e9793ea65ad90..a9e99940c4689 100644 --- a/src/libstd/prelude.rs +++ b/src/libstd/prelude.rs @@ -50,9 +50,9 @@ #[doc(no_inline)] pub use ops::{Fn, FnMut, FnOnce}; // Reexported functions -#[doc(no_inline)] pub use from_str::from_str; #[doc(no_inline)] pub use iter::{range, repeat}; #[doc(no_inline)] pub use mem::drop; +#[doc(no_inline)] pub use str::from_str; // Reexported types and traits @@ -76,14 +76,13 @@ #[doc(no_inline)] pub use io::{Buffer, Writer, Reader, Seek, BufferPrelude}; #[doc(no_inline)] pub use str::{Str, StrVector, StrPrelude}; #[doc(no_inline)] pub use str::{IntoMaybeOwned, StrAllocating, UnicodeStrPrelude}; -#[doc(no_inline)] pub use to_string::{ToString, IntoStr}; #[doc(no_inline)] pub use tuple::{Tuple1, Tuple2, Tuple3, Tuple4}; #[doc(no_inline)] pub use tuple::{Tuple5, Tuple6, Tuple7, Tuple8}; #[doc(no_inline)] pub use tuple::{Tuple9, Tuple10, Tuple11, Tuple12}; #[doc(no_inline)] pub use slice::{SlicePrelude, AsSlice, CloneSlicePrelude}; #[doc(no_inline)] pub use slice::{VectorVector, PartialEqSlicePrelude, OrdSlicePrelude}; #[doc(no_inline)] pub use slice::{CloneSliceAllocPrelude, OrdSliceAllocPrelude, SliceAllocPrelude}; -#[doc(no_inline)] pub use string::String; +#[doc(no_inline)] pub use string::{IntoString, String, ToString}; #[doc(no_inline)] pub use vec::Vec; // Reexported runtime types diff --git a/src/libstd/rt/backtrace.rs b/src/libstd/rt/backtrace.rs index b08b92b8587b6..8b457d1639dc4 100644 --- a/src/libstd/rt/backtrace.rs +++ b/src/libstd/rt/backtrace.rs @@ -12,13 +12,12 @@ #![allow(non_camel_case_types)] -use from_str::from_str; use io::{IoResult, Writer}; use iter::Iterator; use option::{Some, None}; use os; use result::{Ok, Err}; -use str::StrPrelude; +use str::{StrPrelude, from_str}; use sync::atomic; use unicode::char::UnicodeChar; diff --git a/src/libstd/rt/util.rs b/src/libstd/rt/util.rs index 56f2dbf667a7c..92657d1b59bee 100644 --- a/src/libstd/rt/util.rs +++ b/src/libstd/rt/util.rs @@ -8,12 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use from_str::FromStr; -use from_str::from_str; use libc::uintptr_t; use option::{Some, None, Option}; use os; -use str::Str; +use str::{FromStr, from_str, Str}; use sync::atomic; /// Dynamically inquire about whether we're running under V. diff --git a/src/libstd/sync/task_pool.rs b/src/libstd/sync/task_pool.rs index d4a60fb584457..4ae5cd054f620 100644 --- a/src/libstd/sync/task_pool.rs +++ b/src/libstd/sync/task_pool.rs @@ -1,4 +1,4 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -12,91 +12,195 @@ use core::prelude::*; -use task; use task::spawn; -use vec::Vec; -use comm::{channel, Sender}; +use comm::{channel, Sender, Receiver}; +use sync::{Arc, Mutex}; -enum Msg { - Execute(proc(&T):Send), - Quit +struct Sentinel<'a> { + jobs: &'a Arc>>, + active: bool } -/// A task pool used to execute functions in parallel. -pub struct TaskPool { - channels: Vec>>, - next_index: uint, +impl<'a> Sentinel<'a> { + fn new(jobs: &Arc>>) -> Sentinel { + Sentinel { + jobs: jobs, + active: true + } + } + + // Cancel and destroy this sentinel. + fn cancel(mut self) { + self.active = false; + } } #[unsafe_destructor] -impl Drop for TaskPool { +impl<'a> Drop for Sentinel<'a> { fn drop(&mut self) { - for channel in self.channels.iter_mut() { - channel.send(Quit); + if self.active { + spawn_in_pool(self.jobs.clone()) } } } -impl TaskPool { - /// Spawns a new task pool with `n_tasks` tasks. The provided - /// `init_fn_factory` returns a function which, given the index of the - /// task, should return local data to be kept around in that task. +/// A task pool used to execute functions in parallel. +/// +/// Spawns `n` worker tasks and replenishes the pool if any worker tasks +/// panic. +/// +/// # Example +/// +/// ```rust +/// # use std::sync::TaskPool; +/// # use std::iter::AdditiveIterator; +/// +/// let pool = TaskPool::new(4u); +/// +/// let (tx, rx) = channel(); +/// for _ in range(0, 8u) { +/// let tx = tx.clone(); +/// pool.execute(proc() { +/// tx.send(1u); +/// }); +/// } +/// +/// assert_eq!(rx.iter().take(8u).sum(), 8u); +/// ``` +pub struct TaskPool { + // How the taskpool communicates with subtasks. + // + // This is the only such Sender, so when it is dropped all subtasks will + // quit. + jobs: Sender +} + +impl TaskPool { + /// Spawns a new task pool with `tasks` tasks. /// /// # Panics /// - /// This function will panic if `n_tasks` is less than 1. - pub fn new(n_tasks: uint, - init_fn_factory: || -> proc(uint):Send -> T) - -> TaskPool { - assert!(n_tasks >= 1); - - let channels = Vec::from_fn(n_tasks, |i| { - let (tx, rx) = channel::>(); - let init_fn = init_fn_factory(); - - let task_body = proc() { - let local_data = init_fn(i); - loop { - match rx.recv() { - Execute(f) => f(&local_data), - Quit => break - } - } - }; + /// This function will panic if `tasks` is 0. + pub fn new(tasks: uint) -> TaskPool { + assert!(tasks >= 1); - // Run on this scheduler. - task::spawn(task_body); + let (tx, rx) = channel::(); + let rx = Arc::new(Mutex::new(rx)); - tx - }); + // Taskpool tasks. + for _ in range(0, tasks) { + spawn_in_pool(rx.clone()); + } - return TaskPool { - channels: channels, - next_index: 0, - }; + TaskPool { jobs: tx } } - /// Executes the function `f` on a task in the pool. The function - /// receives a reference to the local data returned by the `init_fn`. - pub fn execute(&mut self, f: proc(&T):Send) { - self.channels[self.next_index].send(Execute(f)); - self.next_index += 1; - if self.next_index == self.channels.len() { self.next_index = 0; } + /// Executes the function `job` on a task in the pool. + pub fn execute(&self, job: proc():Send) { + self.jobs.send(job); } } -#[test] -fn test_task_pool() { - let f: || -> proc(uint):Send -> uint = || { proc(i) i }; - let mut pool = TaskPool::new(4, f); - for _ in range(0u, 8) { - pool.execute(proc(i) println!("Hello from thread {}!", *i)); - } +fn spawn_in_pool(jobs: Arc>>) { + spawn(proc() { + // Will spawn a new task on panic unless it is cancelled. + let sentinel = Sentinel::new(&jobs); + + loop { + let message = { + // Only lock jobs for the time it takes + // to get a job, not run it. + let lock = jobs.lock(); + lock.recv_opt() + }; + + match message { + Ok(job) => job(), + + // The Taskpool was dropped. + Err(..) => break + } + } + + sentinel.cancel(); + }) } -#[test] -#[should_fail] -fn test_zero_tasks_panic() { - let f: || -> proc(uint):Send -> uint = || { proc(i) i }; - TaskPool::new(0, f); +#[cfg(test)] +mod test { + use core::prelude::*; + use super::*; + use comm::channel; + use iter::range; + + const TEST_TASKS: uint = 4u; + + #[test] + fn test_works() { + use iter::AdditiveIterator; + + let pool = TaskPool::new(TEST_TASKS); + + let (tx, rx) = channel(); + for _ in range(0, TEST_TASKS) { + let tx = tx.clone(); + pool.execute(proc() { + tx.send(1u); + }); + } + + assert_eq!(rx.iter().take(TEST_TASKS).sum(), TEST_TASKS); + } + + #[test] + #[should_fail] + fn test_zero_tasks_panic() { + TaskPool::new(0); + } + + #[test] + fn test_recovery_from_subtask_panic() { + use iter::AdditiveIterator; + + let pool = TaskPool::new(TEST_TASKS); + + // Panic all the existing tasks. + for _ in range(0, TEST_TASKS) { + pool.execute(proc() { panic!() }); + } + + // Ensure new tasks were spawned to compensate. + let (tx, rx) = channel(); + for _ in range(0, TEST_TASKS) { + let tx = tx.clone(); + pool.execute(proc() { + tx.send(1u); + }); + } + + assert_eq!(rx.iter().take(TEST_TASKS).sum(), TEST_TASKS); + } + + #[test] + fn test_should_not_panic_on_drop_if_subtasks_panic_after_drop() { + use sync::{Arc, Barrier}; + + let pool = TaskPool::new(TEST_TASKS); + let waiter = Arc::new(Barrier::new(TEST_TASKS + 1)); + + // Panic all the existing tasks in a bit. + for _ in range(0, TEST_TASKS) { + let waiter = waiter.clone(); + pool.execute(proc() { + waiter.wait(); + panic!(); + }); + } + + drop(pool); + + // Kick off the failure. + waiter.wait(); + } } + diff --git a/src/libstd/task.rs b/src/libstd/task.rs index f0bb8a0f4bc4b..c7e31dae3d459 100644 --- a/src/libstd/task.rs +++ b/src/libstd/task.rs @@ -105,9 +105,8 @@ use rt::local::Local; use rt::task; use rt::task::Task; use str::{Str, SendStr, IntoMaybeOwned}; -use string::String; +use string::{String, ToString}; use sync::Future; -use to_string::ToString; /// A means of spawning a task pub trait Spawner { diff --git a/src/libstd/time/duration.rs b/src/libstd/time/duration.rs index 5c4e8bda84c87..83340c9faac22 100644 --- a/src/libstd/time/duration.rs +++ b/src/libstd/time/duration.rs @@ -388,7 +388,7 @@ mod tests { use super::{Duration, MIN, MAX}; use {i32, i64}; use option::{Some, None}; - use to_string::ToString; + use string::ToString; #[test] fn test_duration() { diff --git a/src/libstd/to_string.rs b/src/libstd/to_string.rs deleted file mode 100644 index c19fd81b57056..0000000000000 --- a/src/libstd/to_string.rs +++ /dev/null @@ -1,66 +0,0 @@ -// 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -/*! - -The `ToString` trait for converting to strings - -*/ - -#![experimental] - -use fmt; -use string::String; - -/// A generic trait for converting a value to a string -pub trait ToString { - /// Converts the value of `self` to an owned string - fn to_string(&self) -> String; -} - -/// Trait for converting a type to a string, consuming it in the process. -pub trait IntoStr { - /// Consume and convert to a string. - fn into_string(self) -> String; -} - -impl ToString for T { - fn to_string(&self) -> String { - format!("{}", *self) - } -} - -#[cfg(test)] -mod tests { - use prelude::*; - use super::*; - - #[test] - fn test_simple_types() { - assert_eq!(1i.to_string(), "1".to_string()); - assert_eq!((-1i).to_string(), "-1".to_string()); - assert_eq!(200u.to_string(), "200".to_string()); - assert_eq!(2u8.to_string(), "2".to_string()); - assert_eq!(true.to_string(), "true".to_string()); - assert_eq!(false.to_string(), "false".to_string()); - assert_eq!(().to_string(), "()".to_string()); - assert_eq!(("hi".to_string()).to_string(), "hi".to_string()); - } - - #[test] - fn test_vectors() { - let x: Vec = vec![]; - assert_eq!(x.to_string(), "[]".to_string()); - assert_eq!((vec![1i]).to_string(), "[1]".to_string()); - assert_eq!((vec![1i, 2, 3]).to_string(), "[1, 2, 3]".to_string()); - assert!((vec![vec![], vec![1i], vec![1i, 1]]).to_string() == - "[[], [1], [1, 1]]".to_string()); - } -} diff --git a/src/libsyntax/ext/deriving/encodable.rs b/src/libsyntax/ext/deriving/encodable.rs index 103253560df65..69eb260b8c4cc 100644 --- a/src/libsyntax/ext/deriving/encodable.rs +++ b/src/libsyntax/ext/deriving/encodable.rs @@ -22,19 +22,23 @@ //! would generate two implementations like: //! //! ```ignore -//! impl Encodable for Node { -//! fn encode(&self, s: &S) { -//! s.emit_struct("Node", 1, || { -//! s.emit_field("id", 0, || s.emit_uint(self.id)) +//! impl, E> Encodable for Node { +//! fn encode(&self, s: &mut S) -> Result<(), E> { +//! s.emit_struct("Node", 1, |this| { +//! this.emit_struct_field("id", 0, |this| { +//! Encodable::encode(&self.id, this) +//! /* this.emit_uint(self.id) can also be used */ +//! }) //! }) //! } //! } //! -//! impl Decodable for node_id { -//! fn decode(d: &D) -> Node { -//! d.read_struct("Node", 1, || { -//! Node { -//! id: d.read_field("x".to_string(), 0, || decode(d)) +//! impl, E> Decodable for Node { +//! fn decode(d: &mut D) -> Result { +//! d.read_struct("Node", 1, |this| { +//! match this.read_struct_field("id", 0, |this| Decodable::decode(this)) { +//! Ok(id) => Ok(Node { id: id }), +//! Err(e) => Err(e), //! } //! }) //! } @@ -46,37 +50,42 @@ //! //! ```ignore //! #[deriving(Encodable, Decodable)] -//! struct spanned { node: T, span: Span } +//! struct Spanned { node: T, span: Span } //! ``` //! //! would yield functions like: //! //! ```ignore -//! impl< -//! S: Encoder, -//! T: Encodable -//! > spanned: Encodable { -//! fn encode(s: &S) { -//! s.emit_rec(|| { -//! s.emit_field("node", 0, || self.node.encode(s)); -//! s.emit_field("span", 1, || self.span.encode(s)); -//! }) -//! } +//! impl< +//! S: Encoder, +//! E, +//! T: Encodable +//! > Encodable for Spanned { +//! fn encode(&self, s: &mut S) -> Result<(), E> { +//! s.emit_struct("Spanned", 2, |this| { +//! this.emit_struct_field("node", 0, |this| self.node.encode(this)) +//! .ok().unwrap(); +//! this.emit_struct_field("span", 1, |this| self.span.encode(this)) +//! }) //! } +//! } //! -//! impl< -//! D: Decoder, -//! T: Decodable -//! > spanned: Decodable { -//! fn decode(d: &D) -> spanned { -//! d.read_rec(|| { -//! { -//! node: d.read_field("node".to_string(), 0, || decode(d)), -//! span: d.read_field("span".to_string(), 1, || decode(d)), -//! } +//! impl< +//! D: Decoder, +//! E, +//! T: Decodable +//! > Decodable for Spanned { +//! fn decode(d: &mut D) -> Result, E> { +//! d.read_struct("Spanned", 2, |this| { +//! Ok(Spanned { +//! node: this.read_struct_field("node", 0, |this| Decodable::decode(this)) +//! .ok().unwrap(), +//! span: this.read_struct_field("span", 1, |this| Decodable::decode(this)) +//! .ok().unwrap(), //! }) -//! } +//! }) //! } +//! } //! ``` use ast::{MetaItem, Item, Expr, ExprRet, MutMutable, LitNil}; diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index 986f90389e769..ff96f806faccb 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -53,13 +53,13 @@ use std::cmp; use std::f64; use std::fmt::Show; use std::fmt; -use std::from_str::FromStr; use std::io::fs::PathExtensions; use std::io::stdio::StdWriter; use std::io::{File, ChanReader, ChanWriter}; use std::io; use std::num::{Float, FloatMath, Int}; use std::os; +use std::str::FromStr; use std::string::String; use std::task::TaskBuilder; use std::time::Duration; diff --git a/src/test/run-make/codegen-options-parsing/Makefile b/src/test/run-make/codegen-options-parsing/Makefile new file mode 100644 index 0000000000000..e439b27a19061 --- /dev/null +++ b/src/test/run-make/codegen-options-parsing/Makefile @@ -0,0 +1,24 @@ +-include ../tools.mk + +all: + #Option taking a number + $(RUSTC) -C codegen-units dummy.rs 2>&1 | \ + grep 'codegen option `codegen-units` requires a number' + $(RUSTC) -C codegen-units= dummy.rs 2>&1 | \ + grep 'incorrect value `` for codegen option `codegen-units` - a number was expected' + $(RUSTC) -C codegen-units=foo dummy.rs 2>&1 | \ + grep 'incorrect value `foo` for codegen option `codegen-units` - a number was expected' + $(RUSTC) -C codegen-units=1 dummy.rs + #Option taking a string + $(RUSTC) -C extra-filename dummy.rs 2>&1 | \ + grep 'codegen option `extra-filename` requires a string' + $(RUSTC) -C extra-filename= dummy.rs 2>&1 + $(RUSTC) -C extra-filename=foo dummy.rs 2>&1 + #Option taking no argument + $(RUSTC) -C lto= dummy.rs 2>&1 | \ + grep 'codegen option `lto` takes no value' + $(RUSTC) -C lto=1 dummy.rs 2>&1 | \ + grep 'codegen option `lto` takes no value' + $(RUSTC) -C lto=foo dummy.rs 2>&1 | \ + grep 'codegen option `lto` takes no value' + $(RUSTC) -C lto dummy.rs diff --git a/src/test/run-make/codegen-options-parsing/dummy.rs b/src/test/run-make/codegen-options-parsing/dummy.rs new file mode 100644 index 0000000000000..8ae3d072362ed --- /dev/null +++ b/src/test/run-make/codegen-options-parsing/dummy.rs @@ -0,0 +1,11 @@ +// Copyright 2014 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() {} diff --git a/src/test/run-pass/class-cast-to-trait-cross-crate-2.rs b/src/test/run-pass/class-cast-to-trait-cross-crate-2.rs index cfee1a812311b..a041bbfe8ad92 100644 --- a/src/test/run-pass/class-cast-to-trait-cross-crate-2.rs +++ b/src/test/run-pass/class-cast-to-trait-cross-crate-2.rs @@ -11,7 +11,7 @@ // aux-build:cci_class_cast.rs extern crate cci_class_cast; -use std::to_string::ToString; +use std::string::ToString; use cci_class_cast::kitty::cat; fn print_out(thing: Box, expected: String) { diff --git a/src/test/run-pass/send_str_treemap.rs b/src/test/run-pass/send_str_treemap.rs index c52f9458f99d5..0d88141984750 100644 --- a/src/test/run-pass/send_str_treemap.rs +++ b/src/test/run-pass/send_str_treemap.rs @@ -11,7 +11,7 @@ extern crate collections; use std::str::{SendStr, Owned, Slice}; -use std::to_string::ToString; +use std::string::ToString; use self::collections::TreeMap; use std::option::Some;