diff --git a/src/compiletest/compiletest.rs b/src/compiletest/compiletest.rs index 1c06b2a23d54..8d2558e4344e 100644 --- a/src/compiletest/compiletest.rs +++ b/src/compiletest/compiletest.rs @@ -13,7 +13,6 @@ #![feature(box_syntax)] #![feature(libc)] #![feature(rustc_private)] -#![feature(str_char)] #![feature(test)] #![feature(question_mark)] @@ -412,16 +411,26 @@ fn extract_gdb_version(full_version_line: Option) -> Option { // used to be a regex "(^|[^0-9])([0-9]\.[0-9]+)" for (pos, c) in full_version_line.char_indices() { - if !c.is_digit(10) { continue } - if pos + 2 >= full_version_line.len() { continue } - if full_version_line.char_at(pos + 1) != '.' { continue } - if !full_version_line.char_at(pos + 2).is_digit(10) { continue } - if pos > 0 && full_version_line.char_at_reverse(pos).is_digit(10) { + if !c.is_digit(10) { + continue + } + if pos + 2 >= full_version_line.len() { + continue + } + if full_version_line[pos + 1..].chars().next().unwrap() != '.' { + continue + } + if !full_version_line[pos + 2..].chars().next().unwrap().is_digit(10) { + continue + } + if pos > 0 && full_version_line[..pos].chars().next_back() + .unwrap().is_digit(10) { continue } let mut end = pos + 3; while end < full_version_line.len() && - full_version_line.char_at(end).is_digit(10) { + full_version_line[end..].chars().next() + .unwrap().is_digit(10) { end += 1; } return Some(full_version_line[pos..end].to_owned()); @@ -453,13 +462,13 @@ fn extract_lldb_version(full_version_line: Option) -> Option { for (pos, l) in full_version_line.char_indices() { if l != 'l' && l != 'L' { continue } if pos + 5 >= full_version_line.len() { continue } - let l = full_version_line.char_at(pos + 1); + let l = full_version_line[pos + 1..].chars().next().unwrap(); if l != 'l' && l != 'L' { continue } - let d = full_version_line.char_at(pos + 2); + let d = full_version_line[pos + 2..].chars().next().unwrap(); if d != 'd' && d != 'D' { continue } - let b = full_version_line.char_at(pos + 3); + let b = full_version_line[pos + 3..].chars().next().unwrap(); if b != 'b' && b != 'B' { continue } - let dash = full_version_line.char_at(pos + 4); + let dash = full_version_line[pos + 4..].chars().next().unwrap(); if dash != '-' { continue } let vers = full_version_line[pos + 5..].chars().take_while(|c| { diff --git a/src/compiletest/errors.rs b/src/compiletest/errors.rs index 7ad0cd2a95d4..418a0bc7121c 100644 --- a/src/compiletest/errors.rs +++ b/src/compiletest/errors.rs @@ -115,7 +115,7 @@ fn parse_expected(last_nonfollow_error: Option, tag: &str) -> Option<(WhichLine, ExpectedError)> { let start = match line.find(tag) { Some(i) => i, None => return None }; - let (follow, adjusts) = if line.char_at(start + tag.len()) == '|' { + let (follow, adjusts) = if line[start + tag.len()..].chars().next().unwrap() == '|' { (true, 0) } else { (false, line[start + tag.len()..].chars().take_while(|c| *c == '^').count()) diff --git a/src/compiletest/runtest.rs b/src/compiletest/runtest.rs index 994f45da1462..6773c34c7d76 100644 --- a/src/compiletest/runtest.rs +++ b/src/compiletest/runtest.rs @@ -1177,7 +1177,7 @@ fn scan_char(haystack: &str, needle: char, idx: &mut usize) -> bool { if *idx >= haystack.len() { return false; } - let ch = haystack.char_at(*idx); + let ch = haystack[*idx..].chars().next().unwrap(); if ch != needle { return false; } @@ -1188,7 +1188,7 @@ fn scan_char(haystack: &str, needle: char, idx: &mut usize) -> bool { fn scan_integer(haystack: &str, idx: &mut usize) -> bool { let mut i = *idx; while i < haystack.len() { - let ch = haystack.char_at(i); + let ch = haystack[i..].chars().next().unwrap(); if ch < '0' || '9' < ch { break; } @@ -1208,7 +1208,7 @@ fn scan_string(haystack: &str, needle: &str, idx: &mut usize) -> bool { if haystack_i >= haystack.len() { return false; } - let ch = haystack.char_at(haystack_i); + let ch = haystack[haystack_i..].chars().next().unwrap(); haystack_i += ch.len_utf8(); if !scan_char(needle, ch, &mut needle_i) { return false; diff --git a/src/libcollections/btree/set.rs b/src/libcollections/btree/set.rs index 23e0af8113bf..e679381f223f 100644 --- a/src/libcollections/btree/set.rs +++ b/src/libcollections/btree/set.rs @@ -379,7 +379,7 @@ impl BTreeSet { /// The value may be any borrowed form of the set's value type, /// but the ordering on the borrowed form *must* match the /// ordering on the value type. - #[unstable(feature = "set_recovery", issue = "28050")] + #[stable(feature = "set_recovery", since = "1.9.0")] pub fn get(&self, value: &Q) -> Option<&T> where T: Borrow, Q: Ord @@ -502,7 +502,7 @@ impl BTreeSet { /// Adds a value to the set, replacing the existing value, if any, that is equal to the given /// one. Returns the replaced value. - #[unstable(feature = "set_recovery", issue = "28050")] + #[stable(feature = "set_recovery", since = "1.9.0")] pub fn replace(&mut self, value: T) -> Option { Recover::replace(&mut self.map, value) } @@ -538,7 +538,7 @@ impl BTreeSet { /// The value may be any borrowed form of the set's value type, /// but the ordering on the borrowed form *must* match the /// ordering on the value type. - #[unstable(feature = "set_recovery", issue = "28050")] + #[stable(feature = "set_recovery", since = "1.9.0")] pub fn take(&mut self, value: &Q) -> Option where T: Borrow, Q: Ord diff --git a/src/libcollections/lib.rs b/src/libcollections/lib.rs index 8e62b389a6e3..7540c51e236d 100644 --- a/src/libcollections/lib.rs +++ b/src/libcollections/lib.rs @@ -27,7 +27,6 @@ test(no_crate_inject, attr(allow(unused_variables), deny(warnings))))] #![cfg_attr(test, allow(deprecated))] // rand -#![cfg_attr(not(test), feature(copy_from_slice))] // impl [T] #![cfg_attr(not(stage0), deny(warnings))] #![feature(alloc)] @@ -35,7 +34,6 @@ #![feature(box_patterns)] #![feature(box_syntax)] #![feature(core_intrinsics)] -#![feature(decode_utf16)] #![feature(dropck_parametricity)] #![feature(fmt_internals)] #![feature(heap_api)] diff --git a/src/libcollections/slice.rs b/src/libcollections/slice.rs index 8fa594c967cf..db91d911c735 100644 --- a/src/libcollections/slice.rs +++ b/src/libcollections/slice.rs @@ -845,14 +845,13 @@ impl [T] { /// # Example /// /// ```rust - /// #![feature(copy_from_slice)] /// let mut dst = [0, 0, 0]; /// let src = [1, 2, 3]; /// /// dst.copy_from_slice(&src); /// assert_eq!(src, dst); /// ``` - #[unstable(feature = "copy_from_slice", issue = "31755")] + #[stable(feature = "copy_from_slice", since = "1.9.0")] pub fn copy_from_slice(&mut self, src: &[T]) where T: Copy { core_slice::SliceExt::copy_from_slice(self, src) } diff --git a/src/libcollections/str.rs b/src/libcollections/str.rs index 9798e323a614..b2b1e019a1b8 100644 --- a/src/libcollections/str.rs +++ b/src/libcollections/str.rs @@ -228,8 +228,6 @@ impl str { /// # Examples /// /// ``` - /// #![feature(str_char)] - /// /// let s = "Löwe 老虎 Léopard"; /// assert!(s.is_char_boundary(0)); /// // start of `老` @@ -242,12 +240,7 @@ impl str { /// // third byte of `老` /// assert!(!s.is_char_boundary(8)); /// ``` - #[unstable(feature = "str_char", - reason = "it is unclear whether this method pulls its weight \ - with the existence of the char_indices iterator or \ - this method may want to be replaced with checked \ - slicing", - issue = "27754")] + #[stable(feature = "is_char_boundary", since = "1.9.0")] #[inline] pub fn is_char_boundary(&self, index: usize) -> bool { core_str::StrExt::is_char_boundary(self, index) @@ -374,6 +367,7 @@ impl str { /// /// ``` /// #![feature(str_char)] + /// #![allow(deprecated)] /// /// use std::str::CharRange; /// @@ -408,6 +402,9 @@ impl str { removed altogether", issue = "27754")] #[inline] + #[rustc_deprecated(reason = "use slicing plus chars() plus len_utf8", + since = "1.9.0")] + #[allow(deprecated)] pub fn char_range_at(&self, start: usize) -> CharRange { core_str::StrExt::char_range_at(self, start) } @@ -432,6 +429,7 @@ impl str { /// /// ``` /// #![feature(str_char)] + /// #![allow(deprecated)] /// /// use std::str::CharRange; /// @@ -466,6 +464,9 @@ impl str { eventually removed altogether", issue = "27754")] #[inline] + #[rustc_deprecated(reason = "use slicing plus chars().rev() plus len_utf8", + since = "1.9.0")] + #[allow(deprecated)] pub fn char_range_at_reverse(&self, start: usize) -> CharRange { core_str::StrExt::char_range_at_reverse(self, start) } @@ -481,6 +482,7 @@ impl str { /// /// ``` /// #![feature(str_char)] + /// #![allow(deprecated)] /// /// let s = "abπc"; /// assert_eq!(s.char_at(1), 'b'); @@ -495,6 +497,9 @@ impl str { subslice", issue = "27754")] #[inline] + #[allow(deprecated)] + #[rustc_deprecated(reason = "use slicing plus chars()", + since = "1.9.0")] pub fn char_at(&self, i: usize) -> char { core_str::StrExt::char_at(self, i) } @@ -511,6 +516,7 @@ impl str { /// /// ``` /// #![feature(str_char)] + /// #![allow(deprecated)] /// /// let s = "abπc"; /// assert_eq!(s.char_at_reverse(1), 'a'); @@ -523,6 +529,9 @@ impl str { cases generate panics", issue = "27754")] #[inline] + #[rustc_deprecated(reason = "use slicing plus chars().rev()", + since = "1.9.0")] + #[allow(deprecated)] pub fn char_at_reverse(&self, i: usize) -> char { core_str::StrExt::char_at_reverse(self, i) } @@ -541,6 +550,7 @@ impl str { /// /// ``` /// #![feature(str_char)] + /// #![allow(deprecated)] /// /// let s = "Łódź"; // \u{141}o\u{301}dz\u{301} /// let (c, s1) = s.slice_shift_char().unwrap(); @@ -559,6 +569,9 @@ impl str { and/or char_indices iterators", issue = "27754")] #[inline] + #[rustc_deprecated(reason = "use chars() plus Chars::as_str", + since = "1.9.0")] + #[allow(deprecated)] pub fn slice_shift_char(&self) -> Option<(char, &str)> { core_str::StrExt::slice_shift_char(self) } diff --git a/src/libcollections/string.rs b/src/libcollections/string.rs index c84d84959dbc..2226116585fc 100644 --- a/src/libcollections/string.rs +++ b/src/libcollections/string.rs @@ -1037,14 +1037,13 @@ impl String { #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn pop(&mut self) -> Option { - let len = self.len(); - if len == 0 { - return None; - } - - let ch = self.char_at_reverse(len); + let ch = match self.chars().rev().next() { + Some(ch) => ch, + None => return None, + }; + let newlen = self.len() - ch.len_utf8(); unsafe { - self.vec.set_len(len - ch.len_utf8()); + self.vec.set_len(newlen); } Some(ch) } @@ -1075,11 +1074,13 @@ impl String { #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn remove(&mut self, idx: usize) -> char { - let len = self.len(); - assert!(idx < len); + let ch = match self[idx..].chars().next() { + Some(ch) => ch, + None => panic!("cannot remove a char from the end of a string"), + }; - let ch = self.char_at(idx); let next = idx + ch.len_utf8(); + let len = self.len(); unsafe { ptr::copy(self.vec.as_ptr().offset(next as isize), self.vec.as_mut_ptr().offset(idx as isize), diff --git a/src/libcollectionstest/lib.rs b/src/libcollectionstest/lib.rs index 045ac1ce977f..211942f2294e 100644 --- a/src/libcollectionstest/lib.rs +++ b/src/libcollectionstest/lib.rs @@ -10,13 +10,11 @@ #![deny(warnings)] -#![feature(ascii)] #![feature(binary_heap_extras)] #![feature(box_syntax)] #![feature(btree_range)] #![feature(collections)] #![feature(collections_bound)] -#![feature(copy_from_slice)] #![feature(const_fn)] #![feature(fn_traits)] #![feature(enumset)] @@ -25,7 +23,6 @@ #![feature(map_values_mut)] #![feature(pattern)] #![feature(rand)] -#![feature(set_recovery)] #![feature(step_by)] #![feature(str_char)] #![feature(str_escape)] diff --git a/src/libcollectionstest/str.rs b/src/libcollectionstest/str.rs index 1150035eb425..929ac7a52ab2 100644 --- a/src/libcollectionstest/str.rs +++ b/src/libcollectionstest/str.rs @@ -464,12 +464,14 @@ fn test_is_whitespace() { } #[test] +#[allow(deprecated)] fn test_slice_shift_char() { let data = "ประเทศไทย中"; assert_eq!(data.slice_shift_char(), Some(('ป', "ระเทศไทย中"))); } #[test] +#[allow(deprecated)] fn test_slice_shift_char_2() { let empty = ""; assert_eq!(empty.slice_shift_char(), None); @@ -657,6 +659,7 @@ fn test_contains_char() { } #[test] +#[allow(deprecated)] fn test_char_at() { let s = "ศไทย中华Việt Nam"; let v = vec!['ศ','ไ','ท','ย','中','华','V','i','ệ','t',' ','N','a','m']; @@ -668,6 +671,7 @@ fn test_char_at() { } #[test] +#[allow(deprecated)] fn test_char_at_reverse() { let s = "ศไทย中华Việt Nam"; let v = vec!['ศ','ไ','ท','ย','中','华','V','i','ệ','t',' ','N','a','m']; @@ -745,6 +749,7 @@ fn test_total_ord() { } #[test] +#[allow(deprecated)] fn test_char_range_at() { let data = "b¢€𤭢𤭢€¢b"; assert_eq!('b', data.char_range_at(0).ch); @@ -758,6 +763,7 @@ fn test_char_range_at() { } #[test] +#[allow(deprecated)] fn test_char_range_at_reverse_underflow() { assert_eq!("abc".char_range_at_reverse(0).next, 0); } diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index 42aef3ab3dd7..a6b5355d9478 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -166,9 +166,16 @@ pub unsafe fn write(dst: *mut T, src: T) { /// /// Volatile operations are intended to act on I/O memory, and are guaranteed /// to not be elided or reordered by the compiler across other volatile -/// operations. See the LLVM documentation on [[volatile]]. +/// operations. /// -/// [volatile]: http://llvm.org/docs/LangRef.html#volatile-memory-accesses +/// # Notes +/// +/// Rust does not currently have a rigorously and formally defined memory model, +/// so the precise semantics of what "volatile" means here is subject to change +/// over time. That being said, the semantics will almost always end up pretty +/// similar to [C11's definition of volatile][c11]. +/// +/// [c11]: http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf /// /// # Safety /// @@ -179,7 +186,7 @@ pub unsafe fn write(dst: *mut T, src: T) { /// `zero_memory`, or `copy_memory`). Note that `*src = foo` counts as a use /// because it will attempt to drop the value previously at `*src`. #[inline] -#[unstable(feature = "volatile", reason = "recently added", issue = "31756")] +#[stable(feature = "volatile", since = "1.9.0")] pub unsafe fn read_volatile(src: *const T) -> T { intrinsics::volatile_load(src) } @@ -189,9 +196,16 @@ pub unsafe fn read_volatile(src: *const T) -> T { /// /// Volatile operations are intended to act on I/O memory, and are guaranteed /// to not be elided or reordered by the compiler across other volatile -/// operations. See the LLVM documentation on [[volatile]]. +/// operations. +/// +/// # Notes /// -/// [volatile]: http://llvm.org/docs/LangRef.html#volatile-memory-accesses +/// Rust does not currently have a rigorously and formally defined memory model, +/// so the precise semantics of what "volatile" means here is subject to change +/// over time. That being said, the semantics will almost always end up pretty +/// similar to [C11's definition of volatile][c11]. +/// +/// [c11]: http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf /// /// # Safety /// @@ -204,7 +218,7 @@ pub unsafe fn read_volatile(src: *const T) -> T { /// This is appropriate for initializing uninitialized memory, or overwriting /// memory that has previously been `read` from. #[inline] -#[unstable(feature = "volatile", reason = "recently added", issue = "31756")] +#[stable(feature = "volatile", since = "1.9.0")] pub unsafe fn write_volatile(dst: *mut T, src: T) { intrinsics::volatile_store(dst, src); } @@ -238,6 +252,9 @@ impl *const T { /// operation because the returned value could be pointing to invalid /// memory. /// + /// Additionally, the lifetime `'a` returned is arbitrarily chosen and does + /// not necessarily reflect the actual lifetime of the data. + /// /// # Examples /// /// Basic usage: @@ -251,17 +268,13 @@ impl *const T { /// } /// } /// ``` - #[unstable(feature = "ptr_as_ref", - reason = "Option is not clearly the right return type, and we \ - may want to tie the return lifetime to a borrow of \ - the raw pointer", - issue = "27780")] + #[stable(feature = "ptr_as_ref", since = "1.9.0")] #[inline] - pub unsafe fn as_ref<'a>(&self) -> Option<&'a T> where T: Sized { + pub unsafe fn as_ref<'a>(self) -> Option<&'a T> where T: Sized { if self.is_null() { None } else { - Some(&**self) + Some(&*self) } } @@ -324,6 +337,9 @@ impl *mut T { /// operation because the returned value could be pointing to invalid /// memory. /// + /// Additionally, the lifetime `'a` returned is arbitrarily chosen and does + /// not necessarily reflect the actual lifetime of the data. + /// /// # Examples /// /// Basic usage: @@ -337,17 +353,13 @@ impl *mut T { /// } /// } /// ``` - #[unstable(feature = "ptr_as_ref", - reason = "Option is not clearly the right return type, and we \ - may want to tie the return lifetime to a borrow of \ - the raw pointer", - issue = "27780")] + #[stable(feature = "ptr_as_ref", since = "1.9.0")] #[inline] - pub unsafe fn as_ref<'a>(&self) -> Option<&'a T> where T: Sized { + pub unsafe fn as_ref<'a>(self) -> Option<&'a T> where T: Sized { if self.is_null() { None } else { - Some(&**self) + Some(&*self) } } @@ -385,7 +397,8 @@ impl *mut T { /// # Safety /// /// As with `as_ref`, this is unsafe because it cannot verify the validity - /// of the returned pointer. + /// of the returned pointer, nor can it ensure that the lifetime `'a` + /// returned is indeed a valid lifetime for the contained data. /// /// # Examples /// @@ -395,16 +408,13 @@ impl *mut T { /// let mut s = [1, 2, 3]; /// let ptr: *mut u32 = s.as_mut_ptr(); /// ``` - #[unstable(feature = "ptr_as_ref", - reason = "return value does not necessarily convey all possible \ - information", - issue = "27780")] + #[stable(feature = "ptr_as_ref", since = "1.9.0")] #[inline] - pub unsafe fn as_mut<'a>(&self) -> Option<&'a mut T> where T: Sized { + pub unsafe fn as_mut<'a>(self) -> Option<&'a mut T> where T: Sized { if self.is_null() { None } else { - Some(&mut **self) + Some(&mut *self) } } } diff --git a/src/libcore/raw.rs b/src/libcore/raw.rs index 20c85b5efc11..19226d81f168 100644 --- a/src/libcore/raw.rs +++ b/src/libcore/raw.rs @@ -60,12 +60,17 @@ use mem; /// ``` #[repr(C)] #[allow(missing_debug_implementations)] +#[rustc_deprecated(reason = "use raw accessors/constructors in `slice` module", + since = "1.9.0")] +#[unstable(feature = "raw", issue = "27751")] pub struct Slice { pub data: *const T, pub len: usize, } +#[allow(deprecated)] impl Copy for Slice {} +#[allow(deprecated)] impl Clone for Slice { fn clone(&self) -> Slice { *self } } @@ -152,6 +157,9 @@ pub struct TraitObject { /// This trait is meant to map equivalences between raw structs and their /// corresponding rust values. +#[rustc_deprecated(reason = "use raw accessors/constructors in `slice` module", + since = "1.9.0")] +#[unstable(feature = "raw", issue = "27751")] pub unsafe trait Repr { /// This function "unwraps" a rust value (without consuming it) into its raw /// struct representation. This can be used to read/write different values @@ -161,5 +169,7 @@ pub unsafe trait Repr { fn repr(&self) -> T { unsafe { mem::transmute_copy(&self) } } } +#[allow(deprecated)] unsafe impl Repr> for [T] {} +#[allow(deprecated)] unsafe impl Repr> for str {} diff --git a/src/libcore/slice.rs b/src/libcore/slice.rs index f21af7d917e2..2e91238bff3c 100644 --- a/src/libcore/slice.rs +++ b/src/libcore/slice.rs @@ -50,10 +50,12 @@ use result::Result::{Ok, Err}; use ptr; use mem; use marker::{Copy, Send, Sync, self}; -use raw::Repr; -// Avoid conflicts with *both* the Slice trait (buggy) and the `slice::raw` module. -use raw::Slice as RawSlice; +#[repr(C)] +struct Repr { + pub data: *const T, + pub len: usize, +} // // Extension traits @@ -152,8 +154,8 @@ pub trait SliceExt { fn ends_with(&self, needle: &[Self::Item]) -> bool where Self::Item: PartialEq; #[stable(feature = "clone_from_slice", since = "1.7.0")] - fn clone_from_slice(&mut self, &[Self::Item]) where Self::Item: Clone; - #[unstable(feature = "copy_from_slice", issue = "31755")] + fn clone_from_slice(&mut self, src: &[Self::Item]) where Self::Item: Clone; + #[stable(feature = "copy_from_slice", since = "1.9.0")] fn copy_from_slice(&mut self, src: &[Self::Item]) where Self::Item: Copy; } @@ -317,7 +319,11 @@ impl SliceExt for [T] { } #[inline] - fn len(&self) -> usize { self.repr().len } + fn len(&self) -> usize { + unsafe { + mem::transmute::<&[T], Repr>(self).len + } + } #[inline] fn get_mut(&mut self, index: usize) -> Option<&mut T> { @@ -1695,7 +1701,7 @@ impl<'a, T> ExactSizeIterator for ChunksMut<'a, T> {} #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub unsafe fn from_raw_parts<'a, T>(p: *const T, len: usize) -> &'a [T] { - mem::transmute(RawSlice { data: p, len: len }) + mem::transmute(Repr { data: p, len: len }) } /// Performs the same functionality as `from_raw_parts`, except that a mutable @@ -1707,7 +1713,7 @@ pub unsafe fn from_raw_parts<'a, T>(p: *const T, len: usize) -> &'a [T] { #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub unsafe fn from_raw_parts_mut<'a, T>(p: *mut T, len: usize) -> &'a mut [T] { - mem::transmute(RawSlice { data: p, len: len }) + mem::transmute(Repr { data: p, len: len }) } // diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index f1be10da8724..f3c31d59fc46 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -29,7 +29,6 @@ use marker::Sized; use mem; use ops::{Fn, FnMut, FnOnce}; use option::Option::{self, None, Some}; -use raw::{Repr, Slice}; use result::Result::{self, Ok, Err}; use slice::{self, SliceExt}; @@ -1664,24 +1663,23 @@ pub trait StrExt { #[stable(feature = "core", since = "1.6.0")] fn trim_right_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str where P::Searcher: ReverseSearcher<'a>; - #[unstable(feature = "str_char", - reason = "it is unclear whether this method pulls its weight \ - with the existence of the char_indices iterator or \ - this method may want to be replaced with checked \ - slicing", - issue = "27754")] + #[stable(feature = "is_char_boundary", since = "1.9.0")] fn is_char_boundary(&self, index: usize) -> bool; #[unstable(feature = "str_char", reason = "often replaced by char_indices, this method may \ be removed in favor of just char_at() or eventually \ removed altogether", issue = "27754")] + #[rustc_deprecated(reason = "use slicing plus chars() plus len_utf8", + since = "1.9.0")] fn char_range_at(&self, start: usize) -> CharRange; #[unstable(feature = "str_char", reason = "often replaced by char_indices, this method may \ be removed in favor of just char_at_reverse() or \ eventually removed altogether", issue = "27754")] + #[rustc_deprecated(reason = "use slicing plus chars().rev() plus len_utf8", + since = "1.9.0")] fn char_range_at_reverse(&self, start: usize) -> CharRange; #[unstable(feature = "str_char", reason = "frequently replaced by the chars() iterator, this \ @@ -1690,12 +1688,16 @@ pub trait StrExt { iterators or by getting the first char from a \ subslice", issue = "27754")] + #[rustc_deprecated(reason = "use slicing plus chars()", + since = "1.9.0")] fn char_at(&self, i: usize) -> char; #[unstable(feature = "str_char", reason = "see char_at for more details, but reverse semantics \ are also somewhat unclear, especially with which \ cases generate panics", issue = "27754")] + #[rustc_deprecated(reason = "use slicing plus chars().rev()", + since = "1.9.0")] fn char_at_reverse(&self, i: usize) -> char; #[stable(feature = "core", since = "1.6.0")] fn as_bytes(&self) -> &[u8]; @@ -1714,6 +1716,8 @@ pub trait StrExt { may not be warranted with the existence of the chars \ and/or char_indices iterators", issue = "27754")] + #[rustc_deprecated(reason = "use chars() plus Chars::as_str", + since = "1.9.0")] fn slice_shift_char(&self) -> Option<(char, &str)>; #[stable(feature = "core", since = "1.6.0")] fn as_ptr(&self) -> *const u8; @@ -1857,18 +1861,16 @@ impl StrExt for str { #[inline] unsafe fn slice_unchecked(&self, begin: usize, end: usize) -> &str { - mem::transmute(Slice { - data: self.as_ptr().offset(begin as isize), - len: end - begin, - }) + let ptr = self.as_ptr().offset(begin as isize); + let len = end - begin; + from_utf8_unchecked(slice::from_raw_parts(ptr, len)) } #[inline] unsafe fn slice_mut_unchecked(&mut self, begin: usize, end: usize) -> &mut str { - mem::transmute(Slice { - data: self.as_ptr().offset(begin as isize), - len: end - begin, - }) + let ptr = self.as_ptr().offset(begin as isize); + let len = end - begin; + mem::transmute(slice::from_raw_parts_mut(ptr as *mut u8, len)) } #[inline] @@ -1983,11 +1985,13 @@ impl StrExt for str { } #[inline] + #[allow(deprecated)] fn char_at(&self, i: usize) -> char { self.char_range_at(i).ch } #[inline] + #[allow(deprecated)] fn char_at_reverse(&self, i: usize) -> char { self.char_range_at_reverse(i).ch } @@ -2039,6 +2043,7 @@ impl StrExt for str { } #[inline] + #[allow(deprecated)] fn slice_shift_char(&self) -> Option<(char, &str)> { if self.is_empty() { None @@ -2055,7 +2060,9 @@ impl StrExt for str { } #[inline] - fn len(&self) -> usize { self.repr().len } + fn len(&self) -> usize { + self.as_bytes().len() + } #[inline] fn is_empty(&self) -> bool { self.len() == 0 } diff --git a/src/libcoretest/char.rs b/src/libcoretest/char.rs index ba8918fc6cb4..41fd742c9e01 100644 --- a/src/libcoretest/char.rs +++ b/src/libcoretest/char.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::char; + #[test] fn test_is_lowercase() { assert!('a'.is_lowercase()); @@ -213,7 +215,10 @@ fn test_len_utf16() { #[test] fn test_decode_utf16() { fn check(s: &[u16], expected: &[Result]) { - assert_eq!(::std::char::decode_utf16(s.iter().cloned()).collect::>(), expected); + let v = char::decode_utf16(s.iter().cloned()) + .map(|r| r.map_err(|e| e.unpaired_surrogate())) + .collect::>(); + assert_eq!(v, expected); } check(&[0xD800, 0x41, 0x42], &[Err(0xD800), Ok('A'), Ok('B')]); check(&[0xD800, 0], &[Err(0xD800), Ok('\0')]); diff --git a/src/libcoretest/lib.rs b/src/libcoretest/lib.rs index 506f9e9b7a57..aa7ab4b4e3f8 100644 --- a/src/libcoretest/lib.rs +++ b/src/libcoretest/lib.rs @@ -15,12 +15,10 @@ #![feature(box_syntax)] #![feature(cell_extras)] #![feature(const_fn)] -#![feature(copy_from_slice)] #![feature(core_float)] #![feature(core_private_bignum)] #![feature(core_private_diy_float)] #![feature(dec2flt)] -#![feature(decode_utf16)] #![feature(fixed_size_array)] #![feature(float_extras)] #![feature(flt2dec)] @@ -28,7 +26,6 @@ #![feature(libc)] #![feature(nonzero)] #![feature(peekable_is_empty)] -#![feature(ptr_as_ref)] #![feature(rand)] #![feature(raw)] #![feature(slice_patterns)] diff --git a/src/libgetopts/lib.rs b/src/libgetopts/lib.rs index 884f4490d9f4..eda20699755a 100644 --- a/src/libgetopts/lib.rs +++ b/src/libgetopts/lib.rs @@ -91,7 +91,6 @@ #![deny(missing_docs)] #![feature(staged_api)] -#![feature(str_char)] use self::Name::*; use self::HasArg::*; @@ -223,7 +222,7 @@ pub type Result = result::Result; impl Name { fn from_str(nm: &str) -> Name { if nm.len() == 1 { - Short(nm.char_at(0)) + Short(nm.chars().next().unwrap()) } else { Long(nm.to_owned()) } @@ -261,7 +260,7 @@ impl OptGroup { } (1, 0) => { Opt { - name: Short(short_name.char_at(0)), + name: Short(short_name.chars().next().unwrap()), hasarg: hasarg, occur: occur, aliases: Vec::new(), @@ -273,7 +272,7 @@ impl OptGroup { hasarg: hasarg, occur: occur, aliases: vec![Opt { - name: Short(short_name.char_at(0)), + name: Short(short_name.chars().next().unwrap()), hasarg: hasarg, occur: occur, aliases: Vec::new(), @@ -599,7 +598,7 @@ pub fn getopts(args: &[String], optgrps: &[OptGroup]) -> Result { let mut j = 1; names = Vec::new(); while j < curlen { - let ch = cur.char_at(j); + let ch = cur[j..].chars().next().unwrap(); let opt = Short(ch); // In a series of potential options (eg. -aheJ), if we diff --git a/src/librbml/lib.rs b/src/librbml/lib.rs index ef89b5d25b88..4edbeab5dfb1 100644 --- a/src/librbml/lib.rs +++ b/src/librbml/lib.rs @@ -122,7 +122,6 @@ test(attr(deny(warnings))))] #![cfg_attr(not(stage0), deny(warnings))] -#![feature(copy_from_slice)] #![feature(rustc_private)] #![feature(staged_api)] #![feature(question_mark)] diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs index 7affb129313c..e9ed0ed574ea 100644 --- a/src/librustc/hir/print.rs +++ b/src/librustc/hir/print.rs @@ -1494,11 +1494,14 @@ impl<'a> State<'a> { let mut out_idx = 0; self.commasep(Inconsistent, &a.outputs, |s, out| { - match out.constraint.slice_shift_char() { - Some(('=', operand)) if out.is_rw => { - s.print_string(&format!("+{}", operand), ast::StrStyle::Cooked)? + let mut ch = out.constraint.chars(); + match ch.next() { + Some('=') if out.is_rw => { + s.print_string(&format!("+{}", ch.as_str()), + ast::StrStyle::Cooked)? } - _ => s.print_string(&out.constraint, ast::StrStyle::Cooked)?, + _ => s.print_string(&out.constraint, + ast::StrStyle::Cooked)?, } s.popen()?; s.print_expr(&outputs[out_idx])?; diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index deb206277722..d1bbbf08ac23 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -28,7 +28,6 @@ #![feature(box_syntax)] #![feature(collections)] #![feature(const_fn)] -#![feature(copy_from_slice)] #![feature(enumset)] #![feature(iter_arith)] #![feature(libc)] @@ -39,7 +38,6 @@ #![feature(slice_patterns)] #![feature(staged_api)] #![feature(step_by)] -#![feature(str_char)] #![feature(question_mark)] #![cfg_attr(test, feature(test))] diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index d3005ff2ded2..815e60a8e034 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -351,11 +351,11 @@ fn split_msg_into_multilines(msg: &str) -> Option { return None } let first = msg.match_indices("expected").filter(|s| { - s.0 > 0 && (msg.char_at_reverse(s.0) == ' ' || - msg.char_at_reverse(s.0) == '(') + let last = msg[..s.0].chars().rev().next(); + last == Some(' ') || last == Some('(') }).map(|(a, b)| (a - 1, a + b.len())); let second = msg.match_indices("found").filter(|s| { - msg.char_at_reverse(s.0) == ' ' + msg[..s.0].chars().rev().next() == Some(' ') }).map(|(a, b)| (a - 1, a + b.len())); let mut new_msg = String::new(); diff --git a/src/librustc_back/lib.rs b/src/librustc_back/lib.rs index 25edaf4b8e4e..67b11a930d6f 100644 --- a/src/librustc_back/lib.rs +++ b/src/librustc_back/lib.rs @@ -32,7 +32,6 @@ #![feature(box_syntax)] #![feature(const_fn)] -#![feature(copy_from_slice)] #![feature(libc)] #![feature(rand)] #![feature(rustc_private)] diff --git a/src/librustc_lint/bad_style.rs b/src/librustc_lint/bad_style.rs index d10691d12ed9..f4fb226d3525 100644 --- a/src/librustc_lint/bad_style.rs +++ b/src/librustc_lint/bad_style.rs @@ -63,7 +63,9 @@ impl NonCamelCaseTypes { // start with a non-lowercase letter rather than non-uppercase // ones (some scripts don't have a concept of upper/lowercase) - !name.is_empty() && !name.char_at(0).is_lowercase() && !name.contains('_') + !name.is_empty() && + !name.chars().next().unwrap().is_lowercase() && + !name.contains('_') } fn to_camel_case(s: &str) -> String { diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs index 2075bd5edcae..e7c9097a56a5 100644 --- a/src/librustc_lint/lib.rs +++ b/src/librustc_lint/lib.rs @@ -36,7 +36,6 @@ #![feature(rustc_private)] #![feature(slice_patterns)] #![feature(staged_api)] -#![feature(str_char)] #[macro_use] extern crate syntax; diff --git a/src/librustc_unicode/char.rs b/src/librustc_unicode/char.rs index 4d8021138a0d..863cada5b880 100644 --- a/src/librustc_unicode/char.rs +++ b/src/librustc_unicode/char.rs @@ -29,8 +29,7 @@ #![stable(feature = "rust1", since = "1.0.0")] use core::char::CharExt as C; -use core::option::Option::{self, Some, None}; -use core::iter::Iterator; +use core::fmt; use tables::{derived_property, property, general_category, conversions}; // stable reexports @@ -739,7 +738,7 @@ impl char { } /// An iterator that decodes UTF-16 encoded code points from an iterator of `u16`s. -#[unstable(feature = "decode_utf16", reason = "recently exposed", issue = "27830")] +#[stable(feature = "decode_utf16", since = "1.9.0")] #[derive(Clone)] pub struct DecodeUtf16 where I: Iterator @@ -748,6 +747,13 @@ pub struct DecodeUtf16 buf: Option, } +/// An iterator that decodes UTF-16 encoded code points from an iterator of `u16`s. +#[stable(feature = "decode_utf16", since = "1.9.0")] +#[derive(Debug, Clone, Eq, PartialEq)] +pub struct DecodeUtf16Error { + code: u16, +} + /// Create an iterator over the UTF-16 encoded code points in `iter`, /// returning unpaired surrogates as `Err`s. /// @@ -756,8 +762,6 @@ pub struct DecodeUtf16 /// Basic usage: /// /// ``` -/// #![feature(decode_utf16)] -/// /// use std::char::decode_utf16; /// /// fn main() { @@ -766,7 +770,9 @@ pub struct DecodeUtf16 /// 0x0073, 0xDD1E, 0x0069, 0x0063, /// 0xD834]; /// -/// assert_eq!(decode_utf16(v.iter().cloned()).collect::>(), +/// assert_eq!(decode_utf16(v.iter().cloned()) +/// .map(|r| r.map_err(|e| e.unpaired_surrogate())) +/// .collect::>(), /// vec![Ok('𝄞'), /// Ok('m'), Ok('u'), Ok('s'), /// Err(0xDD1E), @@ -778,8 +784,6 @@ pub struct DecodeUtf16 /// A lossy decoder can be obtained by replacing `Err` results with the replacement character: /// /// ``` -/// #![feature(decode_utf16)] -/// /// use std::char::{decode_utf16, REPLACEMENT_CHARACTER}; /// /// fn main() { @@ -794,7 +798,7 @@ pub struct DecodeUtf16 /// "𝄞mus�ic�"); /// } /// ``` -#[unstable(feature = "decode_utf16", reason = "recently exposed", issue = "27830")] +#[stable(feature = "decode_utf16", since = "1.9.0")] #[inline] pub fn decode_utf16>(iter: I) -> DecodeUtf16 { DecodeUtf16 { @@ -803,11 +807,11 @@ pub fn decode_utf16>(iter: I) -> DecodeUtf16> Iterator for DecodeUtf16 { - type Item = Result; + type Item = Result; - fn next(&mut self) -> Option> { + fn next(&mut self) -> Option> { let u = match self.buf.take() { Some(buf) => buf, None => match self.iter.next() { @@ -821,18 +825,18 @@ impl> Iterator for DecodeUtf16 { Some(Ok(unsafe { from_u32_unchecked(u as u32) })) } else if u >= 0xDC00 { // a trailing surrogate - Some(Err(u)) + Some(Err(DecodeUtf16Error { code: u })) } else { let u2 = match self.iter.next() { Some(u2) => u2, // eof - None => return Some(Err(u)), + None => return Some(Err(DecodeUtf16Error { code: u })), }; if u2 < 0xDC00 || u2 > 0xDFFF { // not a trailing surrogate so we're not a valid // surrogate pair, so rewind to redecode u2 next time. self.buf = Some(u2); - return Some(Err(u)); + return Some(Err(DecodeUtf16Error { code: u })); } // all ok, so lets decode it. @@ -850,8 +854,25 @@ impl> Iterator for DecodeUtf16 { } } -/// `U+FFFD REPLACEMENT CHARACTER` (�) is used in Unicode to represent a decoding error. +impl DecodeUtf16Error { + /// Returns the unpaired surrogate which caused this error. + #[stable(feature = "decode_utf16", since = "1.9.0")] + pub fn unpaired_surrogate(&self) -> u16 { + self.code + } +} + +#[stable(feature = "decode_utf16", since = "1.9.0")] +impl fmt::Display for DecodeUtf16Error { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "unpaired surrogate found: {:x}", self.code) + } +} + +/// `U+FFFD REPLACEMENT CHARACTER` (�) is used in Unicode to represent a +/// decoding error. +/// /// It can occur, for example, when giving ill-formed UTF-8 bytes to /// [`String::from_utf8_lossy`](../../std/string/struct.String.html#method.from_utf8_lossy). -#[unstable(feature = "decode_utf16", reason = "recently added", issue = "27830")] +#[stable(feature = "decode_utf16", since = "1.9.0")] pub const REPLACEMENT_CHARACTER: char = '\u{FFFD}'; diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 34c0edd8ee1e..bc7c7c5e0caf 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -21,12 +21,10 @@ #![feature(box_patterns)] #![feature(box_syntax)] #![feature(libc)] -#![feature(recover)] #![feature(rustc_private)] #![feature(set_stdio)] #![feature(slice_patterns)] #![feature(staged_api)] -#![feature(std_panic)] #![feature(test)] #![feature(unicode)] #![feature(question_mark)] diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index 1fe9a8240fa8..982f477fc4ae 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -15,7 +15,7 @@ use std::ffi::OsString; use std::io::prelude::*; use std::io; use std::path::PathBuf; -use std::panic::{self, AssertRecoverSafe}; +use std::panic::{self, AssertUnwindSafe}; use std::process::Command; use std::rc::Rc; use std::str; @@ -256,18 +256,13 @@ fn runtest(test: &str, cratename: &str, cfgs: Vec, libs: SearchPaths, control.after_analysis.stop = Compilation::Stop; } - match { - let b_sess = AssertRecoverSafe(&sess); - let b_cstore = AssertRecoverSafe(&cstore); - let b_cfg = AssertRecoverSafe(cfg.clone()); - let b_control = AssertRecoverSafe(&control); - - panic::recover(|| { - driver::compile_input(&b_sess, &b_cstore, (*b_cfg).clone(), - &input, &out, - &None, None, &b_control) - }) - } { + let res = panic::catch_unwind(AssertUnwindSafe(|| { + driver::compile_input(&sess, &cstore, cfg.clone(), + &input, &out, + &None, None, &control) + })); + + match res { Ok(r) => { match r { Err(count) if count > 0 && compile_fail == false => { diff --git a/src/libserialize/hex.rs b/src/libserialize/hex.rs index 609ebe854616..31b71dbc80b6 100644 --- a/src/libserialize/hex.rs +++ b/src/libserialize/hex.rs @@ -132,7 +132,10 @@ impl FromHex for str { buf >>= 4; continue } - _ => return Err(InvalidHexCharacter(self.char_at(idx), idx)), + _ => { + let ch = self[idx..].chars().next().unwrap(); + return Err(InvalidHexCharacter(ch, idx)) + } } modulus += 1; diff --git a/src/libserialize/lib.rs b/src/libserialize/lib.rs index 173ecca648c4..80cd47c85ccd 100644 --- a/src/libserialize/lib.rs +++ b/src/libserialize/lib.rs @@ -32,7 +32,6 @@ Core encoding and decoding interfaces. #![feature(enumset)] #![feature(rustc_private)] #![feature(staged_api)] -#![feature(str_char)] #![feature(unicode)] #![feature(question_mark)] #![cfg_attr(test, feature(test))] diff --git a/src/libstd/ascii.rs b/src/libstd/ascii.rs index 3ae3cf8504ea..0db91034eb5a 100644 --- a/src/libstd/ascii.rs +++ b/src/libstd/ascii.rs @@ -128,8 +128,6 @@ pub trait AsciiExt { /// # Examples /// /// ``` - /// #![feature(ascii)] - /// /// use std::ascii::AsciiExt; /// /// let mut ascii = 'a'; @@ -138,7 +136,7 @@ pub trait AsciiExt { /// /// assert_eq!('A', ascii); /// ``` - #[unstable(feature = "ascii", issue = "27809")] + #[stable(feature = "ascii", since = "1.9.0")] fn make_ascii_uppercase(&mut self); /// Converts this type to its ASCII lower case equivalent in-place. @@ -148,8 +146,6 @@ pub trait AsciiExt { /// # Examples /// /// ``` - /// #![feature(ascii)] - /// /// use std::ascii::AsciiExt; /// /// let mut ascii = 'A'; @@ -158,7 +154,7 @@ pub trait AsciiExt { /// /// assert_eq!('a', ascii); /// ``` - #[unstable(feature = "ascii", issue = "27809")] + #[stable(feature = "ascii", since = "1.9.0")] fn make_ascii_lowercase(&mut self); } diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index 234042ab011b..c20270e83066 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -620,8 +620,7 @@ impl HashMap } /// Returns a reference to the map's hasher. - #[unstable(feature = "hashmap_public_hasher", reason = "don't want to make insta-stable", - issue = "31262")] + #[stable(feature = "hashmap_public_hasher", since = "1.9.0")] pub fn hasher(&self) -> &S { &self.hash_builder } diff --git a/src/libstd/collections/hash/set.rs b/src/libstd/collections/hash/set.rs index 954adf313be0..b353a4c1ba12 100644 --- a/src/libstd/collections/hash/set.rs +++ b/src/libstd/collections/hash/set.rs @@ -194,8 +194,7 @@ impl HashSet } /// Returns a reference to the set's hasher. - #[unstable(feature = "hashmap_public_hasher", reason = "don't want to make insta-stable", - issue = "31262")] + #[stable(feature = "hashmap_public_hasher", since = "1.9.0")] pub fn hasher(&self) -> &S { self.map.hasher() } @@ -459,7 +458,7 @@ impl HashSet /// The value may be any borrowed form of the set's value type, but /// `Hash` and `Eq` on the borrowed form *must* match those for /// the value type. - #[unstable(feature = "set_recovery", issue = "28050")] + #[stable(feature = "set_recovery", since = "1.9.0")] pub fn get(&self, value: &Q) -> Option<&T> where T: Borrow, Q: Hash + Eq { @@ -556,7 +555,7 @@ impl HashSet /// Adds a value to the set, replacing the existing value, if any, that is equal to the given /// one. Returns the replaced value. - #[unstable(feature = "set_recovery", issue = "28050")] + #[stable(feature = "set_recovery", since = "1.9.0")] pub fn replace(&mut self, value: T) -> Option { Recover::replace(&mut self.map, value) } @@ -591,7 +590,7 @@ impl HashSet /// The value may be any borrowed form of the set's value type, but /// `Hash` and `Eq` on the borrowed form *must* match those for /// the value type. - #[unstable(feature = "set_recovery", issue = "28050")] + #[stable(feature = "set_recovery", since = "1.9.0")] pub fn take(&mut self, value: &Q) -> Option where T: Borrow, Q: Hash + Eq { diff --git a/src/libstd/error.rs b/src/libstd/error.rs index 660948b0acca..35cd4a5ec529 100644 --- a/src/libstd/error.rs +++ b/src/libstd/error.rs @@ -49,13 +49,11 @@ use any::TypeId; use boxed::Box; -use convert::From; +use char; use fmt::{self, Debug, Display}; use marker::{Send, Sync, Reflect}; use mem::transmute; use num; -use option::Option::{self, Some, None}; -use result::Result::{self, Ok, Err}; use raw::TraitObject; use str; use string::{self, String}; @@ -189,6 +187,13 @@ impl Error for string::ParseError { } } +#[stable(feature = "decode_utf16", since = "1.9.0")] +impl Error for char::DecodeUtf16Error { + fn description(&self) -> &str { + "unpaired surrogate found" + } +} + #[stable(feature = "box_error", since = "1.7.0")] impl Error for Box { fn description(&self) -> &str { diff --git a/src/libstd/ffi/os_str.rs b/src/libstd/ffi/os_str.rs index de840457a01f..0d29e62485ab 100644 --- a/src/libstd/ffi/os_str.rs +++ b/src/libstd/ffi/os_str.rs @@ -86,13 +86,14 @@ impl OsString { self.inner.push_slice(&s.as_ref().inner) } - /// Creates a new `OsString` with the given capacity. The string will be - /// able to hold exactly `capacity` bytes without reallocating. If - /// `capacity` is 0, the string will not allocate. + /// Creates a new `OsString` with the given capacity. + /// + /// The string will be able to hold exactly `capacity` lenth units of other + /// OS strings without reallocating. If `capacity` is 0, the string will not + /// allocate. /// /// See main `OsString` documentation information about encoding. - #[unstable(feature = "osstring_simple_functions", - reason = "recently added", issue = "29453")] + #[stable(feature = "osstring_simple_functions", since = "1.9.0")] pub fn with_capacity(capacity: usize) -> OsString { OsString { inner: Buf::with_capacity(capacity) @@ -100,40 +101,36 @@ impl OsString { } /// Truncates the `OsString` to zero length. - #[unstable(feature = "osstring_simple_functions", - reason = "recently added", issue = "29453")] + #[stable(feature = "osstring_simple_functions", since = "1.9.0")] pub fn clear(&mut self) { self.inner.clear() } - /// Returns the number of bytes this `OsString` can hold without - /// reallocating. + /// Returns the capacity this `OsString` can hold without reallocating. /// /// See `OsString` introduction for information about encoding. - #[unstable(feature = "osstring_simple_functions", - reason = "recently added", issue = "29453")] + #[stable(feature = "osstring_simple_functions", since = "1.9.0")] pub fn capacity(&self) -> usize { self.inner.capacity() } - /// Reserves capacity for at least `additional` more bytes to be inserted - /// in the given `OsString`. The collection may reserve more space to avoid - /// frequent reallocations. - #[unstable(feature = "osstring_simple_functions", - reason = "recently added", issue = "29453")] + /// Reserves capacity for at least `additional` more capacity to be inserted + /// in the given `OsString`. + /// + /// The collection may reserve more space to avoid frequent reallocations. + #[stable(feature = "osstring_simple_functions", since = "1.9.0")] pub fn reserve(&mut self, additional: usize) { self.inner.reserve(additional) } - /// Reserves the minimum capacity for exactly `additional` more bytes to be - /// inserted in the given `OsString`. Does nothing if the capacity is + /// Reserves the minimum capacity for exactly `additional` more capacity to + /// be inserted in the given `OsString`. Does nothing if the capacity is /// already sufficient. /// /// Note that the allocator may give the collection more space than it /// requests. Therefore capacity can not be relied upon to be precisely /// minimal. Prefer reserve if future insertions are expected. - #[unstable(feature = "osstring_simple_functions", - reason = "recently added", issue = "29453")] + #[stable(feature = "osstring_simple_functions", since = "1.9.0")] pub fn reserve_exact(&mut self, additional: usize) { self.inner.reserve_exact(additional) } @@ -286,17 +283,20 @@ impl OsStr { } /// Checks whether the `OsStr` is empty. - #[unstable(feature = "osstring_simple_functions", - reason = "recently added", issue = "29453")] + #[stable(feature = "osstring_simple_functions", since = "1.9.0")] pub fn is_empty(&self) -> bool { self.inner.inner.is_empty() } - /// Returns the number of bytes in this `OsStr`. + /// Returns the length of this `OsStr`. + /// + /// Note that this does **not** return the number of bytes in this string + /// as, for example, OS strings on Windows are encoded as a list of `u16` + /// rather than a list of bytes. This number is simply useful for passing to + /// other methods like `OsString::with_capacity` to avoid reallocations. /// - /// See `OsStr` introduction for information about encoding. - #[unstable(feature = "osstring_simple_functions", - reason = "recently added", issue = "29453")] + /// See `OsStr` introduction for more information about encoding. + #[stable(feature = "osstring_simple_functions", since = "1.9.0")] pub fn len(&self) -> usize { self.inner.inner.len() } diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs index c4d6cb33365d..f5a51e974272 100644 --- a/src/libstd/fs.rs +++ b/src/libstd/fs.rs @@ -302,7 +302,7 @@ impl File { /// The returned `File` is a reference to the same state that this object /// references. Both handles will read and write with the same cursor /// position. - #[unstable(feature = "file_try_clone", reason = "newly added", issue = "31405")] + #[stable(feature = "file_try_clone", since = "1.9.0")] pub fn try_clone(&self) -> io::Result { Ok(File { inner: self.inner.duplicate()? @@ -523,16 +523,13 @@ impl OpenOptions { /// # Examples /// /// ```no_run - /// #![feature(expand_open_options)] /// use std::fs::OpenOptions; /// /// let file = OpenOptions::new().write(true) /// .create_new(true) /// .open("foo.txt"); /// ``` - #[unstable(feature = "expand_open_options", - reason = "recently added", - issue = "30014")] + #[stable(feature = "expand_open_options2", since = "1.9.0")] pub fn create_new(&mut self, create_new: bool) -> &mut OpenOptions { self.0.create_new(create_new); self } diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index bcce8ee6abf4..6dd7273c17fe 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -1596,7 +1596,7 @@ impl Iterator for Chars { } } Some(match str::from_utf8(&buf[..width]).ok() { - Some(s) => Ok(s.char_at(0)), + Some(s) => Ok(s.chars().next().unwrap()), None => Err(CharsError::NotUtf8), }) } diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 8dcac5141722..e14a31453d38 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -222,10 +222,8 @@ #![feature(collections)] #![feature(collections_bound)] #![feature(const_fn)] -#![feature(copy_from_slice)] #![feature(core_float)] #![feature(core_intrinsics)] -#![feature(decode_utf16)] #![feature(dropck_parametricity)] #![feature(float_extras)] #![feature(float_from_str_radix)] diff --git a/src/libstd/net/addr.rs b/src/libstd/net/addr.rs index a915872d8ac9..d510339f1c5b 100644 --- a/src/libstd/net/addr.rs +++ b/src/libstd/net/addr.rs @@ -68,7 +68,7 @@ impl SocketAddr { } /// Change the IP address associated with this socket address. - #[unstable(feature = "sockaddr_setters", reason = "recent addition", issue = "31572")] + #[stable(feature = "sockaddr_setters", since = "1.9.0")] pub fn set_ip(&mut self, new_ip: IpAddr) { // `match (*self, new_ip)` would have us mutate a copy of self only to throw it away. match (self, new_ip) { @@ -88,7 +88,7 @@ impl SocketAddr { } /// Change the port number associated with this socket address. - #[unstable(feature = "sockaddr_setters", reason = "recent addition", issue = "31572")] + #[stable(feature = "sockaddr_setters", since = "1.9.0")] pub fn set_port(&mut self, new_port: u16) { match *self { SocketAddr::V4(ref mut a) => a.set_port(new_port), @@ -120,16 +120,22 @@ impl SocketAddrV4 { } /// Change the IP address associated with this socket address. - #[unstable(feature = "sockaddr_setters", reason = "recent addition", issue = "31572")] - pub fn set_ip(&mut self, new_ip: Ipv4Addr) { self.inner.sin_addr = *new_ip.as_inner() } + #[stable(feature = "sockaddr_setters", since = "1.9.0")] + pub fn set_ip(&mut self, new_ip: Ipv4Addr) { + self.inner.sin_addr = *new_ip.as_inner() + } /// Returns the port number associated with this socket address. #[stable(feature = "rust1", since = "1.0.0")] - pub fn port(&self) -> u16 { ntoh(self.inner.sin_port) } + pub fn port(&self) -> u16 { + ntoh(self.inner.sin_port) + } /// Change the port number associated with this socket address. - #[unstable(feature = "sockaddr_setters", reason = "recent addition", issue = "31572")] - pub fn set_port(&mut self, new_port: u16) { self.inner.sin_port = hton(new_port) } + #[stable(feature = "sockaddr_setters", since = "1.9.0")] + pub fn set_port(&mut self, new_port: u16) { + self.inner.sin_port = hton(new_port); + } } impl SocketAddrV6 { @@ -159,24 +165,32 @@ impl SocketAddrV6 { } /// Change the IP address associated with this socket address. - #[unstable(feature = "sockaddr_setters", reason = "recent addition", issue = "31572")] - pub fn set_ip(&mut self, new_ip: Ipv6Addr) { self.inner.sin6_addr = *new_ip.as_inner() } + #[stable(feature = "sockaddr_setters", since = "1.9.0")] + pub fn set_ip(&mut self, new_ip: Ipv6Addr) { + self.inner.sin6_addr = *new_ip.as_inner() + } /// Returns the port number associated with this socket address. #[stable(feature = "rust1", since = "1.0.0")] - pub fn port(&self) -> u16 { ntoh(self.inner.sin6_port) } + pub fn port(&self) -> u16 { + ntoh(self.inner.sin6_port) + } /// Change the port number associated with this socket address. - #[unstable(feature = "sockaddr_setters", reason = "recent addition", issue = "31572")] - pub fn set_port(&mut self, new_port: u16) { self.inner.sin6_port = hton(new_port) } + #[stable(feature = "sockaddr_setters", since = "1.9.0")] + pub fn set_port(&mut self, new_port: u16) { + self.inner.sin6_port = hton(new_port); + } /// Returns the flow information associated with this address, /// corresponding to the `sin6_flowinfo` field in C. #[stable(feature = "rust1", since = "1.0.0")] - pub fn flowinfo(&self) -> u32 { self.inner.sin6_flowinfo } + pub fn flowinfo(&self) -> u32 { + self.inner.sin6_flowinfo + } /// Change the flow information associated with this socket address. - #[unstable(feature = "sockaddr_setters", reason = "recent addition", issue = "31572")] + #[stable(feature = "sockaddr_setters", since = "1.9.0")] pub fn set_flowinfo(&mut self, new_flowinfo: u32) { self.inner.sin6_flowinfo = new_flowinfo; } @@ -184,10 +198,12 @@ impl SocketAddrV6 { /// Returns the scope ID associated with this address, /// corresponding to the `sin6_scope_id` field in C. #[stable(feature = "rust1", since = "1.0.0")] - pub fn scope_id(&self) -> u32 { self.inner.sin6_scope_id } + pub fn scope_id(&self) -> u32 { + self.inner.sin6_scope_id + } /// Change the scope ID associated with this socket address. - #[unstable(feature = "sockaddr_setters", reason = "recent addition", issue = "31572")] + #[stable(feature = "sockaddr_setters", since = "1.9.0")] pub fn set_scope_id(&mut self, new_scope_id: u32) { self.inner.sin6_scope_id = new_scope_id; } diff --git a/src/libstd/panic.rs b/src/libstd/panic.rs index 4462ce24dce0..16401c4527f1 100644 --- a/src/libstd/panic.rs +++ b/src/libstd/panic.rs @@ -10,8 +10,7 @@ //! Panic support in the standard library -#![unstable(feature = "std_panic", reason = "awaiting feedback", - issue = "27719")] +#![stable(feature = "std_panic", since = "1.9.0")] use any::Any; use boxed::Box; @@ -23,6 +22,7 @@ use sync::{Arc, Mutex, RwLock}; use sys_common::unwind; use thread::Result; +#[unstable(feature = "panic_handler", issue = "30449")] pub use panicking::{take_hook, set_hook, PanicInfo, Location}; /// @@ -92,7 +92,7 @@ pub fn take_handler() -> Box { /// "speed bump" to alert users of `recover` that broken invariants may be /// witnessed and may need to be accounted for. /// -/// ## Who implements `RecoverSafe`? +/// ## Who implements `UnwindSafe`? /// /// Types such as `&mut T` and `&RefCell` are examples which are **not** /// recover safe. The general idea is that any mutable state which can be shared @@ -104,7 +104,7 @@ pub fn take_handler() -> Box { /// poisoning by default. They still allow witnessing a broken invariant, but /// they already provide their own "speed bumps" to do so. /// -/// ## When should `RecoverSafe` be used? +/// ## When should `UnwindSafe` be used? /// /// Is not intended that most types or functions need to worry about this trait. /// It is only used as a bound on the `recover` function and as mentioned above, @@ -112,10 +112,18 @@ pub fn take_handler() -> Box { /// wrapper struct in this module can be used to force this trait to be /// implemented for any closed over variables passed to the `recover` function /// (more on this below). -#[unstable(feature = "recover", reason = "awaiting feedback", issue = "27719")] +#[stable(feature = "catch_unwind", since = "1.9.0")] #[rustc_on_unimplemented = "the type {Self} may not be safely transferred \ across a recover boundary"] +pub trait UnwindSafe {} + +/// Deprecated, renamed to UnwindSafe +#[unstable(feature = "recover", reason = "awaiting feedback", issue = "27719")] +#[rustc_deprecated(reason = "renamed to `UnwindSafe`", since = "1.9.0")] pub trait RecoverSafe {} +#[unstable(feature = "recover", reason = "awaiting feedback", issue = "27719")] +#[allow(deprecated)] +impl RecoverSafe for T {} /// A marker trait representing types where a shared reference is considered /// recover safe. @@ -124,12 +132,12 @@ pub trait RecoverSafe {} /// interior mutability. /// /// This is a "helper marker trait" used to provide impl blocks for the -/// `RecoverSafe` trait, for more information see that documentation. -#[unstable(feature = "recover", reason = "awaiting feedback", issue = "27719")] +/// `UnwindSafe` trait, for more information see that documentation. +#[stable(feature = "catch_unwind", since = "1.9.0")] #[rustc_on_unimplemented = "the type {Self} contains interior mutability \ and a reference may not be safely transferrable \ across a recover boundary"] -pub trait RefRecoverSafe {} +pub trait RefUnwindSafe {} /// A simple wrapper around a type to assert that it is panic safe. /// @@ -143,90 +151,141 @@ pub trait RefRecoverSafe {} /// /// # Examples /// -/// One way to use `AssertRecoverSafe` is to assert that the entire closure +/// One way to use `AssertUnwindSafe` is to assert that the entire closure /// itself is recover safe, bypassing all checks for all variables: /// /// ``` -/// #![feature(recover, std_panic)] -/// -/// use std::panic::{self, AssertRecoverSafe}; +/// use std::panic::{self, AssertUnwindSafe}; /// /// let mut variable = 4; /// /// // This code will not compile because the closure captures `&mut variable` /// // which is not considered panic safe by default. /// -/// // panic::recover(|| { +/// // panic::catch_unwind(|| { /// // variable += 3; /// // }); /// -/// // This, however, will compile due to the `AssertRecoverSafe` wrapper -/// let result = panic::recover(AssertRecoverSafe(|| { +/// // This, however, will compile due to the `AssertUnwindSafe` wrapper +/// let result = panic::catch_unwind(AssertUnwindSafe(|| { /// variable += 3; /// })); /// // ... /// ``` /// /// Wrapping the entire closure amounts to a blanket assertion that all captured -/// variables are recover safe. This has the downside that if new captures are -/// added in the future, they will also be considered recover safe. Therefore, +/// variables are unwind safe. This has the downside that if new captures are +/// added in the future, they will also be considered unwind safe. Therefore, /// you may prefer to just wrap individual captures, as shown below. This is /// more annotation, but it ensures that if a new capture is added which is not -/// recover safe, you will get a compilation error at that time, which will +/// unwind safe, you will get a compilation error at that time, which will /// allow you to consider whether that new capture in fact represent a bug or /// not. /// /// ``` -/// #![feature(recover, std_panic)] -/// -/// use std::panic::{self, AssertRecoverSafe}; +/// use std::panic::{self, AssertUnwindSafe}; /// /// let mut variable = 4; /// let other_capture = 3; /// /// let result = { -/// let mut wrapper = AssertRecoverSafe(&mut variable); -/// panic::recover(move || { +/// let mut wrapper = AssertUnwindSafe(&mut variable); +/// panic::catch_unwind(move || { /// **wrapper += other_capture; /// }) /// }; /// // ... /// ``` -#[unstable(feature = "recover", reason = "awaiting feedback", issue = "27719")] +#[stable(feature = "catch_unwind", since = "1.9.0")] +pub struct AssertUnwindSafe( + #[stable(feature = "catch_unwind", since = "1.9.0")] + pub T +); + +/// Deprecated, renamed to `AssertUnwindSafe` +#[unstable(feature = "recover", issue = "27719")] +#[rustc_deprecated(reason = "renamed to `AssertUnwindSafe`", since = "1.9.0")] pub struct AssertRecoverSafe(pub T); -// Implementations of the `RecoverSafe` trait: +// Implementations of the `UnwindSafe` trait: // -// * By default everything is recover safe -// * pointers T contains mutability of some form are not recover safe +// * By default everything is unwind safe +// * pointers T contains mutability of some form are not unwind safe // * Unique, an owning pointer, lifts an implementation -// * Types like Mutex/RwLock which are explicilty poisoned are recover safe -// * Our custom AssertRecoverSafe wrapper is indeed recover safe -impl RecoverSafe for .. {} -impl<'a, T: ?Sized> !RecoverSafe for &'a mut T {} -impl<'a, T: RefRecoverSafe + ?Sized> RecoverSafe for &'a T {} -impl RecoverSafe for *const T {} -impl RecoverSafe for *mut T {} -impl RecoverSafe for Unique {} -impl RecoverSafe for Shared {} -impl RecoverSafe for Mutex {} -impl RecoverSafe for RwLock {} -impl RecoverSafe for AssertRecoverSafe {} +// * Types like Mutex/RwLock which are explicilty poisoned are unwind safe +// * Our custom AssertUnwindSafe wrapper is indeed unwind safe +#[stable(feature = "catch_unwind", since = "1.9.0")] +impl UnwindSafe for .. {} +#[stable(feature = "catch_unwind", since = "1.9.0")] +impl<'a, T: ?Sized> !UnwindSafe for &'a mut T {} +#[stable(feature = "catch_unwind", since = "1.9.0")] +impl<'a, T: RefUnwindSafe + ?Sized> UnwindSafe for &'a T {} +#[stable(feature = "catch_unwind", since = "1.9.0")] +impl UnwindSafe for *const T {} +#[stable(feature = "catch_unwind", since = "1.9.0")] +impl UnwindSafe for *mut T {} +#[stable(feature = "catch_unwind", since = "1.9.0")] +impl UnwindSafe for Unique {} +#[stable(feature = "catch_unwind", since = "1.9.0")] +impl UnwindSafe for Shared {} +#[stable(feature = "catch_unwind", since = "1.9.0")] +impl UnwindSafe for Mutex {} +#[stable(feature = "catch_unwind", since = "1.9.0")] +impl UnwindSafe for RwLock {} +#[stable(feature = "catch_unwind", since = "1.9.0")] +impl UnwindSafe for AssertUnwindSafe {} +#[unstable(feature = "recover", issue = "27719")] +#[allow(deprecated)] +impl UnwindSafe for AssertRecoverSafe {} // not covered via the Shared impl above b/c the inner contents use // Cell/AtomicUsize, but the usage here is recover safe so we can lift the // impl up one level to Arc/Rc itself -impl RecoverSafe for Rc {} -impl RecoverSafe for Arc {} +#[stable(feature = "catch_unwind", since = "1.9.0")] +impl UnwindSafe for Rc {} +#[stable(feature = "catch_unwind", since = "1.9.0")] +impl UnwindSafe for Arc {} // Pretty simple implementations for the `RefRecoverSafe` marker trait, // basically just saying that this is a marker trait and `UnsafeCell` is the // only thing which doesn't implement it (which then transitively applies to // everything else). -impl RefRecoverSafe for .. {} -impl !RefRecoverSafe for UnsafeCell {} -impl RefRecoverSafe for AssertRecoverSafe {} +#[stable(feature = "catch_unwind", since = "1.9.0")] +impl RefUnwindSafe for .. {} +#[stable(feature = "catch_unwind", since = "1.9.0")] +impl !RefUnwindSafe for UnsafeCell {} +#[stable(feature = "catch_unwind", since = "1.9.0")] +impl RefUnwindSafe for AssertUnwindSafe {} +#[unstable(feature = "recover", issue = "27719")] +#[allow(deprecated)] +impl RefUnwindSafe for AssertRecoverSafe {} + +#[stable(feature = "catch_unwind", since = "1.9.0")] +impl Deref for AssertUnwindSafe { + type Target = T; + + fn deref(&self) -> &T { + &self.0 + } +} + +#[stable(feature = "catch_unwind", since = "1.9.0")] +impl DerefMut for AssertUnwindSafe { + fn deref_mut(&mut self) -> &mut T { + &mut self.0 + } +} +#[stable(feature = "catch_unwind", since = "1.9.0")] +impl R> FnOnce<()> for AssertUnwindSafe { + type Output = R; + + extern "rust-call" fn call_once(self, _args: ()) -> R { + (self.0)() + } +} + +#[allow(deprecated)] impl AssertRecoverSafe { /// Creates a new `AssertRecoverSafe` wrapper around the provided type. #[unstable(feature = "recover", reason = "awaiting feedback", issue = "27719")] @@ -245,6 +304,8 @@ impl AssertRecoverSafe { } } +#[unstable(feature = "recover", issue = "27719")] +#[allow(deprecated)] impl Deref for AssertRecoverSafe { type Target = T; @@ -253,12 +314,16 @@ impl Deref for AssertRecoverSafe { } } +#[unstable(feature = "recover", issue = "27719")] +#[allow(deprecated)] impl DerefMut for AssertRecoverSafe { fn deref_mut(&mut self) -> &mut T { &mut self.0 } } +#[unstable(feature = "recover", issue = "27719")] +#[allow(deprecated)] impl R> FnOnce<()> for AssertRecoverSafe { type Output = R; @@ -267,7 +332,7 @@ impl R> FnOnce<()> for AssertRecoverSafe { } } -/// Invokes a closure, capturing the cause of panic if one occurs. +/// Invokes a closure, capturing the cause of an unwinding panic if one occurs. /// /// This function will return `Ok` with the closure's result if the closure /// does not panic, and will return `Err(cause)` if the closure panics. The @@ -280,38 +345,44 @@ impl R> FnOnce<()> for AssertRecoverSafe { /// /// It is **not** recommended to use this function for a general try/catch /// mechanism. The `Result` type is more appropriate to use for functions that -/// can fail on a regular basis. -/// -/// The closure provided is required to adhere to the `RecoverSafe` to ensure -/// that all captured variables are safe to cross this recover boundary. The -/// purpose of this bound is to encode the concept of [exception safety][rfc] in -/// the type system. Most usage of this function should not need to worry about -/// this bound as programs are naturally panic safe without `unsafe` code. If it -/// becomes a problem the associated `AssertRecoverSafe` wrapper type in this +/// can fail on a regular basis. Additionally, this function is not guaranteed +/// to catch all panics, see the "Notes" sectino below. +/// +/// The closure provided is required to adhere to the `UnwindSafe` to ensure +/// that all captured variables are safe to cross this boundary. The purpose of +/// this bound is to encode the concept of [exception safety][rfc] in the type +/// system. Most usage of this function should not need to worry about this +/// bound as programs are naturally panic safe without `unsafe` code. If it +/// becomes a problem the associated `AssertUnwindSafe` wrapper type in this /// module can be used to quickly assert that the usage here is indeed exception /// safe. /// /// [rfc]: https://github.com/rust-lang/rfcs/blob/master/text/1236-stabilize-catch-panic.md /// +/// # Notes +/// +/// Note that this function **may not catch all panics** in Rust. A panic in +/// Rust is not always implemented via unwinding, but can be implemented by +/// aborting the process as well. This function *only* catches unwinding panics, +/// not those that abort the process. +/// /// # Examples /// /// ``` -/// #![feature(recover, std_panic)] -/// /// use std::panic; /// -/// let result = panic::recover(|| { +/// let result = panic::catch_unwind(|| { /// println!("hello!"); /// }); /// assert!(result.is_ok()); /// -/// let result = panic::recover(|| { +/// let result = panic::catch_unwind(|| { /// panic!("oh no!"); /// }); /// assert!(result.is_err()); /// ``` -#[unstable(feature = "recover", reason = "awaiting feedback", issue = "27719")] -pub fn recover R + RecoverSafe, R>(f: F) -> Result { +#[stable(feature = "catch_unwind", since = "1.9.0")] +pub fn catch_unwind R + UnwindSafe, R>(f: F) -> Result { let mut result = None; unsafe { let result = &mut result; @@ -320,27 +391,46 @@ pub fn recover R + RecoverSafe, R>(f: F) -> Result { Ok(result.unwrap()) } +/// Deprecated, renamed to `catch_unwind` +#[unstable(feature = "recover", reason = "awaiting feedback", issue = "27719")] +#[rustc_deprecated(reason = "renamed to `catch_unwind`", since = "1.9.0")] +pub fn recover R + UnwindSafe, R>(f: F) -> Result { + catch_unwind(f) +} + /// Triggers a panic without invoking the panic handler. /// -/// This is designed to be used in conjunction with `recover` to, for example, -/// carry a panic across a layer of C code. +/// This is designed to be used in conjunction with `catch_unwind` to, for +/// example, carry a panic across a layer of C code. +/// +/// # Notes +/// +/// Note that panics in Rust are not always implemented via unwinding, but they +/// may be implemented by aborting the process. If this function is called when +/// panics are implemented this way then this function will abort the process, +/// not trigger an unwind. /// /// # Examples /// /// ```should_panic -/// #![feature(std_panic, recover, panic_propagate)] -/// /// use std::panic; /// -/// let result = panic::recover(|| { +/// let result = panic::catch_unwind(|| { /// panic!("oh no!"); /// }); /// /// if let Err(err) = result { -/// panic::propagate(err); +/// panic::resume_unwind(err); /// } /// ``` +#[stable(feature = "resume_unwind", since = "1.9.0")] +pub fn resume_unwind(payload: Box) -> ! { + unwind::rust_panic(payload) +} + +/// Deprecated, use resume_unwind instead #[unstable(feature = "panic_propagate", reason = "awaiting feedback", issue = "30752")] +#[rustc_deprecated(reason = "renamed to `resume_unwind`", since = "1.9.0")] pub fn propagate(payload: Box) -> ! { - unwind::rust_panic(payload) + resume_unwind(payload) } diff --git a/src/libstd/rt.rs b/src/libstd/rt.rs index fcd827e2a8b7..83091c72c0d6 100644 --- a/src/libstd/rt.rs +++ b/src/libstd/rt.rs @@ -60,7 +60,7 @@ fn lang_start(main: *const u8, argc: isize, argv: *const *const u8) -> isize { sys_common::args::init(argc, argv); // Let's run some code! - let res = panic::recover(mem::transmute::<_, fn()>(main)); + let res = panic::catch_unwind(mem::transmute::<_, fn()>(main)); sys_common::cleanup(); res.is_err() }; diff --git a/src/libstd/sync/once.rs b/src/libstd/sync/once.rs index e673879d20db..e228d236a3ca 100644 --- a/src/libstd/sync/once.rs +++ b/src/libstd/sync/once.rs @@ -425,13 +425,13 @@ mod tests { static O: Once = Once::new(); // poison the once - let t = panic::recover(|| { + let t = panic::catch_unwind(|| { O.call_once(|| panic!()); }); assert!(t.is_err()); // poisoning propagates - let t = panic::recover(|| { + let t = panic::catch_unwind(|| { O.call_once(|| {}); }); assert!(t.is_err()); @@ -453,7 +453,7 @@ mod tests { static O: Once = Once::new(); // poison the once - let t = panic::recover(|| { + let t = panic::catch_unwind(|| { O.call_once(|| panic!()); }); assert!(t.is_err()); diff --git a/src/libstd/sys/common/backtrace.rs b/src/libstd/sys/common/backtrace.rs index 24e1a82a593b..6f185437e50a 100644 --- a/src/libstd/sys/common/backtrace.rs +++ b/src/libstd/sys/common/backtrace.rs @@ -131,7 +131,7 @@ pub fn demangle(writer: &mut Write, s: &str) -> io::Result<()> { first = false; } let mut rest = inner; - while rest.char_at(0).is_numeric() { + while rest.chars().next().unwrap().is_numeric() { rest = &rest[1..]; } let i: usize = inner[.. (inner.len() - rest.len())].parse().unwrap(); diff --git a/src/libstd/sys/common/wtf8.rs b/src/libstd/sys/common/wtf8.rs index f64f835e1985..55e485e5811a 100644 --- a/src/libstd/sys/common/wtf8.rs +++ b/src/libstd/sys/common/wtf8.rs @@ -191,8 +191,11 @@ impl Wtf8Buf { match item { Ok(ch) => string.push_char(ch), Err(surrogate) => { + let surrogate = surrogate.unpaired_surrogate(); // Surrogates are known to be in the code point range. - let code_point = unsafe { CodePoint::from_u32_unchecked(surrogate as u32) }; + let code_point = unsafe { + CodePoint::from_u32_unchecked(surrogate as u32) + }; // Skip the WTF-8 concatenation check, // surrogate pairs are already decoded by decode_utf16 string.push_code_point_unchecked(code_point) diff --git a/src/libstd/sys/unix/ext/mod.rs b/src/libstd/sys/unix/ext/mod.rs index 4d8f12c2d7c4..1be3d75d866d 100644 --- a/src/libstd/sys/unix/ext/mod.rs +++ b/src/libstd/sys/unix/ext/mod.rs @@ -49,7 +49,9 @@ pub mod prelude { #[doc(no_inline)] #[stable(feature = "rust1", since = "1.0.0")] pub use super::fs::{PermissionsExt, OpenOptionsExt, MetadataExt, FileTypeExt}; #[doc(no_inline)] #[stable(feature = "rust1", since = "1.0.0")] - pub use super::fs::{DirEntryExt}; + pub use super::fs::DirEntryExt; + #[doc(no_inline)] #[stable(feature = "rust1", since = "1.0.0")] + pub use super::thread::JoinHandleExt; #[doc(no_inline)] #[stable(feature = "rust1", since = "1.0.0")] pub use super::process::{CommandExt, ExitStatusExt}; } diff --git a/src/libstd/sys/unix/ext/process.rs b/src/libstd/sys/unix/ext/process.rs index 8cc291d00ee0..7f31cf9f3bf8 100644 --- a/src/libstd/sys/unix/ext/process.rs +++ b/src/libstd/sys/unix/ext/process.rs @@ -45,6 +45,8 @@ pub trait CommandExt { /// (the daemon) in the same session. #[unstable(feature = "process_session_leader", reason = "recently added", issue = "27811")] + #[rustc_deprecated(reason = "use `before_exec` instead", + since = "1.9.0")] fn session_leader(&mut self, on: bool) -> &mut process::Command; /// Schedules a closure to be run just before the `exec` function is @@ -94,7 +96,7 @@ pub trait CommandExt { /// file descriptors may have changed. If a "transactional spawn" is /// required to gracefully handle errors it is recommended to use the /// cross-platform `spawn` instead. - #[unstable(feature = "process_exec", issue = "31398")] + #[stable(feature = "process_exec2", since = "1.9.0")] fn exec(&mut self) -> io::Error; } diff --git a/src/libstd/sys/unix/ext/thread.rs b/src/libstd/sys/unix/ext/thread.rs index c98e42faba7c..fe2a48764dc3 100644 --- a/src/libstd/sys/unix/ext/thread.rs +++ b/src/libstd/sys/unix/ext/thread.rs @@ -8,37 +8,41 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! Unix-specific extensions to primitives in the `std::process` module. +//! Unix-specific extensions to primitives in the `std::thread` module. -#![unstable(feature = "thread_extensions", issue = "29791")] +#![stable(feature = "thread_extensions", since = "1.9.0")] #[allow(deprecated)] use os::unix::raw::pthread_t; use sys_common::{AsInner, IntoInner}; use thread::JoinHandle; -#[unstable(feature = "thread_extensions", issue = "29791")] +#[stable(feature = "thread_extensions", since = "1.9.0")] #[allow(deprecated)] pub type RawPthread = pthread_t; /// Unix-specific extensions to `std::thread::JoinHandle` -#[unstable(feature = "thread_extensions", issue = "29791")] +#[stable(feature = "thread_extensions", since = "1.9.0")] pub trait JoinHandleExt { /// Extracts the raw pthread_t without taking ownership + #[stable(feature = "thread_extensions", since = "1.9.0")] fn as_pthread_t(&self) -> RawPthread; + /// Consumes the thread, returning the raw pthread_t /// /// This function **transfers ownership** of the underlying pthread_t to /// the caller. Callers are then the unique owners of the pthread_t and /// must either detach or join the pthread_t once it's no longer needed. + #[stable(feature = "thread_extensions", since = "1.9.0")] fn into_pthread_t(self) -> RawPthread; } -#[unstable(feature = "thread_extensions", issue = "29791")] +#[stable(feature = "thread_extensions", since = "1.9.0")] impl JoinHandleExt for JoinHandle { fn as_pthread_t(&self) -> RawPthread { self.as_inner().id() as RawPthread } + fn into_pthread_t(self) -> RawPthread { self.into_inner().into_id() as RawPthread } diff --git a/src/libstd/sys/windows/ext/thread.rs b/src/libstd/sys/windows/ext/thread.rs index 3a07204b2bcf..36b3a3d4bdec 100644 --- a/src/libstd/sys/windows/ext/thread.rs +++ b/src/libstd/sys/windows/ext/thread.rs @@ -10,18 +10,20 @@ //! Extensions to `std::thread` for Windows. -#![unstable(feature = "thread_extensions", issue = "29791")] +#![stable(feature = "thread_extensions", since = "1.9.0")] use os::windows::io::{RawHandle, AsRawHandle, IntoRawHandle}; use thread; use sys_common::{AsInner, IntoInner}; +#[stable(feature = "thread_extensions", since = "1.9.0")] impl AsRawHandle for thread::JoinHandle { fn as_raw_handle(&self) -> RawHandle { self.as_inner().handle().raw() as *mut _ } } +#[stable(feature = "thread_extensions", since = "1.9.0")] impl IntoRawHandle for thread::JoinHandle { fn into_raw_handle(self) -> RawHandle { self.into_inner().into_handle().into_raw() as *mut _ diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index fbe38aee295a..fc18ef407ab2 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -237,7 +237,7 @@ const KNOWN_FEATURES: &'static [(&'static str, &'static str, Option, Status ("stmt_expr_attributes", "1.6.0", Some(15701), Active), // Allows `#[deprecated]` attribute - ("deprecated", "1.6.0", Some(29935), Active), + ("deprecated", "1.9.0", Some(29935), Accepted), // allow using type ascription in expressions ("type_ascription", "1.6.0", Some(23416), Active), @@ -435,7 +435,7 @@ pub const KNOWN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeGat ("must_use", Whitelisted, Ungated), ("stable", Whitelisted, Ungated), ("unstable", Whitelisted, Ungated), - ("deprecated", Normal, Gated("deprecated", "`#[deprecated]` attribute is unstable")), + ("deprecated", Normal, Ungated), ("rustc_paren_sugar", Normal, Gated("unboxed_closures", "unboxed_closures are still evolving")), diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs index ab14e21e251c..ca7e5729c0b7 100644 --- a/src/libsyntax/lib.rs +++ b/src/libsyntax/lib.rs @@ -29,7 +29,6 @@ #![feature(libc)] #![feature(rustc_private)] #![feature(staged_api)] -#![feature(str_char)] #![feature(str_escape)] #![feature(unicode)] #![feature(question_mark)] diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index e2b1d2f5e7ab..fcd83b410413 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -2209,12 +2209,14 @@ impl<'a> State<'a> { self.commasep(Inconsistent, &a.outputs, |s, out| { - match out.constraint.slice_shift_char() { - Some(('=', operand)) if out.is_rw => { - s.print_string(&format!("+{}", operand), + let mut ch = out.constraint.chars(); + match ch.next() { + Some('=') if out.is_rw => { + s.print_string(&format!("+{}", ch.as_str()), ast::StrStyle::Cooked)? } - _ => s.print_string(&out.constraint, ast::StrStyle::Cooked)? + _ => s.print_string(&out.constraint, + ast::StrStyle::Cooked)? } s.popen()?; s.print_expr(&out.expr)?; diff --git a/src/libsyntax_ext/asm.rs b/src/libsyntax_ext/asm.rs index b9ba1f107ad7..50d2b9d31fe0 100644 --- a/src/libsyntax_ext/asm.rs +++ b/src/libsyntax_ext/asm.rs @@ -131,11 +131,12 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) // It's the opposite of '=&' which means that the memory // cannot be shared with any other operand (usually when // a register is clobbered early.) - let output = match constraint.slice_shift_char() { - Some(('=', _)) => None, - Some(('+', operand)) => { + let mut ch = constraint.chars(); + let output = match ch.next() { + Some('=') => None, + Some('+') => { Some(token::intern_and_get_ident(&format!( - "={}", operand))) + "={}", ch.as_str()))) } _ => { cx.span_err(span, "output operand constraint lacks '=' or '+'"); @@ -146,7 +147,7 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) let is_rw = output.is_some(); let is_indirect = constraint.contains("*"); outputs.push(ast::InlineAsmOutput { - constraint: output.unwrap_or(constraint), + constraint: output.unwrap_or(constraint.clone()), expr: out, is_rw: is_rw, is_indirect: is_indirect, diff --git a/src/libsyntax_ext/lib.rs b/src/libsyntax_ext/lib.rs index f214ecdc3368..8f5362b4d289 100644 --- a/src/libsyntax_ext/lib.rs +++ b/src/libsyntax_ext/lib.rs @@ -21,7 +21,6 @@ #![feature(rustc_private)] #![feature(staged_api)] -#![feature(str_char)] extern crate fmt_macros; #[macro_use] extern crate log; diff --git a/src/test/compile-fail/deprecation-in-staged-api.rs b/src/test/compile-fail/deprecation-in-staged-api.rs index 4f4aed21f994..8170c9fd8f16 100644 --- a/src/test/compile-fail/deprecation-in-staged-api.rs +++ b/src/test/compile-fail/deprecation-in-staged-api.rs @@ -10,7 +10,7 @@ // #[deprecated] can't be used in staged api -#![feature(deprecated, staged_api)] +#![feature(staged_api)] #![stable(feature = "test_feature", since = "1.0.0")] diff --git a/src/test/compile-fail/deprecation-lint.rs b/src/test/compile-fail/deprecation-lint.rs index 58fa00fb4108..5fc8f684a66f 100644 --- a/src/test/compile-fail/deprecation-lint.rs +++ b/src/test/compile-fail/deprecation-lint.rs @@ -10,8 +10,6 @@ // aux-build:deprecation-lint.rs -#![feature(deprecated)] - #![deny(deprecated)] #![allow(warnings)] diff --git a/src/test/compile-fail/deprecation-sanity.rs b/src/test/compile-fail/deprecation-sanity.rs index 6ee5cd2c7e3c..af2ac79ea807 100644 --- a/src/test/compile-fail/deprecation-sanity.rs +++ b/src/test/compile-fail/deprecation-sanity.rs @@ -10,8 +10,6 @@ // Various checks that deprecation attributes are used correctly -#![feature(deprecated)] - mod bogus_attribute_types_1 { #[deprecated(since = "a", note = "a", reason)] //~ ERROR unknown meta item 'reason' fn f1() { } diff --git a/src/test/compile-fail/not-panic-safe.rs b/src/test/compile-fail/not-panic-safe.rs index fd0f830a17d8..ece8fa7dc47b 100644 --- a/src/test/compile-fail/not-panic-safe.rs +++ b/src/test/compile-fail/not-panic-safe.rs @@ -11,10 +11,10 @@ #![allow(dead_code)] #![feature(recover)] -use std::panic::RecoverSafe; +use std::panic::UnwindSafe; -fn assert() {} +fn assert() {} fn main() { - assert::<&mut i32>(); //~ ERROR: RecoverSafe` is not satisfied + assert::<&mut i32>(); //~ ERROR: UnwindSafe` is not satisfied } diff --git a/src/test/compile-fail/placement-expr-unstable.rs b/src/test/compile-fail/placement-expr-unstable.rs index b3aa4e9187d3..cc73cbe15fe5 100644 --- a/src/test/compile-fail/placement-expr-unstable.rs +++ b/src/test/compile-fail/placement-expr-unstable.rs @@ -18,9 +18,6 @@ fn main() { use std::boxed::HEAP; //~ ERROR use of unstable library feature let _ = HEAP <- { //~ ERROR use of unstable library feature - ::core::raw::Slice { //~ ERROR use of unstable library feature - data: &42, //~ ERROR use of unstable library feature - len: 1 //~ ERROR use of unstable library feature - } + HEAP //~ ERROR use of unstable library feature }; } diff --git a/src/test/run-pass/panic-safe.rs b/src/test/run-pass/panic-safe.rs index 9949b79278c1..b918f79f2d5d 100644 --- a/src/test/run-pass/panic-safe.rs +++ b/src/test/run-pass/panic-safe.rs @@ -11,14 +11,14 @@ #![allow(dead_code)] #![feature(recover)] -use std::panic::{RecoverSafe, AssertRecoverSafe}; +use std::panic::{UnwindSafe, AssertUnwindSafe}; use std::cell::RefCell; use std::sync::{Mutex, RwLock, Arc}; use std::rc::Rc; struct Foo { a: i32 } -fn assert() {} +fn assert() {} fn main() { assert::(); @@ -43,13 +43,13 @@ fn main() { assert::>(); assert::>(); } - fn baz() { + fn baz() { assert::>(); assert::>(); assert::>(); - assert::>(); - assert::<&AssertRecoverSafe>(); - assert::>>(); - assert::>>(); + assert::>(); + assert::<&AssertUnwindSafe>(); + assert::>>(); + assert::>>(); } }