diff options
| author | bors <bors@rust-lang.org> | 2017-02-05 14:15:18 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2017-02-05 14:15:18 +0000 |
| commit | 9c8cdb2923a69177017165a4cdb0e1ea673fc49f (patch) | |
| tree | 69ebb9fa31a84a98c42c14f56e866762a844ce2f /src/libstd | |
| parent | 696f5c1fc695494053709ae3b18b4c6a65b619a6 (diff) | |
| parent | 0a09274e27c7b409a321c0c7ed20d99492601b44 (diff) | |
| download | rust-9c8cdb2923a69177017165a4cdb0e1ea673fc49f.tar.gz rust-9c8cdb2923a69177017165a4cdb0e1ea673fc49f.zip | |
Auto merge of #39563 - frewsxcv:rollup, r=frewsxcv
Rollup of 19 pull requests - Successful merges: #38518, #38921, #38959, #38983, #39009, #39107, #39193, #39289, #39312, #39393, #39442, #39443, #39453, #39454, #39471, #39477, #39478, #39527, #39552 - Failed merges:
Diffstat (limited to 'src/libstd')
28 files changed, 352 insertions, 72 deletions
diff --git a/src/libstd/ascii.rs b/src/libstd/ascii.rs index b220504d2b4..35c388ba076 100644 --- a/src/libstd/ascii.rs +++ b/src/libstd/ascii.rs @@ -399,7 +399,7 @@ impl ExactSizeIterator for EscapeDefault {} #[unstable(feature = "fused", issue = "35602")] impl FusedIterator for EscapeDefault {} -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for EscapeDefault { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad("EscapeDefault { .. }") diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index 8058972e750..ffb7a1a1fc1 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -1283,7 +1283,7 @@ impl<'a, K, V> Clone for Iter<'a, K, V> { } } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl<'a, K: Debug, V: Debug> fmt::Debug for Iter<'a, K, V> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_list() @@ -1318,7 +1318,7 @@ impl<'a, K, V> Clone for Keys<'a, K, V> { } } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl<'a, K: Debug, V: Debug> fmt::Debug for Keys<'a, K, V> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_list() @@ -1341,7 +1341,7 @@ impl<'a, K, V> Clone for Values<'a, K, V> { } } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl<'a, K: Debug, V: Debug> fmt::Debug for Values<'a, K, V> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_list() @@ -1591,7 +1591,7 @@ impl<'a, K, V> ExactSizeIterator for IterMut<'a, K, V> { #[unstable(feature = "fused", issue = "35602")] impl<'a, K, V> FusedIterator for IterMut<'a, K, V> {} -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl<'a, K, V> fmt::Debug for IterMut<'a, K, V> where K: fmt::Debug, V: fmt::Debug, @@ -1626,7 +1626,7 @@ impl<K, V> ExactSizeIterator for IntoIter<K, V> { #[unstable(feature = "fused", issue = "35602")] impl<K, V> FusedIterator for IntoIter<K, V> {} -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl<K: Debug, V: Debug> fmt::Debug for IntoIter<K, V> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_list() @@ -1704,7 +1704,7 @@ impl<'a, K, V> ExactSizeIterator for ValuesMut<'a, K, V> { #[unstable(feature = "fused", issue = "35602")] impl<'a, K, V> FusedIterator for ValuesMut<'a, K, V> {} -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl<'a, K, V> fmt::Debug for ValuesMut<'a, K, V> where K: fmt::Debug, V: fmt::Debug, @@ -1739,7 +1739,7 @@ impl<'a, K, V> ExactSizeIterator for Drain<'a, K, V> { #[unstable(feature = "fused", issue = "35602")] impl<'a, K, V> FusedIterator for Drain<'a, K, V> {} -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl<'a, K, V> fmt::Debug for Drain<'a, K, V> where K: fmt::Debug, V: fmt::Debug, @@ -2227,7 +2227,7 @@ impl Default for RandomState { } } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for RandomState { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad("RandomState { .. }") diff --git a/src/libstd/collections/hash/set.rs b/src/libstd/collections/hash/set.rs index 341b050862f..a3f7e13bbf9 100644 --- a/src/libstd/collections/hash/set.rs +++ b/src/libstd/collections/hash/set.rs @@ -948,7 +948,7 @@ impl<'a, K> ExactSizeIterator for Iter<'a, K> { #[unstable(feature = "fused", issue = "35602")] impl<'a, K> FusedIterator for Iter<'a, K> {} -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl<'a, K: fmt::Debug> fmt::Debug for Iter<'a, K> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_list() @@ -977,7 +977,7 @@ impl<K> ExactSizeIterator for IntoIter<K> { #[unstable(feature = "fused", issue = "35602")] impl<K> FusedIterator for IntoIter<K> {} -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl<K: fmt::Debug> fmt::Debug for IntoIter<K> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let entries_iter = self.iter.inner.iter().map(|(k, _)| k); @@ -1007,7 +1007,7 @@ impl<'a, K> ExactSizeIterator for Drain<'a, K> { #[unstable(feature = "fused", issue = "35602")] impl<'a, K> FusedIterator for Drain<'a, K> {} -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl<'a, K: fmt::Debug> fmt::Debug for Drain<'a, K> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let entries_iter = self.iter.inner.iter().map(|(k, _)| k); @@ -1050,7 +1050,7 @@ impl<'a, T, S> Iterator for Intersection<'a, T, S> } } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl<'a, T, S> fmt::Debug for Intersection<'a, T, S> where T: fmt::Debug + Eq + Hash, S: BuildHasher, @@ -1109,7 +1109,7 @@ impl<'a, T, S> FusedIterator for Difference<'a, T, S> { } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl<'a, T, S> fmt::Debug for Difference<'a, T, S> where T: fmt::Debug + Eq + Hash, S: BuildHasher, @@ -1150,7 +1150,7 @@ impl<'a, T, S> FusedIterator for SymmetricDifference<'a, T, S> { } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl<'a, T, S> fmt::Debug for SymmetricDifference<'a, T, S> where T: fmt::Debug + Eq + Hash, S: BuildHasher, @@ -1176,7 +1176,7 @@ impl<'a, T, S> FusedIterator for Union<'a, T, S> { } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl<'a, T, S> fmt::Debug for Union<'a, T, S> where T: fmt::Debug + Eq + Hash, S: BuildHasher, diff --git a/src/libstd/env.rs b/src/libstd/env.rs index c3a6b2433ed..29f2ac6ab44 100644 --- a/src/libstd/env.rs +++ b/src/libstd/env.rs @@ -145,7 +145,7 @@ impl Iterator for Vars { fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() } } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for Vars { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad("Vars { .. }") @@ -159,7 +159,7 @@ impl Iterator for VarsOs { fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() } } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for VarsOs { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad("VarsOs { .. }") @@ -382,7 +382,7 @@ impl<'a> Iterator for SplitPaths<'a> { fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() } } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl<'a> fmt::Debug for SplitPaths<'a> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad("SplitPaths { .. }") @@ -665,7 +665,7 @@ impl DoubleEndedIterator for Args { } } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for Args { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad("Args { .. }") @@ -690,7 +690,7 @@ impl DoubleEndedIterator for ArgsOs { fn next_back(&mut self) -> Option<OsString> { self.inner.next_back() } } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for ArgsOs { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad("ArgsOs { .. }") diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs index 249627c430c..e5562d05f10 100644 --- a/src/libstd/fs.rs +++ b/src/libstd/fs.rs @@ -869,7 +869,7 @@ impl Metadata { } } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for Metadata { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("Metadata") diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index de5fc5bfad1..8cb7b2bda75 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -1450,7 +1450,7 @@ pub struct Chain<T, U> { done_first: bool, } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl<T: fmt::Debug, U: fmt::Debug> fmt::Debug for Chain<T, U> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("Chain") diff --git a/src/libstd/io/stdio.rs b/src/libstd/io/stdio.rs index 83a675eb512..e16e8019b5f 100644 --- a/src/libstd/io/stdio.rs +++ b/src/libstd/io/stdio.rs @@ -282,7 +282,7 @@ impl Stdin { } } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for Stdin { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad("Stdin { .. }") @@ -321,7 +321,7 @@ impl<'a> BufRead for StdinLock<'a> { fn consume(&mut self, n: usize) { self.inner.consume(n) } } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl<'a> fmt::Debug for StdinLock<'a> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad("StdinLock { .. }") @@ -438,7 +438,7 @@ impl Stdout { } } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for Stdout { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad("Stdout { .. }") @@ -470,7 +470,7 @@ impl<'a> Write for StdoutLock<'a> { } } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl<'a> fmt::Debug for StdoutLock<'a> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad("StdoutLock { .. }") @@ -573,7 +573,7 @@ impl Stderr { } } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for Stderr { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad("Stderr { .. }") @@ -605,7 +605,7 @@ impl<'a> Write for StderrLock<'a> { } } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl<'a> fmt::Debug for StderrLock<'a> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad("StderrLock { .. }") diff --git a/src/libstd/io/util.rs b/src/libstd/io/util.rs index e50665120eb..4163187488e 100644 --- a/src/libstd/io/util.rs +++ b/src/libstd/io/util.rs @@ -98,7 +98,7 @@ impl BufRead for Empty { fn consume(&mut self, _n: usize) {} } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for Empty { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad("Empty { .. }") @@ -141,7 +141,7 @@ impl Read for Repeat { } } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for Repeat { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad("Repeat { .. }") @@ -180,7 +180,7 @@ impl Write for Sink { fn flush(&mut self) -> io::Result<()> { Ok(()) } } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for Sink { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad("Sink { .. }") diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 181694dead0..9bcecebf693 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -277,6 +277,7 @@ #![feature(oom)] #![feature(optin_builtin_traits)] #![feature(panic_unwind)] +#![feature(peek)] #![feature(placement_in_syntax)] #![feature(prelude_import)] #![feature(pub_restricted)] diff --git a/src/libstd/net/mod.rs b/src/libstd/net/mod.rs index 2b60fc38198..b0d2e3e4687 100644 --- a/src/libstd/net/mod.rs +++ b/src/libstd/net/mod.rs @@ -106,7 +106,10 @@ impl Iterator for LookupHost { fn next(&mut self) -> Option<SocketAddr> { self.0.next() } } -#[stable(feature = "std_debug", since = "1.15.0")] +#[unstable(feature = "lookup_host", reason = "unsure about the returned \ + iterator and returning socket \ + addresses", + issue = "27705")] impl fmt::Debug for LookupHost { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad("LookupHost { .. }") diff --git a/src/libstd/net/tcp.rs b/src/libstd/net/tcp.rs index cbc672c28bc..9bead22ef7f 100644 --- a/src/libstd/net/tcp.rs +++ b/src/libstd/net/tcp.rs @@ -296,6 +296,29 @@ impl TcpStream { self.0.write_timeout() } + /// Receives data on the socket from the remote adress to which it is + /// connected, without removing that data from the queue. On success, + /// returns the number of bytes peeked. + /// + /// Successive calls return the same data. This is accomplished by passing + /// `MSG_PEEK` as a flag to the underlying `recv` system call. + /// + /// # Examples + /// + /// ```no_run + /// #![feature(peek)] + /// use std::net::TcpStream; + /// + /// let stream = TcpStream::connect("127.0.0.1:8000") + /// .expect("couldn't bind to address"); + /// let mut buf = [0; 10]; + /// let len = stream.peek(&mut buf).expect("peek failed"); + /// ``` + #[unstable(feature = "peek", issue = "38980")] + pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> { + self.0.peek(buf) + } + /// Sets the value of the `TCP_NODELAY` option on this socket. /// /// If set, this option disables the Nagle algorithm. This means that @@ -1406,4 +1429,35 @@ mod tests { Err(e) => panic!("unexpected error {}", e), } } + + #[test] + fn peek() { + each_ip(&mut |addr| { + let (txdone, rxdone) = channel(); + + let srv = t!(TcpListener::bind(&addr)); + let _t = thread::spawn(move|| { + let mut cl = t!(srv.accept()).0; + cl.write(&[1,3,3,7]).unwrap(); + t!(rxdone.recv()); + }); + + let mut c = t!(TcpStream::connect(&addr)); + let mut b = [0; 10]; + for _ in 1..3 { + let len = c.peek(&mut b).unwrap(); + assert_eq!(len, 4); + } + let len = c.read(&mut b).unwrap(); + assert_eq!(len, 4); + + t!(c.set_nonblocking(true)); + match c.peek(&mut b) { + Ok(_) => panic!("expected error"), + Err(ref e) if e.kind() == ErrorKind::WouldBlock => {} + Err(e) => panic!("unexpected error {}", e), + } + t!(txdone.send(())); + }) + } } diff --git a/src/libstd/net/udp.rs b/src/libstd/net/udp.rs index 492e57f6e44..f452c75d389 100644 --- a/src/libstd/net/udp.rs +++ b/src/libstd/net/udp.rs @@ -83,6 +83,30 @@ impl UdpSocket { self.0.recv_from(buf) } + /// Receives data from the socket, without removing it from the queue. + /// + /// Successive calls return the same data. This is accomplished by passing + /// `MSG_PEEK` as a flag to the underlying `recvfrom` system call. + /// + /// On success, returns the number of bytes peeked and the address from + /// whence the data came. + /// + /// # Examples + /// + /// ```no_run + /// #![feature(peek)] + /// use std::net::UdpSocket; + /// + /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address"); + /// let mut buf = [0; 10]; + /// let (number_of_bytes, src_addr) = socket.peek_from(&mut buf) + /// .expect("Didn't receive data"); + /// ``` + #[unstable(feature = "peek", issue = "38980")] + pub fn peek_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> { + self.0.peek_from(buf) + } + /// Sends data on the socket to the given address. On success, returns the /// number of bytes written. /// @@ -579,6 +603,37 @@ impl UdpSocket { self.0.recv(buf) } + /// Receives data on the socket from the remote adress to which it is + /// connected, without removing that data from the queue. On success, + /// returns the number of bytes peeked. + /// + /// Successive calls return the same data. This is accomplished by passing + /// `MSG_PEEK` as a flag to the underlying `recv` system call. + /// + /// # Errors + /// + /// This method will fail if the socket is not connected. The `connect` method + /// will connect this socket to a remote address. + /// + /// # Examples + /// + /// ```no_run + /// #![feature(peek)] + /// use std::net::UdpSocket; + /// + /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address"); + /// socket.connect("127.0.0.1:8080").expect("connect function failed"); + /// let mut buf = [0; 10]; + /// match socket.peek(&mut buf) { + /// Ok(received) => println!("received {} bytes", received), + /// Err(e) => println!("peek function failed: {:?}", e), + /// } + /// ``` + #[unstable(feature = "peek", issue = "38980")] + pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> { + self.0.peek(buf) + } + /// Moves this UDP socket into or out of nonblocking mode. /// /// On Unix this corresponds to calling fcntl, and on Windows this @@ -870,6 +925,48 @@ mod tests { } #[test] + fn connect_send_peek_recv() { + each_ip(&mut |addr, _| { + let socket = t!(UdpSocket::bind(&addr)); + t!(socket.connect(addr)); + + t!(socket.send(b"hello world")); + + for _ in 1..3 { + let mut buf = [0; 11]; + let size = t!(socket.peek(&mut buf)); + assert_eq!(b"hello world", &buf[..]); + assert_eq!(size, 11); + } + + let mut buf = [0; 11]; + let size = t!(socket.recv(&mut buf)); + assert_eq!(b"hello world", &buf[..]); + assert_eq!(size, 11); + }) + } + + #[test] + fn peek_from() { + each_ip(&mut |addr, _| { + let socket = t!(UdpSocket::bind(&addr)); + t!(socket.send_to(b"hello world", &addr)); + + for _ in 1..3 { + let mut buf = [0; 11]; + let (size, _) = t!(socket.peek_from(&mut buf)); + assert_eq!(b"hello world", &buf[..]); + assert_eq!(size, 11); + } + + let mut buf = [0; 11]; + let (size, _) = t!(socket.recv_from(&mut buf)); + assert_eq!(b"hello world", &buf[..]); + assert_eq!(size, 11); + }) + } + + #[test] fn ttl() { let ttl = 100; diff --git a/src/libstd/os/raw.rs b/src/libstd/os/raw.rs index cc154f7ab41..68d4ca90019 100644 --- a/src/libstd/os/raw.rs +++ b/src/libstd/os/raw.rs @@ -73,7 +73,7 @@ pub enum c_void { #[doc(hidden)] __variant2, } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for c_void { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad("c_void") diff --git a/src/libstd/panic.rs b/src/libstd/panic.rs index faf4949e861..ac0d0d2afb8 100644 --- a/src/libstd/panic.rs +++ b/src/libstd/panic.rs @@ -297,7 +297,7 @@ impl<R, F: FnOnce() -> R> FnOnce<()> for AssertUnwindSafe<F> { } } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl<T: fmt::Debug> fmt::Debug for AssertUnwindSafe<T> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_tuple("AssertUnwindSafe") diff --git a/src/libstd/process.rs b/src/libstd/process.rs index 5af4ba53bf9..c16b97ebda5 100644 --- a/src/libstd/process.rs +++ b/src/libstd/process.rs @@ -114,7 +114,7 @@ impl IntoInner<imp::Process> for Child { fn into_inner(self) -> imp::Process { self.handle } } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for Child { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("Child") @@ -160,7 +160,7 @@ impl FromInner<AnonPipe> for ChildStdin { } } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for ChildStdin { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad("ChildStdin { .. }") @@ -201,7 +201,7 @@ impl FromInner<AnonPipe> for ChildStdout { } } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for ChildStdout { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad("ChildStdout { .. }") @@ -242,7 +242,7 @@ impl FromInner<AnonPipe> for ChildStderr { } } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for ChildStderr { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad("ChildStderr { .. }") @@ -696,7 +696,7 @@ impl FromInner<imp::Stdio> for Stdio { } } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for Stdio { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad("Stdio { .. }") @@ -959,10 +959,27 @@ impl Child { /// /// # Examples /// +/// Due to this function’s behavior regarding destructors, a conventional way +/// to use the function is to extract the actual computation to another +/// function and compute the exit code from its return value: +/// /// ``` -/// use std::process; +/// use std::io::{self, Write}; +/// +/// fn run_app() -> Result<(), ()> { +/// // Application logic here +/// Ok(()) +/// } /// -/// process::exit(0); +/// fn main() { +/// ::std::process::exit(match run_app() { +/// Ok(_) => 0, +/// Err(err) => { +/// writeln!(io::stderr(), "error: {:?}", err).unwrap(); +/// 1 +/// } +/// }); +/// } /// ``` /// /// Due to [platform-specific behavior], the exit code for this example will be diff --git a/src/libstd/sync/barrier.rs b/src/libstd/sync/barrier.rs index b8e83dced8d..fc4fd4ce92b 100644 --- a/src/libstd/sync/barrier.rs +++ b/src/libstd/sync/barrier.rs @@ -55,7 +55,7 @@ struct BarrierState { #[stable(feature = "rust1", since = "1.0.0")] pub struct BarrierWaitResult(bool); -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for Barrier { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad("Barrier { .. }") @@ -110,7 +110,7 @@ impl Barrier { } } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for BarrierWaitResult { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("BarrierWaitResult") diff --git a/src/libstd/sync/condvar.rs b/src/libstd/sync/condvar.rs index 5c85c4879a8..7ee1c98565c 100644 --- a/src/libstd/sync/condvar.rs +++ b/src/libstd/sync/condvar.rs @@ -240,7 +240,7 @@ impl Condvar { } } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for Condvar { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad("Condvar { .. }") diff --git a/src/libstd/sync/mutex.rs b/src/libstd/sync/mutex.rs index 2efddeb4610..0d6ad5e38e9 100644 --- a/src/libstd/sync/mutex.rs +++ b/src/libstd/sync/mutex.rs @@ -428,7 +428,7 @@ impl<'a, T: ?Sized> Drop for MutexGuard<'a, T> { } } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl<'a, T: ?Sized + fmt::Debug> fmt::Debug for MutexGuard<'a, T> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("MutexGuard") diff --git a/src/libstd/sync/once.rs b/src/libstd/sync/once.rs index a9747639aac..ba993751391 100644 --- a/src/libstd/sync/once.rs +++ b/src/libstd/sync/once.rs @@ -330,7 +330,7 @@ impl Once { } } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for Once { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad("Once { .. }") diff --git a/src/libstd/sync/rwlock.rs b/src/libstd/sync/rwlock.rs index adbb98e4b1f..a3db0adeda0 100644 --- a/src/libstd/sync/rwlock.rs +++ b/src/libstd/sync/rwlock.rs @@ -361,7 +361,7 @@ impl<'rwlock, T: ?Sized> RwLockWriteGuard<'rwlock, T> { } } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl<'a, T: fmt::Debug> fmt::Debug for RwLockReadGuard<'a, T> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("RwLockReadGuard") @@ -370,7 +370,7 @@ impl<'a, T: fmt::Debug> fmt::Debug for RwLockReadGuard<'a, T> { } } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl<'a, T: fmt::Debug> fmt::Debug for RwLockWriteGuard<'a, T> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("RwLockWriteGuard") diff --git a/src/libstd/sys/unix/ext/process.rs b/src/libstd/sys/unix/ext/process.rs index 585dcbb9a34..2961c4ec582 100644 --- a/src/libstd/sys/unix/ext/process.rs +++ b/src/libstd/sys/unix/ext/process.rs @@ -67,10 +67,20 @@ pub trait CommandExt { /// an error indicating why the exec (or another part of the setup of the /// `Command`) failed. /// + /// `exec` not returning has the same implications as calling + /// [`process::exit`] – no destructors on the current stack or any other + /// thread’s stack will be run. Therefore, it is recommended to only call + /// `exec` at a point where it is fine to not run any destructors. Note, + /// that the `execvp` syscall independently guarantees that all memory is + /// freed and all file descriptors with the `CLOEXEC` option (set by default + /// on all file descriptors opened by the standard library) are closed. + /// /// This function, unlike `spawn`, will **not** `fork` the process to create /// a new child. Like spawn, however, the default behavior for the stdio /// descriptors will be to inherited from the current process. /// + /// [`process::exit`]: ../../../process/fn.exit.html + /// /// # Notes /// /// The process may be in a "broken state" if this function returns in diff --git a/src/libstd/sys/unix/net.rs b/src/libstd/sys/unix/net.rs index ad287bbec38..5efddca110f 100644 --- a/src/libstd/sys/unix/net.rs +++ b/src/libstd/sys/unix/net.rs @@ -10,12 +10,13 @@ use ffi::CStr; use io; -use libc::{self, c_int, size_t, sockaddr, socklen_t, EAI_SYSTEM}; +use libc::{self, c_int, c_void, size_t, sockaddr, socklen_t, EAI_SYSTEM, MSG_PEEK}; +use mem; use net::{SocketAddr, Shutdown}; use str; use sys::fd::FileDesc; use sys_common::{AsInner, FromInner, IntoInner}; -use sys_common::net::{getsockopt, setsockopt}; +use sys_common::net::{getsockopt, setsockopt, sockaddr_to_addr}; use time::Duration; pub use sys::{cvt, cvt_r}; @@ -155,8 +156,46 @@ impl Socket { self.0.duplicate().map(Socket) } + fn recv_with_flags(&self, buf: &mut [u8], flags: c_int) -> io::Result<usize> { + let ret = cvt(unsafe { + libc::recv(self.0.raw(), + buf.as_mut_ptr() as *mut c_void, + buf.len(), + flags) + })?; + Ok(ret as usize) + } + pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> { - self.0.read(buf) + self.recv_with_flags(buf, 0) + } + + pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> { + self.recv_with_flags(buf, MSG_PEEK) + } + + fn recv_from_with_flags(&self, buf: &mut [u8], flags: c_int) + -> io::Result<(usize, SocketAddr)> { + let mut storage: libc::sockaddr_storage = unsafe { mem::zeroed() }; + let mut addrlen = mem::size_of_val(&storage) as libc::socklen_t; + + let n = cvt(unsafe { + libc::recvfrom(self.0.raw(), + buf.as_mut_ptr() as *mut c_void, + buf.len(), + flags, + &mut storage as *mut _ as *mut _, + &mut addrlen) + })?; + Ok((n as usize, sockaddr_to_addr(&storage, addrlen as usize)?)) + } + + pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> { + self.recv_from_with_flags(buf, 0) + } + + pub fn peek_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> { + self.recv_from_with_flags(buf, MSG_PEEK) } pub fn read_to_end(&self, buf: &mut Vec<u8>) -> io::Result<usize> { diff --git a/src/libstd/sys/windows/c.rs b/src/libstd/sys/windows/c.rs index 1b29bf73c7a..850d6f49612 100644 --- a/src/libstd/sys/windows/c.rs +++ b/src/libstd/sys/windows/c.rs @@ -167,6 +167,7 @@ pub const SYMLINK_FLAG_RELATIVE: DWORD = 0x00000001; pub const FSCTL_SET_REPARSE_POINT: DWORD = 0x900a4; pub const SYMBOLIC_LINK_FLAG_DIRECTORY: DWORD = 0x1; +pub const SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE: DWORD = 0x2; // Note that these are not actually HANDLEs, just values to pass to GetStdHandle pub const STD_INPUT_HANDLE: DWORD = -10i32 as DWORD; @@ -245,6 +246,7 @@ pub const IP_ADD_MEMBERSHIP: c_int = 12; pub const IP_DROP_MEMBERSHIP: c_int = 13; pub const IPV6_ADD_MEMBERSHIP: c_int = 12; pub const IPV6_DROP_MEMBERSHIP: c_int = 13; +pub const MSG_PEEK: c_int = 0x2; #[repr(C)] pub struct ip_mreq { diff --git a/src/libstd/sys/windows/fs.rs b/src/libstd/sys/windows/fs.rs index c410fcd1ee0..4efc68afdc4 100644 --- a/src/libstd/sys/windows/fs.rs +++ b/src/libstd/sys/windows/fs.rs @@ -646,9 +646,25 @@ pub fn symlink_inner(src: &Path, dst: &Path, dir: bool) -> io::Result<()> { let src = to_u16s(src)?; let dst = to_u16s(dst)?; let flags = if dir { c::SYMBOLIC_LINK_FLAG_DIRECTORY } else { 0 }; - cvt(unsafe { - c::CreateSymbolicLinkW(dst.as_ptr(), src.as_ptr(), flags) as c::BOOL - })?; + // Formerly, symlink creation required the SeCreateSymbolicLink privilege. For the Windows 10 + // Creators Update, Microsoft loosened this to allow unprivileged symlink creation if the + // computer is in Developer Mode, but SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE must be + // added to dwFlags to opt into this behaviour. + let result = cvt(unsafe { + c::CreateSymbolicLinkW(dst.as_ptr(), src.as_ptr(), + flags | c::SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE) as c::BOOL + }); + if let Err(err) = result { + if err.raw_os_error() == Some(c::ERROR_INVALID_PARAMETER as i32) { + // Older Windows objects to SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE, + // so if we encounter ERROR_INVALID_PARAMETER, retry without that flag. + cvt(unsafe { + c::CreateSymbolicLinkW(dst.as_ptr(), src.as_ptr(), flags) as c::BOOL + })?; + } else { + return Err(err); + } + } Ok(()) } diff --git a/src/libstd/sys/windows/net.rs b/src/libstd/sys/windows/net.rs index aca6994503f..adf6210d82e 100644 --- a/src/libstd/sys/windows/net.rs +++ b/src/libstd/sys/windows/net.rs @@ -147,12 +147,12 @@ impl Socket { Ok(socket) } - pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> { + fn recv_with_flags(&self, buf: &mut [u8], flags: c_int) -> io::Result<usize> { // On unix when a socket is shut down all further reads return 0, so we // do the same on windows to map a shut down socket to returning EOF. let len = cmp::min(buf.len(), i32::max_value() as usize) as i32; unsafe { - match c::recv(self.0, buf.as_mut_ptr() as *mut c_void, len, 0) { + match c::recv(self.0, buf.as_mut_ptr() as *mut c_void, len, flags) { -1 if c::WSAGetLastError() == c::WSAESHUTDOWN => Ok(0), -1 => Err(last_error()), n => Ok(n as usize) @@ -160,6 +160,46 @@ impl Socket { } } + pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> { + self.recv_with_flags(buf, 0) + } + + pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> { + self.recv_with_flags(buf, c::MSG_PEEK) + } + + fn recv_from_with_flags(&self, buf: &mut [u8], flags: c_int) + -> io::Result<(usize, SocketAddr)> { + let mut storage: c::SOCKADDR_STORAGE_LH = unsafe { mem::zeroed() }; + let mut addrlen = mem::size_of_val(&storage) as c::socklen_t; + let len = cmp::min(buf.len(), <wrlen_t>::max_value() as usize) as wrlen_t; + + // On unix when a socket is shut down all further reads return 0, so we + // do the same on windows to map a shut down socket to returning EOF. + unsafe { + match c::recvfrom(self.0, + buf.as_mut_ptr() as *mut c_void, + len, + flags, + &mut storage as *mut _ as *mut _, + &mut addrlen) { + -1 if c::WSAGetLastError() == c::WSAESHUTDOWN => { + Ok((0, net::sockaddr_to_addr(&storage, addrlen as usize)?)) + }, + -1 => Err(last_error()), + n => Ok((n as usize, net::sockaddr_to_addr(&storage, addrlen as usize)?)), + } + } + } + + pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> { + self.recv_from_with_flags(buf, 0) + } + + pub fn peek_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> { + self.recv_from_with_flags(buf, c::MSG_PEEK) + } + pub fn read_to_end(&self, buf: &mut Vec<u8>) -> io::Result<usize> { let mut me = self; (&mut me).read_to_end(buf) diff --git a/src/libstd/sys_common/net.rs b/src/libstd/sys_common/net.rs index 10ad61f4c80..3cdeb511945 100644 --- a/src/libstd/sys_common/net.rs +++ b/src/libstd/sys_common/net.rs @@ -91,7 +91,7 @@ fn sockname<F>(f: F) -> io::Result<SocketAddr> } } -fn sockaddr_to_addr(storage: &c::sockaddr_storage, +pub fn sockaddr_to_addr(storage: &c::sockaddr_storage, len: usize) -> io::Result<SocketAddr> { match storage.ss_family as c_int { c::AF_INET => { @@ -222,6 +222,10 @@ impl TcpStream { self.inner.timeout(c::SO_SNDTIMEO) } + pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> { + self.inner.peek(buf) + } + pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> { self.inner.read(buf) } @@ -441,17 +445,11 @@ impl UdpSocket { } pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> { - let mut storage: c::sockaddr_storage = unsafe { mem::zeroed() }; - let mut addrlen = mem::size_of_val(&storage) as c::socklen_t; - let len = cmp::min(buf.len(), <wrlen_t>::max_value() as usize) as wrlen_t; + self.inner.recv_from(buf) + } - let n = cvt(unsafe { - c::recvfrom(*self.inner.as_inner(), - buf.as_mut_ptr() as *mut c_void, - len, 0, - &mut storage as *mut _ as *mut _, &mut addrlen) - })?; - Ok((n as usize, sockaddr_to_addr(&storage, addrlen as usize)?)) + pub fn peek_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> { + self.inner.peek_from(buf) } pub fn send_to(&self, buf: &[u8], dst: &SocketAddr) -> io::Result<usize> { @@ -578,6 +576,10 @@ impl UdpSocket { self.inner.read(buf) } + pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> { + self.inner.peek(buf) + } + pub fn send(&self, buf: &[u8]) -> io::Result<usize> { let len = cmp::min(buf.len(), <wrlen_t>::max_value() as usize) as wrlen_t; let ret = cvt(unsafe { diff --git a/src/libstd/thread/local.rs b/src/libstd/thread/local.rs index 01584979aab..5166ddf8a21 100644 --- a/src/libstd/thread/local.rs +++ b/src/libstd/thread/local.rs @@ -99,7 +99,7 @@ pub struct LocalKey<T: 'static> { init: fn() -> T, } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl<T: 'static> fmt::Debug for LocalKey<T> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad("LocalKey { .. }") @@ -332,7 +332,6 @@ pub mod os { marker: marker::PhantomData<Cell<T>>, } - #[stable(feature = "std_debug", since = "1.15.0")] impl<T> fmt::Debug for Key<T> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad("Key { .. }") diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs index 8789006436c..93e320c4522 100644 --- a/src/libstd/thread/mod.rs +++ b/src/libstd/thread/mod.rs @@ -698,7 +698,7 @@ impl ThreadId { } } -#[stable(feature = "std_debug", since = "1.15.0")] +#[unstable(feature = "thread_id", issue = "21507")] impl fmt::Debug for ThreadId { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad("ThreadId { .. }") @@ -1002,7 +1002,7 @@ impl<T> IntoInner<imp::Thread> for JoinHandle<T> { fn into_inner(self) -> imp::Thread { self.0.native.unwrap() } } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl<T> fmt::Debug for JoinHandle<T> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad("JoinHandle { .. }") |
