From 1076a3d66141e32eb0c03a65d3e92d5ec22c7f07 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 11 Aug 2016 14:08:24 -0700 Subject: [PATCH 1/6] std: Stabilize APIs for the 1.12 release Stabilized * `Cell::as_ptr` * `RefCell::as_ptr` * `IpAddr::is_{unspecified,loopback,multicast}` * `Ipv6Addr::octets` * `LinkedList::contains` * `VecDeque::contains` * `ExitStatusExt::from_raw` - both on Unix and Windows * `Receiver::recv_timeout` * `RecvTimeoutError` * `BinaryHeap::peek_mut` * `PeekMut` * `iter::Product` * `iter::Sum` * `OccupiedEntry::remove_entry` * `VacantEntry::into_key` Deprecated * `Cell::as_unsafe_cell` * `RefCell::as_unsafe_cell` * `OccupiedEntry::remove_pair` Closes #27708 cc #27709 Closes #32313 Closes #32630 Closes #32713 Closes #34029 Closes #34392 Closes #34285 Closes #34529 --- src/libcollections/binary_heap.rs | 11 ++++---- src/libcollections/btree/map.rs | 19 ++++++++------ src/libcollections/linked_list.rs | 5 +--- src/libcollections/vec_deque.rs | 5 +--- src/libcollectionstest/lib.rs | 3 --- src/libcore/cell.rs | 36 +++++++++++++++++++++++++++ src/libcore/iter/traits.rs | 22 ++++++++-------- src/libcoretest/cell.rs | 10 ++++---- src/libcoretest/lib.rs | 1 - src/libstd/collections/hash/map.rs | 19 ++++++++------ src/libstd/net/ip.rs | 15 ++++------- src/libstd/sync/mpsc/mod.rs | 8 +++--- src/libstd/sys/unix/ext/process.rs | 2 +- src/libstd/sys/windows/ext/process.rs | 3 ++- src/libtest/lib.rs | 1 - 15 files changed, 94 insertions(+), 66 deletions(-) diff --git a/src/libcollections/binary_heap.rs b/src/libcollections/binary_heap.rs index b9f5c6fcab909..fe9b60c393f09 100644 --- a/src/libcollections/binary_heap.rs +++ b/src/libcollections/binary_heap.rs @@ -223,19 +223,19 @@ pub struct BinaryHeap { /// on `BinaryHeap`. See its documentation for details. /// /// [`peek_mut()`]: struct.BinaryHeap.html#method.peek_mut -#[unstable(feature = "binary_heap_peek_mut", issue = "34392")] +#[stable(feature = "binary_heap_peek_mut", since = "1.12.0")] pub struct PeekMut<'a, T: 'a + Ord> { heap: &'a mut BinaryHeap } -#[unstable(feature = "binary_heap_peek_mut", issue = "34392")] +#[stable(feature = "binary_heap_peek_mut", since = "1.12.0")] impl<'a, T: Ord> Drop for PeekMut<'a, T> { fn drop(&mut self) { self.heap.sift_down(0); } } -#[unstable(feature = "binary_heap_peek_mut", issue = "34392")] +#[stable(feature = "binary_heap_peek_mut", since = "1.12.0")] impl<'a, T: Ord> Deref for PeekMut<'a, T> { type Target = T; fn deref(&self) -> &T { @@ -243,7 +243,7 @@ impl<'a, T: Ord> Deref for PeekMut<'a, T> { } } -#[unstable(feature = "binary_heap_peek_mut", issue = "34392")] +#[stable(feature = "binary_heap_peek_mut", since = "1.12.0")] impl<'a, T: Ord> DerefMut for PeekMut<'a, T> { fn deref_mut(&mut self) -> &mut T { &mut self.heap.data[0] @@ -366,7 +366,6 @@ impl BinaryHeap { /// Basic usage: /// /// ``` - /// #![feature(binary_heap_peek_mut)] /// use std::collections::BinaryHeap; /// let mut heap = BinaryHeap::new(); /// assert!(heap.peek_mut().is_none()); @@ -380,7 +379,7 @@ impl BinaryHeap { /// } /// assert_eq!(heap.peek(), Some(&2)); /// ``` - #[unstable(feature = "binary_heap_peek_mut", issue = "34392")] + #[stable(feature = "binary_heap_peek_mut", since = "1.12.0")] pub fn peek_mut(&mut self) -> Option> { if self.is_empty() { None diff --git a/src/libcollections/btree/map.rs b/src/libcollections/btree/map.rs index c3a7d4023754a..a2e2ad37acb84 100644 --- a/src/libcollections/btree/map.rs +++ b/src/libcollections/btree/map.rs @@ -1981,8 +1981,6 @@ impl<'a, K: Ord, V> VacantEntry<'a, K, V> { /// # Examples /// /// ``` - /// #![feature(map_entry_recover_keys)] - /// /// use std::collections::BTreeMap; /// use std::collections::btree_map::Entry; /// @@ -1992,7 +1990,7 @@ impl<'a, K: Ord, V> VacantEntry<'a, K, V> { /// v.into_key(); /// } /// ``` - #[unstable(feature = "map_entry_recover_keys", issue = "34285")] + #[stable(feature = "map_entry_recover_keys2", since = "1.12.0")] pub fn into_key(self) -> K { self.key } @@ -2074,13 +2072,18 @@ impl<'a, K: Ord, V> OccupiedEntry<'a, K, V> { self.handle.reborrow().into_kv().0 } + /// Deprecated, renamed to `remove_entry` + #[unstable(feature = "map_entry_recover_keys", issue = "34285")] + #[rustc_deprecated(since = "1.12.0", reason = "renamed to `remove_entry`")] + pub fn remove_pair(self) -> (K, V) { + self.remove_entry() + } + /// Take ownership of the key and value from the map. /// /// # Examples /// /// ``` - /// #![feature(map_entry_recover_keys)] - /// /// use std::collections::BTreeMap; /// use std::collections::btree_map::Entry; /// @@ -2089,14 +2092,14 @@ impl<'a, K: Ord, V> OccupiedEntry<'a, K, V> { /// /// if let Entry::Occupied(o) = map.entry("poneyland") { /// // We delete the entry from the map. - /// o.remove_pair(); + /// o.remove_entry(); /// } /// /// // If now try to get the value, it will panic: /// // println!("{}", map["poneyland"]); /// ``` - #[unstable(feature = "map_entry_recover_keys", issue = "34285")] - pub fn remove_pair(self) -> (K, V) { + #[stable(feature = "map_entry_recover_keys2", since = "1.12.0")] + pub fn remove_entry(self) -> (K, V) { self.remove_kv() } diff --git a/src/libcollections/linked_list.rs b/src/libcollections/linked_list.rs index 6842f02e0e19b..73aa67849fd2a 100644 --- a/src/libcollections/linked_list.rs +++ b/src/libcollections/linked_list.rs @@ -379,8 +379,6 @@ impl LinkedList { /// # Examples /// /// ``` - /// #![feature(linked_list_contains)] - /// /// use std::collections::LinkedList; /// /// let mut list: LinkedList = LinkedList::new(); @@ -392,8 +390,7 @@ impl LinkedList { /// assert_eq!(list.contains(&0), true); /// assert_eq!(list.contains(&10), false); /// ``` - #[unstable(feature = "linked_list_contains", reason = "recently added", - issue = "32630")] + #[stable(feature = "linked_list_contains", since = "1.12.0")] pub fn contains(&self, x: &T) -> bool where T: PartialEq { diff --git a/src/libcollections/vec_deque.rs b/src/libcollections/vec_deque.rs index 9c3792afa2f1c..aa42daec4c2d1 100644 --- a/src/libcollections/vec_deque.rs +++ b/src/libcollections/vec_deque.rs @@ -938,8 +938,6 @@ impl VecDeque { /// # Examples /// /// ``` - /// #![feature(vec_deque_contains)] - /// /// use std::collections::VecDeque; /// /// let mut vector: VecDeque = VecDeque::new(); @@ -950,8 +948,7 @@ impl VecDeque { /// assert_eq!(vector.contains(&1), true); /// assert_eq!(vector.contains(&10), false); /// ``` - #[unstable(feature = "vec_deque_contains", reason = "recently added", - issue = "32630")] + #[stable(feature = "vec_deque_contains", since = "1.12.0")] pub fn contains(&self, x: &T) -> bool where T: PartialEq { diff --git a/src/libcollectionstest/lib.rs b/src/libcollectionstest/lib.rs index ab3231b2b9955..f448fcf2dbf99 100644 --- a/src/libcollectionstest/lib.rs +++ b/src/libcollectionstest/lib.rs @@ -11,7 +11,6 @@ #![deny(warnings)] #![feature(binary_heap_extras)] -#![feature(binary_heap_peek_mut)] #![feature(box_syntax)] #![feature(btree_range)] #![feature(collections)] @@ -19,7 +18,6 @@ #![feature(const_fn)] #![feature(fn_traits)] #![feature(enumset)] -#![feature(linked_list_contains)] #![feature(pattern)] #![feature(rand)] #![feature(step_by)] @@ -27,7 +25,6 @@ #![feature(test)] #![feature(unboxed_closures)] #![feature(unicode)] -#![feature(vec_deque_contains)] #![feature(vec_into_iter_as_slice)] extern crate collections; diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs index 17ec325e257b0..a388012e1daf2 100644 --- a/src/libcore/cell.rs +++ b/src/libcore/cell.rs @@ -233,10 +233,28 @@ impl Cell { /// ``` #[inline] #[unstable(feature = "as_unsafe_cell", issue = "27708")] + #[rustc_deprecated(since = "1.12.0", reason = "renamed to as_ptr")] pub fn as_unsafe_cell(&self) -> &UnsafeCell { &self.value } + /// Returns a raw pointer to the underlying data in this cell. + /// + /// # Examples + /// + /// ``` + /// use std::cell::Cell; + /// + /// let c = Cell::new(5); + /// + /// let ptr = c.as_ptr(); + /// ``` + #[inline] + #[stable(feature = "cell_as_ptr", since = "1.12.0")] + pub fn as_ptr(&self) -> *mut T { + self.value.get() + } + /// Returns a mutable reference to the underlying data. /// /// This call borrows `Cell` mutably (at compile-time) which guarantees @@ -653,10 +671,28 @@ impl RefCell { /// ``` #[inline] #[unstable(feature = "as_unsafe_cell", issue = "27708")] + #[rustc_deprecated(since = "1.12.0", reason = "renamed to as_ptr")] pub unsafe fn as_unsafe_cell(&self) -> &UnsafeCell { &self.value } + /// Returns a raw pointer to the underlying data in this cell. + /// + /// # Examples + /// + /// ``` + /// use std::cell::RefCell; + /// + /// let c = RefCell::new(5); + /// + /// let ptr = c.as_ptr(); + /// ``` + #[inline] + #[stable(feature = "cell_as_ptr", since = "1.12.0")] + pub fn as_ptr(&self) -> *mut T { + self.value.get() + } + /// Returns a mutable reference to the underlying data. /// /// This call borrows `RefCell` mutably (at compile-time) so there is no diff --git a/src/libcore/iter/traits.rs b/src/libcore/iter/traits.rs index 4cbabe3f5edaf..cb509156e325e 100644 --- a/src/libcore/iter/traits.rs +++ b/src/libcore/iter/traits.rs @@ -563,10 +563,11 @@ impl<'a, I: ExactSizeIterator + ?Sized> ExactSizeIterator for &'a mut I {} /// implement the trait can be generated by the `sum` method. Like /// `FromIterator` this trait should rarely be called directly and instead /// interacted with through `Iterator::sum`. -#[unstable(feature = "iter_arith_traits", issue = "34529")] +#[stable(feature = "iter_arith_traits", since = "1.12.0")] pub trait Sum: Sized { /// Method which takes an iterator and generates `Self` from the elements by /// "summing up" the items. + #[stable(feature = "iter_arith_traits", since = "1.12.0")] fn sum>(iter: I) -> Self; } @@ -577,16 +578,17 @@ pub trait Sum: Sized { /// which implement the trait can be generated by the `product` method. Like /// `FromIterator` this trait should rarely be called directly and instead /// interacted with through `Iterator::product`. -#[unstable(feature = "iter_arith_traits", issue = "34529")] +#[stable(feature = "iter_arith_traits", since = "1.12.0")] pub trait Product: Sized { /// Method which takes an iterator and generates `Self` from the elements by /// multiplying the items. + #[stable(feature = "iter_arith_traits", since = "1.12.0")] fn product>(iter: I) -> Self; } macro_rules! integer_sum_product { ($($a:ident)*) => ($( - #[unstable(feature = "iter_arith_traits", issue = "34529")] + #[stable(feature = "iter_arith_traits", since = "1.12.0")] impl Sum for $a { fn sum>(iter: I) -> $a { iter.fold(0, |a, b| { @@ -595,7 +597,7 @@ macro_rules! integer_sum_product { } } - #[unstable(feature = "iter_arith_traits", issue = "34529")] + #[stable(feature = "iter_arith_traits", since = "1.12.0")] impl Product for $a { fn product>(iter: I) -> $a { iter.fold(1, |a, b| { @@ -604,7 +606,7 @@ macro_rules! integer_sum_product { } } - #[unstable(feature = "iter_arith_traits", issue = "34529")] + #[stable(feature = "iter_arith_traits", since = "1.12.0")] impl<'a> Sum<&'a $a> for $a { fn sum>(iter: I) -> $a { iter.fold(0, |a, b| { @@ -613,7 +615,7 @@ macro_rules! integer_sum_product { } } - #[unstable(feature = "iter_arith_traits", issue = "34529")] + #[stable(feature = "iter_arith_traits", since = "1.12.0")] impl<'a> Product<&'a $a> for $a { fn product>(iter: I) -> $a { iter.fold(1, |a, b| { @@ -626,28 +628,28 @@ macro_rules! integer_sum_product { macro_rules! float_sum_product { ($($a:ident)*) => ($( - #[unstable(feature = "iter_arith_traits", issue = "34529")] + #[stable(feature = "iter_arith_traits", since = "1.12.0")] impl Sum for $a { fn sum>(iter: I) -> $a { iter.fold(0.0, |a, b| a + b) } } - #[unstable(feature = "iter_arith_traits", issue = "34529")] + #[stable(feature = "iter_arith_traits", since = "1.12.0")] impl Product for $a { fn product>(iter: I) -> $a { iter.fold(1.0, |a, b| a * b) } } - #[unstable(feature = "iter_arith_traits", issue = "34529")] + #[stable(feature = "iter_arith_traits", since = "1.12.0")] impl<'a> Sum<&'a $a> for $a { fn sum>(iter: I) -> $a { iter.fold(0.0, |a, b| a + *b) } } - #[unstable(feature = "iter_arith_traits", issue = "34529")] + #[stable(feature = "iter_arith_traits", since = "1.12.0")] impl<'a> Product<&'a $a> for $a { fn product>(iter: I) -> $a { iter.fold(1.0, |a, b| a * *b) diff --git a/src/libcoretest/cell.rs b/src/libcoretest/cell.rs index a635620d12abd..a7c230ba979be 100644 --- a/src/libcoretest/cell.rs +++ b/src/libcoretest/cell.rs @@ -176,21 +176,21 @@ fn ref_mut_map_accessor() { } #[test] -fn as_unsafe_cell() { +fn as_ptr() { let c1: Cell = Cell::new(0); c1.set(1); - assert_eq!(1, unsafe { *c1.as_unsafe_cell().get() }); + assert_eq!(1, unsafe { *c1.as_ptr() }); let c2: Cell = Cell::new(0); - unsafe { *c2.as_unsafe_cell().get() = 1; } + unsafe { *c2.as_ptr() = 1; } assert_eq!(1, c2.get()); let r1: RefCell = RefCell::new(0); *r1.borrow_mut() = 1; - assert_eq!(1, unsafe { *r1.as_unsafe_cell().get() }); + assert_eq!(1, unsafe { *r1.as_ptr() }); let r2: RefCell = RefCell::new(0); - unsafe { *r2.as_unsafe_cell().get() = 1; } + unsafe { *r2.as_ptr() = 1; } assert_eq!(1, *r2.borrow()); } diff --git a/src/libcoretest/lib.rs b/src/libcoretest/lib.rs index 9428b4096bfec..9116344c57938 100644 --- a/src/libcoretest/lib.rs +++ b/src/libcoretest/lib.rs @@ -10,7 +10,6 @@ #![deny(warnings)] -#![feature(as_unsafe_cell)] #![feature(borrow_state)] #![feature(box_syntax)] #![feature(cell_extras)] diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index 8039421ae7730..94710a9190f03 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -1640,13 +1640,18 @@ impl<'a, K, V> OccupiedEntry<'a, K, V> { self.elem.read().0 } + /// Deprecated, renamed to `remove_entry` + #[unstable(feature = "map_entry_recover_keys", issue = "34285")] + #[rustc_deprecated(since = "1.12.0", reason = "renamed to `remove_entry`")] + pub fn remove_pair(self) -> (K, V) { + self.remove_entry() + } + /// Take the ownership of the key and value from the map. /// /// # Examples /// /// ``` - /// #![feature(map_entry_recover_keys)] - /// /// use std::collections::HashMap; /// use std::collections::hash_map::Entry; /// @@ -1655,13 +1660,13 @@ impl<'a, K, V> OccupiedEntry<'a, K, V> { /// /// if let Entry::Occupied(o) = map.entry("poneyland") { /// // We delete the entry from the map. - /// o.remove_pair(); + /// o.remove_entry(); /// } /// /// assert_eq!(map.contains_key("poneyland"), false); /// ``` - #[unstable(feature = "map_entry_recover_keys", issue = "34285")] - pub fn remove_pair(self) -> (K, V) { + #[stable(feature = "map_entry_recover_keys2", since = "1.12.0")] + pub fn remove_entry(self) -> (K, V) { pop_internal(self.elem) } @@ -1808,8 +1813,6 @@ impl<'a, K: 'a, V: 'a> VacantEntry<'a, K, V> { /// # Examples /// /// ``` - /// #![feature(map_entry_recover_keys)] - /// /// use std::collections::HashMap; /// use std::collections::hash_map::Entry; /// @@ -1819,7 +1822,7 @@ impl<'a, K: 'a, V: 'a> VacantEntry<'a, K, V> { /// v.into_key(); /// } /// ``` - #[unstable(feature = "map_entry_recover_keys", issue = "34285")] + #[stable(feature = "map_entry_recover_keys2", since = "1.12.0")] pub fn into_key(self) -> K { self.key } diff --git a/src/libstd/net/ip.rs b/src/libstd/net/ip.rs index 2a8bd0c88beb6..4c3b993497cf5 100644 --- a/src/libstd/net/ip.rs +++ b/src/libstd/net/ip.rs @@ -63,8 +63,7 @@ impl IpAddr { /// Returns true for the special 'unspecified' address ([IPv4], [IPv6]). /// [IPv4]: ../../std/net/struct.Ipv4Addr.html#method.is_unspecified /// [IPv6]: ../../std/net/struct.Ipv6Addr.html#method.is_unspecified - #[unstable(feature="ip", issue="27709", - reason="recently added and depends on unstable Ipv4Addr.is_unspecified()")] + #[stable(feature = "ip_shared", since = "1.12.0")] pub fn is_unspecified(&self) -> bool { match *self { IpAddr::V4(ref a) => a.is_unspecified(), @@ -75,7 +74,7 @@ impl IpAddr { /// Returns true if this is a loopback address ([IPv4], [IPv6]). /// [IPv4]: ../../std/net/struct.Ipv4Addr.html#method.is_loopback /// [IPv6]: ../../std/net/struct.Ipv6Addr.html#method.is_loopback - #[unstable(feature="ip", reason="recently added", issue="27709")] + #[stable(feature = "ip_shared", since = "1.12.0")] pub fn is_loopback(&self) -> bool { match *self { IpAddr::V4(ref a) => a.is_loopback(), @@ -86,8 +85,6 @@ impl IpAddr { /// Returns true if the address appears to be globally routable ([IPv4], [IPv6]). /// [IPv4]: ../../std/net/struct.Ipv4Addr.html#method.is_global /// [IPv6]: ../../std/net/struct.Ipv6Addr.html#method.is_global - #[unstable(feature="ip", issue="27709", - reason="recently added and depends on unstable Ip{v4,v6}Addr.is_global()")] pub fn is_global(&self) -> bool { match *self { IpAddr::V4(ref a) => a.is_global(), @@ -98,7 +95,7 @@ impl IpAddr { /// Returns true if this is a multicast address ([IPv4], [IPv6]). /// [IPv4]: ../../std/net/struct.Ipv4Addr.html#method.is_multicast /// [IPv6]: ../../std/net/struct.Ipv6Addr.html#method.is_multicast - #[unstable(feature="ip", reason="recently added", issue="27709")] + #[stable(feature = "ip_shared", since = "1.12.0")] pub fn is_multicast(&self) -> bool { match *self { IpAddr::V4(ref a) => a.is_multicast(), @@ -109,8 +106,6 @@ impl IpAddr { /// Returns true if this address is in a range designated for documentation ([IPv4], [IPv6]). /// [IPv4]: ../../std/net/struct.Ipv4Addr.html#method.is_documentation /// [IPv6]: ../../std/net/struct.Ipv6Addr.html#method.is_documentation - #[unstable(feature="ip", issue="27709", - reason="recently added and depends on unstable Ipv6Addr.is_documentation()")] pub fn is_documentation(&self) -> bool { match *self { IpAddr::V4(ref a) => a.is_documentation(), @@ -147,6 +142,7 @@ impl Ipv4Addr { /// This property is defined in _UNIX Network Programming, Second Edition_, /// W. Richard Stevens, p. 891; see also [ip7] /// [ip7][http://man7.org/linux/man-pages/man7/ip.7.html] + #[stable(feature = "ip_shared", since = "1.12.0")] pub fn is_unspecified(&self) -> bool { self.inner.s_addr == 0 } @@ -515,8 +511,7 @@ impl Ipv6Addr { } /// Returns the sixteen eight-bit integers the IPv6 address consists of. - #[unstable(feature = "ipv6_to_octets", reason = "needs some testing", - issue = "32313")] + #[stable(feature = "ipv6_to_octets", since = "1.12.0")] pub fn octets(&self) -> [u8; 16] { self.inner.s6_addr } diff --git a/src/libstd/sync/mpsc/mod.rs b/src/libstd/sync/mpsc/mod.rs index 11f785dffd16a..d8b8c6a77a266 100644 --- a/src/libstd/sync/mpsc/mod.rs +++ b/src/libstd/sync/mpsc/mod.rs @@ -394,13 +394,15 @@ pub enum TryRecvError { /// This enumeration is the list of possible errors that `recv_timeout` could /// not return data when called. #[derive(PartialEq, Eq, Clone, Copy, Debug)] -#[unstable(feature = "mpsc_recv_timeout", issue = "34029")] +#[stable(feature = "mpsc_recv_timeout", since = "1.12.0")] pub enum RecvTimeoutError { /// This channel is currently empty, but the sender(s) have not yet /// disconnected, so data may yet become available. + #[stable(feature = "mpsc_recv_timeout", since = "1.12.0")] Timeout, /// This channel's sending half has become disconnected, and there will /// never be any more data received on this channel + #[stable(feature = "mpsc_recv_timeout", since = "1.12.0")] Disconnected, } @@ -912,8 +914,6 @@ impl Receiver { /// # Examples /// /// ```no_run - /// #![feature(mpsc_recv_timeout)] - /// /// use std::sync::mpsc::{self, RecvTimeoutError}; /// use std::time::Duration; /// @@ -922,7 +922,7 @@ impl Receiver { /// let timeout = Duration::from_millis(100); /// assert_eq!(Err(RecvTimeoutError::Timeout), recv.recv_timeout(timeout)); /// ``` - #[unstable(feature = "mpsc_recv_timeout", issue = "34029")] + #[stable(feature = "mpsc_recv_timeout", since = "1.12.0")] pub fn recv_timeout(&self, timeout: Duration) -> Result { // Do an optimistic try_recv to avoid the performance impact of // Instant::now() in the full-channel case. diff --git a/src/libstd/sys/unix/ext/process.rs b/src/libstd/sys/unix/ext/process.rs index 430ec5f94a6f8..dd70ba2e490ad 100644 --- a/src/libstd/sys/unix/ext/process.rs +++ b/src/libstd/sys/unix/ext/process.rs @@ -114,7 +114,7 @@ impl CommandExt for process::Command { pub trait ExitStatusExt { /// Creates a new `ExitStatus` from the raw underlying `i32` return value of /// a process. - #[unstable(feature = "exit_status_from", issue = "32713")] + #[stable(feature = "exit_status_from", since = "1.12.0")] fn from_raw(raw: i32) -> Self; /// If the process was terminated by a signal, returns that signal. diff --git a/src/libstd/sys/windows/ext/process.rs b/src/libstd/sys/windows/ext/process.rs index 56c6a73d4f82b..98166bf8cda09 100644 --- a/src/libstd/sys/windows/ext/process.rs +++ b/src/libstd/sys/windows/ext/process.rs @@ -83,10 +83,11 @@ impl IntoRawHandle for process::ChildStderr { } /// Windows-specific extensions to `std::process::ExitStatus` -#[unstable(feature = "exit_status_from", issue = "32713")] +#[stable(feature = "exit_status_from", since = "1.12.0")] pub trait ExitStatusExt { /// Creates a new `ExitStatus` from the raw underlying `u32` return value of /// a process. + #[stable(feature = "exit_status_from", since = "1.12.0")] fn from_raw(raw: u32) -> Self; } diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index 850127d9f2950..2b4193306ddf5 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -42,7 +42,6 @@ #![feature(staged_api)] #![feature(question_mark)] #![feature(panic_unwind)] -#![feature(mpsc_recv_timeout)] extern crate getopts; extern crate term; From ad90ef82b43c2c538b4145148408c763b978789d Mon Sep 17 00:00:00 2001 From: Andrew Paseltiner Date: Tue, 16 Aug 2016 20:45:07 -0400 Subject: [PATCH 2/6] Make `vec::IntoIter` covariant again Closes #35721 --- src/libcollections/vec.rs | 15 +++++++++------ src/libcollectionstest/vec.rs | 3 ++- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index a6f817a89624c..3aefcc7d4cfa4 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -1453,10 +1453,11 @@ impl IntoIterator for Vec { } else { begin.offset(self.len() as isize) as *const T }; - let buf = ptr::read(&self.buf); + let cap = self.buf.cap(); mem::forget(self); IntoIter { - _buf: buf, + buf: Shared::new(begin), + cap: cap, ptr: begin, end: end, } @@ -1708,8 +1709,9 @@ impl<'a, T> FromIterator for Cow<'a, [T]> where T: Clone { /// [`IntoIterator`]: ../../std/iter/trait.IntoIterator.html #[stable(feature = "rust1", since = "1.0.0")] pub struct IntoIter { - _buf: RawVec, - ptr: *mut T, + buf: Shared, + cap: usize, + ptr: *const T, end: *const T, } @@ -1750,7 +1752,7 @@ impl IntoIter { #[unstable(feature = "vec_into_iter_as_slice", issue = "35601")] pub fn as_mut_slice(&self) -> &mut [T] { unsafe { - slice::from_raw_parts_mut(self.ptr, self.len()) + slice::from_raw_parts_mut(self.ptr as *mut T, self.len()) } } } @@ -1846,9 +1848,10 @@ impl Drop for IntoIter { #[unsafe_destructor_blind_to_params] fn drop(&mut self) { // destroy the remaining elements - for _x in self {} + for _x in self.by_ref() {} // RawVec handles deallocation + let _ = unsafe { RawVec::from_raw_parts(*self.buf, self.cap) }; } } diff --git a/src/libcollectionstest/vec.rs b/src/libcollectionstest/vec.rs index 9556174bd2294..537fabf8ab69b 100644 --- a/src/libcollectionstest/vec.rs +++ b/src/libcollectionstest/vec.rs @@ -11,7 +11,7 @@ use std::borrow::Cow; use std::iter::{FromIterator, repeat}; use std::mem::size_of; -use std::vec::Drain; +use std::vec::{Drain, IntoIter}; use test::Bencher; @@ -537,6 +537,7 @@ fn test_cow_from() { #[allow(dead_code)] fn assert_covariance() { fn drain<'new>(d: Drain<'static, &'static str>) -> Drain<'new, &'new str> { d } + fn into_iter<'new>(i: IntoIter<&'static str>) -> IntoIter<&'new str> { i } } #[bench] From a1c08042b054a0e2b95535cee7f2819b113f8014 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Tue, 16 Aug 2016 16:11:03 -0700 Subject: [PATCH 3/6] 1.11 changelog --- RELEASES.md | 177 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 177 insertions(+) diff --git a/RELEASES.md b/RELEASES.md index c798c56cd6d03..8817d7f88a738 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1,3 +1,180 @@ +Version 1.11.0 (2016-08-18) +=========================== + +Language +-------- + +* [`cfg_attr` works on `path` attributes] + (https://github.com/rust-lang/rust/pull/34546) +* [Support nested `cfg_attr` attributes] + (https://github.com/rust-lang/rust/pull/34216) +* [Allow statement-generating braced macro invocations at the end of blocks] + (https://github.com/rust-lang/rust/pull/34436) +* [Macros can be expanded inside of trait definitions] + (https://github.com/rust-lang/rust/pull/34213) +* [`#[macro_use]` works properly when it is itself expanded from a macro] + (https://github.com/rust-lang/rust/pull/34032) + +Stabilized APIs +--------------- + +* [`BinaryHeap::append`] + (https://doc.rust-lang.org/std/collections/binary_heap/struct.BinaryHeap.html#method.append) +* [`BTreeMap::append`] + (https://doc.rust-lang.org/std/collections/btree_map/struct.BTreeMap.html#method.append) +* [`BTreeMap::split_off`] + (https://doc.rust-lang.org/std/collections/btree_map/struct.BTreeMap.html#method.split_off) +* [`BTreeSet::append`] + (https://doc.rust-lang.org/std/collections/btree_set/struct.BTreeSet.html#method.append) +* [`BTreeSet::split_off`] + (https://doc.rust-lang.org/std/collections/btree_set/struct.BTreeSet.html#method.split_off) +* [`f32::to_degrees`] + (https://doc.rust-lang.org/std/primitive.f32.html#method.to_degrees) + (in libcore - previously stabilized in libstd) +* [`f32::to_radians`] + (https://doc.rust-lang.org/std/primitive.f32.html#method.to_radians) + (in libcore - previously stabilized in libstd) +* [`f64::to_degrees`] + (https://doc.rust-lang.org/std/primitive.f64.html#method.to_degrees) + (in libcore - previously stabilized in libstd) +* [`f64::to_radians`] + (https://doc.rust-lang.org/std/primitive.f64.html#method.to_radians) + (in libcore - previously stabilized in libstd) +* [`Iterator::sum`] + (https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.sum) +* [`Iterator::product`] + (https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.sum) +* [`Cell::get_mut`] + (https://doc.rust-lang.org/std/cell/struct.Cell.html#method.get_mut) +* [`RefCell::get_mut`] + (https://doc.rust-lang.org/std/cell/struct.RefCell.html#method.get_mut) + +Libraries +--------- + +* [The `thread_local!` macro supports multiple definitions in a single + invocation, and can apply attributes] + (https://github.com/rust-lang/rust/pull/34077) +* [`Cow` implements `Default`] + (https://github.com/rust-lang/rust/pull/34305) +* [`Wrapping` implements binary, octal, lower-hex and upper-hex + `Display` formatting] + (https://github.com/rust-lang/rust/pull/34190) +* [The range types implement `Hash`] + (https://github.com/rust-lang/rust/pull/34180) +* [`lookup_host` ignores unknown address types] + (https://github.com/rust-lang/rust/pull/34067) +* [`assert_eq!` accepts a custom error message, like `assert!` does] + (https://github.com/rust-lang/rust/pull/33976) +* [The main thread is now called "main" instead of "<main>"] + (https://github.com/rust-lang/rust/pull/33803) + +Cargo +----- + +* [Disallow specifying features of transitive deps] + (https://github.com/rust-lang/cargo/pull/2821) +* [Add color support for Windows consoles] + (https://github.com/rust-lang/cargo/pull/2804) +* [Fix `harness = false` on `[lib]` sections] + (https://github.com/rust-lang/cargo/pull/2795) +* [Don't panic when `links` contains a '.'] + (https://github.com/rust-lang/cargo/pull/2787) +* [Build scripts can emit warnings] + (https://github.com/rust-lang/cargo/pull/2630), + and `-vv` prints warnings for all crates. +* [Ignore file locks on OS X NFS mounts] + (https://github.com/rust-lang/cargo/pull/2720) +* [Don't warn about `package.metadata` keys] + (https://github.com/rust-lang/cargo/pull/2668). + This provides room for expansion by arbitrary tools. +* [Add support for cdylib crate types] + (https://github.com/rust-lang/cargo/pull/2741) +* [Prevent publishing crates when files are dirty] + (https://github.com/rust-lang/cargo/pull/2781) +* [Don't fetch all crates on clean] + (https://github.com/rust-lang/cargo/pull/2704) +* [Propagate --color option to rustc] + (https://github.com/rust-lang/cargo/pull/2779) +* [Fix `cargo doc --open` on Windows] + (https://github.com/rust-lang/cargo/pull/2780) +* [Improve autocompletion] + (https://github.com/rust-lang/cargo/pull/2772) +* [Configure colors of stderr as well as stdout] + (https://github.com/rust-lang/cargo/pull/2739) + +Performance +----------- + +* [Caching projections speeds up type check dramatically for some + workloads] + (https://github.com/rust-lang/rust/pull/33816) +* [The default `HashMap` hasher is SipHash 1-3 instead of SipHash 2-4] + (https://github.com/rust-lang/rust/pull/33940) + This hasher is faster, but is believed to provide sufficient + protection from collision attacks. +* [Comparison of `Ipv4Addr` is 10x faster] + (https://github.com/rust-lang/rust/pull/33891) + +Rustdoc +------- + +* [Fix empty implementation section on some module pages] + (https://github.com/rust-lang/rust/pull/34536) +* [Fix inlined renamed reexports in import lists] + (https://github.com/rust-lang/rust/pull/34479) +* [Fix search result layout for enum variants and struct fields] + (https://github.com/rust-lang/rust/pull/34477) +* [Fix issues with source links to external crates] + (https://github.com/rust-lang/rust/pull/34387) +* [Fix redirect pages for renamed reexports] + (https://github.com/rust-lang/rust/pull/34245) + +Tooling +------- + +* [rustc is better at finding the MSVC toolchain] + (https://github.com/rust-lang/rust/pull/34492) +* [When emitting debug info, rustc emits frame pointers for closures, + shims and glue, as it does for all other functions] + (https://github.com/rust-lang/rust/pull/33909) +* [rust-lldb warns about unsupported versions of LLDB] + (https://github.com/rust-lang/rust/pull/34646) +* Many more errors have been given error codes and extended + explanations +* API documentation continues to be improved, with many new examples + +Misc +---- + +* [rustc no longer hangs when dependencies recursively re-export + submodules] + (https://github.com/rust-lang/rust/pull/34542) +* [rustc requires LLVM 3.7+] + (https://github.com/rust-lang/rust/pull/34104) +* [The 'How Safe and Unsafe Interact' chapter of The Rustonomicon was + rewritten] + (https://github.com/rust-lang/rust/pull/33895) +* [rustc support 16-bit pointer sizes] + (https://github.com/rust-lang/rust/pull/33460). + No targets use this yet, but it works toward AVR support. + +Compatibility Notes +------------------- + +* [`const`s and `static`s may not have unsized types] + (https://github.com/rust-lang/rust/pull/34443) +* [The new follow-set rules that place restrictions on `macro_rules!` + in order to ensure syntax forward-compatibility have been enabled] + (https://github.com/rust-lang/rust/pull/33982) + This was an [ammendment to RFC 550] + (https://github.com/rust-lang/rfcs/pull/1384), + and has been a warning since 1.10. +* [`cfg` attribute process has been refactored to fix various bugs] + (https://github.com/rust-lang/rust/pull/33706). + This causes breakage in some corner cases. + + Version 1.10.0 (2016-07-07) =========================== From e531f2b60902c35a4cbc43657590caec1b01bfd6 Mon Sep 17 00:00:00 2001 From: Simonas Kazlauskas Date: Wed, 17 Aug 2016 04:13:43 +0300 Subject: [PATCH 4/6] Properly invalidate the early exit cache Fixes #35737 --- src/librustc_mir/build/scope.rs | 43 +++++++++++---------- src/test/run-pass/mir_early_return_scope.rs | 37 ++++++++++++++++++ 2 files changed, 60 insertions(+), 20 deletions(-) create mode 100644 src/test/run-pass/mir_early_return_scope.rs diff --git a/src/librustc_mir/build/scope.rs b/src/librustc_mir/build/scope.rs index cae9e8379897c..ca9e108bb415a 100644 --- a/src/librustc_mir/build/scope.rs +++ b/src/librustc_mir/build/scope.rs @@ -198,8 +198,11 @@ impl<'tcx> Scope<'tcx> { /// /// Should always be run for all inner scopes when a drop is pushed into some scope enclosing a /// larger extent of code. - fn invalidate_cache(&mut self) { - self.cached_exits = FnvHashMap(); + /// + /// `unwind` controls whether caches for the unwind branch are also invalidated. + fn invalidate_cache(&mut self, unwind: bool) { + self.cached_exits.clear(); + if !unwind { return; } for dropdata in &mut self.drops { if let DropKind::Value { ref mut cached_block } = dropdata.kind { *cached_block = None; @@ -455,25 +458,29 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { }; for scope in self.scopes.iter_mut().rev() { - if scope.extent == extent { + let this_scope = scope.extent == extent; + // We must invalidate all the caches leading up to the scope we’re looking for, because + // the cached blocks will branch into build of scope not containing the new drop. If we + // add stuff to the currently inspected scope, then in some cases the non-unwind caches + // may become invalid, therefore we should invalidate these as well. The unwind caches + // will stay correct, because the already generated unwind blocks cannot be influenced + // by just added drop. + // + // If we’re scheduling cleanup for non-droppable type (i.e. DropKind::Storage), then we + // do not need to invalidate unwind branch, because DropKind::Storage does not end up + // built in the unwind branch currently. + let invalidate_unwind = needs_drop && !this_scope; + scope.invalidate_cache(invalidate_unwind); + if this_scope { if let DropKind::Value { .. } = drop_kind { scope.needs_cleanup = true; } - - // No need to invalidate any caches here. The just-scheduled drop will branch into - // the drop that comes before it in the vector. scope.drops.push(DropData { span: span, location: lvalue.clone(), kind: drop_kind }); return; - } else { - // We must invalidate all the cached_blocks leading up to the scope we’re - // looking for, because all of the blocks in the chain will become incorrect. - if let DropKind::Value { .. } = drop_kind { - scope.invalidate_cache() - } } } span_bug!(span, "extent {:?} not in scope to drop {:?}", extent, lvalue); @@ -490,11 +497,12 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { value: &Lvalue<'tcx>, item_ty: Ty<'tcx>) { for scope in self.scopes.iter_mut().rev() { + // We must invalidate all the caches leading up to and including the scope we’re + // looking for, because otherwise some of the blocks in the chain will become + // incorrect and must be rebuilt. + scope.invalidate_cache(true); if scope.extent == extent { assert!(scope.free.is_none(), "scope already has a scheduled free!"); - // We also must invalidate the caches in the scope for which the free is scheduled - // because the drops must branch into the free we schedule here. - scope.invalidate_cache(); scope.needs_cleanup = true; scope.free = Some(FreeData { span: span, @@ -503,11 +511,6 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { cached_block: None }); return; - } else { - // We must invalidate all the cached_blocks leading up to the scope we’re looking - // for, because otherwise some/most of the blocks in the chain will become - // incorrect. - scope.invalidate_cache(); } } span_bug!(span, "extent {:?} not in scope to free {:?}", extent, value); diff --git a/src/test/run-pass/mir_early_return_scope.rs b/src/test/run-pass/mir_early_return_scope.rs new file mode 100644 index 0000000000000..c27e57358b09b --- /dev/null +++ b/src/test/run-pass/mir_early_return_scope.rs @@ -0,0 +1,37 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +static mut DROP: bool = false; + +struct ConnWrap(Conn); +impl ::std::ops::Deref for ConnWrap { + type Target=Conn; + fn deref(&self) -> &Conn { &self.0 } +} + +struct Conn; +impl Drop for Conn { + fn drop(&mut self) { unsafe { DROP = true; } } +} + +fn inner() { + let conn = &*match Some(ConnWrap(Conn)) { + Some(val) => val, + None => return, + }; + return; +} + +fn main() { + inner(); + unsafe { + assert_eq!(DROP, true); + } +} From fa131c3ae85a9bcd2f7cff4282c200abeb5e7c5a Mon Sep 17 00:00:00 2001 From: Simonas Kazlauskas Date: Thu, 18 Aug 2016 00:38:30 +0300 Subject: [PATCH 5/6] Nice graphs --- src/librustc_mir/build/scope.rs | 60 ++++++++++++++++++++++++++------- 1 file changed, 48 insertions(+), 12 deletions(-) diff --git a/src/librustc_mir/build/scope.rs b/src/librustc_mir/build/scope.rs index ca9e108bb415a..dc1d63a291118 100644 --- a/src/librustc_mir/build/scope.rs +++ b/src/librustc_mir/build/scope.rs @@ -459,16 +459,52 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { for scope in self.scopes.iter_mut().rev() { let this_scope = scope.extent == extent; - // We must invalidate all the caches leading up to the scope we’re looking for, because - // the cached blocks will branch into build of scope not containing the new drop. If we - // add stuff to the currently inspected scope, then in some cases the non-unwind caches - // may become invalid, therefore we should invalidate these as well. The unwind caches - // will stay correct, because the already generated unwind blocks cannot be influenced - // by just added drop. + // When building drops, we try to cache chains of drops in such a way so these drops + // could be reused by the drops which would branch into the cached (already built) + // blocks. This, however, means that whenever we add a drop into a scope which already + // had some blocks built (and thus, cached) for it, we must invalidate all caches which + // might branch into the scope which had a drop just added to it. This is necessary, + // because otherwise some other code might use the cache to branch into already built + // chain of drops, essentially ignoring the newly added drop. // - // If we’re scheduling cleanup for non-droppable type (i.e. DropKind::Storage), then we - // do not need to invalidate unwind branch, because DropKind::Storage does not end up - // built in the unwind branch currently. + // For example consider there’s two scopes with a drop in each. These are built and + // thus the caches are filled: + // + // +--------------------------------------------------------+ + // | +---------------------------------+ | + // | | +--------+ +-------------+ | +---------------+ | + // | | | return | <-+ | drop(outer) | <-+ | drop(middle) | | + // | | +--------+ +-------------+ | +---------------+ | + // | +------------|outer_scope cache|--+ | + // +------------------------------|middle_scope cache|------+ + // + // Now, a new, inner-most scope is added along with a new drop into both inner-most and + // outer-most scopes: + // + // +------------------------------------------------------------+ + // | +----------------------------------+ | + // | | +--------+ +-------------+ | +---------------+ | +-------------+ + // | | | return | <+ | drop(new) | <-+ | drop(middle) | <--+| drop(inner) | + // | | +--------+ | | drop(outer) | | +---------------+ | +-------------+ + // | | +-+ +-------------+ | | + // | +---|invalid outer_scope cache|----+ | + // +----=----------------|invalid middle_scope cache|-----------+ + // + // If, when adding `drop(new)` we do not invalidate the cached blocks for both + // outer_scope and middle_scope, then, when building drops for the inner (right-most) + // scope, the old, cached blocks, without `drop(new)` will get used, producing the + // wrong results. + // + // The cache and its invalidation for unwind branch is somewhat special. The cache is + // per-drop, rather than per scope, which has a several different implications. Adding + // a new drop into a scope will not invalidate cached blocks of the prior drops in the + // scope. That is true, because none of the already existing drops will have an edge + // into a block with the newly added drop. + // + // Note that this code iterates scopes from the inner-most to the outer-most, + // invalidating caches of each scope visited. This way bare minimum of the + // caches gets invalidated. i.e. if a new drop is added into the middle scope, the + // cache of outer scpoe stays intact. let invalidate_unwind = needs_drop && !this_scope; scope.invalidate_cache(invalidate_unwind); if this_scope { @@ -497,9 +533,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { value: &Lvalue<'tcx>, item_ty: Ty<'tcx>) { for scope in self.scopes.iter_mut().rev() { - // We must invalidate all the caches leading up to and including the scope we’re - // looking for, because otherwise some of the blocks in the chain will become - // incorrect and must be rebuilt. + // See the comment in schedule_drop above. The primary difference is that we invalidate + // the unwind blocks unconditionally. That’s because the box free may be considered + // outer-most cleanup within the scope. scope.invalidate_cache(true); if scope.extent == extent { assert!(scope.free.is_none(), "scope already has a scheduled free!"); From b879ed9db4242ef489dbed7623573b3bc866aa66 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 22 Aug 2016 22:42:07 -0700 Subject: [PATCH 6/6] mk: Bump the beta version to .2 --- mk/main.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mk/main.mk b/mk/main.mk index c6c3e70abc37a..c857c02bb8835 100644 --- a/mk/main.mk +++ b/mk/main.mk @@ -18,7 +18,7 @@ CFG_RELEASE_NUM=1.12.0 # An optional number to put after the label, e.g. '.2' -> '-beta.2' # NB Make sure it starts with a dot to conform to semver pre-release # versions (section 9) -CFG_PRERELEASE_VERSION=.1 +CFG_PRERELEASE_VERSION=.2 ifeq ($(CFG_RELEASE_CHANNEL),stable) # This is the normal semver version string, e.g. "0.12.0", "0.12.0-nightly"