From 552eda70d33cead1398adfecce1a75e7a61e3daf Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 7 Apr 2016 10:42:53 -0700 Subject: [PATCH] std: Stabilize APIs for the 1.9 release This commit applies all stabilizations, renamings, and deprecations that the library team has decided on for the upcoming 1.9 release. All tracking issues have gone through a cycle-long "final comment period" and the specific APIs stabilized/deprecated are: Stable * `std::panic` * `std::panic::catch_unwind` (renamed from `recover`) * `std::panic::resume_unwind` (renamed from `propagate`) * `std::panic::AssertUnwindSafe` (renamed from `AssertRecoverSafe`) * `std::panic::UnwindSafe` (renamed from `RecoverSafe`) * `str::is_char_boundary` * `<*const T>::as_ref` * `<*mut T>::as_ref` * `<*mut T>::as_mut` * `AsciiExt::make_ascii_uppercase` * `AsciiExt::make_ascii_lowercase` * `char::decode_utf16` * `char::DecodeUtf16` * `char::DecodeUtf16Error` * `char::DecodeUtf16Error::unpaired_surrogate` * `BTreeSet::take` * `BTreeSet::replace` * `BTreeSet::get` * `HashSet::take` * `HashSet::replace` * `HashSet::get` * `OsString::with_capacity` * `OsString::clear` * `OsString::capacity` * `OsString::reserve` * `OsString::reserve_exact` * `OsStr::is_empty` * `OsStr::len` * `std::os::unix::thread` * `RawPthread` * `JoinHandleExt` * `JoinHandleExt::as_pthread_t` * `JoinHandleExt::into_pthread_t` * `HashSet::hasher` * `HashMap::hasher` * `CommandExt::exec` * `File::try_clone` * `SocketAddr::set_ip` * `SocketAddr::set_port` * `SocketAddrV4::set_ip` * `SocketAddrV4::set_port` * `SocketAddrV6::set_ip` * `SocketAddrV6::set_port` * `SocketAddrV6::set_flowinfo` * `SocketAddrV6::set_scope_id` * `<[T]>::copy_from_slice` * `ptr::read_volatile` * `ptr::write_volatile` * The `#[deprecated]` attribute * `OpenOptions::create_new` Deprecated * `std::raw::Slice` - use raw parts of `slice` module instead * `std::raw::Repr` - use raw parts of `slice` module instead * `str::char_range_at` - use slicing plus `chars()` plus `len_utf8` * `str::char_range_at_reverse` - use slicing plus `chars().rev()` plus `len_utf8` * `str::char_at` - use slicing plus `chars()` * `str::char_at_reverse` - use slicing plus `chars().rev()` * `str::slice_shift_char` - use `chars()` plus `Chars::as_str` * `CommandExt::session_leader` - use `before_exec` instead. Closes #27719 cc #27751 (deprecating the `Slice` bits) Closes #27754 Closes #27780 Closes #27809 Closes #27811 Closes #27830 Closes #28050 Closes #29453 Closes #29791 Closes #29935 Closes #30014 Closes #30752 Closes #31262 cc #31398 (still need to deal with `before_exec`) Closes #31405 Closes #31572 Closes #31755 Closes #31756 --- src/compiletest/compiletest.rs | 31 ++- src/compiletest/errors.rs | 2 +- src/compiletest/runtest.rs | 6 +- src/libcollections/btree/set.rs | 6 +- src/libcollections/lib.rs | 2 - src/libcollections/slice.rs | 3 +- src/libcollections/str.rs | 29 ++- src/libcollections/string.rs | 21 +- src/libcollectionstest/lib.rs | 3 - src/libcollectionstest/str.rs | 6 + src/libcore/ptr.rs | 64 ++--- src/libcore/raw.rs | 10 + src/libcore/slice.rs | 22 +- src/libcore/str/mod.rs | 39 +-- src/libcoretest/char.rs | 7 +- src/libcoretest/lib.rs | 3 - src/libgetopts/lib.rs | 9 +- src/librbml/lib.rs | 1 - src/librustc/hir/print.rs | 11 +- src/librustc/lib.rs | 2 - src/librustc/session/mod.rs | 6 +- src/librustc_back/lib.rs | 1 - src/librustc_lint/bad_style.rs | 4 +- src/librustc_lint/lib.rs | 1 - src/librustc_unicode/char.rs | 55 +++-- src/librustdoc/lib.rs | 2 - src/librustdoc/test.rs | 21 +- src/libserialize/hex.rs | 5 +- src/libserialize/lib.rs | 1 - src/libstd/ascii.rs | 8 +- src/libstd/collections/hash/map.rs | 3 +- src/libstd/collections/hash/set.rs | 9 +- src/libstd/error.rs | 11 +- src/libstd/ffi/os_str.rs | 52 ++-- src/libstd/fs.rs | 7 +- src/libstd/io/mod.rs | 2 +- src/libstd/lib.rs | 2 - src/libstd/net/addr.rs | 48 ++-- src/libstd/panic.rs | 222 ++++++++++++------ src/libstd/rt.rs | 2 +- src/libstd/sync/once.rs | 6 +- src/libstd/sys/common/backtrace.rs | 2 +- src/libstd/sys/common/wtf8.rs | 5 +- src/libstd/sys/unix/ext/mod.rs | 4 +- src/libstd/sys/unix/ext/process.rs | 4 +- src/libstd/sys/unix/ext/thread.rs | 14 +- src/libstd/sys/windows/ext/thread.rs | 4 +- src/libsyntax/feature_gate.rs | 4 +- src/libsyntax/lib.rs | 1 - src/libsyntax/print/pprust.rs | 10 +- src/libsyntax_ext/asm.rs | 11 +- src/libsyntax_ext/lib.rs | 1 - .../compile-fail/deprecation-in-staged-api.rs | 2 +- src/test/compile-fail/deprecation-lint.rs | 2 - src/test/compile-fail/deprecation-sanity.rs | 2 - src/test/compile-fail/not-panic-safe.rs | 6 +- .../compile-fail/placement-expr-unstable.rs | 5 +- src/test/run-pass/panic-safe.rs | 14 +- 58 files changed, 508 insertions(+), 328 deletions(-) diff --git a/src/compiletest/compiletest.rs b/src/compiletest/compiletest.rs index 1c06b2a23d54d..8d2558e4344e6 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 7ad0cd2a95d4b..418a0bc7121cb 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 994f45da14626..6773c34c7d76d 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 23e0af8113bf1..e679381f223f8 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 8e62b389a6e3f..7540c51e236d2 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 8fa594c967cf7..db91d911c7355 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 9798e323a6140..b2b1e019a1b89 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 c84d84959dbc2..2226116585fcb 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 045ac1ce977fc..211942f2294ec 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 1150035eb4255..929ac7a52ab27 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 42aef3ab3dd75..a6b5355d94786 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 20c85b5efc116..19226d81f1688 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 25082eed2fe6f..ca1abb4fe0bdd 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> { @@ -1614,7 +1620,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 @@ -1626,7 +1632,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 305546df5be2d..ef8670df9121e 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] @@ -1982,11 +1984,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 } @@ -2038,6 +2042,7 @@ impl StrExt for str { } #[inline] + #[allow(deprecated)] fn slice_shift_char(&self) -> Option<(char, &str)> { if self.is_empty() { None @@ -2054,7 +2059,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 ba8918fc6cb45..41fd742c9e011 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 506f9e9b7a576..aa7ab4b4e3f85 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 884f4490d9f4b..eda20699755a1 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 ef89b5d25b887..4edbeab5dfb11 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 7affb129313c8..e9ed0ed574eaf 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 deb2062777220..d1bbbf08ac230 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 d3005ff2ded25..815e60a8e0342 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 25edaf4b8e4e9..67b11a930d6f7 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 d10691d12ed97..f4fb226d3525f 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 2075bd5edcaeb..e7c9097a56a58 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 4d8021138a0d5..863cada5b8809 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 9953fd4b5d8aa..ba0dae6efb9e9 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 3810fb87acf6a..71c522e9e7535 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 609ebe8546164..31b71dbc80b62 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 173ecca648c41..80cd47c85ccdf 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 3ae3cf8504ea4..0db91034eb5ac 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 234042ab011bc..c20270e830665 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 954adf313be0d..b353a4c1ba120 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 660948b0accac..35cd4a5ec5292 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 de840457a01f4..0d29e62485abb 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 c4d6cb33365d0..f5a51e9742727 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 bcce8ee6abf44..6dd7273c17fe7 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 8dcac51417224..e14a31453d381 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 a915872d8ac94..d510339f1c5b4 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 4462ce24dce04..16401c4527f16 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 fcd827e2a8b72..83091c72c0d6b 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 e673879d20db2..e228d236a3ca7 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 24e1a82a593ba..6f185437e50af 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 f64f835e19854..55e485e5811ac 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 4d8f12c2d7c42..1be3d75d866dd 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 8cc291d00ee02..7f31cf9f3bf80 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 c98e42faba7c2..fe2a48764dc3a 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 3a07204b2bcf8..36b3a3d4bdec8 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 f08d3c685bb55..99de4aa00868a 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 ab14e21e251cb..ca7e5729c0b7a 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 e2b1d2f5e7abe..fcd83b4104130 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 b9ba1f107ad7a..50d2b9d31fe01 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 f214ecdc3368d..8f5362b4d2895 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 4f4aed21f994d..8170c9fd8f161 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 58fa00fb41086..5fc8f684a66fe 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 6ee5cd2c7e3cf..af2ac79ea8072 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 fd0f830a17d87..ece8fa7dc47bb 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 b3aa4e9187d34..cc73cbe15fe5f 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 9949b79278c11..b918f79f2d5d6 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::>>(); } }