From c470d4a415fe6f091170cf7e55926e252252d0f9 Mon Sep 17 00:00:00 2001 From: Christophe Biocca Date: Sun, 13 Nov 2016 21:55:41 -0500 Subject: [PATCH 01/73] Add borrow support for slice binary search methods. --- src/libcore/slice.rs | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/src/libcore/slice.rs b/src/libcore/slice.rs index 871b63145ca6d..d716be26139d2 100644 --- a/src/libcore/slice.rs +++ b/src/libcore/slice.rs @@ -33,6 +33,7 @@ // * The `raw` and `bytes` submodules. // * Boilerplate trait implementations. +use borrow::Borrow; use cmp::Ordering::{self, Less, Equal, Greater}; use cmp; use fmt; @@ -94,15 +95,17 @@ pub trait SliceExt { #[stable(feature = "core", since = "1.6.0")] fn as_ptr(&self) -> *const Self::Item; #[stable(feature = "core", since = "1.6.0")] - fn binary_search(&self, x: &Self::Item) -> Result - where Self::Item: Ord; + fn binary_search(&self, x: &Q) -> Result + where Self::Item: Borrow, + Q: Ord; #[stable(feature = "core", since = "1.6.0")] fn binary_search_by<'a, F>(&'a self, f: F) -> Result where F: FnMut(&'a Self::Item) -> Ordering; #[stable(feature = "slice_binary_search_by_key", since = "1.10.0")] - fn binary_search_by_key<'a, B, F>(&'a self, b: &B, f: F) -> Result + fn binary_search_by_key<'a, B, F, Q: ?Sized>(&'a self, b: &Q, f: F) -> Result where F: FnMut(&'a Self::Item) -> B, - B: Ord; + B: Borrow, + Q: Ord; #[stable(feature = "core", since = "1.6.0")] fn len(&self) -> usize; #[stable(feature = "core", since = "1.6.0")] @@ -477,8 +480,8 @@ impl SliceExt for [T] { m >= n && needle == &self[m-n..] } - fn binary_search(&self, x: &T) -> Result where T: Ord { - self.binary_search_by(|p| p.cmp(x)) + fn binary_search(&self, x: &Q) -> Result where T: Borrow, Q: Ord { + self.binary_search_by(|p| p.borrow().cmp(x)) } #[inline] @@ -506,11 +509,12 @@ impl SliceExt for [T] { } #[inline] - fn binary_search_by_key<'a, B, F>(&'a self, b: &B, mut f: F) -> Result + fn binary_search_by_key<'a, B, F, Q: ?Sized>(&'a self, b: &Q, mut f: F) -> Result where F: FnMut(&'a Self::Item) -> B, - B: Ord + B: Borrow, + Q: Ord { - self.binary_search_by(|k| f(k).cmp(b)) + self.binary_search_by(|k| f(k).borrow().cmp(b)) } } From 9976f5f7c551edb557b0f4633dfcd772cf040a2b Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 7 Dec 2016 16:20:53 -0800 Subject: [PATCH 02/73] Add missing doc examples for SocketAddr struct --- src/libstd/sys/unix/ext/net.rs | 36 ++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/src/libstd/sys/unix/ext/net.rs b/src/libstd/sys/unix/ext/net.rs index 80f53da1cefe0..47a803424b534 100644 --- a/src/libstd/sys/unix/ext/net.rs +++ b/src/libstd/sys/unix/ext/net.rs @@ -85,6 +85,21 @@ enum AddressKind<'a> { } /// An address associated with a Unix socket. +/// +/// # Examples +/// +/// ``` +/// use std::os::unix::net::UnixListener; +/// +/// let socket = match UnixListener::bind("/tmp/sock") { +/// Ok(sock) => sock, +/// Err(e) => { +/// println!("Couldn't bind: {:?}", e); +/// return +/// } +/// }; +/// let addr = socket.local_addr().expect("Couldn't get local address"); +/// ``` #[derive(Clone)] #[stable(feature = "unix_socket", since = "1.10.0")] pub struct SocketAddr { @@ -121,6 +136,16 @@ impl SocketAddr { } /// Returns true if and only if the address is unnamed. + /// + /// # Examples + /// + /// ``` + /// use std::os::unix::net::UnixListener; + /// + /// let socket = match UnixListener::bind("/tmp/sock").unwrap(); + /// let addr = socket.local_addr().expect("Couldn't get local address"); + /// assert_eq!(addr.is_unnamed(), false); + /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] pub fn is_unnamed(&self) -> bool { if let AddressKind::Unnamed = self.address() { @@ -131,6 +156,17 @@ impl SocketAddr { } /// Returns the contents of this address if it is a `pathname` address. + /// + /// # Examples + /// + /// ``` + /// use std::os::unix::net::UnixListener; + /// use std::path::Path; + /// + /// let socket = match UnixListener::bind("/tmp/sock").unwrap(); + /// let addr = socket.local_addr().expect("Couldn't get local address"); + /// assert_eq!(addr.as_pathname(), Some(Path::new("/tmp/sock"))); + /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] pub fn as_pathname(&self) -> Option<&Path> { if let AddressKind::Pathname(path) = self.address() { From 7fe17f96d5acf5753e05414748cf3e1f63371c81 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 7 Dec 2016 18:09:39 -0800 Subject: [PATCH 03/73] Add doc examples for UnixStream --- src/libstd/sys/unix/ext/net.rs | 151 +++++++++++++++++++++++++++++++-- 1 file changed, 145 insertions(+), 6 deletions(-) diff --git a/src/libstd/sys/unix/ext/net.rs b/src/libstd/sys/unix/ext/net.rs index 47a803424b534..69954d91857af 100644 --- a/src/libstd/sys/unix/ext/net.rs +++ b/src/libstd/sys/unix/ext/net.rs @@ -218,7 +218,7 @@ impl<'a> fmt::Display for AsciiEscaped<'a> { /// /// # Examples /// -/// ```rust,no_run +/// ```no_run /// use std::os::unix::net::UnixStream; /// use std::io::prelude::*; /// @@ -248,6 +248,20 @@ impl fmt::Debug for UnixStream { impl UnixStream { /// Connects to the socket named by `path`. + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixStream; + /// + /// let socket = match UnixStream::connect("/tmp/sock") { + /// Ok(sock) => sock, + /// Err(e) => { + /// println!("Couldn't connect: {:?}", e); + /// return + /// } + /// }; + /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] pub fn connect>(path: P) -> io::Result { fn inner(path: &Path) -> io::Result { @@ -265,6 +279,20 @@ impl UnixStream { /// Creates an unnamed pair of connected sockets. /// /// Returns two `UnixStream`s which are connected to each other. + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixStream; + /// + /// let (sock1, sock2) = match UnixStream::pair() { + /// Ok((sock1, sock2)) => (sock1, sock2), + /// Err(e) => { + /// println!("Couldn't create a pair of sockets: {:?}", e); + /// return + /// } + /// }; + /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] pub fn pair() -> io::Result<(UnixStream, UnixStream)> { let (i1, i2) = Socket::new_pair(libc::AF_UNIX, libc::SOCK_STREAM)?; @@ -277,18 +305,45 @@ impl UnixStream { /// object references. Both handles will read and write the same stream of /// data, and options set on one stream will be propogated to the other /// stream. + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixStream; + /// + /// let socket = match UnixStream::connect("/tmp/sock").unwrap(); + /// let sock_copy = socket.try_clone().expect("Couldn't clone socket..."); + /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] pub fn try_clone(&self) -> io::Result { self.0.duplicate().map(UnixStream) } /// Returns the socket address of the local half of this connection. + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixStream; + /// + /// let socket = match UnixStream::connect("/tmp/sock").unwrap(); + /// let addr = socket.local_addr().expect("Couldn't get local address"); + /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] pub fn local_addr(&self) -> io::Result { SocketAddr::new(|addr, len| unsafe { libc::getsockname(*self.0.as_inner(), addr, len) }) } /// Returns the socket address of the remote half of this connection. + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixStream; + /// + /// let socket = match UnixStream::connect("/tmp/sock").unwrap(); + /// let addr = socket.peer_addr().expect("Couldn't get peer address"); + /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] pub fn peer_addr(&self) -> io::Result { SocketAddr::new(|addr, len| unsafe { libc::getpeername(*self.0.as_inner(), addr, len) }) @@ -296,9 +351,23 @@ impl UnixStream { /// Sets the read timeout for the socket. /// - /// If the provided value is `None`, then `read` calls will block - /// indefinitely. It is an error to pass the zero `Duration` to this + /// If the provided value is [`None`], then [`read()`] calls will block + /// indefinitely. It is an error to pass the zero [`Duration`] to this /// method. + /// + /// [`None`]: ../../std/option/enum.Option.html#variant.None + /// [`read()`]: ../../std/io/trait.Read.html#tymethod.read + /// [`Duration`]: ../../std/time/struct.Duration.html + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixStream; + /// use std::time::Duration; + /// + /// let socket = match UnixStream::connect("/tmp/sock").unwrap(); + /// socket.set_read_timeout(Some(Duration::new(1, 0))).expect("Couldn't set read timeout"); + /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] pub fn set_read_timeout(&self, timeout: Option) -> io::Result<()> { self.0.set_timeout(timeout, libc::SO_RCVTIMEO) @@ -306,33 +375,91 @@ impl UnixStream { /// Sets the write timeout for the socket. /// - /// If the provided value is `None`, then `write` calls will block - /// indefinitely. It is an error to pass the zero `Duration` to this + /// If the provided value is [`None`], then [`write()`] calls will block + /// indefinitely. It is an error to pass the zero [`Duration`] to this /// method. + /// + /// [`None`]: ../../std/option/enum.Option.html#variant.None + /// [`read()`]: ../../std/io/trait.Write.html#tymethod.write + /// [`Duration`]: ../../std/time/struct.Duration.html + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixStream; + /// use std::time::Duration; + /// + /// let socket = match UnixStream::connect("/tmp/sock").unwrap(); + /// socket.set_write_timeout(Some(Duration::new(1, 0))).expect("Couldn't set write timeout"); + /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] pub fn set_write_timeout(&self, timeout: Option) -> io::Result<()> { self.0.set_timeout(timeout, libc::SO_SNDTIMEO) } /// Returns the read timeout of this socket. + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixStream; + /// use std::time::Duration; + /// + /// let socket = match UnixStream::connect("/tmp/sock").unwrap(); + /// socket.set_read_timeout(Some(Duration::new(1, 0))).expect("Couldn't set read timeout"); + /// assert_eq!(socket.read_timeout().unwrap(), Some(Duration::new(1, 0))); + /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] pub fn read_timeout(&self) -> io::Result> { self.0.timeout(libc::SO_RCVTIMEO) } /// Returns the write timeout of this socket. + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixStream; + /// use std::time::Duration; + /// + /// let socket = match UnixStream::connect("/tmp/sock").unwrap(); + /// socket.set_write_timeout(Some(Duration::new(1, 0))).expect("Couldn't set write timeout"); + /// assert_eq!(socket.write_timeout().unwrap(), Some(Duration::new(1, 0))); + /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] pub fn write_timeout(&self) -> io::Result> { self.0.timeout(libc::SO_SNDTIMEO) } /// Moves the socket into or out of nonblocking mode. + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixStream; + /// use std::time::Duration; + /// + /// let socket = match UnixStream::connect("/tmp/sock").unwrap(); + /// socket.set_nonblocking(true).expect("Couldn't set non blocking"); + /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { self.0.set_nonblocking(nonblocking) } /// Returns the value of the `SO_ERROR` option. + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixStream; + /// use std::time::Duration; + /// + /// let socket = match UnixStream::connect("/tmp/sock").unwrap(); + /// if let Ok(Some(err)) = socket.take_error() { + /// println!("Got error: {:?}", err); + /// } + /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] pub fn take_error(&self) -> io::Result> { self.0.take_error() @@ -342,7 +469,19 @@ impl UnixStream { /// /// This function will cause all pending and future I/O calls on the /// specified portions to immediately return with an appropriate value - /// (see the documentation of `Shutdown`). + /// (see the documentation of [`Shutdown`]). + /// + /// [`Shutdown`]: ../../std/net/enum.Shutdown.html + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixStream; + /// use std::time::Duration; + /// + /// let socket = match UnixStream::connect("/tmp/sock").unwrap(); + /// socket.shutdown(Shutdown::Both).expect("shutdown function failed"); + /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] pub fn shutdown(&self, how: Shutdown) -> io::Result<()> { self.0.shutdown(how) From c35b9f6703e11e08d5250434472b36a109353cc3 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 7 Dec 2016 18:26:54 -0800 Subject: [PATCH 04/73] Add UnixListener doc examples --- src/libstd/sys/unix/ext/net.rs | 111 ++++++++++++++++++++++++++++++--- 1 file changed, 101 insertions(+), 10 deletions(-) diff --git a/src/libstd/sys/unix/ext/net.rs b/src/libstd/sys/unix/ext/net.rs index 69954d91857af..f346e3eb44f05 100644 --- a/src/libstd/sys/unix/ext/net.rs +++ b/src/libstd/sys/unix/ext/net.rs @@ -437,7 +437,6 @@ impl UnixStream { /// /// ```no_run /// use std::os::unix::net::UnixStream; - /// use std::time::Duration; /// /// let socket = match UnixStream::connect("/tmp/sock").unwrap(); /// socket.set_nonblocking(true).expect("Couldn't set non blocking"); @@ -453,7 +452,6 @@ impl UnixStream { /// /// ```no_run /// use std::os::unix::net::UnixStream; - /// use std::time::Duration; /// /// let socket = match UnixStream::connect("/tmp/sock").unwrap(); /// if let Ok(Some(err)) = socket.take_error() { @@ -477,7 +475,6 @@ impl UnixStream { /// /// ```no_run /// use std::os::unix::net::UnixStream; - /// use std::time::Duration; /// /// let socket = match UnixStream::connect("/tmp/sock").unwrap(); /// socket.shutdown(Shutdown::Both).expect("shutdown function failed"); @@ -557,7 +554,7 @@ impl IntoRawFd for UnixStream { /// /// # Examples /// -/// ```rust,no_run +/// ```no_run /// use std::thread; /// use std::os::unix::net::{UnixStream, UnixListener}; /// @@ -580,9 +577,6 @@ impl IntoRawFd for UnixStream { /// } /// } /// } -/// -/// // close the listener socket -/// drop(listener); /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] pub struct UnixListener(Socket); @@ -601,6 +595,20 @@ impl fmt::Debug for UnixListener { impl UnixListener { /// Creates a new `UnixListener` bound to the specified socket. + /// + /// # Examples + /// + /// ``` + /// use std::os::unix::net::UnixListener; + /// + /// let listener = match UnixListener::bind("/path/to/the/socket") { + /// Ok(sock) => sock, + /// Err(e) => { + /// println!("Couldn't connect: {:?}", e); + /// return + /// } + /// }; + /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] pub fn bind>(path: P) -> io::Result { fn inner(path: &Path) -> io::Result { @@ -620,8 +628,23 @@ impl UnixListener { /// Accepts a new incoming connection to this listener. /// /// This function will block the calling thread until a new Unix connection - /// is established. When established, the corersponding `UnixStream` and + /// is established. When established, the corersponding [`UnixStream`] and /// the remote peer's address will be returned. + /// + /// [`UnixStream`]: ../../std/os/unix/net/struct.UnixStream.html + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixListener; + /// + /// let listener = UnixListener::bind("/path/to/the/socket").unwrap(); + /// + /// match listener.accept() { + /// Ok((socket, addr)) => println!("Got a client: {:?}", addr), + /// Err(e) => println!("accept function failed: {:?}", e), + /// } + /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] pub fn accept(&self) -> io::Result<(UnixStream, SocketAddr)> { let mut storage: libc::sockaddr_un = unsafe { mem::zeroed() }; @@ -636,24 +659,65 @@ impl UnixListener { /// The returned `UnixListener` is a reference to the same socket that this /// object references. Both handles can be used to accept incoming /// connections and options set on one listener will affect the other. + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixListener; + /// + /// let listener = UnixListener::bind("/path/to/the/socket").unwrap(); + /// + /// let listener_copy = listener.try_clone().expect("try_clone failed"); + /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] pub fn try_clone(&self) -> io::Result { self.0.duplicate().map(UnixListener) } /// Returns the local socket address of this listener. + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixListener; + /// + /// let listener = UnixListener::bind("/path/to/the/socket").unwrap(); + /// + /// let addr = socket.local_addr().expect("Couldn't get local address"); + /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] pub fn local_addr(&self) -> io::Result { SocketAddr::new(|addr, len| unsafe { libc::getsockname(*self.0.as_inner(), addr, len) }) } /// Moves the socket into or out of nonblocking mode. + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixListener; + /// + /// let listener = UnixListener::bind("/path/to/the/socket").unwrap(); + /// + /// socket.set_nonblocking(true).expect("Couldn't set non blocking"); + /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { self.0.set_nonblocking(nonblocking) } /// Returns the value of the `SO_ERROR` option. + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixListener; + /// + /// let socket = match UnixListener::bind("/tmp/sock").unwrap(); + /// if let Ok(Some(err)) = socket.take_error() { + /// println!("Got error: {:?}", err); + /// } + /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] pub fn take_error(&self) -> io::Result> { self.0.take_error() @@ -661,8 +725,35 @@ impl UnixListener { /// Returns an iterator over incoming connections. /// - /// The iterator will never return `None` and will also not yield the - /// peer's `SocketAddr` structure. + /// The iterator will never return [`None`] and will also not yield the + /// peer's [`SocketAddr`] structure. + /// + /// [`None`]: ../../std/option/enum.Option.html#variant.None + /// [`SocketAddr`]: struct.SocketAddr.html + /// + /// # Examples + /// + /// ```no_run + /// use std::thread; + /// use std::os::unix::net::{UnixStream, UnixListener}; + /// + /// fn handle_client(stream: UnixStream) { + /// // ... + /// } + /// + /// let listener = UnixListener::bind("/path/to/the/socket").unwrap(); + /// + /// for stream in listener.incoming() { + /// match stream { + /// Ok(stream) => { + /// thread::spawn(|| handle_client(stream)); + /// } + /// Err(err) => { + /// break; + /// } + /// } + /// } + /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] pub fn incoming<'a>(&'a self) -> Incoming<'a> { Incoming { listener: self } From a78a33c52a3a4766e170a8dbe0328cbbd03d4f14 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 7 Dec 2016 18:28:07 -0800 Subject: [PATCH 05/73] Add Incoming doc examples --- src/libstd/sys/unix/ext/net.rs | 33 ++++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/src/libstd/sys/unix/ext/net.rs b/src/libstd/sys/unix/ext/net.rs index f346e3eb44f05..d49f9343b0e77 100644 --- a/src/libstd/sys/unix/ext/net.rs +++ b/src/libstd/sys/unix/ext/net.rs @@ -791,9 +791,36 @@ impl<'a> IntoIterator for &'a UnixListener { } } -/// An iterator over incoming connections to a `UnixListener`. +/// An iterator over incoming connections to a [`UnixListener`]. /// -/// It will never return `None`. +/// It will never return [`None`]. +/// +/// [`None`]: ../../std/option/enum.Option.html#variant.None +/// [`UnixListener`]: struct.UnixListener.html +/// +/// # Examples +/// +/// ```no_run +/// use std::thread; +/// use std::os::unix::net::{UnixStream, UnixListener}; +/// +/// fn handle_client(stream: UnixStream) { +/// // ... +/// } +/// +/// let listener = UnixListener::bind("/path/to/the/socket").unwrap(); +/// +/// for stream in listener.incoming() { +/// match stream { +/// Ok(stream) => { +/// thread::spawn(|| handle_client(stream)); +/// } +/// Err(err) => { +/// break; +/// } +/// } +/// } +/// ``` #[derive(Debug)] #[stable(feature = "unix_socket", since = "1.10.0")] pub struct Incoming<'a> { @@ -817,7 +844,7 @@ impl<'a> Iterator for Incoming<'a> { /// /// # Examples /// -/// ```rust,no_run +/// ```no_run /// use std::os::unix::net::UnixDatagram; /// /// let socket = UnixDatagram::bind("/path/to/my/socket").unwrap(); From ef09db0ff301b98f6980f4bd3dad6fb060d18daa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sat, 3 Dec 2016 17:41:14 -0800 Subject: [PATCH 06/73] Point out the known type when field doesn't satisfy bound For file ```rust use std::path::Path; fn f(p: Path) { } ``` provide the following error ```nocode error[E0277]: the trait bound `[u8]: std::marker::Sized` is not satisfied in `std::path::Path` --> file.rs:3:6 | 3 | fn f(p: Path) { } | ^ within `std::path::Path`, the trait `std::marker::Sized` is not implemented for `[u8]` | = note: `[u8]` does not have a constant size known at compile-time = note: required because it appears within the type `std::path::Path` = note: all local variables must have a statically known size ``` --- src/librustc/traits/error_reporting.rs | 30 ++++++++++++++++++++------ src/test/compile-fail/E0277.rs | 9 ++++++++ 2 files changed, 32 insertions(+), 7 deletions(-) diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 2e8e45468ddcb..db375f2be735b 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -487,13 +487,29 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { } else { let trait_ref = trait_predicate.to_poly_trait_ref(); - let mut err = struct_span_err!(self.tcx.sess, span, E0277, - "the trait bound `{}` is not satisfied", - trait_ref.to_predicate()); - err.span_label(span, &format!("the trait `{}` is not implemented \ - for `{}`", - trait_ref, - trait_ref.self_ty())); + let (post_message, pre_message) = + if let ObligationCauseCode::BuiltinDerivedObligation(ref data) + = obligation.cause.code { + let parent_trait_ref = self.resolve_type_vars_if_possible( + &data.parent_trait_ref); + (format!(" in `{}`", parent_trait_ref.0.self_ty()), + format!("within `{}`, ", parent_trait_ref.0.self_ty())) + } else { + (String::new(), String::new()) + }; + let mut err = struct_span_err!( + self.tcx.sess, + span, + E0277, + "the trait bound `{}` is not satisfied{}", + trait_ref.to_predicate(), + post_message); + err.span_label(span, + &format!("{}the trait `{}` is not \ + implemented for `{}`", + pre_message, + trait_ref, + trait_ref.self_ty())); // Try to report a help message diff --git a/src/test/compile-fail/E0277.rs b/src/test/compile-fail/E0277.rs index e4cb50cd3f253..e31fea1e45863 100644 --- a/src/test/compile-fail/E0277.rs +++ b/src/test/compile-fail/E0277.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::path::Path; + trait Foo { fn bar(&self); } @@ -16,6 +18,13 @@ fn some_func(foo: T) { foo.bar(); } +fn f(p: Path) { } +//~^ ERROR the trait bound `[u8]: std::marker::Sized` is not satisfied in `std::path::Path` +//~| NOTE within `std::path::Path`, the trait `std::marker::Sized` is not implemented for `[u8]` +//~| NOTE `[u8]` does not have a constant size known at compile-time +//~| NOTE required because it appears within the type `std::path::Path` +//~| NOTE all local variables must have a statically known size + fn main() { some_func(5i32); //~^ ERROR the trait bound `i32: Foo` is not satisfied From 90c5b7187cf2d30e90f1023d9d78d0a9f33669a2 Mon Sep 17 00:00:00 2001 From: Ulrik Sverdrup Date: Sat, 10 Dec 2016 22:24:29 +0100 Subject: [PATCH 07/73] compiletest: A more verbose matching failure for mir tests This makes it easier to work with mir test failures during development. - Show which expected line was not found - Show full expected output - Show full actual output --- src/tools/compiletest/src/runtest.rs | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 3cc14541fcdf2..d65205fe65aa9 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -2294,7 +2294,18 @@ actual:\n\ }; } if !found { - panic!("ran out of mir dump output to match against"); + let normalize_all = dumped_string.lines() + .map(nocomment_mir_line) + .filter(|l| !l.is_empty()) + .collect::>() + .join("\n"); + panic!("ran out of mir dump output to match against.\n\ + Did not find expected line: {:?}\n\ + Expected:\n{}\n\ + Actual:\n{}", + expected_line, + expected_content.join("\n"), + normalize_all); } } } @@ -2439,11 +2450,14 @@ enum TargetLocation { } fn normalize_mir_line(line: &str) -> String { - let no_comments = if let Some(idx) = line.find("//") { + nocomment_mir_line(line).replace(char::is_whitespace, "") +} + +fn nocomment_mir_line(line: &str) -> &str { + if let Some(idx) = line.find("//") { let (l, _) = line.split_at(idx); - l + l.trim_right() } else { line - }; - no_comments.replace(char::is_whitespace, "") + } } From f09e2cc7ed34ae1623c334df92981bc53a11a6ae Mon Sep 17 00:00:00 2001 From: Jon Gjengset Date: Sun, 11 Dec 2016 23:57:15 -0500 Subject: [PATCH 08/73] Expand E0309 explanation with motivating example --- src/librustc/diagnostics.rs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/librustc/diagnostics.rs b/src/librustc/diagnostics.rs index ec09877ae121c..1655c716b6bfa 100644 --- a/src/librustc/diagnostics.rs +++ b/src/librustc/diagnostics.rs @@ -1236,6 +1236,23 @@ struct Foo<'a, T: 'a> { foo: &'a T } ``` + +To see why this is important, consider the case where `T` is itself a reference +(e.g., `T = &str`). If we don't include the restriction that `T: 'a`, the +following code would be perfectly legal: + +```compile_fail,E0309 +struct Foo<'a, T> { + foo: &'a T +} + +fn main() { + let v = "42".to_string(); + let f = Foo{foo: &v}; + drop(v); + println!("{}", f.foo); // but we've already dropped v! +} +``` "##, E0310: r##" From 83231859417efc363d6929b58d75cdcf40bb5f2d Mon Sep 17 00:00:00 2001 From: Liigo Zhuang Date: Wed, 7 Dec 2016 16:37:38 +0800 Subject: [PATCH 09/73] minor fix about visibility in reference --- src/doc/reference.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/doc/reference.md b/src/doc/reference.md index bf286aaec4bb3..ce3fef982b962 100644 --- a/src/doc/reference.md +++ b/src/doc/reference.md @@ -1731,7 +1731,8 @@ of an item to see whether it should be allowed or not. This is where privacy warnings are generated, or otherwise "you used a private item of another module and weren't allowed to." -By default, everything in Rust is *private*, with one exception. Enum variants +By default, everything in Rust is *private*, with two exceptions: Associated +items of a Trait are public by default; Enum variants in a `pub` enum are also public by default. When an item is declared as `pub`, it can be thought of as being accessible to the outside world. For example: From e095c710f73ae98cdc769a3e7992d3a44e91bb8f Mon Sep 17 00:00:00 2001 From: Liigo Date: Tue, 13 Dec 2016 20:21:00 +0800 Subject: [PATCH 10/73] Associated items and variants inherit visibility from their traits and enums respectively. --- src/doc/reference.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/reference.md b/src/doc/reference.md index ce3fef982b962..b5a91a170d8ed 100644 --- a/src/doc/reference.md +++ b/src/doc/reference.md @@ -1732,7 +1732,7 @@ warnings are generated, or otherwise "you used a private item of another module and weren't allowed to." By default, everything in Rust is *private*, with two exceptions: Associated -items of a Trait are public by default; Enum variants +items in a `pub` Trait are public by default; Enum variants in a `pub` enum are also public by default. When an item is declared as `pub`, it can be thought of as being accessible to the outside world. For example: From 16d4b7b0e5d011c69b41a4a0a440193544795f5e Mon Sep 17 00:00:00 2001 From: Martin Pool Date: Sat, 3 Dec 2016 13:05:05 -0800 Subject: [PATCH 11/73] doc: Explain meaning of Result iters and link to factory functions. --- src/libcore/result.rs | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/src/libcore/result.rs b/src/libcore/result.rs index afed99d265f19..99c407e5273ea 100644 --- a/src/libcore/result.rs +++ b/src/libcore/result.rs @@ -501,6 +501,8 @@ impl Result { /// Returns an iterator over the possibly contained value. /// + /// The iterator yields one value if the result is [`Ok`], otherwise none. + /// /// # Examples /// /// Basic usage: @@ -512,6 +514,8 @@ impl Result { /// let x: Result = Err("nothing!"); /// assert_eq!(x.iter().next(), None); /// ``` + /// + /// [`Ok`]: enum.Result.html#variant.Ok #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn iter(&self) -> Iter { @@ -520,6 +524,8 @@ impl Result { /// Returns a mutable iterator over the possibly contained value. /// + /// The iterator yields one value if the result is [`Ok`], otherwise none. + /// /// # Examples /// /// Basic usage: @@ -535,6 +541,8 @@ impl Result { /// let mut x: Result = Err("nothing!"); /// assert_eq!(x.iter_mut().next(), None); /// ``` + /// + /// [`Ok`]: enum.Result.html#variant.Ok #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn iter_mut(&mut self) -> IterMut { @@ -848,6 +856,8 @@ impl IntoIterator for Result { /// Returns a consuming iterator over the possibly contained value. /// + /// The iterator yields one value if the result is [`Ok`], otherwise none. + /// /// # Examples /// /// Basic usage: @@ -861,6 +871,8 @@ impl IntoIterator for Result { /// let v: Vec = x.into_iter().collect(); /// assert_eq!(v, []); /// ``` + /// + /// [`Ok`]: enum.Result.html#variant.Ok #[inline] fn into_iter(self) -> IntoIter { IntoIter { inner: self.ok() } @@ -893,8 +905,13 @@ impl<'a, T, E> IntoIterator for &'a mut Result { /// An iterator over a reference to the [`Ok`] variant of a [`Result`]. /// +/// The iterator yields one value if the result is [`Ok`], otherwise none. +/// +/// Created by [`Result::iter`]. +/// /// [`Ok`]: enum.Result.html#variant.Ok /// [`Result`]: enum.Result.html +/// [`Result::iter`]: enum.Result.html#method.iter #[derive(Debug)] #[stable(feature = "rust1", since = "1.0.0")] pub struct Iter<'a, T: 'a> { inner: Option<&'a T> } @@ -934,8 +951,11 @@ impl<'a, T> Clone for Iter<'a, T> { /// An iterator over a mutable reference to the [`Ok`] variant of a [`Result`]. /// +/// Created by [`Result::iter_mut`]. +/// /// [`Ok`]: enum.Result.html#variant.Ok /// [`Result`]: enum.Result.html +/// [`Result::iter_mut`]: enum.Result.html#method.iter_mut #[derive(Debug)] #[stable(feature = "rust1", since = "1.0.0")] pub struct IterMut<'a, T: 'a> { inner: Option<&'a mut T> } @@ -968,9 +988,12 @@ impl<'a, T> FusedIterator for IterMut<'a, T> {} #[unstable(feature = "trusted_len", issue = "37572")] unsafe impl<'a, A> TrustedLen for IterMut<'a, A> {} -/// An iterator over the value in a [`Ok`] variant of a [`Result`]. This struct is -/// created by the [`into_iter`] method on [`Result`][`Result`] (provided by -/// the [`IntoIterator`] trait). +/// An iterator over the value in a [`Ok`] variant of a [`Result`]. +/// +/// The iterator yields one value if the result is [`Ok`], otherwise none. +/// +/// This struct is created by the [`into_iter`] method on +/// [`Result`][`Result`] (provided by the [`IntoIterator`] trait). /// /// [`Ok`]: enum.Result.html#variant.Ok /// [`Result`]: enum.Result.html From 60fbe7a5e336feb757203ce95c40144f59d44842 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 13 Dec 2016 14:03:36 +0100 Subject: [PATCH 12/73] Add missing Duration examples --- src/libstd/time/duration.rs | 79 +++++++++++++++++++++++++++++++------ 1 file changed, 66 insertions(+), 13 deletions(-) diff --git a/src/libstd/time/duration.rs b/src/libstd/time/duration.rs index 41d675b6f88fc..162ce530f17cd 100644 --- a/src/libstd/time/duration.rs +++ b/src/libstd/time/duration.rs @@ -14,16 +14,19 @@ const NANOS_PER_SEC: u32 = 1_000_000_000; const NANOS_PER_MILLI: u32 = 1_000_000; const MILLIS_PER_SEC: u64 = 1_000; -/// A duration type to represent a span of time, typically used for system +/// A `Duration` type to represent a span of time, typically used for system /// timeouts. /// -/// Each duration is composed of a number of seconds and nanosecond precision. +/// Each `Duration` is composed of a number of seconds and nanosecond precision. /// APIs binding a system timeout will typically round up the nanosecond /// precision if the underlying system does not support that level of precision. /// -/// Durations implement many common traits, including `Add`, `Sub`, and other -/// ops traits. Currently a duration may only be inspected for its number of -/// seconds and its nanosecond precision. +/// `Duration`s implement many common traits, including [`Add`], [`Sub`], and other +/// [`ops`] traits. +/// +/// [`Add`]: ../../std/ops/trait.Add.html +/// [`Sub`]: ../../std/ops/trait.Sub.html +/// [`ops`]: ../../std/ops/index.html /// /// # Examples /// @@ -56,6 +59,14 @@ impl Duration { /// /// This constructor will panic if the carry from the nanoseconds overflows /// the seconds counter. + /// + /// # Examples + /// + /// ``` + /// use std::time::Duration; + /// + /// let five_seconds = Duration::new(5, 0); + /// ``` #[stable(feature = "duration", since = "1.3.0")] #[inline] pub fn new(secs: u64, nanos: u32) -> Duration { @@ -66,6 +77,14 @@ impl Duration { } /// Creates a new `Duration` from the specified number of seconds. + /// + /// # Examples + /// + /// ``` + /// use std::time::Duration; + /// + /// let five_seconds = Duration::from_secs(5); + /// ``` #[stable(feature = "duration", since = "1.3.0")] #[inline] pub fn from_secs(secs: u64) -> Duration { @@ -73,6 +92,14 @@ impl Duration { } /// Creates a new `Duration` from the specified number of milliseconds. + /// + /// # Examples + /// + /// ``` + /// use std::time::Duration; + /// + /// let five_seconds = Duration::from_millis(5000); + /// ``` #[stable(feature = "duration", since = "1.3.0")] #[inline] pub fn from_millis(millis: u64) -> Duration { @@ -81,26 +108,46 @@ impl Duration { Duration { secs: secs, nanos: nanos } } - /// Returns the number of whole seconds represented by this duration. + /// Returns the number of whole seconds represented by this `Duration`. /// /// The extra precision represented by this duration is ignored (i.e. extra /// nanoseconds are not represented in the returned value). + /// + /// # Examples + /// + /// ``` + /// use std::time::Duration; + /// + /// let five_seconds = Duration::new(5, 0); + /// assert_eq!(five_seconds.as_secs(), 5); + /// ``` #[stable(feature = "duration", since = "1.3.0")] #[inline] pub fn as_secs(&self) -> u64 { self.secs } - /// Returns the nanosecond precision represented by this duration. + /// Returns the nanosecond precision represented by this `Duration`. /// /// This method does **not** return the length of the duration when /// represented by nanoseconds. The returned number always represents a /// fractional portion of a second (i.e. it is less than one billion). + /// + /// # Examples + /// + /// ``` + /// use std::time::Duration; + /// + /// let duration = Duration::from_millis(5010); + /// assert_eq!(duration.subsec_nanos(), 10000000); + /// ``` #[stable(feature = "duration", since = "1.3.0")] #[inline] pub fn subsec_nanos(&self) -> u32 { self.nanos } - /// Checked duration addition. Computes `self + other`, returning `None` + /// Checked `Duration` addition. Computes `self + other`, returning [`None`] /// if overflow occurred. /// + /// [`None`]: ../../std/option/enum.Option.html#variant.None + /// /// # Examples /// /// Basic usage: @@ -136,9 +183,11 @@ impl Duration { } } - /// Checked duration subtraction. Computes `self + other`, returning `None` + /// Checked `Duration` subtraction. Computes `self - other`, returning [`None`] /// if the result would be negative or if underflow occurred. /// + /// [`None`]: ../../std/option/enum.Option.html#variant.None + /// /// # Examples /// /// Basic usage: @@ -172,8 +221,10 @@ impl Duration { } } - /// Checked duration multiplication. Computes `self * other`, returning - /// `None` if underflow or overflow occurred. + /// Checked `Duration` multiplication. Computes `self * other`, returning + /// [`None`] if overflow occurred. + /// + /// [`None`]: ../../std/option/enum.Option.html#variant.None /// /// # Examples /// @@ -207,8 +258,10 @@ impl Duration { } } - /// Checked duration division. Computes `self / other`, returning `None` - /// if `other == 0` or the operation results in underflow or overflow. + /// Checked `Duration` division. Computes `self / other`, returning [`None`] + /// if `other == 0`. + /// + /// [`None`]: ../../std/option/enum.Option.html#variant.None /// /// # Examples /// From cf56c1f744c3e7c71a1d5a80b8889b9fab8f6de7 Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Tue, 6 Dec 2016 15:20:51 -1000 Subject: [PATCH 13/73] Indicate `BTreeSet` in docs is code-like. --- src/libcollections/btree/set.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/libcollections/btree/set.rs b/src/libcollections/btree/set.rs index c57266d9e3b4a..46302db0d5bea 100644 --- a/src/libcollections/btree/set.rs +++ b/src/libcollections/btree/set.rs @@ -74,19 +74,19 @@ pub struct BTreeSet { map: BTreeMap, } -/// An iterator over a BTreeSet's items. +/// An iterator over a `BTreeSet`'s items. #[stable(feature = "rust1", since = "1.0.0")] pub struct Iter<'a, T: 'a> { iter: Keys<'a, T, ()>, } -/// An owning iterator over a BTreeSet's items. +/// An owning iterator over a `BTreeSet`'s items. #[stable(feature = "rust1", since = "1.0.0")] pub struct IntoIter { iter: ::btree_map::IntoIter, } -/// An iterator over a sub-range of BTreeSet's items. +/// An iterator over a sub-range of `BTreeSet`'s items. pub struct Range<'a, T: 'a> { iter: ::btree_map::Range<'a, T, ()>, } @@ -120,7 +120,7 @@ pub struct Union<'a, T: 'a> { } impl BTreeSet { - /// Makes a new BTreeSet with a reasonable choice of B. + /// Makes a new `BTreeSet` with a reasonable choice of B. /// /// # Examples /// @@ -137,7 +137,7 @@ impl BTreeSet { } impl BTreeSet { - /// Gets an iterator over the BTreeSet's contents. + /// Gets an iterator over the `BTreeSet`'s contents. /// /// # Examples /// From 5c130411e907b018aef90aabe766d04e989abe9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 12 Dec 2016 14:51:40 -0800 Subject: [PATCH 14/73] review comments --- src/librustc/traits/error_reporting.rs | 34 ++++++++++++++++++-------- src/test/compile-fail/E0277-2.rs | 34 ++++++++++++++++++++++++++ 2 files changed, 58 insertions(+), 10 deletions(-) create mode 100644 src/test/compile-fail/E0277-2.rs diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index db375f2be735b..51f9c1b353e27 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -457,11 +457,28 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { err } + + /// Get the parent trait chain start + fn get_parent_trait_ref(&self, code: &ObligationCauseCode<'tcx>) -> Option { + match code { + &ObligationCauseCode::BuiltinDerivedObligation(ref data) => { + let parent_trait_ref = self.resolve_type_vars_if_possible( + &data.parent_trait_ref); + match self.get_parent_trait_ref(&data.parent_code) { + Some(t) => Some(t), + None => Some(format!("{}", parent_trait_ref.0.self_ty())), + } + } + _ => None, + } + } + pub fn report_selection_error(&self, obligation: &PredicateObligation<'tcx>, error: &SelectionError<'tcx>) { let span = obligation.cause.span; + let mut err = match *error { SelectionError::Unimplemented => { if let ObligationCauseCode::CompareImplMethodObligation { @@ -486,16 +503,13 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { return; } else { let trait_ref = trait_predicate.to_poly_trait_ref(); - - let (post_message, pre_message) = - if let ObligationCauseCode::BuiltinDerivedObligation(ref data) - = obligation.cause.code { - let parent_trait_ref = self.resolve_type_vars_if_possible( - &data.parent_trait_ref); - (format!(" in `{}`", parent_trait_ref.0.self_ty()), - format!("within `{}`, ", parent_trait_ref.0.self_ty())) - } else { - (String::new(), String::new()) + let (post_message, pre_message) = match self.get_parent_trait_ref( + &obligation.cause.code) + { + Some(t) => { + (format!(" in `{}`", t), format!("within `{}`, ", t)) + } + None => (String::new(), String::new()), }; let mut err = struct_span_err!( self.tcx.sess, diff --git a/src/test/compile-fail/E0277-2.rs b/src/test/compile-fail/E0277-2.rs new file mode 100644 index 0000000000000..211c0e6f89031 --- /dev/null +++ b/src/test/compile-fail/E0277-2.rs @@ -0,0 +1,34 @@ +// 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. + +struct Foo { + bar: Bar +} + +struct Bar { + baz: Baz +} + +struct Baz { + x: *const u8 +} + +fn is_send() { } + +fn main() { + is_send::(); + //~^ ERROR the trait bound `*const u8: std::marker::Send` is not satisfied in `Foo` + //~| NOTE within `Foo`, the trait `std::marker::Send` is not implemented for `*const u8` + //~| NOTE: `*const u8` cannot be sent between threads safely + //~| NOTE: required because it appears within the type `Baz` + //~| NOTE: required because it appears within the type `Bar` + //~| NOTE: required because it appears within the type `Foo` + //~| NOTE: required by `is_send` +} From 868fb030cc565bc3c0204433eebf90808b21e41f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 8 Dec 2016 11:06:18 -0800 Subject: [PATCH 15/73] When cast needs a dereference point at full cast After the fix of #37453 in PR #37369, instead of pointing at only the cast type, point at the full cast span when a cast needs a dereference: ``` error: casting `&{float}` as `f32` is invalid --> ../../../src/test/ui/mismatched_types/cast-rfc0401.rs:81:30 | 81 | vec![0.0].iter().map(|s| s as f32).collect::>(); | ^^^^^^^^ cannot cast `&{float}` as `f32` | help: did you mean `*s`? --> ../../../src/test/ui/mismatched_types/cast-rfc0401.rs:81:30 | 81 | vec![0.0].iter().map(|s| s as f32).collect::>(); | ^ ``` instead of ``` error: casting `&{float}` as `f32` is invalid --> ../../../src/test/ui/mismatched_types/cast-rfc0401.rs:81:35 | 81 | vec![0.0].iter().map(|s| s as f32).collect::>(); | - ^^^ | | | | | did you mean `*s`? | cannot cast `&{float}` as `f32` ``` --- src/librustc_typeck/check/cast.rs | 7 +- src/test/compile-fail/cast-rfc0401.rs | 123 --------- src/test/ui/mismatched_types/cast-rfc0401.rs | 82 ++++++ .../ui/mismatched_types/cast-rfc0401.stderr | 240 ++++++++++++++++++ 4 files changed, 326 insertions(+), 126 deletions(-) delete mode 100644 src/test/compile-fail/cast-rfc0401.rs create mode 100644 src/test/ui/mismatched_types/cast-rfc0401.rs create mode 100644 src/test/ui/mismatched_types/cast-rfc0401.stderr diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs index f2c8ef46a7e25..265dcada1f810 100644 --- a/src/librustc_typeck/check/cast.rs +++ b/src/librustc_typeck/check/cast.rs @@ -142,20 +142,21 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> { fn report_cast_error(&self, fcx: &FnCtxt<'a, 'gcx, 'tcx>, e: CastError) { match e { CastError::NeedDeref => { + let error_span = self.span; let cast_ty = fcx.ty_to_string(self.cast_ty); - let mut err = fcx.type_error_struct(self.cast_span, + let mut err = fcx.type_error_struct(error_span, |actual| { format!("casting `{}` as `{}` is invalid", actual, cast_ty) }, self.expr_ty); - err.span_label(self.expr.span, + err.span_label(error_span, &format!("cannot cast `{}` as `{}`", fcx.ty_to_string(self.expr_ty), cast_ty)); if let Ok(snippet) = fcx.sess().codemap().span_to_snippet(self.expr.span) { - err.span_label(self.expr.span, + err.span_help(self.expr.span, &format!("did you mean `*{}`?", snippet)); } err.emit(); diff --git a/src/test/compile-fail/cast-rfc0401.rs b/src/test/compile-fail/cast-rfc0401.rs deleted file mode 100644 index b98f464c90227..0000000000000 --- a/src/test/compile-fail/cast-rfc0401.rs +++ /dev/null @@ -1,123 +0,0 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn illegal_cast(u: *const U) -> *const V -{ - u as *const V - //~^ ERROR casting - //~^^ NOTE vtable kinds -} - -fn illegal_cast_2(u: *const U) -> *const str -{ - u as *const str - //~^ ERROR casting - //~^^ NOTE vtable kinds -} - -trait Foo { fn foo(&self) {} } -impl Foo for T {} - -trait Bar { fn foo(&self) {} } -impl Bar for T {} - -enum E { - A, B -} - -fn main() -{ - let f: f32 = 1.2; - let v = 0 as *const u8; - let fat_v : *const [u8] = unsafe { &*(0 as *const [u8; 1])}; - let fat_sv : *const [i8] = unsafe { &*(0 as *const [i8; 1])}; - let foo: &Foo = &f; - - let _ = v as &u8; //~ ERROR non-scalar - let _ = v as E; //~ ERROR non-scalar - let _ = v as fn(); //~ ERROR non-scalar - let _ = v as (u32,); //~ ERROR non-scalar - let _ = Some(&v) as *const u8; //~ ERROR non-scalar - - let _ = v as f32; - //~^ ERROR casting - let _ = main as f64; - //~^ ERROR casting - let _ = &v as usize; - //~^ ERROR casting - //~^^ HELP through a raw pointer first - let _ = f as *const u8; - //~^ ERROR casting - let _ = 3_i32 as bool; - //~^ ERROR cannot cast as `bool` [E0054] - //~| unsupported cast - //~| HELP compare with zero - let _ = E::A as bool; - //~^ ERROR cannot cast as `bool` [E0054] - //~| unsupported cast - //~| HELP compare with zero - let _ = 0x61u32 as char; //~ ERROR only `u8` can be cast - - let _ = false as f32; - //~^ ERROR casting - //~^^ HELP through an integer first - let _ = E::A as f32; - //~^ ERROR casting - //~^^ HELP through an integer first - let _ = 'a' as f32; - //~^ ERROR casting - //~^^ HELP through an integer first - - let _ = false as *const u8; - //~^ ERROR casting - let _ = E::A as *const u8; - //~^ ERROR casting - let _ = 'a' as *const u8; - //~^ ERROR casting - - let _ = 42usize as *const [u8]; //~ ERROR casting - let _ = v as *const [u8]; //~ ERROR cannot cast - let _ = fat_v as *const Foo; - //~^ ERROR the trait bound `[u8]: std::marker::Sized` is not satisfied - //~| NOTE the trait `std::marker::Sized` is not implemented for `[u8]` - //~| NOTE `[u8]` does not have a constant size known at compile-time - //~| NOTE required for the cast to the object type `Foo` - let _ = foo as *const str; //~ ERROR casting - let _ = foo as *mut str; //~ ERROR casting - let _ = main as *mut str; //~ ERROR casting - let _ = &f as *mut f32; //~ ERROR casting - let _ = &f as *const f64; //~ ERROR casting - let _ = fat_sv as usize; - //~^ ERROR casting - //~^^ HELP through a thin pointer first - - let a : *const str = "hello"; - let _ = a as *const Foo; - //~^ ERROR the trait bound `str: std::marker::Sized` is not satisfied - //~| NOTE the trait `std::marker::Sized` is not implemented for `str` - //~| NOTE `str` does not have a constant size known at compile-time - //~| NOTE required for the cast to the object type `Foo` - - // check no error cascade - let _ = main.f as *const u32; //~ no field `f` on type `fn() {main}` - - let cf: *const Foo = &0; - let _ = cf as *const [u16]; - //~^ ERROR casting - //~^^ NOTE vtable kinds - let _ = cf as *const Bar; - //~^ ERROR casting - //~^^ NOTE vtable kinds - - vec![0.0].iter().map(|s| s as f32).collect::>(); - //~^ ERROR casting `&{float}` as `f32` is invalid - //~| NOTE cannot cast `&{float}` as `f32` - //~| NOTE did you mean `*s`? -} diff --git a/src/test/ui/mismatched_types/cast-rfc0401.rs b/src/test/ui/mismatched_types/cast-rfc0401.rs new file mode 100644 index 0000000000000..f72be0d7054db --- /dev/null +++ b/src/test/ui/mismatched_types/cast-rfc0401.rs @@ -0,0 +1,82 @@ +// 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. + +fn illegal_cast(u: *const U) -> *const V +{ + u as *const V +} + +fn illegal_cast_2(u: *const U) -> *const str +{ + u as *const str +} + +trait Foo { fn foo(&self) {} } +impl Foo for T {} + +trait Bar { fn foo(&self) {} } +impl Bar for T {} + +enum E { + A, B +} + +fn main() +{ + let f: f32 = 1.2; + let v = 0 as *const u8; + let fat_v : *const [u8] = unsafe { &*(0 as *const [u8; 1])}; + let fat_sv : *const [i8] = unsafe { &*(0 as *const [i8; 1])}; + let foo: &Foo = &f; + + let _ = v as &u8; + let _ = v as E; + let _ = v as fn(); + let _ = v as (u32,); + let _ = Some(&v) as *const u8; + + let _ = v as f32; + let _ = main as f64; + let _ = &v as usize; + let _ = f as *const u8; + let _ = 3_i32 as bool; + let _ = E::A as bool; + let _ = 0x61u32 as char; + + let _ = false as f32; + let _ = E::A as f32; + let _ = 'a' as f32; + + let _ = false as *const u8; + let _ = E::A as *const u8; + let _ = 'a' as *const u8; + + let _ = 42usize as *const [u8]; + let _ = v as *const [u8]; + let _ = fat_v as *const Foo; + let _ = foo as *const str; + let _ = foo as *mut str; + let _ = main as *mut str; + let _ = &f as *mut f32; + let _ = &f as *const f64; + let _ = fat_sv as usize; + + let a : *const str = "hello"; + let _ = a as *const Foo; + + // check no error cascade + let _ = main.f as *const u32; + + let cf: *const Foo = &0; + let _ = cf as *const [u16]; + let _ = cf as *const Bar; + + vec![0.0].iter().map(|s| s as f32).collect::>(); +} diff --git a/src/test/ui/mismatched_types/cast-rfc0401.stderr b/src/test/ui/mismatched_types/cast-rfc0401.stderr new file mode 100644 index 0000000000000..7fd10f3cb6891 --- /dev/null +++ b/src/test/ui/mismatched_types/cast-rfc0401.stderr @@ -0,0 +1,240 @@ +error: casting `*const U` as `*const V` is invalid + --> $DIR/cast-rfc0401.rs:13:5 + | +13 | u as *const V + | ^^^^^^^^^^^^^ + | + = note: vtable kinds may not match + +error: casting `*const U` as `*const str` is invalid + --> $DIR/cast-rfc0401.rs:18:5 + | +18 | u as *const str + | ^^^^^^^^^^^^^^^ + | + = note: vtable kinds may not match + +error: no field `f` on type `fn() {main}` + --> $DIR/cast-rfc0401.rs:75:18 + | +75 | let _ = main.f as *const u32; + | ^ + +error: non-scalar cast: `*const u8` as `&u8` + --> $DIR/cast-rfc0401.rs:39:13 + | +39 | let _ = v as &u8; + | ^^^^^^^^ + +error: non-scalar cast: `*const u8` as `E` + --> $DIR/cast-rfc0401.rs:40:13 + | +40 | let _ = v as E; + | ^^^^^^ + +error: non-scalar cast: `*const u8` as `fn()` + --> $DIR/cast-rfc0401.rs:41:13 + | +41 | let _ = v as fn(); + | ^^^^^^^^^ + +error: non-scalar cast: `*const u8` as `(u32,)` + --> $DIR/cast-rfc0401.rs:42:13 + | +42 | let _ = v as (u32,); + | ^^^^^^^^^^^ + +error: non-scalar cast: `std::option::Option<&*const u8>` as `*const u8` + --> $DIR/cast-rfc0401.rs:43:13 + | +43 | let _ = Some(&v) as *const u8; + | ^^^^^^^^^^^^^^^^^^^^^ + +error: casting `*const u8` as `f32` is invalid + --> $DIR/cast-rfc0401.rs:45:13 + | +45 | let _ = v as f32; + | ^^^^^^^^ + +error: casting `fn() {main}` as `f64` is invalid + --> $DIR/cast-rfc0401.rs:46:13 + | +46 | let _ = main as f64; + | ^^^^^^^^^^^ + +error: casting `&*const u8` as `usize` is invalid + --> $DIR/cast-rfc0401.rs:47:13 + | +47 | let _ = &v as usize; + | ^^^^^^^^^^^ + | + = help: cast through a raw pointer first + +error: casting `f32` as `*const u8` is invalid + --> $DIR/cast-rfc0401.rs:48:13 + | +48 | let _ = f as *const u8; + | ^^^^^^^^^^^^^^ + +error[E0054]: cannot cast as `bool` + --> $DIR/cast-rfc0401.rs:49:13 + | +49 | let _ = 3_i32 as bool; + | ^^^^^^^^^^^^^ unsupported cast + | + = help: compare with zero instead + +error[E0054]: cannot cast as `bool` + --> $DIR/cast-rfc0401.rs:50:13 + | +50 | let _ = E::A as bool; + | ^^^^^^^^^^^^ unsupported cast + | + = help: compare with zero instead + +error: only `u8` can be cast as `char`, not `u32` + --> $DIR/cast-rfc0401.rs:51:13 + | +51 | let _ = 0x61u32 as char; + | ^^^^^^^^^^^^^^^ + +error: casting `bool` as `f32` is invalid + --> $DIR/cast-rfc0401.rs:53:13 + | +53 | let _ = false as f32; + | ^^^^^^^^^^^^ + | + = help: cast through an integer first + +error: casting `E` as `f32` is invalid + --> $DIR/cast-rfc0401.rs:54:13 + | +54 | let _ = E::A as f32; + | ^^^^^^^^^^^ + | + = help: cast through an integer first + +error: casting `char` as `f32` is invalid + --> $DIR/cast-rfc0401.rs:55:13 + | +55 | let _ = 'a' as f32; + | ^^^^^^^^^^ + | + = help: cast through an integer first + +error: casting `bool` as `*const u8` is invalid + --> $DIR/cast-rfc0401.rs:57:13 + | +57 | let _ = false as *const u8; + | ^^^^^^^^^^^^^^^^^^ + +error: casting `E` as `*const u8` is invalid + --> $DIR/cast-rfc0401.rs:58:13 + | +58 | let _ = E::A as *const u8; + | ^^^^^^^^^^^^^^^^^ + +error: casting `char` as `*const u8` is invalid + --> $DIR/cast-rfc0401.rs:59:13 + | +59 | let _ = 'a' as *const u8; + | ^^^^^^^^^^^^^^^^ + +error: casting `usize` as `*const [u8]` is invalid + --> $DIR/cast-rfc0401.rs:61:13 + | +61 | let _ = 42usize as *const [u8]; + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: cannot cast thin pointer `*const u8` to fat pointer `*const [u8]` + --> $DIR/cast-rfc0401.rs:62:13 + | +62 | let _ = v as *const [u8]; + | ^^^^^^^^^^^^^^^^ + +error: casting `&Foo` as `*const str` is invalid + --> $DIR/cast-rfc0401.rs:64:13 + | +64 | let _ = foo as *const str; + | ^^^^^^^^^^^^^^^^^ + +error: casting `&Foo` as `*mut str` is invalid + --> $DIR/cast-rfc0401.rs:65:13 + | +65 | let _ = foo as *mut str; + | ^^^^^^^^^^^^^^^ + +error: casting `fn() {main}` as `*mut str` is invalid + --> $DIR/cast-rfc0401.rs:66:13 + | +66 | let _ = main as *mut str; + | ^^^^^^^^^^^^^^^^ + +error: casting `&f32` as `*mut f32` is invalid + --> $DIR/cast-rfc0401.rs:67:13 + | +67 | let _ = &f as *mut f32; + | ^^^^^^^^^^^^^^ + +error: casting `&f32` as `*const f64` is invalid + --> $DIR/cast-rfc0401.rs:68:13 + | +68 | let _ = &f as *const f64; + | ^^^^^^^^^^^^^^^^ + +error: casting `*const [i8]` as `usize` is invalid + --> $DIR/cast-rfc0401.rs:69:13 + | +69 | let _ = fat_sv as usize; + | ^^^^^^^^^^^^^^^ + | + = help: cast through a thin pointer first + +error: casting `*const Foo` as `*const [u16]` is invalid + --> $DIR/cast-rfc0401.rs:78:13 + | +78 | let _ = cf as *const [u16]; + | ^^^^^^^^^^^^^^^^^^ + | + = note: vtable kinds may not match + +error: casting `*const Foo` as `*const Bar` is invalid + --> $DIR/cast-rfc0401.rs:79:13 + | +79 | let _ = cf as *const Bar; + | ^^^^^^^^^^^^^^^^ + | + = note: vtable kinds may not match + +error[E0277]: the trait bound `[u8]: std::marker::Sized` is not satisfied + --> $DIR/cast-rfc0401.rs:63:13 + | +63 | let _ = fat_v as *const Foo; + | ^^^^^ the trait `std::marker::Sized` is not implemented for `[u8]` + | + = note: `[u8]` does not have a constant size known at compile-time + = note: required for the cast to the object type `Foo` + +error[E0277]: the trait bound `str: std::marker::Sized` is not satisfied + --> $DIR/cast-rfc0401.rs:72:13 + | +72 | let _ = a as *const Foo; + | ^ the trait `std::marker::Sized` is not implemented for `str` + | + = note: `str` does not have a constant size known at compile-time + = note: required for the cast to the object type `Foo` + +error: casting `&{float}` as `f32` is invalid + --> $DIR/cast-rfc0401.rs:81:30 + | +81 | vec![0.0].iter().map(|s| s as f32).collect::>(); + | ^^^^^^^^ cannot cast `&{float}` as `f32` + | +help: did you mean `*s`? + --> $DIR/cast-rfc0401.rs:81:30 + | +81 | vec![0.0].iter().map(|s| s as f32).collect::>(); + | ^ + +error: aborting due to 34 previous errors + From ae369340473fc4bb5b30d20d32022f7ae9f8324c Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Tue, 6 Dec 2016 15:34:55 -1000 Subject: [PATCH 16/73] Document how `BTreeSet` iterator structures are created. --- src/libcollections/btree/set.rs | 36 +++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/src/libcollections/btree/set.rs b/src/libcollections/btree/set.rs index 46302db0d5bea..91da8e8b07951 100644 --- a/src/libcollections/btree/set.rs +++ b/src/libcollections/btree/set.rs @@ -75,23 +75,43 @@ pub struct BTreeSet { } /// An iterator over a `BTreeSet`'s items. +/// +/// This structure is created by the [`iter`] method on [`BTreeSet`]. +/// +/// [`BTreeSet`]: struct.BTreeSet.html +/// [`iter`]: struct.BTreeSet.html#method.iter #[stable(feature = "rust1", since = "1.0.0")] pub struct Iter<'a, T: 'a> { iter: Keys<'a, T, ()>, } /// An owning iterator over a `BTreeSet`'s items. +/// +/// This structure is created by the `into_iter` method on [`BTreeSet`] +/// [`BTreeSet`] (provided by the `IntoIterator` trait). +/// +/// [`BTreeSet`]: struct.BTreeSet.html #[stable(feature = "rust1", since = "1.0.0")] pub struct IntoIter { iter: ::btree_map::IntoIter, } /// An iterator over a sub-range of `BTreeSet`'s items. +/// +/// This structure is created by the [`range`] method on [`BTreeSet`]. +/// +/// [`BTreeSet`]: struct.BTreeSet.html +/// [`range`]: struct.BTreeSet.html#method.range pub struct Range<'a, T: 'a> { iter: ::btree_map::Range<'a, T, ()>, } /// A lazy iterator producing elements in the set difference (in-order). +/// +/// This structure is created by the [`difference`] method on [`BTreeSet`]. +/// +/// [`BTreeSet`]: struct.BTreeSet.html +/// [`difference`]: struct.BTreeSet.html#method.difference #[stable(feature = "rust1", since = "1.0.0")] pub struct Difference<'a, T: 'a> { a: Peekable>, @@ -99,6 +119,12 @@ pub struct Difference<'a, T: 'a> { } /// A lazy iterator producing elements in the set symmetric difference (in-order). +/// +/// This structure is created by the [`symmetric_difference`] method on +/// [`BTreeSet`]. +/// +/// [`BTreeSet`]: struct.BTreeSet.html +/// [`symmetric_difference`]: struct.BTreeSet.html#method.symmetric_difference #[stable(feature = "rust1", since = "1.0.0")] pub struct SymmetricDifference<'a, T: 'a> { a: Peekable>, @@ -106,6 +132,11 @@ pub struct SymmetricDifference<'a, T: 'a> { } /// A lazy iterator producing elements in the set intersection (in-order). +/// +/// This structure is created by the [`intersection`] method on [`BTreeSet`]. +/// +/// [`BTreeSet`]: struct.BTreeSet.html +/// [`intersection`]: struct.BTreeSet.html#method.intersection #[stable(feature = "rust1", since = "1.0.0")] pub struct Intersection<'a, T: 'a> { a: Peekable>, @@ -113,6 +144,11 @@ pub struct Intersection<'a, T: 'a> { } /// A lazy iterator producing elements in the set union (in-order). +/// +/// This structure is created by the [`union`] method on [`BTreeSet`]. +/// +/// [`BTreeSet`]: struct.BTreeSet.html +/// [`union`]: struct.BTreeSet.html#method.union #[stable(feature = "rust1", since = "1.0.0")] pub struct Union<'a, T: 'a> { a: Peekable>, From 4c4e8c4af77edda2d62dc8de3cfbcb8393a30ea9 Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Tue, 6 Dec 2016 15:44:46 -1000 Subject: [PATCH 17/73] Simplify `BTreeSet::iter` doc example. --- src/libcollections/btree/set.rs | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/libcollections/btree/set.rs b/src/libcollections/btree/set.rs index 91da8e8b07951..ffd5d7a919271 100644 --- a/src/libcollections/btree/set.rs +++ b/src/libcollections/btree/set.rs @@ -180,14 +180,12 @@ impl BTreeSet { /// ``` /// use std::collections::BTreeSet; /// - /// let set: BTreeSet = [1, 2, 3, 4].iter().cloned().collect(); - /// - /// for x in set.iter() { - /// println!("{}", x); - /// } - /// - /// let v: Vec<_> = set.iter().cloned().collect(); - /// assert_eq!(v, [1, 2, 3, 4]); + /// let set: BTreeSet = [1, 2, 3].iter().cloned().collect(); + /// let mut set_iter = set.iter(); + /// assert_eq!(set_iter.next(), Some(&1)); + /// assert_eq!(set_iter.next(), Some(&2)); + /// assert_eq!(set_iter.next(), Some(&3)); + /// assert_eq!(set_iter.next(), None); /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn iter(&self) -> Iter { From 8cd3081b5ac0e3c2594e5e89b615f5e92625eaae Mon Sep 17 00:00:00 2001 From: Tshepang Lekhonkhobe Date: Thu, 15 Dec 2016 20:42:10 +0200 Subject: [PATCH 18/73] rustdoc: a formatting nit --- src/librustdoc/lib.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 174118db93e0b..835825d31eec9 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -259,10 +259,11 @@ pub fn main_args(args: &[String]) -> isize { } let external_html = match ExternalHtml::load( - &matches.opt_strs("html-in-header"), &matches.opt_strs("html-before-content"), + &matches.opt_strs("html-in-header"), + &matches.opt_strs("html-before-content"), &matches.opt_strs("html-after-content")) { Some(eh) => eh, - None => return 3 + None => return 3, }; let crate_name = matches.opt_str("crate-name"); let playground_url = matches.opt_str("playground-url"); From c49e3172954151920802b1c434a536ebf9a776bb Mon Sep 17 00:00:00 2001 From: Oliver Middleton Date: Thu, 15 Dec 2016 21:10:29 +0000 Subject: [PATCH 19/73] rustbuild: Stop building docs for libtest by default They cause the search index from the std docs to get overwritten just like #34800. Part of #38319. --- src/bootstrap/step.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bootstrap/step.rs b/src/bootstrap/step.rs index 13c0c644d6357..d17be6b41a251 100644 --- a/src/bootstrap/step.rs +++ b/src/bootstrap/step.rs @@ -458,7 +458,7 @@ pub fn build_rules(build: &Build) -> Rules { for (krate, path, default) in krates("test_shim") { rules.doc(&krate.doc_step, path) .dep(|s| s.name("libtest")) - .default(default && build.config.docs) + .default(default && build.config.compiler_docs) .run(move |s| doc::test(build, s.stage, s.target)); } for (krate, path, default) in krates("rustc-main") { From 897cf9bba0866edf878a04f0bc408c9ebcb3e61d Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Thu, 15 Dec 2016 10:08:06 -0700 Subject: [PATCH 20/73] Add prefix to config.toml --- src/bootstrap/config.rs | 2 ++ src/bootstrap/config.toml.example | 3 +++ 2 files changed, 5 insertions(+) diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index 60f65f623006c..beb62ef20744c 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -126,6 +126,7 @@ struct Build { target: Vec, cargo: Option, rustc: Option, + prefix: Option, compiler_docs: Option, docs: Option, submodules: Option, @@ -238,6 +239,7 @@ impl Config { } config.rustc = build.rustc.map(PathBuf::from); config.cargo = build.cargo.map(PathBuf::from); + config.prefix = build.prefix; config.nodejs = build.nodejs.map(PathBuf::from); config.gdb = build.gdb.map(PathBuf::from); config.python = build.python.map(PathBuf::from); diff --git a/src/bootstrap/config.toml.example b/src/bootstrap/config.toml.example index b6774b3af20a5..e1f0dac7ddbab 100644 --- a/src/bootstrap/config.toml.example +++ b/src/bootstrap/config.toml.example @@ -70,6 +70,9 @@ # specified, use this rustc binary instead as the stage0 snapshot compiler. #rustc = "/path/to/bin/rustc" +# Instead of installing installing to /usr/local, install to this path instead. +#prefix = "/path/to/install" + # Flag to specify whether any documentation is built. If false, rustdoc and # friends will still be compiled but they will not be used to generate any # documentation. From 58b94bd3a84600047f6a994b55b51bb2baf143d9 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Thu, 15 Dec 2016 14:32:40 -0700 Subject: [PATCH 21/73] Update config.toml.example --- src/bootstrap/config.toml.example | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bootstrap/config.toml.example b/src/bootstrap/config.toml.example index e1f0dac7ddbab..76fcfebdb9456 100644 --- a/src/bootstrap/config.toml.example +++ b/src/bootstrap/config.toml.example @@ -70,7 +70,7 @@ # specified, use this rustc binary instead as the stage0 snapshot compiler. #rustc = "/path/to/bin/rustc" -# Instead of installing installing to /usr/local, install to this path instead. +# Instead of installing to /usr/local, install to this path instead. #prefix = "/path/to/install" # Flag to specify whether any documentation is built. If false, rustdoc and From 2938e6a41172d1c71f5c58e9a71958f2d5c1a262 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 7 Dec 2016 21:55:09 -0800 Subject: [PATCH 22/73] Add missing doc examples for UnixDatagram --- src/libstd/sys/unix/ext/net.rs | 323 +++++++++++++++++++++++++++++---- 1 file changed, 285 insertions(+), 38 deletions(-) diff --git a/src/libstd/sys/unix/ext/net.rs b/src/libstd/sys/unix/ext/net.rs index d49f9343b0e77..e822488c01851 100644 --- a/src/libstd/sys/unix/ext/net.rs +++ b/src/libstd/sys/unix/ext/net.rs @@ -139,13 +139,25 @@ impl SocketAddr { /// /// # Examples /// + /// A named address: + /// /// ``` /// use std::os::unix::net::UnixListener; /// - /// let socket = match UnixListener::bind("/tmp/sock").unwrap(); + /// let socket = UnixListener::bind("/tmp/sock").unwrap(); /// let addr = socket.local_addr().expect("Couldn't get local address"); /// assert_eq!(addr.is_unnamed(), false); /// ``` + /// + /// An unnamed address: + /// + /// ``` + /// use std::os::unix::net::UnixDatagram; + /// + /// let socket = UnixDatagram::unbound().unwrap(); + /// let addr = socket.local_addr().expect("Couldn't get local address"); + /// assert_eq!(addr.is_unnamed(), true); + /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] pub fn is_unnamed(&self) -> bool { if let AddressKind::Unnamed = self.address() { @@ -159,14 +171,27 @@ impl SocketAddr { /// /// # Examples /// + /// With a pathname: + /// /// ``` /// use std::os::unix::net::UnixListener; /// use std::path::Path; /// - /// let socket = match UnixListener::bind("/tmp/sock").unwrap(); + /// let socket = UnixListener::bind("/tmp/sock").unwrap(); /// let addr = socket.local_addr().expect("Couldn't get local address"); /// assert_eq!(addr.as_pathname(), Some(Path::new("/tmp/sock"))); /// ``` + /// + /// Without a pathname: + /// + /// ``` + /// use std::os::unix::net::UnixDatagram; + /// use std::path::Path; + /// + /// let socket = UnixDatagram::unbound().unwrap(); + /// let addr = socket.local_addr().expect("Couldn't get local address"); + /// assert_eq!(addr.as_pathname(), None); + /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] pub fn as_pathname(&self) -> Option<&Path> { if let AddressKind::Pathname(path) = self.address() { @@ -311,8 +336,8 @@ impl UnixStream { /// ```no_run /// use std::os::unix::net::UnixStream; /// - /// let socket = match UnixStream::connect("/tmp/sock").unwrap(); - /// let sock_copy = socket.try_clone().expect("Couldn't clone socket..."); + /// let socket = UnixStream::connect("/tmp/sock").unwrap(); + /// let sock_copy = socket.try_clone().expect("Couldn't clone socket"); /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] pub fn try_clone(&self) -> io::Result { @@ -326,7 +351,7 @@ impl UnixStream { /// ```no_run /// use std::os::unix::net::UnixStream; /// - /// let socket = match UnixStream::connect("/tmp/sock").unwrap(); + /// let socket = UnixStream::connect("/tmp/sock").unwrap(); /// let addr = socket.local_addr().expect("Couldn't get local address"); /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] @@ -341,7 +366,7 @@ impl UnixStream { /// ```no_run /// use std::os::unix::net::UnixStream; /// - /// let socket = match UnixStream::connect("/tmp/sock").unwrap(); + /// let socket = UnixStream::connect("/tmp/sock").unwrap(); /// let addr = socket.peer_addr().expect("Couldn't get peer address"); /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] @@ -355,9 +380,9 @@ impl UnixStream { /// indefinitely. It is an error to pass the zero [`Duration`] to this /// method. /// - /// [`None`]: ../../std/option/enum.Option.html#variant.None - /// [`read()`]: ../../std/io/trait.Read.html#tymethod.read - /// [`Duration`]: ../../std/time/struct.Duration.html + /// [`None`]: ../../../../std/option/enum.Option.html#variant.None + /// [`read()`]: ../../../../std/io/trait.Read.html#tymethod.read + /// [`Duration`]: ../../../../std/time/struct.Duration.html /// /// # Examples /// @@ -365,7 +390,7 @@ impl UnixStream { /// use std::os::unix::net::UnixStream; /// use std::time::Duration; /// - /// let socket = match UnixStream::connect("/tmp/sock").unwrap(); + /// let socket = UnixStream::connect("/tmp/sock").unwrap(); /// socket.set_read_timeout(Some(Duration::new(1, 0))).expect("Couldn't set read timeout"); /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] @@ -379,9 +404,9 @@ impl UnixStream { /// indefinitely. It is an error to pass the zero [`Duration`] to this /// method. /// - /// [`None`]: ../../std/option/enum.Option.html#variant.None - /// [`read()`]: ../../std/io/trait.Write.html#tymethod.write - /// [`Duration`]: ../../std/time/struct.Duration.html + /// [`None`]: ../../../../std/option/enum.Option.html#variant.None + /// [`read()`]: ../../../../std/io/trait.Write.html#tymethod.write + /// [`Duration`]: ../../../../std/time/struct.Duration.html /// /// # Examples /// @@ -389,7 +414,7 @@ impl UnixStream { /// use std::os::unix::net::UnixStream; /// use std::time::Duration; /// - /// let socket = match UnixStream::connect("/tmp/sock").unwrap(); + /// let socket = UnixStream::connect("/tmp/sock").unwrap(); /// socket.set_write_timeout(Some(Duration::new(1, 0))).expect("Couldn't set write timeout"); /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] @@ -405,7 +430,7 @@ impl UnixStream { /// use std::os::unix::net::UnixStream; /// use std::time::Duration; /// - /// let socket = match UnixStream::connect("/tmp/sock").unwrap(); + /// let socket = UnixStream::connect("/tmp/sock").unwrap(); /// socket.set_read_timeout(Some(Duration::new(1, 0))).expect("Couldn't set read timeout"); /// assert_eq!(socket.read_timeout().unwrap(), Some(Duration::new(1, 0))); /// ``` @@ -422,7 +447,7 @@ impl UnixStream { /// use std::os::unix::net::UnixStream; /// use std::time::Duration; /// - /// let socket = match UnixStream::connect("/tmp/sock").unwrap(); + /// let socket = UnixStream::connect("/tmp/sock").unwrap(); /// socket.set_write_timeout(Some(Duration::new(1, 0))).expect("Couldn't set write timeout"); /// assert_eq!(socket.write_timeout().unwrap(), Some(Duration::new(1, 0))); /// ``` @@ -438,8 +463,8 @@ impl UnixStream { /// ```no_run /// use std::os::unix::net::UnixStream; /// - /// let socket = match UnixStream::connect("/tmp/sock").unwrap(); - /// socket.set_nonblocking(true).expect("Couldn't set non blocking"); + /// let socket = UnixStream::connect("/tmp/sock").unwrap(); + /// socket.set_nonblocking(true).expect("Couldn't set nonblocking"); /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { @@ -453,7 +478,7 @@ impl UnixStream { /// ```no_run /// use std::os::unix::net::UnixStream; /// - /// let socket = match UnixStream::connect("/tmp/sock").unwrap(); + /// let socket = UnixStream::connect("/tmp/sock").unwrap(); /// if let Ok(Some(err)) = socket.take_error() { /// println!("Got error: {:?}", err); /// } @@ -469,14 +494,15 @@ impl UnixStream { /// specified portions to immediately return with an appropriate value /// (see the documentation of [`Shutdown`]). /// - /// [`Shutdown`]: ../../std/net/enum.Shutdown.html + /// [`Shutdown`]: ../../../../std/net/enum.Shutdown.html /// /// # Examples /// /// ```no_run /// use std::os::unix::net::UnixStream; + /// use std::net::Shutdown; /// - /// let socket = match UnixStream::connect("/tmp/sock").unwrap(); + /// let socket = UnixStream::connect("/tmp/sock").unwrap(); /// socket.shutdown(Shutdown::Both).expect("shutdown function failed"); /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] @@ -631,7 +657,7 @@ impl UnixListener { /// is established. When established, the corersponding [`UnixStream`] and /// the remote peer's address will be returned. /// - /// [`UnixStream`]: ../../std/os/unix/net/struct.UnixStream.html + /// [`UnixStream`]: ../../../../std/os/unix/net/struct.UnixStream.html /// /// # Examples /// @@ -683,7 +709,7 @@ impl UnixListener { /// /// let listener = UnixListener::bind("/path/to/the/socket").unwrap(); /// - /// let addr = socket.local_addr().expect("Couldn't get local address"); + /// let addr = listener.local_addr().expect("Couldn't get local address"); /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] pub fn local_addr(&self) -> io::Result { @@ -699,7 +725,7 @@ impl UnixListener { /// /// let listener = UnixListener::bind("/path/to/the/socket").unwrap(); /// - /// socket.set_nonblocking(true).expect("Couldn't set non blocking"); + /// listener.set_nonblocking(true).expect("Couldn't set non blocking"); /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { @@ -713,8 +739,9 @@ impl UnixListener { /// ```no_run /// use std::os::unix::net::UnixListener; /// - /// let socket = match UnixListener::bind("/tmp/sock").unwrap(); - /// if let Ok(Some(err)) = socket.take_error() { + /// let listener = UnixListener::bind("/tmp/sock").unwrap(); + /// + /// if let Ok(Some(err)) = listener.take_error() { /// println!("Got error: {:?}", err); /// } /// ``` @@ -728,7 +755,7 @@ impl UnixListener { /// The iterator will never return [`None`] and will also not yield the /// peer's [`SocketAddr`] structure. /// - /// [`None`]: ../../std/option/enum.Option.html#variant.None + /// [`None`]: ../../../../std/option/enum.Option.html#variant.None /// [`SocketAddr`]: struct.SocketAddr.html /// /// # Examples @@ -795,7 +822,7 @@ impl<'a> IntoIterator for &'a UnixListener { /// /// It will never return [`None`]. /// -/// [`None`]: ../../std/option/enum.Option.html#variant.None +/// [`None`]: ../../../../std/option/enum.Option.html#variant.None /// [`UnixListener`]: struct.UnixListener.html /// /// # Examples @@ -873,6 +900,20 @@ impl fmt::Debug for UnixDatagram { impl UnixDatagram { /// Creates a Unix datagram socket bound to the given path. + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixDatagram; + /// + /// let sock = match UnixDatagram::bind("/path/to/the/socket") { + /// Ok(sock) => sock, + /// Err(e) => { + /// println!("Couldn't bind: {:?}", e); + /// return + /// } + /// }; + /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] pub fn bind>(path: P) -> io::Result { fn inner(path: &Path) -> io::Result { @@ -889,6 +930,20 @@ impl UnixDatagram { } /// Creates a Unix Datagram socket which is not bound to any address. + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixDatagram; + /// + /// let sock = match UnixDatagram::unbound() { + /// Ok(sock) => sock, + /// Err(e) => { + /// println!("Couldn't unbound: {:?}", e); + /// return + /// } + /// }; + /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] pub fn unbound() -> io::Result { let inner = Socket::new_raw(libc::AF_UNIX, libc::SOCK_DGRAM)?; @@ -898,6 +953,20 @@ impl UnixDatagram { /// Create an unnamed pair of connected sockets. /// /// Returns two `UnixDatagrams`s which are connected to each other. + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixDatagram; + /// + /// let (sock1, sock2) = match UnixDatagram::pair() { + /// Ok((sock1, sock2)) => (sock1, sock2), + /// Err(e) => { + /// println!("Couldn't unbound: {:?}", e); + /// return + /// } + /// }; + /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] pub fn pair() -> io::Result<(UnixDatagram, UnixDatagram)> { let (i1, i2) = Socket::new_pair(libc::AF_UNIX, libc::SOCK_DGRAM)?; @@ -906,8 +975,27 @@ impl UnixDatagram { /// Connects the socket to the specified address. /// - /// The `send` method may be used to send data to the specified address. - /// `recv` and `recv_from` will only receive data from that address. + /// The [`send()`] method may be used to send data to the specified address. + /// [`recv()`] and [`recv_from()`] will only receive data from that address. + /// + /// [`send()`]: #method.send + /// [`recv()`]: #method.recv + /// [`recv_from()`]: #method.recv_from + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixDatagram; + /// + /// let sock = UnixDatagram::unbound().unwrap(); + /// match sock.connect("/path/to/the/socket") { + /// Ok(sock) => sock, + /// Err(e) => { + /// println!("Couldn't connect: {:?}", e); + /// return + /// } + /// }; + /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] pub fn connect>(&self, path: P) -> io::Result<()> { fn inner(d: &UnixDatagram, path: &Path) -> io::Result<()> { @@ -924,15 +1012,35 @@ impl UnixDatagram { /// Creates a new independently owned handle to the underlying socket. /// - /// The returned `UnixListener` is a reference to the same socket that this + /// The returned `UnixDatagram` is a reference to the same socket that this /// object references. Both handles can be used to accept incoming - /// connections and options set on one listener will affect the other. + /// connections and options set on one side will affect the other. + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixDatagram; + /// + /// let sock = UnixDatagram::bind("/path/to/the/socket").unwrap(); + /// + /// let sock_copy = sock.try_clone().expect("try_clone failed"); + /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] pub fn try_clone(&self) -> io::Result { self.0.duplicate().map(UnixDatagram) } /// Returns the address of this socket. + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixDatagram; + /// + /// let sock = UnixDatagram::bind("/path/to/the/socket").unwrap(); + /// + /// let addr = sock.local_addr().expect("Couldn't get local address"); + /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] pub fn local_addr(&self) -> io::Result { SocketAddr::new(|addr, len| unsafe { libc::getsockname(*self.0.as_inner(), addr, len) }) @@ -940,7 +1048,20 @@ impl UnixDatagram { /// Returns the address of this socket's peer. /// - /// The `connect` method will connect the socket to a peer. + /// The [`connect()`] method will connect the socket to a peer. + /// + /// [`connect()`]: #method.connect + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixDatagram; + /// + /// let sock = UnixDatagram::unbound().unwrap(); + /// sock.connect("/path/to/the/socket").unwrap(); + /// + /// let addr = sock.peer_addr().expect("Couldn't get peer address"); + /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] pub fn peer_addr(&self) -> io::Result { SocketAddr::new(|addr, len| unsafe { libc::getpeername(*self.0.as_inner(), addr, len) }) @@ -950,6 +1071,19 @@ impl UnixDatagram { /// /// On success, returns the number of bytes read and the address from /// whence the data came. + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixDatagram; + /// + /// let sock = UnixDatagram::unbound().unwrap(); + /// let mut buf = vec![0; 10]; + /// match sock.recv_from(buf.as_mut_slice()) { + /// Ok((size, sender)) => println!("received {} bytes from {:?}", size, sender), + /// Err(e) => println!("recv_from function failed: {:?}", e), + /// } + /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> { let mut count = 0; @@ -977,6 +1111,16 @@ impl UnixDatagram { /// Receives data from the socket. /// /// On success, returns the number of bytes read. + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixDatagram; + /// + /// let sock = UnixDatagram::bind("/path/to/the/socket").unwrap(); + /// let mut buf = vec![0; 10]; + /// sock.recv(buf.as_mut_slice()).expect("recv function failed"); + /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] pub fn recv(&self, buf: &mut [u8]) -> io::Result { self.0.read(buf) @@ -985,6 +1129,15 @@ impl UnixDatagram { /// Sends data on the socket to the specified address. /// /// On success, returns the number of bytes written. + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixDatagram; + /// + /// let sock = UnixDatagram::unbound().unwrap(); + /// sock.send_to(b"omelette au fromage", "/some/sock").expect("send_to function failed"); + /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] pub fn send_to>(&self, buf: &[u8], path: P) -> io::Result { fn inner(d: &UnixDatagram, buf: &[u8], path: &Path) -> io::Result { @@ -1009,6 +1162,16 @@ impl UnixDatagram { /// will return an error if the socket has not already been connected. /// /// On success, returns the number of bytes written. + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixDatagram; + /// + /// let sock = UnixDatagram::unbound().unwrap(); + /// sock.connect("/some/sock").expect("Couldn't connect"); + /// sock.send(b"omelette au fromage").expect("send_to function failed"); + /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] pub fn send(&self, buf: &[u8]) -> io::Result { self.0.write(buf) @@ -1016,9 +1179,24 @@ impl UnixDatagram { /// Sets the read timeout for the socket. /// - /// If the provided value is `None`, then `recv` and `recv_from` calls will - /// block indefinitely. It is an error to pass the zero `Duration` to this + /// If the provided value is [`None`], then [`recv()`] and [`recv_from()`] calls will + /// block indefinitely. It is an error to pass the zero [`Duration`] to this /// method. + /// + /// [`None`]: ../../../../std/option/enum.Option.html#variant.None + /// [`recv()`]: #method.recv + /// [`recv_from()`]: #method.recv_from + /// [`Duration`]: ../../../../std/time/struct.Duration.html + /// + /// # Examples + /// + /// ``` + /// use std::os::unix::net::UnixDatagram; + /// use std::time::Duration; + /// + /// let sock = UnixDatagram::unbound().unwrap(); + /// sock.set_read_timeout(Some(Duration::new(1, 0))).expect("set_read_timeout function failed"); + /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] pub fn set_read_timeout(&self, timeout: Option) -> io::Result<()> { self.0.set_timeout(timeout, libc::SO_RCVTIMEO) @@ -1026,33 +1204,92 @@ impl UnixDatagram { /// Sets the write timeout for the socket. /// - /// If the provided value is `None`, then `send` and `send_to` calls will - /// block indefinitely. It is an error to pass the zero `Duration` to this + /// If the provided value is [`None`], then [`send()`] and [`send_to()`] calls will + /// block indefinitely. It is an error to pass the zero [`Duration`] to this /// method. + /// + /// [`None`]: ../../../../std/option/enum.Option.html#variant.None + /// [`send()`]: #method.send + /// [`send_to()`]: #method.send_to + /// [`Duration`]: ../../../../std/time/struct.Duration.html + /// + /// # Examples + /// + /// ``` + /// use std::os::unix::net::UnixDatagram; + /// use std::time::Duration; + /// + /// let sock = UnixDatagram::unbound().unwrap(); + /// sock.set_write_timeout(Some(Duration::new(1, 0))) + /// .expect("set_write_timeout function failed"); + /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] pub fn set_write_timeout(&self, timeout: Option) -> io::Result<()> { self.0.set_timeout(timeout, libc::SO_SNDTIMEO) } /// Returns the read timeout of this socket. + /// + /// # Examples + /// + /// ``` + /// use std::os::unix::net::UnixDatagram; + /// use std::time::Duration; + /// + /// let sock = UnixDatagram::unbound().unwrap(); + /// sock.set_read_timeout(Some(Duration::new(1, 0))).expect("set_read_timeout function failed"); + /// assert_eq!(sock.read_timeout().unwrap(), Some(Duration::new(1, 0))); + /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] pub fn read_timeout(&self) -> io::Result> { self.0.timeout(libc::SO_RCVTIMEO) } /// Returns the write timeout of this socket. + /// + /// # Examples + /// + /// ``` + /// use std::os::unix::net::UnixDatagram; + /// use std::time::Duration; + /// + /// let sock = UnixDatagram::unbound().unwrap(); + /// sock.set_write_timeout(Some(Duration::new(1, 0))) + /// .expect("set_write_timeout function failed"); + /// assert_eq!(sock.write_timeout().unwrap(), Some(Duration::new(1, 0))); + /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] pub fn write_timeout(&self) -> io::Result> { self.0.timeout(libc::SO_SNDTIMEO) } /// Moves the socket into or out of nonblocking mode. + /// + /// # Examples + /// + /// ``` + /// use std::os::unix::net::UnixDatagram; + /// + /// let sock = UnixDatagram::unbound().unwrap(); + /// sock.set_nonblocking(true).expect("set_nonblocking function failed"); + /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { self.0.set_nonblocking(nonblocking) } /// Returns the value of the `SO_ERROR` option. + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixDatagram; + /// + /// let sock = UnixDatagram::unbound().unwrap(); + /// if let Ok(Some(err)) = sock.take_error() { + /// println!("Got error: {:?}", err); + /// } + /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] pub fn take_error(&self) -> io::Result> { self.0.take_error() @@ -1062,7 +1299,17 @@ impl UnixDatagram { /// /// This function will cause all pending and future I/O calls on the /// specified portions to immediately return with an appropriate value - /// (see the documentation of `Shutdown`). + /// (see the documentation of [`Shutdown`]). + /// + /// [`Shutdown`]: ../../../../std/net/enum.Shutdown.html + /// + /// ```no_run + /// use std::os::unix::net::UnixDatagram; + /// use std::net::Shutdown; + /// + /// let sock = UnixDatagram::unbound().unwrap(); + /// sock.shutdown(Shutdown::Both).expect("shutdown function failed"); + /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] pub fn shutdown(&self, how: Shutdown) -> io::Result<()> { self.0.shutdown(how) From 87b407136b7b0ba60af3a6c282b5bef15282d76d Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Tue, 13 Dec 2016 17:48:52 -0500 Subject: [PATCH 23/73] Definitions: Split out NodeId <-> DefIndex mapping --- src/librustc/hir/map/definitions.rs | 44 ++++++++++++++--------------- 1 file changed, 21 insertions(+), 23 deletions(-) diff --git a/src/librustc/hir/map/definitions.rs b/src/librustc/hir/map/definitions.rs index a684563512da6..72c1ff9ee2efc 100644 --- a/src/librustc/hir/map/definitions.rs +++ b/src/librustc/hir/map/definitions.rs @@ -18,12 +18,20 @@ use syntax::symbol::{Symbol, InternedString}; use ty::TyCtxt; use util::nodemap::NodeMap; +//! For each definition, we track the following data. A definition +//! here is defined somewhat circularly as "something with a def-id", +//! but it generally corresponds to things like structs, enums, etc. +//! There are also some rather random cases (like const initializer +//! expressions) that are mostly just leftovers. + + /// The definition table containing node definitions #[derive(Clone)] pub struct Definitions { - data: Vec, + data: Vec, key_map: FxHashMap, - node_map: NodeMap, + node_to_def_index: NodeMap, + def_index_to_node: Vec, } /// A unique identifier that we can use to lookup a definition @@ -50,19 +58,6 @@ pub struct DisambiguatedDefPathData { pub disambiguator: u32 } -/// For each definition, we track the following data. A definition -/// here is defined somewhat circularly as "something with a def-id", -/// but it generally corresponds to things like structs, enums, etc. -/// There are also some rather random cases (like const initializer -/// expressions) that are mostly just leftovers. -#[derive(Clone, Debug)] -pub struct DefData { - pub key: DefKey, - - /// Local ID within the HIR. - pub node_id: ast::NodeId, -} - #[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] pub struct DefPath { /// the path leading from the crate root to the item @@ -221,7 +216,8 @@ impl Definitions { Definitions { data: vec![], key_map: FxHashMap(), - node_map: NodeMap(), + node_to_def_index: NodeMap(), + def_index_to_node: vec![], } } @@ -248,7 +244,7 @@ impl Definitions { } pub fn opt_def_index(&self, node: ast::NodeId) -> Option { - self.node_map.get(&node).cloned() + self.node_to_def_index.get(&node).cloned() } pub fn opt_local_def_id(&self, node: ast::NodeId) -> Option { @@ -262,7 +258,8 @@ impl Definitions { pub fn as_local_node_id(&self, def_id: DefId) -> Option { if def_id.krate == LOCAL_CRATE { assert!(def_id.index.as_usize() < self.data.len()); - Some(self.data[def_id.index.as_usize()].node_id) + // Some(self.data[def_id.index.as_usize()].node_id) + Some(self.def_index_to_node[def_id.index.as_usize()]) } else { None } @@ -277,11 +274,11 @@ impl Definitions { debug!("create_def_with_parent(parent={:?}, node_id={:?}, data={:?})", parent, node_id, data); - assert!(!self.node_map.contains_key(&node_id), + assert!(!self.node_to_def_index.contains_key(&node_id), "adding a def'n for node-id {:?} and data {:?} but a previous def'n exists: {:?}", node_id, data, - self.data[self.node_map[&node_id].as_usize()]); + self.data[self.node_to_def_index[&node_id].as_usize()]); assert!(parent.is_some() ^ match data { DefPathData::CrateRoot | DefPathData::InlinedRoot(_) => true, @@ -306,9 +303,10 @@ impl Definitions { // Create the definition. let index = DefIndex::new(self.data.len()); - self.data.push(DefData { key: key.clone(), node_id: node_id }); - debug!("create_def_with_parent: node_map[{:?}] = {:?}", node_id, index); - self.node_map.insert(node_id, index); + self.data.push(DefData { key: key.clone() }); + self.def_index_to_node.push(node_id); + debug!("create_def_with_parent: node_to_def_index[{:?}] = {:?}", node_id, index); + self.node_to_def_index.insert(node_id, index); debug!("create_def_with_parent: key_map[{:?}] = {:?}", key, index); self.key_map.insert(key, index); From 8e34a8e4223a744bcc4fb2d77c06fb6c183dcc26 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Wed, 14 Dec 2016 11:27:39 -0500 Subject: [PATCH 24/73] Definitions: Extract DefPath interning into its own data structure. --- src/librustc/hir/map/definitions.rs | 108 ++++++++++++++++++++++------ 1 file changed, 85 insertions(+), 23 deletions(-) diff --git a/src/librustc/hir/map/definitions.rs b/src/librustc/hir/map/definitions.rs index 72c1ff9ee2efc..159e80d7d3975 100644 --- a/src/librustc/hir/map/definitions.rs +++ b/src/librustc/hir/map/definitions.rs @@ -8,9 +8,19 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. + +//! For each definition, we track the following data. A definition +//! here is defined somewhat circularly as "something with a def-id", +//! but it generally corresponds to things like structs, enums, etc. +//! There are also some rather random cases (like const initializer +//! expressions) that are mostly just leftovers. + + + use hir::def_id::{CrateNum, DefId, DefIndex, LOCAL_CRATE}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::stable_hasher::StableHasher; +use serialize::{Encodable, Decodable, Encoder, Decoder}; use std::fmt::Write; use std::hash::{Hash, Hasher}; use syntax::ast; @@ -18,18 +28,72 @@ use syntax::symbol::{Symbol, InternedString}; use ty::TyCtxt; use util::nodemap::NodeMap; -//! For each definition, we track the following data. A definition -//! here is defined somewhat circularly as "something with a def-id", -//! but it generally corresponds to things like structs, enums, etc. -//! There are also some rather random cases (like const initializer -//! expressions) that are mostly just leftovers. +#[derive(Clone)] +pub struct DefPathTable { + index_to_key: Vec, + key_to_index: FxHashMap, +} + +impl DefPathTable { + fn insert(&mut self, key: DefKey) -> DefIndex { + let index = DefIndex::new(self.index_to_key.len()); + debug!("DefPathTable::insert() - {:?} <-> {:?}", key, index); + self.index_to_key.push(key.clone()); + self.key_to_index.insert(key, index); + index + } + + #[inline(always)] + pub fn def_key(&self, index: DefIndex) -> DefKey { + self.index_to_key[index.as_usize()].clone() + } + + #[inline(always)] + pub fn def_index_for_def_key(&self, key: &DefKey) -> Option { + self.key_to_index.get(key).cloned() + } + + #[inline(always)] + pub fn contains_key(&self, key: &DefKey) -> bool { + self.key_to_index.contains_key(key) + } + + /// Returns the path from the crate root to `index`. The root + /// nodes are not included in the path (i.e., this will be an + /// empty vector for the crate root). For an inlined item, this + /// will be the path of the item in the external crate (but the + /// path will begin with the path to the external crate). + pub fn def_path(&self, index: DefIndex) -> DefPath { + DefPath::make(LOCAL_CRATE, index, |p| self.def_key(p)) + } +} + + +impl Encodable for DefPathTable { + fn encode(&self, s: &mut S) -> Result<(), S::Error> { + self.index_to_key.encode(s) + } +} + +impl Decodable for DefPathTable { + fn decode(d: &mut D) -> Result { + let index_to_key: Vec = Decodable::decode(d)?; + let key_to_index = index_to_key.iter() + .enumerate() + .map(|(index, key)| (key.clone(), DefIndex::new(index))) + .collect(); + Ok(DefPathTable { + index_to_key: index_to_key, + key_to_index: key_to_index, + }) + } +} /// The definition table containing node definitions #[derive(Clone)] pub struct Definitions { - data: Vec, - key_map: FxHashMap, + table: DefPathTable, node_to_def_index: NodeMap, def_index_to_node: Vec, } @@ -214,8 +278,10 @@ impl Definitions { /// Create new empty definition map. pub fn new() -> Definitions { Definitions { - data: vec![], - key_map: FxHashMap(), + table: DefPathTable { + index_to_key: vec![], + key_to_index: FxHashMap(), + }, node_to_def_index: NodeMap(), def_index_to_node: vec![], } @@ -223,15 +289,15 @@ impl Definitions { /// Get the number of definitions. pub fn len(&self) -> usize { - self.data.len() + self.def_index_to_node.len() } pub fn def_key(&self, index: DefIndex) -> DefKey { - self.data[index.as_usize()].key.clone() + self.table.def_key(index) } pub fn def_index_for_def_key(&self, key: DefKey) -> Option { - self.key_map.get(&key).cloned() + self.table.def_index_for_def_key(&key) } /// Returns the path from the crate root to `index`. The root @@ -257,8 +323,7 @@ impl Definitions { pub fn as_local_node_id(&self, def_id: DefId) -> Option { if def_id.krate == LOCAL_CRATE { - assert!(def_id.index.as_usize() < self.data.len()); - // Some(self.data[def_id.index.as_usize()].node_id) + assert!(def_id.index.as_usize() < self.def_index_to_node.len()); Some(self.def_index_to_node[def_id.index.as_usize()]) } else { None @@ -278,7 +343,7 @@ impl Definitions { "adding a def'n for node-id {:?} and data {:?} but a previous def'n exists: {:?}", node_id, data, - self.data[self.node_to_def_index[&node_id].as_usize()]); + self.table.def_key(self.node_to_def_index[&node_id])); assert!(parent.is_some() ^ match data { DefPathData::CrateRoot | DefPathData::InlinedRoot(_) => true, @@ -295,21 +360,18 @@ impl Definitions { } }; - while self.key_map.contains_key(&key) { + while self.table.contains_key(&key) { key.disambiguated_data.disambiguator += 1; } debug!("create_def_with_parent: after disambiguation, key = {:?}", key); // Create the definition. - let index = DefIndex::new(self.data.len()); - self.data.push(DefData { key: key.clone() }); - self.def_index_to_node.push(node_id); - debug!("create_def_with_parent: node_to_def_index[{:?}] = {:?}", node_id, index); + let index = self.table.insert(key); + debug!("create_def_with_parent: def_index_to_node[{:?} <-> {:?}", index, node_id); self.node_to_def_index.insert(node_id, index); - debug!("create_def_with_parent: key_map[{:?}] = {:?}", key, index); - self.key_map.insert(key, index); - + assert_eq!(index.as_usize(), self.def_index_to_node.len()); + self.def_index_to_node.push(node_id); index } From aed0cdbfd21984b144d685131e0070cfa811fb49 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Fri, 16 Dec 2016 12:48:54 -0500 Subject: [PATCH 25/73] definitions: Don't allocate DefIds for inlined HIR --- src/librustc/hir/map/collector.rs | 4 -- src/librustc/hir/map/def_collector.rs | 21 +--------- src/librustc/hir/map/definitions.rs | 57 ++------------------------- src/librustc/hir/map/mod.rs | 13 +----- src/librustc/ty/item_path.rs | 5 --- src/librustc_metadata/astencode.rs | 10 ----- src/librustc_metadata/decoder.rs | 5 +-- 7 files changed, 6 insertions(+), 109 deletions(-) diff --git a/src/librustc/hir/map/collector.rs b/src/librustc/hir/map/collector.rs index c46c8f044e0ff..45988886a608a 100644 --- a/src/librustc/hir/map/collector.rs +++ b/src/librustc/hir/map/collector.rs @@ -11,7 +11,6 @@ use super::*; use hir::intravisit::{Visitor, NestedVisitorMap}; -use hir::def_id::DefId; use middle::cstore::InlinedItem; use std::iter::repeat; use syntax::ast::{NodeId, CRATE_NODE_ID}; @@ -47,8 +46,6 @@ impl<'ast> NodeCollector<'ast> { pub fn extend(krate: &'ast Crate, parent: &'ast InlinedItem, parent_node: NodeId, - parent_def_path: DefPath, - parent_def_id: DefId, map: Vec>) -> NodeCollector<'ast> { let mut collector = NodeCollector { @@ -58,7 +55,6 @@ impl<'ast> NodeCollector<'ast> { ignore_nested_items: true }; - assert_eq!(parent_def_path.krate, parent_def_id.krate); collector.insert_entry(parent_node, RootInlinedParent(parent)); collector diff --git a/src/librustc/hir/map/def_collector.rs b/src/librustc/hir/map/def_collector.rs index eb5a89f320e7b..8c303a96b0ced 100644 --- a/src/librustc/hir/map/def_collector.rs +++ b/src/librustc/hir/map/def_collector.rs @@ -12,7 +12,7 @@ use hir::map::definitions::*; use hir; use hir::intravisit::{self, Visitor, NestedVisitorMap}; -use hir::def_id::{CRATE_DEF_INDEX, DefId, DefIndex}; +use hir::def_id::{CRATE_DEF_INDEX, DefIndex}; use middle::cstore::InlinedItem; @@ -47,25 +47,6 @@ impl<'a> DefCollector<'a> { } } - pub fn extend(parent_node: NodeId, - parent_def_path: DefPath, - parent_def_id: DefId, - definitions: &'a mut Definitions) - -> Self { - let mut collector = DefCollector::new(definitions); - - assert_eq!(parent_def_path.krate, parent_def_id.krate); - let root_path = Box::new(InlinedRootPath { - data: parent_def_path.data, - def_id: parent_def_id, - }); - - let def = collector.create_def(parent_node, DefPathData::InlinedRoot(root_path)); - collector.parent_def = Some(def); - - collector - } - pub fn collect_root(&mut self) { let root = self.create_def_with_parent(None, CRATE_NODE_ID, DefPathData::CrateRoot); assert_eq!(root, CRATE_DEF_INDEX); diff --git a/src/librustc/hir/map/definitions.rs b/src/librustc/hir/map/definitions.rs index 159e80d7d3975..d90a9ef7d80d3 100644 --- a/src/librustc/hir/map/definitions.rs +++ b/src/librustc/hir/map/definitions.rs @@ -57,15 +57,6 @@ impl DefPathTable { pub fn contains_key(&self, key: &DefKey) -> bool { self.key_to_index.contains_key(key) } - - /// Returns the path from the crate root to `index`. The root - /// nodes are not included in the path (i.e., this will be an - /// empty vector for the crate root). For an inlined item, this - /// will be the path of the item in the external crate (but the - /// path will begin with the path to the external crate). - pub fn def_path(&self, index: DefIndex) -> DefPath { - DefPath::make(LOCAL_CRATE, index, |p| self.def_key(p)) - } } @@ -136,12 +127,11 @@ impl DefPath { self.krate == LOCAL_CRATE } - pub fn make(start_krate: CrateNum, + pub fn make(krate: CrateNum, start_index: DefIndex, mut get_key: FN) -> DefPath where FN: FnMut(DefIndex) -> DefKey { - let mut krate = start_krate; let mut data = vec![]; let mut index = Some(start_index); loop { @@ -154,13 +144,6 @@ impl DefPath { assert!(key.parent.is_none()); break; } - DefPathData::InlinedRoot(ref p) => { - assert!(key.parent.is_none()); - assert!(!p.def_id.is_local()); - data.extend(p.data.iter().cloned().rev()); - krate = p.def_id.krate; - break; - } _ => { data.push(key.disambiguated_data); index = key.parent; @@ -203,31 +186,6 @@ impl DefPath { } } -/// Root of an inlined item. We track the `DefPath` of the item within -/// the original crate but also its def-id. This is kind of an -/// augmented version of a `DefPath` that includes a `DefId`. This is -/// all sort of ugly but the hope is that inlined items will be going -/// away soon anyway. -/// -/// Some of the constraints that led to the current approach: -/// -/// - I don't want to have a `DefId` in the main `DefPath` because -/// that gets serialized for incr. comp., and when reloaded the -/// `DefId` is no longer valid. I'd rather maintain the invariant -/// that every `DefId` is valid, and a potentially outdated `DefId` is -/// represented as a `DefPath`. -/// - (We don't serialize def-paths from inlined items, so it's ok to have one here.) -/// - We need to be able to extract the def-id from inline items to -/// make the symbol name. In theory we could retrace it from the -/// data, but the metadata doesn't have the required indices, and I -/// don't want to write the code to create one just for this. -/// - It may be that we don't actually need `data` at all. We'll have -/// to see about that. -#[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] -pub struct InlinedRootPath { - pub data: Vec, - pub def_id: DefId, -} #[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] pub enum DefPathData { @@ -235,9 +193,7 @@ pub enum DefPathData { // they are treated specially by the `def_path` function. /// The crate root (marker) CrateRoot, - /// An inlined root - InlinedRoot(Box), - + // Catch-all for random DefId things like DUMMY_NODE_ID Misc, @@ -345,10 +301,7 @@ impl Definitions { data, self.table.def_key(self.node_to_def_index[&node_id])); - assert!(parent.is_some() ^ match data { - DefPathData::CrateRoot | DefPathData::InlinedRoot(_) => true, - _ => false, - }); + assert!(parent.is_some() ^ (data == DefPathData::CrateRoot)); // Find a unique DefKey. This basically means incrementing the disambiguator // until we get no match. @@ -393,7 +346,6 @@ impl DefPathData { Impl | CrateRoot | - InlinedRoot(_) | Misc | ClosureExpr | StructCtor | @@ -420,9 +372,6 @@ impl DefPathData { // note that this does not show up in user printouts CrateRoot => "{{root}}", - // note that this does not show up in user printouts - InlinedRoot(_) => "{{inlined-root}}", - Impl => "{{impl}}", Misc => "{{?}}", ClosureExpr => "{{closure}}", diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index 117edcf14a1d1..569d697f374a1 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -13,7 +13,7 @@ use self::MapEntry::*; use self::collector::NodeCollector; pub use self::def_collector::{DefCollector, MacroInvocationData}; pub use self::definitions::{Definitions, DefKey, DefPath, DefPathData, - DisambiguatedDefPathData, InlinedRootPath}; + DisambiguatedDefPathData}; use dep_graph::{DepGraph, DepNode}; @@ -945,8 +945,6 @@ pub fn map_crate<'ast>(forest: &'ast mut Forest, /// Used for items loaded from external crate that are being inlined into this /// crate. pub fn map_decoded_item<'ast>(map: &Map<'ast>, - parent_def_path: DefPath, - parent_def_id: DefId, ii: InlinedItem, ii_parent_id: NodeId) -> &'ast InlinedItem { @@ -954,18 +952,9 @@ pub fn map_decoded_item<'ast>(map: &Map<'ast>, let ii = map.forest.inlined_items.alloc(ii); - let defs = &mut *map.definitions.borrow_mut(); - let mut def_collector = DefCollector::extend(ii_parent_id, - parent_def_path.clone(), - parent_def_id, - defs); - def_collector.walk_item(ii, map.krate()); - let mut collector = NodeCollector::extend(map.krate(), ii, ii_parent_id, - parent_def_path, - parent_def_id, mem::replace(&mut *map.map.borrow_mut(), vec![])); ii.visit(&mut collector); *map.map.borrow_mut() = collector.map; diff --git a/src/librustc/ty/item_path.rs b/src/librustc/ty/item_path.rs index 440a3916786fa..0e4c14029e9b9 100644 --- a/src/librustc/ty/item_path.rs +++ b/src/librustc/ty/item_path.rs @@ -160,11 +160,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { self.push_krate_path(buffer, def_id.krate); } - DefPathData::InlinedRoot(ref root_path) => { - assert!(key.parent.is_none()); - self.push_item_path(buffer, root_path.def_id); - } - DefPathData::Impl => { self.push_impl_path(buffer, def_id); } diff --git a/src/librustc_metadata/astencode.rs b/src/librustc_metadata/astencode.rs index 6598b7dcc527f..926c44824ce48 100644 --- a/src/librustc_metadata/astencode.rs +++ b/src/librustc_metadata/astencode.rs @@ -102,8 +102,6 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for SideTableEncodingIdVisitor<'a, 'b, 'tcx> { /// ast-map. pub fn decode_inlined_item<'a, 'tcx>(cdata: &CrateMetadata, tcx: TyCtxt<'a, 'tcx, 'tcx>, - parent_def_path: ast_map::DefPath, - parent_did: DefId, ast: Ast<'tcx>, orig_did: DefId) -> &'tcx InlinedItem { @@ -120,17 +118,9 @@ pub fn decode_inlined_item<'a, 'tcx>(cdata: &CrateMetadata, let ii = ast.item.decode((cdata, tcx, id_ranges)); let item_node_id = tcx.sess.next_node_id(); let ii = ast_map::map_decoded_item(&tcx.map, - parent_def_path, - parent_did, ii, item_node_id); - let inlined_did = tcx.map.local_def_id(item_node_id); - let ty = tcx.item_type(orig_did); - let generics = tcx.item_generics(orig_did); - tcx.item_types.borrow_mut().insert(inlined_did, ty); - tcx.generics.borrow_mut().insert(inlined_did, generics); - for (id, entry) in ast.side_tables.decode((cdata, tcx, id_ranges)) { match entry { TableEntry::TypeRelativeDef(def) => { diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 539c05b71bb1c..d487d2e6da679 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -839,12 +839,9 @@ impl<'a, 'tcx> CrateMetadata { if self.is_proc_macro(id) { return None; } let item_doc = self.entry(id); let item_did = self.local_def_id(id); - let parent_def_id = self.local_def_id(self.def_key(id).parent.unwrap()); - let mut parent_def_path = self.def_path(id).unwrap(); - parent_def_path.data.pop(); item_doc.ast.map(|ast| { let ast = ast.decode(self); - decode_inlined_item(self, tcx, parent_def_path, parent_def_id, ast, item_did) + decode_inlined_item(self, tcx, ast, item_did) }) } From ed5a88e3d03a57cb390662e44611bb0d33c28a4b Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Fri, 16 Dec 2016 12:51:36 -0500 Subject: [PATCH 26/73] definitions: Store DefPath data in separate table in metadata --- src/librustc/hir/map/definitions.rs | 6 +++- src/librustc/hir/map/mod.rs | 6 +++- src/librustc_metadata/creader.rs | 2 +- src/librustc_metadata/cstore.rs | 4 +-- src/librustc_metadata/cstore_impl.rs | 2 +- src/librustc_metadata/decoder.rs | 49 ++++++++-------------------- src/librustc_metadata/encoder.rs | 32 ++++++++---------- src/librustc_metadata/schema.rs | 2 +- 8 files changed, 41 insertions(+), 62 deletions(-) diff --git a/src/librustc/hir/map/definitions.rs b/src/librustc/hir/map/definitions.rs index d90a9ef7d80d3..ef574b61aa7e9 100644 --- a/src/librustc/hir/map/definitions.rs +++ b/src/librustc/hir/map/definitions.rs @@ -193,7 +193,7 @@ pub enum DefPathData { // they are treated specially by the `def_path` function. /// The crate root (marker) CrateRoot, - + // Catch-all for random DefId things like DUMMY_NODE_ID Misc, @@ -243,6 +243,10 @@ impl Definitions { } } + pub fn def_path_table(&self) -> &DefPathTable { + &self.table + } + /// Get the number of definitions. pub fn len(&self) -> usize { self.def_index_to_node.len() diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index 569d697f374a1..e5c5b43081167 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -29,7 +29,7 @@ use hir::*; use hir::print as pprust; use arena::TypedArena; -use std::cell::RefCell; +use std::cell::{RefCell, Ref}; use std::io; use std::mem; @@ -395,6 +395,10 @@ impl<'ast> Map<'ast> { self.definitions.borrow().len() } + pub fn definitions(&self) -> Ref { + self.definitions.borrow() + } + pub fn def_key(&self, def_id: DefId) -> DefKey { assert!(def_id.is_local()); self.definitions.borrow().def_key(def_id.index) diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index d36242537b8e5..9eed5cb8fe8c4 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -300,7 +300,7 @@ impl<'a> CrateLoader<'a> { let mut cmeta = cstore::CrateMetadata { name: name, extern_crate: Cell::new(None), - key_map: metadata.load_key_map(crate_root.index), + def_path_table: crate_root.def_path_table.decode(&metadata), proc_macros: crate_root.macro_derive_registrar.map(|_| { self.load_derive_macros(&crate_root, dylib.clone().map(|p| p.0), span) }), diff --git a/src/librustc_metadata/cstore.rs b/src/librustc_metadata/cstore.rs index 7700ebde18133..7ec847d24cfa3 100644 --- a/src/librustc_metadata/cstore.rs +++ b/src/librustc_metadata/cstore.rs @@ -16,7 +16,7 @@ use schema; use rustc::dep_graph::DepGraph; use rustc::hir::def_id::{CRATE_DEF_INDEX, LOCAL_CRATE, CrateNum, DefIndex, DefId}; -use rustc::hir::map::DefKey; +use rustc::hir::map::definitions::DefPathTable; use rustc::hir::svh::Svh; use rustc::middle::cstore::{DepKind, ExternCrate}; use rustc_back::PanicStrategy; @@ -78,7 +78,7 @@ pub struct CrateMetadata { /// hashmap, which gives the reverse mapping. This allows us to /// quickly retrace a `DefPath`, which is needed for incremental /// compilation support. - pub key_map: FxHashMap, + pub def_path_table: DefPathTable, pub dep_kind: Cell, pub source: CrateSource, diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index 1a1bb1432eec1..7305b23951590 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -341,7 +341,7 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { def: DefKey) -> Option { let cdata = self.get_crate_data(cnum); - cdata.key_map.get(&def).cloned() + cdata.def_path_table.def_index_for_def_key(&def) } /// Returns the `DefKey` for a given `DefId`. This indicates the diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index d487d2e6da679..cf550f03d8eb8 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -12,12 +12,10 @@ use astencode::decode_inlined_item; use cstore::{self, CrateMetadata, MetadataBlob, NativeLibrary}; -use index::Index; use schema::*; use rustc::hir::map as hir_map; use rustc::hir::map::{DefKey, DefPathData}; -use rustc::util::nodemap::FxHashMap; use rustc::hir; use rustc::hir::intravisit::IdRange; @@ -456,14 +454,6 @@ impl<'a, 'tcx> MetadataBlob { Lazy::with_position(pos).decode(self) } - /// Go through each item in the metadata and create a map from that - /// item's def-key to the item's DefIndex. - pub fn load_key_map(&self, index: LazySeq) -> FxHashMap { - index.iter_enumerated(self.raw_bytes()) - .map(|(index, item)| (item.decode(self).def_key.decode(self), index)) - .collect() - } - pub fn list_crate_metadata(&self, out: &mut io::Write) -> io::Result<()> { write!(out, "=External Dependencies=\n")?; let root = self.get_root(); @@ -543,9 +533,8 @@ impl<'a, 'tcx> CrateMetadata { } } - fn item_name(&self, item: &Entry<'tcx>) -> ast::Name { - item.def_key - .decode(self) + fn item_name(&self, item_index: DefIndex) -> ast::Name { + self.def_key(item_index) .disambiguated_data .data .get_opt_name() @@ -594,12 +583,12 @@ impl<'a, 'tcx> CrateMetadata { (ty::VariantDef { did: self.local_def_id(data.struct_ctor.unwrap_or(index)), - name: self.item_name(item), + name: self.item_name(index), fields: item.children.decode(self).map(|index| { let f = self.entry(index); ty::FieldDef { did: self.local_def_id(index), - name: self.item_name(&f), + name: self.item_name(index), vis: f.visibility } }).collect(), @@ -771,7 +760,7 @@ impl<'a, 'tcx> CrateMetadata { if let Some(def) = self.get_def(child_index) { callback(def::Export { def: def, - name: self.item_name(&self.entry(child_index)), + name: self.item_name(child_index), }); } } @@ -783,7 +772,7 @@ impl<'a, 'tcx> CrateMetadata { _ => {} } - let def_key = child.def_key.decode(self); + let def_key = self.def_key(child_index); if let (Some(def), Some(name)) = (self.get_def(child_index), def_key.disambiguated_data.data.get_opt_name()) { callback(def::Export { @@ -886,7 +875,7 @@ impl<'a, 'tcx> CrateMetadata { pub fn get_associated_item(&self, id: DefIndex) -> Option { let item = self.entry(id); let parent_and_name = || { - let def_key = item.def_key.decode(self); + let def_key = self.def_key(id); (self.local_def_id(def_key.parent.unwrap()), def_key.disambiguated_data.data.get_opt_name().unwrap()) }; @@ -963,7 +952,7 @@ impl<'a, 'tcx> CrateMetadata { // we assume that someone passing in a tuple struct ctor is actually wanting to // look at the definition let mut item = self.entry(node_id); - let def_key = item.def_key.decode(self); + let def_key = self.def_key(node_id); if def_key.disambiguated_data.data == DefPathData::StructCtor { item = self.entry(def_key.parent.unwrap()); } @@ -974,7 +963,7 @@ impl<'a, 'tcx> CrateMetadata { self.entry(id) .children .decode(self) - .map(|index| self.item_name(&self.entry(index))) + .map(|index| self.item_name(index)) .collect() } @@ -1036,7 +1025,7 @@ impl<'a, 'tcx> CrateMetadata { } pub fn get_trait_of_item(&self, id: DefIndex) -> Option { - self.entry(id).def_key.decode(self).parent.and_then(|parent_index| { + self.def_key(id).parent.and_then(|parent_index| { match self.entry(parent_index).kind { EntryKind::Trait(_) => Some(self.local_def_id(parent_index)), _ => None, @@ -1082,7 +1071,7 @@ impl<'a, 'tcx> CrateMetadata { pub fn get_macro(&self, id: DefIndex) -> (ast::Name, MacroDef) { let entry = self.entry(id); match entry.kind { - EntryKind::MacroDef(macro_def) => (self.item_name(&entry), macro_def.decode(self)), + EntryKind::MacroDef(macro_def) => (self.item_name(id), macro_def.decode(self)), _ => bug!(), } } @@ -1135,20 +1124,8 @@ impl<'a, 'tcx> CrateMetadata { } } - pub fn def_key(&self, id: DefIndex) -> hir_map::DefKey { - debug!("def_key: id={:?}", id); - if self.is_proc_macro(id) { - let name = self.proc_macros.as_ref().unwrap()[id.as_usize() - 1].0; - hir_map::DefKey { - parent: Some(CRATE_DEF_INDEX), - disambiguated_data: hir_map::DisambiguatedDefPathData { - data: hir_map::DefPathData::MacroDef(name.as_str()), - disambiguator: 0, - }, - } - } else { - self.entry(id).def_key.decode(self) - } + pub fn def_key(&self, index: DefIndex) -> DefKey { + self.def_path_table.def_key(index) } // Returns the path leading to the thing with this `id`. Note that diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 443f3fbaa6e41..cf032013ac962 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -16,6 +16,7 @@ use rustc::middle::cstore::{InlinedItemRef, LinkMeta}; use rustc::middle::cstore::{LinkagePreference, NativeLibrary}; use rustc::hir::def; use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefIndex, DefId}; +use rustc::hir::map::definitions::DefPathTable; use rustc::middle::dependency_format::Linkage; use rustc::middle::lang_items; use rustc::mir; @@ -233,13 +234,6 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { Ok(()) } - /// For every DefId that we create a metadata item for, we include a - /// serialized copy of its DefKey, which allows us to recreate a path. - fn encode_def_key(&mut self, def_id: DefId) -> Lazy { - let tcx = self.tcx; - self.lazy(&tcx.map.def_key(def_id)) - } - fn encode_item_variances(&mut self, def_id: DefId) -> LazySeq { let tcx = self.tcx; self.lazy_seq(tcx.item_variances(def_id).iter().cloned()) @@ -276,7 +270,6 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { kind: EntryKind::Variant(self.lazy(&data)), visibility: enum_vis.simplify(), span: self.lazy(&tcx.def_span(def_id)), - def_key: self.encode_def_key(def_id), attributes: self.encode_attributes(&tcx.get_attrs(def_id)), children: self.lazy_seq(variant.fields.iter().map(|f| { assert!(f.did.is_local()); @@ -315,7 +308,6 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { kind: EntryKind::Mod(self.lazy(&data)), visibility: vis.simplify(), span: self.lazy(&md.inner), - def_key: self.encode_def_key(def_id), attributes: self.encode_attributes(attrs), children: self.lazy_seq(md.item_ids.iter().map(|item_id| { tcx.map.local_def_id(item_id.id).index @@ -396,7 +388,6 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { kind: EntryKind::Field, visibility: field.vis.simplify(), span: self.lazy(&tcx.def_span(def_id)), - def_key: self.encode_def_key(def_id), attributes: self.encode_attributes(&variant_data.fields()[field_index].attrs), children: LazySeq::empty(), stability: self.encode_stability(def_id), @@ -430,7 +421,6 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { kind: EntryKind::Struct(self.lazy(&data)), visibility: struct_vis.simplify(), span: self.lazy(&tcx.def_span(def_id)), - def_key: self.encode_def_key(def_id), attributes: LazySeq::empty(), children: LazySeq::empty(), stability: self.encode_stability(def_id), @@ -497,7 +487,6 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { kind: kind, visibility: trait_item.vis.simplify(), span: self.lazy(&ast_item.span), - def_key: self.encode_def_key(def_id), attributes: self.encode_attributes(&ast_item.attrs), children: LazySeq::empty(), stability: self.encode_stability(def_id), @@ -587,7 +576,6 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { kind: kind, visibility: impl_item.vis.simplify(), span: self.lazy(&ast_item.span), - def_key: self.encode_def_key(def_id), attributes: self.encode_attributes(&ast_item.attrs), children: LazySeq::empty(), stability: self.encode_stability(def_id), @@ -750,7 +738,6 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { kind: kind, visibility: item.vis.simplify(), span: self.lazy(&item.span), - def_key: self.encode_def_key(def_id), attributes: self.encode_attributes(&item.attrs), children: match item.node { hir::ItemForeignMod(ref fm) => { @@ -858,14 +845,12 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { /// Serialize the text of exported macros fn encode_info_for_macro_def(&mut self, macro_def: &hir::MacroDef) -> Entry<'tcx> { - let def_id = self.tcx.map.local_def_id(macro_def.id); Entry { kind: EntryKind::MacroDef(self.lazy(&MacroDef { body: ::syntax::print::pprust::tts_to_string(¯o_def.body) })), visibility: ty::Visibility::Public, span: self.lazy(¯o_def.span), - def_key: self.encode_def_key(def_id), attributes: self.encode_attributes(¯o_def.attrs), children: LazySeq::empty(), @@ -967,7 +952,6 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { kind: kind, visibility: nitem.vis.simplify(), span: self.lazy(&nitem.span), - def_key: self.encode_def_key(def_id), attributes: self.encode_attributes(&nitem.attrs), children: LazySeq::empty(), stability: self.encode_stability(def_id), @@ -1050,7 +1034,6 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { kind: EntryKind::Type, visibility: ty::Visibility::Public, span: self.lazy(&tcx.def_span(def_id)), - def_key: self.encode_def_key(def_id), attributes: LazySeq::empty(), children: LazySeq::empty(), stability: None, @@ -1079,7 +1062,6 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { kind: EntryKind::Closure(self.lazy(&data)), visibility: ty::Visibility::Public, span: self.lazy(&tcx.def_span(def_id)), - def_key: self.encode_def_key(def_id), attributes: self.encode_attributes(&tcx.get_attrs(def_id)), children: LazySeq::empty(), stability: None, @@ -1179,6 +1161,11 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { }) .map(|filemap| &**filemap)) } + + fn encode_def_path_table(&mut self) -> Lazy { + let definitions = self.tcx.map.definitions(); + self.lazy(definitions.def_path_table()) + } } struct ImplVisitor<'a, 'tcx: 'a> { @@ -1276,6 +1263,11 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let codemap = self.encode_codemap(); let codemap_bytes = self.position() - i; + // Encode DefPathTable + i = self.position(); + let def_path_table = self.encode_def_path_table(); + let def_path_table_bytes = self.position() - i; + // Encode the def IDs of impls, for coherence checking. i = self.position(); let impls = self.encode_impls(); @@ -1321,6 +1313,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { lang_items_missing: lang_items_missing, native_libraries: native_libraries, codemap: codemap, + def_path_table: def_path_table, impls: impls, exported_symbols: exported_symbols, index: index, @@ -1343,6 +1336,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { println!(" codemap bytes: {}", codemap_bytes); println!(" impl bytes: {}", impl_bytes); println!(" exp. symbols bytes: {}", exported_symbols_bytes); + println!(" def-path table bytes: {}", def_path_table_bytes); println!(" item bytes: {}", item_bytes); println!(" index bytes: {}", index_bytes); println!(" zero bytes: {}", zero_bytes); diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs index f92051cbf1943..0b6606a00d3c0 100644 --- a/src/librustc_metadata/schema.rs +++ b/src/librustc_metadata/schema.rs @@ -179,6 +179,7 @@ pub struct CrateRoot { pub lang_items_missing: LazySeq, pub native_libraries: LazySeq, pub codemap: LazySeq, + pub def_path_table: Lazy, pub impls: LazySeq, pub exported_symbols: LazySeq, pub index: LazySeq, @@ -202,7 +203,6 @@ pub struct Entry<'tcx> { pub kind: EntryKind<'tcx>, pub visibility: ty::Visibility, pub span: Lazy, - pub def_key: Lazy, pub attributes: LazySeq, pub children: LazySeq, pub stability: Option>, From e0d26294cd2d1034accf7b7b317c877a4a9b28af Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Fri, 16 Dec 2016 16:27:29 -0500 Subject: [PATCH 27/73] definitions: Add some timing stats for DefPathTable decoding. --- src/librustc/session/mod.rs | 5 +++++ src/librustc_metadata/creader.rs | 7 ++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index 91765e68ae6e1..36a887e062273 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -136,6 +136,8 @@ pub struct PerfStats { pub incr_comp_bytes_hashed: Cell, // The accumulated time spent on computing symbol hashes pub symbol_hash_time: Cell, + // The accumulated time spent decoding def path tables from metadata + pub decode_def_path_tables_time: Cell, } impl Session { @@ -501,6 +503,8 @@ impl Session { self.perf_stats.incr_comp_hashes_count.get()); println!("Total time spent computing symbol hashes: {}", duration_to_secs_str(self.perf_stats.symbol_hash_time.get())); + println!("Total time spent decoding DefPath tables: {}", + duration_to_secs_str(self.perf_stats.decode_def_path_tables_time.get())); } } @@ -635,6 +639,7 @@ pub fn build_session_(sopts: config::Options, incr_comp_hashes_count: Cell::new(0), incr_comp_bytes_hashed: Cell::new(0), symbol_hash_time: Cell::new(Duration::from_secs(0)), + decode_def_path_tables_time: Cell::new(Duration::from_secs(0)), }, code_stats: RefCell::new(CodeStats::new()), }; diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index 9eed5cb8fe8c4..a9af4118c5957 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -22,6 +22,7 @@ use rustc_back::PanicStrategy; use rustc::session::search_paths::PathKind; use rustc::middle; use rustc::middle::cstore::{CrateStore, validate_crate_name, ExternCrate}; +use rustc::util::common::record_time; use rustc::util::nodemap::FxHashSet; use rustc::middle::cstore::NativeLibrary; use rustc::hir::map::Definitions; @@ -297,10 +298,14 @@ impl<'a> CrateLoader<'a> { let cnum_map = self.resolve_crate_deps(root, &crate_root, &metadata, cnum, span, dep_kind); + let def_path_table = record_time(&self.sess.perf_stats.decode_def_path_tables_time, || { + crate_root.def_path_table.decode(&metadata) + }); + let mut cmeta = cstore::CrateMetadata { name: name, extern_crate: Cell::new(None), - def_path_table: crate_root.def_path_table.decode(&metadata), + def_path_table: def_path_table, proc_macros: crate_root.macro_derive_registrar.map(|_| { self.load_derive_macros(&crate_root, dylib.clone().map(|p| p.0), span) }), From ea733b589c2c12b1b635d18ec033122eaa3e0d06 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Fri, 16 Dec 2016 17:23:29 -0500 Subject: [PATCH 28/73] No need to store Definitions in RefCell within HIR map --- src/librustc/hir/map/mod.rs | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index e5c5b43081167..7b827b0a7e5a9 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -29,7 +29,7 @@ use hir::*; use hir::print as pprust; use arena::TypedArena; -use std::cell::{RefCell, Ref}; +use std::cell::RefCell; use std::io; use std::mem; @@ -221,7 +221,7 @@ pub struct Map<'ast> { /// plain old integers. map: RefCell>>, - definitions: RefCell, + definitions: Definitions, /// All NodeIds that are numerically greater or equal to this value come /// from inlined items. @@ -392,16 +392,16 @@ impl<'ast> Map<'ast> { } pub fn num_local_def_ids(&self) -> usize { - self.definitions.borrow().len() + self.definitions.len() } - pub fn definitions(&self) -> Ref { - self.definitions.borrow() + pub fn definitions(&self) -> &Definitions { + &self.definitions } pub fn def_key(&self, def_id: DefId) -> DefKey { assert!(def_id.is_local()); - self.definitions.borrow().def_key(def_id.index) + self.definitions.def_key(def_id.index) } pub fn def_path_from_id(&self, id: NodeId) -> Option { @@ -412,11 +412,11 @@ impl<'ast> Map<'ast> { pub fn def_path(&self, def_id: DefId) -> DefPath { assert!(def_id.is_local()); - self.definitions.borrow().def_path(def_id.index) + self.definitions.def_path(def_id.index) } pub fn def_index_for_def_key(&self, def_key: DefKey) -> Option { - self.definitions.borrow().def_index_for_def_key(def_key) + self.definitions.def_index_for_def_key(def_key) } pub fn local_def_id(&self, node: NodeId) -> DefId { @@ -427,11 +427,11 @@ impl<'ast> Map<'ast> { } pub fn opt_local_def_id(&self, node: NodeId) -> Option { - self.definitions.borrow().opt_local_def_id(node) + self.definitions.opt_local_def_id(node) } pub fn as_local_node_id(&self, def_id: DefId) -> Option { - self.definitions.borrow().as_local_node_id(def_id) + self.definitions.as_local_node_id(def_id) } fn entry_count(&self) -> usize { @@ -940,7 +940,7 @@ pub fn map_crate<'ast>(forest: &'ast mut Forest, forest: forest, dep_graph: forest.dep_graph.clone(), map: RefCell::new(map), - definitions: RefCell::new(definitions), + definitions: definitions, local_node_id_watermark: local_node_id_watermark, local_def_id_watermark: local_def_id_watermark, } From 72f95aac1ba1891fcf13b568514520205e3c848b Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Fri, 16 Dec 2016 17:24:27 -0500 Subject: [PATCH 29/73] Move retrace_path() implementation to DefPathTable --- src/librustc/hir/map/definitions.rs | 33 +++++++++++++++++-- src/librustc/middle/cstore.rs | 27 +++++++-------- src/librustc/ty/context.rs | 49 ++++++---------------------- src/librustc_metadata/cstore_impl.rs | 19 ++++++----- 4 files changed, 65 insertions(+), 63 deletions(-) diff --git a/src/librustc/hir/map/definitions.rs b/src/librustc/hir/map/definitions.rs index ef574b61aa7e9..16b8880b36fea 100644 --- a/src/librustc/hir/map/definitions.rs +++ b/src/librustc/hir/map/definitions.rs @@ -15,8 +15,6 @@ //! There are also some rather random cases (like const initializer //! expressions) that are mostly just leftovers. - - use hir::def_id::{CrateNum, DefId, DefIndex, LOCAL_CRATE}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::stable_hasher::StableHasher; @@ -57,6 +55,37 @@ impl DefPathTable { pub fn contains_key(&self, key: &DefKey) -> bool { self.key_to_index.contains_key(key) } + + pub fn retrace_path(&self, + path_data: &[DisambiguatedDefPathData]) + -> Option { + let root_key = DefKey { + parent: None, + disambiguated_data: DisambiguatedDefPathData { + data: DefPathData::CrateRoot, + disambiguator: 0, + }, + }; + + let root_index = self.key_to_index + .get(&root_key) + .expect("no root key?") + .clone(); + + debug!("retrace_path: root_index={:?}", root_index); + + let mut index = root_index; + for data in path_data { + let key = DefKey { parent: Some(index), disambiguated_data: data.clone() }; + debug!("retrace_path: key={:?}", key); + match self.key_to_index.get(&key) { + Some(&i) => index = i, + None => return None, + } + } + + Some(index) + } } diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs index f2be97c832370..88fac105bf55a 100644 --- a/src/librustc/middle/cstore.rs +++ b/src/librustc/middle/cstore.rs @@ -25,7 +25,7 @@ use hir::def::{self, Def}; use hir::def_id::{CrateNum, DefId, DefIndex}; use hir::map as hir_map; -use hir::map::definitions::{Definitions, DefKey}; +use hir::map::definitions::{Definitions, DefKey, DisambiguatedDefPathData}; use hir::svh::Svh; use middle::lang_items; use ty::{self, Ty, TyCtxt}; @@ -336,11 +336,11 @@ pub trait CrateStore<'tcx> { fn is_no_builtins(&self, cnum: CrateNum) -> bool; // resolve - fn def_index_for_def_key(&self, - cnum: CrateNum, - def: DefKey) - -> Option; - fn def_key(&self, def: DefId) -> hir_map::DefKey; + fn retrace_path(&self, + cnum: CrateNum, + path_data: &[DisambiguatedDefPathData]) + -> Option; + fn def_key(&self, def: DefId) -> DefKey; fn relative_def_path(&self, def: DefId) -> Option; fn struct_field_names(&self, def: DefId) -> Vec; fn item_children(&self, did: DefId) -> Vec; @@ -442,12 +442,6 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore { // trait info fn implementations_of_trait(&self, filter: Option) -> Vec { vec![] } - fn def_index_for_def_key(&self, - cnum: CrateNum, - def: DefKey) - -> Option { - None - } // impl info fn associated_item_def_ids(&self, def_id: DefId) -> Vec @@ -508,7 +502,14 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore { fn is_no_builtins(&self, cnum: CrateNum) -> bool { bug!("is_no_builtins") } // resolve - fn def_key(&self, def: DefId) -> hir_map::DefKey { bug!("def_key") } + fn retrace_path(&self, + cnum: CrateNum, + path_data: &[DisambiguatedDefPathData]) + -> Option { + None + } + + fn def_key(&self, def: DefId) -> DefKey { bug!("def_key") } fn relative_def_path(&self, def: DefId) -> Option { bug!("relative_def_path") } diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 4854a14f733f5..001d18b95cac0 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -15,9 +15,9 @@ use session::Session; use middle; use hir::TraitMap; use hir::def::Def; -use hir::def_id::{CrateNum, DefId, DefIndex, LOCAL_CRATE}; +use hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; use hir::map as ast_map; -use hir::map::{DefKey, DefPathData, DisambiguatedDefPathData}; +use hir::map::DisambiguatedDefPathData; use middle::free_region::FreeRegionMap; use middle::region::RegionMaps; use middle::resolve_lifetime; @@ -627,50 +627,21 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } } - /// Given a def-key `key` and a crate `krate`, finds the def-index - /// that `krate` assigned to `key`. This `DefIndex` will always be - /// relative to `krate`. - /// - /// Returns `None` if there is no `DefIndex` with that key. - pub fn def_index_for_def_key(self, krate: CrateNum, key: DefKey) - -> Option { - if krate == LOCAL_CRATE { - self.map.def_index_for_def_key(key) - } else { - self.sess.cstore.def_index_for_def_key(krate, key) - } - } - pub fn retrace_path(self, krate: CrateNum, path_data: &[DisambiguatedDefPathData]) -> Option { debug!("retrace_path(path={:?}, krate={:?})", path_data, self.crate_name(krate)); - let root_key = DefKey { - parent: None, - disambiguated_data: DisambiguatedDefPathData { - data: DefPathData::CrateRoot, - disambiguator: 0, - }, - }; - - let root_index = self.def_index_for_def_key(krate, root_key) - .expect("no root key?"); - - debug!("retrace_path: root_index={:?}", root_index); - - let mut index = root_index; - for data in path_data { - let key = DefKey { parent: Some(index), disambiguated_data: data.clone() }; - debug!("retrace_path: key={:?}", key); - match self.def_index_for_def_key(krate, key) { - Some(i) => index = i, - None => return None, - } + if krate == LOCAL_CRATE { + self.map + .definitions() + .def_path_table() + .retrace_path(path_data) + .map(|def_index| DefId { krate: krate, index: def_index }) + } else { + self.sess.cstore.retrace_path(krate, path_data) } - - Some(DefId { krate: krate, index: index }) } pub fn type_parameter_def(self, diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index 7305b23951590..bcb30982e1f70 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -22,8 +22,7 @@ use rustc::ty::{self, Ty, TyCtxt}; use rustc::hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE}; use rustc::dep_graph::DepNode; -use rustc::hir::map as hir_map; -use rustc::hir::map::DefKey; +use rustc::hir::map::{DefKey, DefPath, DisambiguatedDefPathData}; use rustc::mir::Mir; use rustc::util::nodemap::{NodeSet, DefIdMap}; use rustc_back::PanicStrategy; @@ -336,18 +335,20 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { self.get_crate_data(cnum).is_no_builtins() } - fn def_index_for_def_key(&self, - cnum: CrateNum, - def: DefKey) - -> Option { + fn retrace_path(&self, + cnum: CrateNum, + path: &[DisambiguatedDefPathData]) + -> Option { let cdata = self.get_crate_data(cnum); - cdata.def_path_table.def_index_for_def_key(&def) + cdata.def_path_table + .retrace_path(&path) + .map(|index| DefId { krate: cnum, index: index }) } /// Returns the `DefKey` for a given `DefId`. This indicates the /// parent `DefId` as well as some idea of what kind of data the /// `DefId` refers to. - fn def_key(&self, def: DefId) -> hir_map::DefKey { + fn def_key(&self, def: DefId) -> DefKey { // Note: loading the def-key (or def-path) for a def-id is not // a *read* of its metadata. This is because the def-id is // really just an interned shorthand for a def-path, which is the @@ -357,7 +358,7 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { self.get_crate_data(def.krate).def_key(def.index) } - fn relative_def_path(&self, def: DefId) -> Option { + fn relative_def_path(&self, def: DefId) -> Option { // See `Note` above in `def_key()` for why this read is // commented out: // From 70944c2b5f81d2e2cbf3fc811ea1ca8330ad8d8c Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Fri, 16 Dec 2016 18:52:47 -0500 Subject: [PATCH 30/73] No need to have tcx::opt_def_path() now that we store all DefPaths --- src/librustc/hir/def_id.rs | 4 +--- src/librustc/middle/cstore.rs | 4 ++-- src/librustc/ty/mod.rs | 35 ++++------------------------ src/librustc_metadata/cstore_impl.rs | 2 +- src/librustc_metadata/decoder.rs | 17 ++++---------- 5 files changed, 13 insertions(+), 49 deletions(-) diff --git a/src/librustc/hir/def_id.rs b/src/librustc/hir/def_id.rs index d3771b1755b16..cbf162cc1366e 100644 --- a/src/librustc/hir/def_id.rs +++ b/src/librustc/hir/def_id.rs @@ -120,9 +120,7 @@ impl fmt::Debug for DefId { ty::tls::with_opt(|opt_tcx| { if let Some(tcx) = opt_tcx { - if let Some(def_path) = tcx.opt_def_path(*self) { - write!(f, " => {}", def_path.to_string(tcx))?; - } + write!(f, " => {}", tcx.def_path(*self).to_string(tcx))?; } Ok(()) })?; diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs index 88fac105bf55a..9f9c6fd87aa85 100644 --- a/src/librustc/middle/cstore.rs +++ b/src/librustc/middle/cstore.rs @@ -341,7 +341,7 @@ pub trait CrateStore<'tcx> { path_data: &[DisambiguatedDefPathData]) -> Option; fn def_key(&self, def: DefId) -> DefKey; - fn relative_def_path(&self, def: DefId) -> Option; + fn def_path(&self, def: DefId) -> hir_map::DefPath; fn struct_field_names(&self, def: DefId) -> Vec; fn item_children(&self, did: DefId) -> Vec; fn load_macro(&self, did: DefId, sess: &Session) -> LoadedMacro; @@ -510,7 +510,7 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore { } fn def_key(&self, def: DefId) -> DefKey { bug!("def_key") } - fn relative_def_path(&self, def: DefId) -> Option { + fn def_path(&self, def: DefId) -> hir_map::DefPath { bug!("relative_def_path") } fn struct_field_names(&self, def: DefId) -> Vec { bug!("struct_field_names") } diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index df12c252907a5..f8dee95f338f8 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -2241,40 +2241,13 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { /// Convert a `DefId` into its fully expanded `DefPath` (every /// `DefId` is really just an interned def-path). /// - /// Note that if `id` is not local to this crate -- or is - /// inlined into this crate -- the result will be a non-local - /// `DefPath`. - /// - /// This function is only safe to use when you are sure that the - /// full def-path is accessible. Examples that are known to be - /// safe are local def-ids or items; see `opt_def_path` for more - /// details. + /// Note that if `id` is not local to this crate, the result will + // be a non-local `DefPath`. pub fn def_path(self, id: DefId) -> ast_map::DefPath { - self.opt_def_path(id).unwrap_or_else(|| { - bug!("could not load def-path for {:?}", id) - }) - } - - /// Convert a `DefId` into its fully expanded `DefPath` (every - /// `DefId` is really just an interned def-path). - /// - /// When going across crates, we do not save the full info for - /// every cross-crate def-id, and hence we may not always be able - /// to create a def-path. Therefore, this returns - /// `Option` to cover that possibility. It will always - /// return `Some` for local def-ids, however, as well as for - /// items. The problems arise with "minor" def-ids like those - /// associated with a pattern, `impl Trait`, or other internal - /// detail to a fn. - /// - /// Note that if `id` is not local to this crate -- or is - /// inlined into this crate -- the result will be a non-local - /// `DefPath`. - pub fn opt_def_path(self, id: DefId) -> Option { if id.is_local() { - Some(self.map.def_path(id)) + self.map.def_path(id) } else { - self.sess.cstore.relative_def_path(id) + self.sess.cstore.def_path(id) } } diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index bcb30982e1f70..8a29f9d627688 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -358,7 +358,7 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { self.get_crate_data(def.krate).def_key(def.index) } - fn relative_def_path(&self, def: DefId) -> Option { + fn def_path(&self, def: DefId) -> DefPath { // See `Note` above in `def_key()` for why this read is // commented out: // diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index cf550f03d8eb8..853a49dffc7b5 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -14,8 +14,7 @@ use astencode::decode_inlined_item; use cstore::{self, CrateMetadata, MetadataBlob, NativeLibrary}; use schema::*; -use rustc::hir::map as hir_map; -use rustc::hir::map::{DefKey, DefPathData}; +use rustc::hir::map::{DefKey, DefPath, DefPathData}; use rustc::hir; use rustc::hir::intravisit::IdRange; @@ -567,7 +566,7 @@ impl<'a, 'tcx> CrateMetadata { ty::TraitDef::new(self.local_def_id(item_id), data.unsafety, data.paren_sugar, - self.def_path(item_id).unwrap().deterministic_hash(tcx)) + self.def_path(item_id).deterministic_hash(tcx)) } fn get_variant(&self, @@ -1128,16 +1127,10 @@ impl<'a, 'tcx> CrateMetadata { self.def_path_table.def_key(index) } - // Returns the path leading to the thing with this `id`. Note that - // some def-ids don't wind up in the metadata, so `def_path` sometimes - // returns `None` - pub fn def_path(&self, id: DefIndex) -> Option { + // Returns the path leading to the thing with this `id`. + pub fn def_path(&self, id: DefIndex) -> DefPath { debug!("def_path(id={:?})", id); - if self.is_proc_macro(id) || self.maybe_entry(id).is_some() { - Some(hir_map::DefPath::make(self.cnum, id, |parent| self.def_key(parent))) - } else { - None - } + DefPath::make(self.cnum, id, |parent| self.def_path_table.def_key(parent)) } /// Imports the codemap from an external crate into the codemap of the crate From 45571f34aaaa904ef58484aad41233f815ccace9 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Fri, 16 Dec 2016 19:12:37 -0500 Subject: [PATCH 31/73] definitions: Add some documentation. --- src/librustc/hir/map/definitions.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/librustc/hir/map/definitions.rs b/src/librustc/hir/map/definitions.rs index 16b8880b36fea..4f64670f48279 100644 --- a/src/librustc/hir/map/definitions.rs +++ b/src/librustc/hir/map/definitions.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - //! For each definition, we track the following data. A definition //! here is defined somewhat circularly as "something with a def-id", //! but it generally corresponds to things like structs, enums, etc. @@ -26,6 +25,10 @@ use syntax::symbol::{Symbol, InternedString}; use ty::TyCtxt; use util::nodemap::NodeMap; +/// The DefPathTable maps DefIndexes to DefKeys and vice versa. +/// Internally the DefPathTable holds a tree of DefKeys, where each DefKey +/// stores the DefIndex of its parent. +/// There is one DefPathTable for each crate. #[derive(Clone)] pub struct DefPathTable { index_to_key: Vec, @@ -110,7 +113,9 @@ impl Decodable for DefPathTable { } -/// The definition table containing node definitions +/// The definition table containing node definitions. +/// It holds the DefPathTable for local DefIds/DefPaths and it also stores a +/// mapping from NodeIds to local DefIds. #[derive(Clone)] pub struct Definitions { table: DefPathTable, From 77e659a6d324bd6f096832899f5f77ae5c5d734e Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Fri, 16 Dec 2016 20:11:59 -0500 Subject: [PATCH 32/73] Remove some more things that were only needed for inlined-HIR DefIds --- src/librustc/dep_graph/README.md | 6 +- src/librustc/dep_graph/visit.rs | 2 - src/librustc/hir/map/def_collector.rs | 192 ----------------------- src/librustc/hir/map/mod.rs | 12 -- src/librustc_incremental/persist/hash.rs | 5 - 5 files changed, 2 insertions(+), 215 deletions(-) diff --git a/src/librustc/dep_graph/README.md b/src/librustc/dep_graph/README.md index 48f5b7ea2595d..d2b94db689bc4 100644 --- a/src/librustc/dep_graph/README.md +++ b/src/librustc/dep_graph/README.md @@ -418,7 +418,7 @@ to see something like: Hir(foo) -> Collect(bar) Collect(bar) -> TypeckItemBody(bar) - + That first edge looks suspicious to you. So you set `RUST_FORBID_DEP_GRAPH_EDGE` to `Hir&foo -> Collect&bar`, re-run, and then observe the backtrace. Voila, bug fixed! @@ -440,6 +440,4 @@ To achieve this, the HIR map will detect if the def-id originates in an inlined node and add a dependency to a suitable `MetaData` node instead. If you are reading a HIR node and are not sure if it may be inlined or not, you can use `tcx.map.read(node_id)` and it will detect -whether the node is inlined or not and do the right thing. You can -also use `tcx.map.is_inlined_def_id()` and -`tcx.map.is_inlined_node_id()` to test. +whether the node is inlined or not and do the right thing. diff --git a/src/librustc/dep_graph/visit.rs b/src/librustc/dep_graph/visit.rs index 600732fc6f70b..f6a22e47cf212 100644 --- a/src/librustc/dep_graph/visit.rs +++ b/src/librustc/dep_graph/visit.rs @@ -40,7 +40,6 @@ pub fn visit_all_item_likes_in_krate<'a, 'tcx, V, F>(tcx: TyCtxt<'a, 'tcx, 'tcx> let task_id = (self.dep_node_fn)(item_def_id); let _task = self.tcx.dep_graph.in_task(task_id.clone()); debug!("Started task {:?}", task_id); - assert!(!self.tcx.map.is_inlined_def_id(item_def_id)); self.tcx.dep_graph.read(DepNode::Hir(item_def_id)); self.visitor.visit_item(i); debug!("Ended task {:?}", task_id); @@ -51,7 +50,6 @@ pub fn visit_all_item_likes_in_krate<'a, 'tcx, V, F>(tcx: TyCtxt<'a, 'tcx, 'tcx> let task_id = (self.dep_node_fn)(impl_item_def_id); let _task = self.tcx.dep_graph.in_task(task_id.clone()); debug!("Started task {:?}", task_id); - assert!(!self.tcx.map.is_inlined_def_id(impl_item_def_id)); self.tcx.dep_graph.read(DepNode::Hir(impl_item_def_id)); self.visitor.visit_impl_item(i); debug!("Ended task {:?}", task_id); diff --git a/src/librustc/hir/map/def_collector.rs b/src/librustc/hir/map/def_collector.rs index 8c303a96b0ced..256aee342a3fc 100644 --- a/src/librustc/hir/map/def_collector.rs +++ b/src/librustc/hir/map/def_collector.rs @@ -9,13 +9,8 @@ // except according to those terms. use hir::map::definitions::*; - -use hir; -use hir::intravisit::{self, Visitor, NestedVisitorMap}; use hir::def_id::{CRATE_DEF_INDEX, DefIndex}; -use middle::cstore::InlinedItem; - use syntax::ast::*; use syntax::ext::hygiene::Mark; use syntax::visit; @@ -23,9 +18,6 @@ use syntax::symbol::{Symbol, keywords}; /// Creates def ids for nodes in the HIR. pub struct DefCollector<'a> { - // If we are walking HIR (c.f., AST), we need to keep a reference to the - // crate. - hir_crate: Option<&'a hir::Crate>, definitions: &'a mut Definitions, parent_def: Option, pub visit_macro_invoc: Option<&'a mut FnMut(MacroInvocationData)>, @@ -40,7 +32,6 @@ pub struct MacroInvocationData { impl<'a> DefCollector<'a> { pub fn new(definitions: &'a mut Definitions) -> Self { DefCollector { - hir_crate: None, definitions: definitions, parent_def: None, visit_macro_invoc: None, @@ -51,13 +42,6 @@ impl<'a> DefCollector<'a> { let root = self.create_def_with_parent(None, CRATE_NODE_ID, DefPathData::CrateRoot); assert_eq!(root, CRATE_DEF_INDEX); self.parent_def = Some(root); - - self.create_def_with_parent(Some(CRATE_DEF_INDEX), DUMMY_NODE_ID, DefPathData::Misc); - } - - pub fn walk_item(&mut self, ii: &'a InlinedItem, krate: &'a hir::Crate) { - self.hir_crate = Some(krate); - ii.visit(self); } fn create_def(&mut self, node_id: NodeId, data: DefPathData) -> DefIndex { @@ -95,16 +79,6 @@ impl<'a> DefCollector<'a> { self.create_def(expr.id, DefPathData::Initializer); } - fn visit_hir_const_integer(&mut self, expr: &hir::Expr) { - // FIXME(eddyb) Closures should have separate - // function definition IDs and expression IDs. - if let hir::ExprClosure(..) = expr.node { - return; - } - - self.create_def(expr.id, DefPathData::Initializer); - } - fn visit_macro_invoc(&mut self, id: NodeId, const_integer: bool) { if let Some(ref mut visit) = self.visit_macro_invoc { visit(MacroInvocationData { @@ -305,169 +279,3 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { } } } - -// We walk the HIR rather than the AST when reading items from metadata. -impl<'ast> Visitor<'ast> for DefCollector<'ast> { - fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'ast> { - // note however that we override `visit_body` below - NestedVisitorMap::None - } - - fn visit_body(&mut self, id: hir::ExprId) { - if let Some(krate) = self.hir_crate { - self.visit_expr(krate.expr(id)); - } - } - - fn visit_item(&mut self, i: &'ast hir::Item) { - debug!("visit_item: {:?}", i); - - // Pick the def data. This need not be unique, but the more - // information we encapsulate into - let def_data = match i.node { - hir::ItemDefaultImpl(..) | hir::ItemImpl(..) => - DefPathData::Impl, - hir::ItemEnum(..) | hir::ItemStruct(..) | hir::ItemUnion(..) | - hir::ItemTrait(..) | hir::ItemExternCrate(..) | hir::ItemMod(..) | - hir::ItemForeignMod(..) | hir::ItemTy(..) => - DefPathData::TypeNs(i.name.as_str()), - hir::ItemStatic(..) | hir::ItemConst(..) | hir::ItemFn(..) => - DefPathData::ValueNs(i.name.as_str()), - hir::ItemUse(..) => DefPathData::Misc, - }; - let def = self.create_def(i.id, def_data); - - self.with_parent(def, |this| { - match i.node { - hir::ItemEnum(ref enum_definition, _) => { - for v in &enum_definition.variants { - let variant_def_index = - this.create_def(v.node.data.id(), - DefPathData::EnumVariant(v.node.name.as_str())); - - this.with_parent(variant_def_index, |this| { - for field in v.node.data.fields() { - this.create_def(field.id, - DefPathData::Field(field.name.as_str())); - } - if let Some(ref expr) = v.node.disr_expr { - this.visit_hir_const_integer(expr); - } - }); - } - } - hir::ItemStruct(ref struct_def, _) | - hir::ItemUnion(ref struct_def, _) => { - // If this is a tuple-like struct, register the constructor. - if !struct_def.is_struct() { - this.create_def(struct_def.id(), - DefPathData::StructCtor); - } - - for field in struct_def.fields() { - this.create_def(field.id, DefPathData::Field(field.name.as_str())); - } - } - _ => {} - } - intravisit::walk_item(this, i); - }); - } - - fn visit_foreign_item(&mut self, foreign_item: &'ast hir::ForeignItem) { - let def = self.create_def(foreign_item.id, - DefPathData::ValueNs(foreign_item.name.as_str())); - - self.with_parent(def, |this| { - intravisit::walk_foreign_item(this, foreign_item); - }); - } - - fn visit_generics(&mut self, generics: &'ast hir::Generics) { - for ty_param in generics.ty_params.iter() { - self.create_def(ty_param.id, DefPathData::TypeParam(ty_param.name.as_str())); - } - - intravisit::walk_generics(self, generics); - } - - fn visit_trait_item(&mut self, ti: &'ast hir::TraitItem) { - let def_data = match ti.node { - hir::MethodTraitItem(..) | hir::ConstTraitItem(..) => - DefPathData::ValueNs(ti.name.as_str()), - hir::TypeTraitItem(..) => DefPathData::TypeNs(ti.name.as_str()), - }; - - let def = self.create_def(ti.id, def_data); - self.with_parent(def, |this| { - if let hir::ConstTraitItem(_, Some(ref expr)) = ti.node { - this.create_def(expr.id, DefPathData::Initializer); - } - - intravisit::walk_trait_item(this, ti); - }); - } - - fn visit_impl_item(&mut self, ii: &'ast hir::ImplItem) { - let def_data = match ii.node { - hir::ImplItemKind::Method(..) | hir::ImplItemKind::Const(..) => - DefPathData::ValueNs(ii.name.as_str()), - hir::ImplItemKind::Type(..) => DefPathData::TypeNs(ii.name.as_str()), - }; - - let def = self.create_def(ii.id, def_data); - self.with_parent(def, |this| { - if let hir::ImplItemKind::Const(_, ref expr) = ii.node { - this.create_def(expr.id, DefPathData::Initializer); - } - - intravisit::walk_impl_item(this, ii); - }); - } - - fn visit_pat(&mut self, pat: &'ast hir::Pat) { - let parent_def = self.parent_def; - - if let hir::PatKind::Binding(_, _, name, _) = pat.node { - let def = self.create_def(pat.id, DefPathData::Binding(name.node.as_str())); - self.parent_def = Some(def); - } - - intravisit::walk_pat(self, pat); - self.parent_def = parent_def; - } - - fn visit_expr(&mut self, expr: &'ast hir::Expr) { - let parent_def = self.parent_def; - - if let hir::ExprRepeat(_, ref count) = expr.node { - self.visit_hir_const_integer(count); - } - - if let hir::ExprClosure(..) = expr.node { - let def = self.create_def(expr.id, DefPathData::ClosureExpr); - self.parent_def = Some(def); - } - - intravisit::walk_expr(self, expr); - self.parent_def = parent_def; - } - - fn visit_ty(&mut self, ty: &'ast hir::Ty) { - if let hir::TyArray(_, ref length) = ty.node { - self.visit_hir_const_integer(length); - } - if let hir::TyImplTrait(..) = ty.node { - self.create_def(ty.id, DefPathData::ImplTrait); - } - intravisit::walk_ty(self, ty); - } - - fn visit_lifetime_def(&mut self, def: &'ast hir::LifetimeDef) { - self.create_def(def.lifetime.id, DefPathData::LifetimeDef(def.lifetime.name.as_str())); - } - - fn visit_macro_def(&mut self, macro_def: &'ast hir::MacroDef) { - self.create_def(macro_def.id, DefPathData::MacroDef(macro_def.name.as_str())); - } -} diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index 7b827b0a7e5a9..4546f6d8c27e6 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -226,17 +226,9 @@ pub struct Map<'ast> { /// All NodeIds that are numerically greater or equal to this value come /// from inlined items. local_node_id_watermark: NodeId, - - /// All def-indices that are numerically greater or equal to this value come - /// from inlined items. - local_def_id_watermark: usize, } impl<'ast> Map<'ast> { - pub fn is_inlined_def_id(&self, id: DefId) -> bool { - id.is_local() && id.index.as_usize() >= self.local_def_id_watermark - } - pub fn is_inlined_node_id(&self, id: NodeId) -> bool { id >= self.local_node_id_watermark } @@ -262,7 +254,6 @@ impl<'ast> Map<'ast> { EntryItem(_, item) => { assert_eq!(id, item.id); let def_id = self.local_def_id(id); - assert!(!self.is_inlined_def_id(def_id)); if let Some(last_id) = last_expr { // The body of the item may have a separate dep node @@ -278,7 +269,6 @@ impl<'ast> Map<'ast> { EntryImplItem(_, item) => { let def_id = self.local_def_id(id); - assert!(!self.is_inlined_def_id(def_id)); if let Some(last_id) = last_expr { // The body of the item may have a separate dep node @@ -934,7 +924,6 @@ pub fn map_crate<'ast>(forest: &'ast mut Forest, } let local_node_id_watermark = NodeId::new(map.len()); - let local_def_id_watermark = definitions.len(); Map { forest: forest, @@ -942,7 +931,6 @@ pub fn map_crate<'ast>(forest: &'ast mut Forest, map: RefCell::new(map), definitions: definitions, local_node_id_watermark: local_node_id_watermark, - local_def_id_watermark: local_def_id_watermark, } } diff --git a/src/librustc_incremental/persist/hash.rs b/src/librustc_incremental/persist/hash.rs index e5203ea02b45a..799cb6c5e3d8c 100644 --- a/src/librustc_incremental/persist/hash.rs +++ b/src/librustc_incremental/persist/hash.rs @@ -66,11 +66,6 @@ impl<'a, 'tcx> HashContext<'a, 'tcx> { def_id, self.tcx.item_path_str(def_id)); - assert!(!self.tcx.map.is_inlined_def_id(def_id), - "cannot hash HIR for inlined def-id {:?} => {:?}", - def_id, - self.tcx.item_path_str(def_id)); - Some(self.incremental_hashes_map[dep_node]) } From dd0fc0a03a680d76d3454f955648876b2a1ccae8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Marie?= Date: Sat, 17 Dec 2016 11:22:41 +0100 Subject: [PATCH 33/73] Disconnect ar from cc on OpenBSD OpenBSD usually use an alternative compiler (`egcc') from ports. But the `ar' is unprefixed as it comes from base. --- src/build_helper/lib.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/build_helper/lib.rs b/src/build_helper/lib.rs index 07f9c91d3c787..bd036fae68955 100644 --- a/src/build_helper/lib.rs +++ b/src/build_helper/lib.rs @@ -47,6 +47,8 @@ pub fn cc2ar(cc: &Path, target: &str) -> Option { None } else if target.contains("musl") { Some(PathBuf::from("ar")) + } else if target.contains("openbsd") { + Some(PathBuf::from("ar")) } else { let parent = cc.parent().unwrap(); let file = cc.file_name().unwrap().to_str().unwrap(); From 18ff6410d8c196537fc64a10d9d5b502308eb6fa Mon Sep 17 00:00:00 2001 From: Stjepan Glavina Date: Sat, 17 Dec 2016 17:36:33 +0100 Subject: [PATCH 34/73] Minor fix in the merge_sort comments There was an off-by-one error discovered by @tbelaire. So, the two invariants we are enforcing are: 1. Run lengths are decreasing. 2. Sum of lengths of any two adjacent runs is less than the length of their predecessor. This commit changes the comment to be clearer and have correct bounds on `i`. --- src/libcollections/slice.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libcollections/slice.rs b/src/libcollections/slice.rs index 5fb8cd6e1e2b7..b5e6669220535 100644 --- a/src/libcollections/slice.rs +++ b/src/libcollections/slice.rs @@ -1496,10 +1496,10 @@ unsafe fn merge(v: &mut [T], mid: usize, buf: *mut T, compare: &mut F) /// The algorithm identifies strictly descending and non-descending subsequences, which are called /// natural runs. There is a stack of pending runs yet to be merged. Each newly found run is pushed /// onto the stack, and then some pairs of adjacent runs are merged until these two invariants are -/// satisfied, for every `i` in `0 .. runs.len() - 2`: +/// satisfied: /// -/// 1. `runs[i].len > runs[i + 1].len` -/// 2. `runs[i].len > runs[i + 1].len + runs[i + 2].len` +/// 1. for every `i` in `1..runs.len()`: `runs[i - 1].len > runs[i].len` +/// 2. for every `i` in `2..runs.len()`: `runs[i - 2].len > runs[i - 1].len + runs[i].len` /// /// The invariants ensure that the total running time is `O(n log n)` worst-case. fn merge_sort(v: &mut [T], mut compare: F) From 9f8c1e28a5c7e042c6522f84a684ad848a200c30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Marie?= Date: Sat, 17 Dec 2016 20:01:05 +0100 Subject: [PATCH 35/73] disable run-pass/backtrace for openbsd the backtrace test doesn't work on openbsd as it doesn't have support for libbacktrace without using filename. --- src/test/run-pass/backtrace.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/run-pass/backtrace.rs b/src/test/run-pass/backtrace.rs index c438c17f51e3a..75c665b04a123 100644 --- a/src/test/run-pass/backtrace.rs +++ b/src/test/run-pass/backtrace.rs @@ -10,6 +10,7 @@ // ignore-android FIXME #17520 // ignore-emscripten spawning processes is not supported +// ignore-openbsd no support for libbacktrace without filename // compile-flags:-g use std::env; From a7d9025e40a55d5d8ddeb2f35075512055c363ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Marie?= Date: Sat, 17 Dec 2016 20:09:23 +0100 Subject: [PATCH 36/73] let BSD to use gmake for GNU-make the diff extends build_helper to provide an function to return the expected name of GNU-make on the host: "make" or "gmake". Fixes #38429 --- src/Cargo.lock | 1 + src/bootstrap/check.rs | 4 +++- src/build_helper/lib.rs | 10 ++++++++++ src/liballoc_jemalloc/build.rs | 2 +- src/libstd/build.rs | 2 +- src/tools/compiletest/Cargo.toml | 1 + src/tools/compiletest/src/runtest.rs | 4 +++- 7 files changed, 20 insertions(+), 4 deletions(-) diff --git a/src/Cargo.lock b/src/Cargo.lock index 9cd77e71b82dd..01a19a0cca862 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -87,6 +87,7 @@ dependencies = [ name = "compiletest" version = "0.0.0" dependencies = [ + "build_helper 0.1.0", "env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "serialize 0.0.0", diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index 712c4c52baa5f..aa15825d8293c 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -13,6 +13,8 @@ //! This file implements the various regression test suites that we execute on //! our CI. +extern crate build_helper; + use std::collections::HashSet; use std::env; use std::fmt; @@ -543,7 +545,7 @@ pub fn distcheck(build: &Build) { build.run(&mut cmd); build.run(Command::new("./configure") .current_dir(&dir)); - build.run(Command::new("make") + build.run(Command::new(build_helper::make(&build.config.build)) .arg("check") .current_dir(&dir)); } diff --git a/src/build_helper/lib.rs b/src/build_helper/lib.rs index bd036fae68955..d0d588f46a754 100644 --- a/src/build_helper/lib.rs +++ b/src/build_helper/lib.rs @@ -63,6 +63,16 @@ pub fn cc2ar(cc: &Path, target: &str) -> Option { } } +pub fn make(host: &str) -> PathBuf { + if host.contains("bitrig") || host.contains("dragonfly") || + host.contains("freebsd") || host.contains("netbsd") || + host.contains("openbsd") { + PathBuf::from("gmake") + } else { + PathBuf::from("make") + } +} + pub fn output(cmd: &mut Command) -> String { let output = match cmd.stderr(Stdio::inherit()).output() { Ok(status) => status, diff --git a/src/liballoc_jemalloc/build.rs b/src/liballoc_jemalloc/build.rs index fc849e7a50cc4..60b7875a97c84 100644 --- a/src/liballoc_jemalloc/build.rs +++ b/src/liballoc_jemalloc/build.rs @@ -151,7 +151,7 @@ fn main() { cmd.arg(format!("--build={}", build_helper::gnu_target(&host))); run(&mut cmd); - let mut make = Command::new("make"); + let mut make = Command::new(build_helper::make(&host)); make.current_dir(&build_dir) .arg("build_lib_static"); diff --git a/src/libstd/build.rs b/src/libstd/build.rs index 1087d1f24471b..b3eba50831698 100644 --- a/src/libstd/build.rs +++ b/src/libstd/build.rs @@ -104,7 +104,7 @@ fn build_libbacktrace(host: &str, target: &str) { .env("AR", &ar) .env("RANLIB", format!("{} s", ar.display())) .env("CFLAGS", cflags)); - run(Command::new("make") + run(Command::new(build_helper::make(host)) .current_dir(&build_dir) .arg(format!("INCDIR={}", src_dir.display())) .arg("-j").arg(env::var("NUM_JOBS").expect("NUM_JOBS was not set"))); diff --git a/src/tools/compiletest/Cargo.toml b/src/tools/compiletest/Cargo.toml index 227b695635dce..faf0a0eaa81ee 100644 --- a/src/tools/compiletest/Cargo.toml +++ b/src/tools/compiletest/Cargo.toml @@ -8,3 +8,4 @@ build = "build.rs" log = "0.3" env_logger = { version = "0.3.5", default-features = false } serialize = { path = "../../libserialize" } +build_helper = { path = "../../build_helper" } diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 3cc14541fcdf2..d33a176b9147e 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +extern crate build_helper; + use common::Config; use common::{CompileFail, ParseFail, Pretty, RunFail, RunPass, RunPassValgrind}; use common::{Codegen, DebugInfoLldb, DebugInfoGdb, Rustdoc, CodegenUnits}; @@ -2108,7 +2110,7 @@ actual:\n\ } self.create_dir_racy(&tmpdir); - let mut cmd = Command::new("make"); + let mut cmd = Command::new(build_helper::make(&self.config.host)); cmd.current_dir(&self.testpaths.file) .env("TARGET", &self.config.target) .env("PYTHON", &self.config.docck_python) From 2c39ee12a99f9548a5e379e8bcea4f7923028fee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Marie?= Date: Sun, 18 Dec 2016 18:31:42 +0100 Subject: [PATCH 37/73] OpenBSD has two stdc++ libraries: use the newer stdc++ is from base, and is an old library (GCC 4.2) estdc++ is from ports, and is a recent library (GCC 4.9 currently) as LLVM requires the newer version, use it if under OpenBSD. --- src/librustc_llvm/build.rs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/librustc_llvm/build.rs b/src/librustc_llvm/build.rs index 50bc3e7b6243f..86c40a0208ad3 100644 --- a/src/librustc_llvm/build.rs +++ b/src/librustc_llvm/build.rs @@ -230,6 +230,13 @@ fn main() { } } + // OpenBSD has a particular C++ runtime library name + let stdcppname = if target.contains("openbsd") { + "estdc++" + } else { + "stdc++" + }; + // C++ runtime library if !target.contains("msvc") { if let Some(s) = env::var_os("LLVM_STATIC_STDCPP") { @@ -237,11 +244,11 @@ fn main() { let path = PathBuf::from(s); println!("cargo:rustc-link-search=native={}", path.parent().unwrap().display()); - println!("cargo:rustc-link-lib=static=stdc++"); + println!("cargo:rustc-link-lib=static={}", stdcppname); } else if cxxflags.contains("stdlib=libc++") { println!("cargo:rustc-link-lib=c++"); } else { - println!("cargo:rustc-link-lib=stdc++"); + println!("cargo:rustc-link-lib={}", stdcppname); } } } From 86fc63e62ddc0a271210b8cc7cc2a6de6874b8f8 Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Fri, 25 Nov 2016 13:21:49 -0500 Subject: [PATCH 38/73] Implement `fmt::Debug` for all structures in libstd. Part of https://github.com/rust-lang/rust/issues/31869. Also turn on the `missing_debug_implementations` lint at the crate level. --- src/libstd/ascii.rs | 8 +++ src/libstd/collections/hash/map.rs | 83 +++++++++++++++++++++++- src/libstd/collections/hash/set.rs | 77 ++++++++++++++++++++++ src/libstd/collections/hash/table.rs | 29 +++++++++ src/libstd/env.rs | 36 ++++++++++ src/libstd/fs.rs | 18 ++++- src/libstd/io/mod.rs | 15 +++++ src/libstd/io/stdio.rs | 42 ++++++++++++ src/libstd/io/util.rs | 22 +++++++ src/libstd/lib.rs | 2 + src/libstd/net/mod.rs | 8 +++ src/libstd/net/tcp.rs | 1 + src/libstd/os/linux/raw.rs | 1 + src/libstd/os/macos/raw.rs | 2 +- src/libstd/os/raw.rs | 9 +++ src/libstd/panic.rs | 10 +++ src/libstd/panicking.rs | 2 + src/libstd/process.rs | 39 +++++++++++ src/libstd/rand/mod.rs | 7 ++ src/libstd/sync/barrier.rs | 17 +++++ src/libstd/sync/condvar.rs | 8 +++ src/libstd/sync/mpsc/mod.rs | 3 + src/libstd/sync/mutex.rs | 9 +++ src/libstd/sync/once.rs | 9 +++ src/libstd/sync/rwlock.rs | 18 +++++ src/libstd/sys/unix/fast_thread_local.rs | 7 ++ src/libstd/sys/unix/fd.rs | 1 + src/libstd/sys/unix/fs.rs | 3 +- src/libstd/sys/windows/fs.rs | 3 +- src/libstd/thread/local.rs | 18 ++++- src/libstd/thread/mod.rs | 15 +++++ 31 files changed, 515 insertions(+), 7 deletions(-) diff --git a/src/libstd/ascii.rs b/src/libstd/ascii.rs index a063b85646809..f5e9ec6d89d0f 100644 --- a/src/libstd/ascii.rs +++ b/src/libstd/ascii.rs @@ -12,6 +12,7 @@ #![stable(feature = "rust1", since = "1.0.0")] +use fmt; use mem; use ops::Range; use iter::FusedIterator; @@ -370,6 +371,13 @@ impl ExactSizeIterator for EscapeDefault {} #[unstable(feature = "fused", issue = "35602")] impl FusedIterator for EscapeDefault {} +#[stable(feature = "std_debug", since = "1.15.0")] +impl fmt::Debug for EscapeDefault { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.pad("EscapeDefault { .. }") + } +} + static ASCII_LOWERCASE_MAP: [u8; 256] = [ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index 0b310eb258577..2fa3a9c4844b5 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -1276,6 +1276,15 @@ impl<'a, K, V> Clone for Iter<'a, K, V> { } } +#[stable(feature = "std_debug", since = "1.15.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() + .entries(self.clone()) + .finish() + } +} + /// HashMap mutable values iterator. #[stable(feature = "rust1", since = "1.0.0")] pub struct IterMut<'a, K: 'a, V: 'a> { @@ -1285,7 +1294,7 @@ pub struct IterMut<'a, K: 'a, V: 'a> { /// HashMap move iterator. #[stable(feature = "rust1", since = "1.0.0")] pub struct IntoIter { - inner: table::IntoIter, + pub(super) inner: table::IntoIter, } /// HashMap keys iterator. @@ -1302,6 +1311,15 @@ impl<'a, K, V> Clone for Keys<'a, K, V> { } } +#[stable(feature = "std_debug", since = "1.15.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() + .entries(self.clone()) + .finish() + } +} + /// HashMap values iterator. #[stable(feature = "rust1", since = "1.0.0")] pub struct Values<'a, K: 'a, V: 'a> { @@ -1316,10 +1334,19 @@ impl<'a, K, V> Clone for Values<'a, K, V> { } } +#[stable(feature = "std_debug", since = "1.15.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() + .entries(self.clone()) + .finish() + } +} + /// HashMap drain iterator. #[stable(feature = "drain", since = "1.6.0")] pub struct Drain<'a, K: 'a, V: 'a> { - inner: table::Drain<'a, K, V>, + pub(super) inner: table::Drain<'a, K, V>, } /// Mutable HashMap values iterator. @@ -1557,6 +1584,18 @@ 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")] +impl<'a, K, V> fmt::Debug for IterMut<'a, K, V> + where K: fmt::Debug, + V: fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_list() + .entries(self.inner.iter()) + .finish() + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl Iterator for IntoIter { type Item = (K, V); @@ -1580,6 +1619,15 @@ impl ExactSizeIterator for IntoIter { #[unstable(feature = "fused", issue = "35602")] impl FusedIterator for IntoIter {} +#[stable(feature = "std_debug", since = "1.15.0")] +impl fmt::Debug for IntoIter { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_list() + .entries(self.inner.iter()) + .finish() + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl<'a, K, V> Iterator for Keys<'a, K, V> { type Item = &'a K; @@ -1649,6 +1697,18 @@ 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")] +impl<'a, K, V> fmt::Debug for ValuesMut<'a, K, V> + where K: fmt::Debug, + V: fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_list() + .entries(self.inner.inner.iter()) + .finish() + } +} + #[stable(feature = "drain", since = "1.6.0")] impl<'a, K, V> Iterator for Drain<'a, K, V> { type Item = (K, V); @@ -1672,6 +1732,18 @@ 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")] +impl<'a, K, V> fmt::Debug for Drain<'a, K, V> + where K: fmt::Debug, + V: fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_list() + .entries(self.inner.iter()) + .finish() + } +} + impl<'a, K, V> Entry<'a, K, V> { #[stable(feature = "rust1", since = "1.0.0")] /// Ensures a value is in the entry by inserting the default if empty, and returns @@ -2148,6 +2220,13 @@ impl Default for RandomState { } } +#[stable(feature = "std_debug", since = "1.15.0")] +impl fmt::Debug for RandomState { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.pad("RandomState { .. }") + } +} + impl super::Recover for HashMap where K: Eq + Hash + Borrow, S: BuildHasher, diff --git a/src/libstd/collections/hash/set.rs b/src/libstd/collections/hash/set.rs index 72af612f5696f..341b050862f5c 100644 --- a/src/libstd/collections/hash/set.rs +++ b/src/libstd/collections/hash/set.rs @@ -948,6 +948,15 @@ 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")] +impl<'a, K: fmt::Debug> fmt::Debug for Iter<'a, K> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_list() + .entries(self.clone()) + .finish() + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl Iterator for IntoIter { type Item = K; @@ -968,6 +977,16 @@ impl ExactSizeIterator for IntoIter { #[unstable(feature = "fused", issue = "35602")] impl FusedIterator for IntoIter {} +#[stable(feature = "std_debug", since = "1.15.0")] +impl fmt::Debug for IntoIter { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let entries_iter = self.iter.inner.iter().map(|(k, _)| k); + f.debug_list() + .entries(entries_iter) + .finish() + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl<'a, K> Iterator for Drain<'a, K> { type Item = K; @@ -988,6 +1007,16 @@ 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")] +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); + f.debug_list() + .entries(entries_iter) + .finish() + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T, S> Clone for Intersection<'a, T, S> { fn clone(&self) -> Intersection<'a, T, S> { @@ -1021,6 +1050,18 @@ impl<'a, T, S> Iterator for Intersection<'a, T, S> } } +#[stable(feature = "std_debug", since = "1.15.0")] +impl<'a, T, S> fmt::Debug for Intersection<'a, T, S> + where T: fmt::Debug + Eq + Hash, + S: BuildHasher, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_list() + .entries(self.clone()) + .finish() + } +} + #[unstable(feature = "fused", issue = "35602")] impl<'a, T, S> FusedIterator for Intersection<'a, T, S> where T: Eq + Hash, @@ -1068,6 +1109,18 @@ impl<'a, T, S> FusedIterator for Difference<'a, T, S> { } +#[stable(feature = "std_debug", since = "1.15.0")] +impl<'a, T, S> fmt::Debug for Difference<'a, T, S> + where T: fmt::Debug + Eq + Hash, + S: BuildHasher, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_list() + .entries(self.clone()) + .finish() + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T, S> Clone for SymmetricDifference<'a, T, S> { fn clone(&self) -> SymmetricDifference<'a, T, S> { @@ -1097,6 +1150,18 @@ impl<'a, T, S> FusedIterator for SymmetricDifference<'a, T, S> { } +#[stable(feature = "std_debug", since = "1.15.0")] +impl<'a, T, S> fmt::Debug for SymmetricDifference<'a, T, S> + where T: fmt::Debug + Eq + Hash, + S: BuildHasher, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_list() + .entries(self.clone()) + .finish() + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T, S> Clone for Union<'a, T, S> { fn clone(&self) -> Union<'a, T, S> { @@ -1111,6 +1176,18 @@ impl<'a, T, S> FusedIterator for Union<'a, T, S> { } +#[stable(feature = "std_debug", since = "1.15.0")] +impl<'a, T, S> fmt::Debug for Union<'a, T, S> + where T: fmt::Debug + Eq + Hash, + S: BuildHasher, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_list() + .entries(self.clone()) + .finish() + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T, S> Iterator for Union<'a, T, S> where T: Eq + Hash, diff --git a/src/libstd/collections/hash/table.rs b/src/libstd/collections/hash/table.rs index a784d8e50f9d0..2cd9362a65791 100644 --- a/src/libstd/collections/hash/table.rs +++ b/src/libstd/collections/hash/table.rs @@ -882,6 +882,15 @@ unsafe impl<'a, K: Sync, V: Sync> Sync for IterMut<'a, K, V> {} // but Send is the more useful bound unsafe impl<'a, K: Send, V: Send> Send for IterMut<'a, K, V> {} +impl<'a, K: 'a, V: 'a> IterMut<'a, K, V> { + pub fn iter(&self) -> Iter { + Iter { + iter: self.iter.clone(), + elems_left: self.elems_left, + } + } +} + /// Iterator over the entries in a table, consuming the table. pub struct IntoIter { table: RawTable, @@ -891,6 +900,15 @@ pub struct IntoIter { unsafe impl Sync for IntoIter {} unsafe impl Send for IntoIter {} +impl IntoIter { + pub fn iter(&self) -> Iter { + Iter { + iter: self.iter.clone(), + elems_left: self.table.size, + } + } +} + /// Iterator over the entries in a table, clearing the table. pub struct Drain<'a, K: 'a, V: 'a> { table: Shared>, @@ -901,6 +919,17 @@ pub struct Drain<'a, K: 'a, V: 'a> { unsafe impl<'a, K: Sync, V: Sync> Sync for Drain<'a, K, V> {} unsafe impl<'a, K: Send, V: Send> Send for Drain<'a, K, V> {} +impl<'a, K, V> Drain<'a, K, V> { + pub fn iter(&self) -> Iter { + unsafe { + Iter { + iter: self.iter.clone(), + elems_left: (**self.table).size, + } + } + } +} + impl<'a, K, V> Iterator for Iter<'a, K, V> { type Item = (&'a K, &'a V); diff --git a/src/libstd/env.rs b/src/libstd/env.rs index ee6a907f6160e..0521f301321a7 100644 --- a/src/libstd/env.rs +++ b/src/libstd/env.rs @@ -143,6 +143,13 @@ impl Iterator for Vars { fn size_hint(&self) -> (usize, Option) { self.inner.size_hint() } } +#[stable(feature = "std_debug", since = "1.15.0")] +impl fmt::Debug for Vars { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.pad("Vars { .. }") + } +} + #[stable(feature = "env", since = "1.0.0")] impl Iterator for VarsOs { type Item = (OsString, OsString); @@ -150,6 +157,13 @@ impl Iterator for VarsOs { fn size_hint(&self) -> (usize, Option) { self.inner.size_hint() } } +#[stable(feature = "std_debug", since = "1.15.0")] +impl fmt::Debug for VarsOs { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.pad("VarsOs { .. }") + } +} + /// Fetches the environment variable `key` from the current process. /// /// The returned result is `Ok(s)` if the environment variable is present and is @@ -364,6 +378,13 @@ impl<'a> Iterator for SplitPaths<'a> { fn size_hint(&self) -> (usize, Option) { self.inner.size_hint() } } +#[stable(feature = "std_debug", since = "1.15.0")] +impl<'a> fmt::Debug for SplitPaths<'a> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.pad("SplitPaths { .. }") + } +} + /// Error type returned from `std::env::join_paths` when paths fail to be /// joined. #[derive(Debug)] @@ -640,6 +661,13 @@ impl DoubleEndedIterator for Args { } } +#[stable(feature = "std_debug", since = "1.15.0")] +impl fmt::Debug for Args { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.pad("Args { .. }") + } +} + #[stable(feature = "env", since = "1.0.0")] impl Iterator for ArgsOs { type Item = OsString; @@ -657,6 +685,14 @@ impl ExactSizeIterator for ArgsOs { impl DoubleEndedIterator for ArgsOs { fn next_back(&mut self) -> Option { self.inner.next_back() } } + +#[stable(feature = "std_debug", since = "1.15.0")] +impl fmt::Debug for ArgsOs { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.pad("ArgsOs { .. }") + } +} + /// Constants associated with the current target #[stable(feature = "env", since = "1.0.0")] pub mod consts { diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs index e91e808c5489a..176b5f66fc4e8 100644 --- a/src/libstd/fs.rs +++ b/src/libstd/fs.rs @@ -140,7 +140,7 @@ pub struct DirEntry(fs_imp::DirEntry); /// .create(true) /// .open("foo.txt"); /// ``` -#[derive(Clone)] +#[derive(Clone, Debug)] #[stable(feature = "rust1", since = "1.0.0")] pub struct OpenOptions(fs_imp::OpenOptions); @@ -168,6 +168,7 @@ pub struct FileType(fs_imp::FileType); /// /// This builder also supports platform-specific options. #[stable(feature = "dir_builder", since = "1.6.0")] +#[derive(Debug)] pub struct DirBuilder { inner: fs_imp::DirBuilder, recursive: bool, @@ -834,6 +835,21 @@ impl Metadata { } } +#[stable(feature = "std_debug", since = "1.15.0")] +impl fmt::Debug for Metadata { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("Metadata") + .field("file_type", &self.file_type()) + .field("is_dir", &self.is_dir()) + .field("is_file", &self.is_file()) + .field("permissions", &self.permissions()) + .field("modified", &self.modified()) + .field("accessed", &self.accessed()) + .field("created", &self.created()) + .finish() + } +} + impl AsInner for Metadata { fn as_inner(&self) -> &fs_imp::FileAttr { &self.0 } } diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index b07da0dc268c4..143a85ae32184 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -1444,6 +1444,16 @@ pub struct Chain { done_first: bool, } +#[stable(feature = "std_debug", since = "1.15.0")] +impl fmt::Debug for Chain { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("Chain") + .field("t", &self.first) + .field("u", &self.second) + .finish() + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl Read for Chain { fn read(&mut self, buf: &mut [u8]) -> Result { @@ -1485,6 +1495,7 @@ impl BufRead for Chain { /// /// [`take()`]: trait.Read.html#method.take #[stable(feature = "rust1", since = "1.0.0")] +#[derive(Debug)] pub struct Take { inner: T, limit: u64, @@ -1602,6 +1613,7 @@ fn read_one_byte(reader: &mut Read) -> Option> { /// /// [`bytes()`]: trait.Read.html#method.bytes #[stable(feature = "rust1", since = "1.0.0")] +#[derive(Debug)] pub struct Bytes { inner: R, } @@ -1623,6 +1635,7 @@ impl Iterator for Bytes { /// [chars]: trait.Read.html#method.chars #[unstable(feature = "io", reason = "awaiting stability of Read::chars", issue = "27802")] +#[derive(Debug)] pub struct Chars { inner: R, } @@ -1712,6 +1725,7 @@ impl fmt::Display for CharsError { /// /// [split]: trait.BufRead.html#method.split #[stable(feature = "rust1", since = "1.0.0")] +#[derive(Debug)] pub struct Split { buf: B, delim: u8, @@ -1743,6 +1757,7 @@ impl Iterator for Split { /// /// [lines]: trait.BufRead.html#method.lines #[stable(feature = "rust1", since = "1.0.0")] +#[derive(Debug)] pub struct Lines { buf: B, } diff --git a/src/libstd/io/stdio.rs b/src/libstd/io/stdio.rs index 1a65bee13b8fb..9d1c8942f8cf8 100644 --- a/src/libstd/io/stdio.rs +++ b/src/libstd/io/stdio.rs @@ -282,6 +282,13 @@ impl Stdin { } } +#[stable(feature = "std_debug", since = "1.15.0")] +impl fmt::Debug for Stdin { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.pad("Stdin { .. }") + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl Read for Stdin { fn read(&mut self, buf: &mut [u8]) -> io::Result { @@ -314,6 +321,13 @@ impl<'a> BufRead for StdinLock<'a> { fn consume(&mut self, n: usize) { self.inner.consume(n) } } +#[stable(feature = "std_debug", since = "1.15.0")] +impl<'a> fmt::Debug for StdinLock<'a> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.pad("StdinLock { .. }") + } +} + /// A handle to the global standard output stream of the current process. /// /// Each handle shares a global buffer of data to be written to the standard @@ -424,6 +438,13 @@ impl Stdout { } } +#[stable(feature = "std_debug", since = "1.15.0")] +impl fmt::Debug for Stdout { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.pad("Stdout { .. }") + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl Write for Stdout { fn write(&mut self, buf: &[u8]) -> io::Result { @@ -449,6 +470,13 @@ impl<'a> Write for StdoutLock<'a> { } } +#[stable(feature = "std_debug", since = "1.15.0")] +impl<'a> fmt::Debug for StdoutLock<'a> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.pad("StdoutLock { .. }") + } +} + /// A handle to the standard error stream of a process. /// /// For more information, see the [`io::stderr`] method. @@ -545,6 +573,13 @@ impl Stderr { } } +#[stable(feature = "std_debug", since = "1.15.0")] +impl fmt::Debug for Stderr { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.pad("Stderr { .. }") + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl Write for Stderr { fn write(&mut self, buf: &[u8]) -> io::Result { @@ -570,6 +605,13 @@ impl<'a> Write for StderrLock<'a> { } } +#[stable(feature = "std_debug", since = "1.15.0")] +impl<'a> fmt::Debug for StderrLock<'a> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.pad("StderrLock { .. }") + } +} + /// Resets the thread-local stderr handle to the specified writer /// /// This will replace the current thread's stderr handle, returning the old diff --git a/src/libstd/io/util.rs b/src/libstd/io/util.rs index 2c6880281b5e6..436511031ef53 100644 --- a/src/libstd/io/util.rs +++ b/src/libstd/io/util.rs @@ -10,6 +10,7 @@ #![allow(missing_copy_implementations)] +use fmt; use io::{self, Read, Write, ErrorKind, BufRead}; /// Copies the entire contents of a reader into a writer. @@ -97,6 +98,13 @@ impl BufRead for Empty { fn consume(&mut self, _n: usize) {} } +#[stable(feature = "std_debug", since = "1.15.0")] +impl fmt::Debug for Empty { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.pad("Empty { .. }") + } +} + /// A reader which yields one byte over and over and over and over and over and... /// /// This struct is generally created by calling [`repeat()`][repeat]. Please @@ -133,6 +141,13 @@ impl Read for Repeat { } } +#[stable(feature = "std_debug", since = "1.15.0")] +impl fmt::Debug for Repeat { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.pad("Repeat { .. }") + } +} + /// A writer which will move data into the void. /// /// This struct is generally created by calling [`sink()`][sink]. Please @@ -165,6 +180,13 @@ impl Write for Sink { fn flush(&mut self) -> io::Result<()> { Ok(()) } } +#[stable(feature = "std_debug", since = "1.15.0")] +impl fmt::Debug for Sink { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.pad("Sink { .. }") + } +} + #[cfg(test)] mod tests { use io::prelude::*; diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 414f25fa5eb33..fc5c6968544e8 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -214,6 +214,7 @@ #![no_std] #![deny(missing_docs)] +#![deny(missing_debug_implementations)] // Tell the compiler to link to either panic_abort or panic_unwind #![needs_panic_runtime] @@ -276,6 +277,7 @@ #![feature(panic_unwind)] #![feature(placement_in_syntax)] #![feature(prelude_import)] +#![feature(pub_restricted)] #![feature(rand)] #![feature(raw)] #![feature(repr_simd)] diff --git a/src/libstd/net/mod.rs b/src/libstd/net/mod.rs index 56286fbe25399..cadf87f32b14a 100644 --- a/src/libstd/net/mod.rs +++ b/src/libstd/net/mod.rs @@ -12,6 +12,7 @@ #![stable(feature = "rust1", since = "1.0.0")] +use fmt; use io::{self, Error, ErrorKind}; use sys_common::net as net_imp; @@ -105,6 +106,13 @@ impl Iterator for LookupHost { fn next(&mut self) -> Option { self.0.next() } } +#[stable(feature = "std_debug", since = "1.15.0")] +impl fmt::Debug for LookupHost { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.pad("LookupHost { .. }") + } +} + /// Resolve the host specified by `host` as a number of `SocketAddr` instances. /// /// This method may perform a DNS query to resolve `host` and may also inspect diff --git a/src/libstd/net/tcp.rs b/src/libstd/net/tcp.rs index be9636a0a19a1..63817c9f10f5f 100644 --- a/src/libstd/net/tcp.rs +++ b/src/libstd/net/tcp.rs @@ -76,6 +76,7 @@ pub struct TcpListener(net_imp::TcpListener); /// [`incoming`]: struct.TcpListener.html#method.incoming /// [`TcpListener`]: struct.TcpListener.html #[stable(feature = "rust1", since = "1.0.0")] +#[derive(Debug)] pub struct Incoming<'a> { listener: &'a TcpListener } impl TcpStream { diff --git a/src/libstd/os/linux/raw.rs b/src/libstd/os/linux/raw.rs index e6a95bc831ffb..7c9274d060161 100644 --- a/src/libstd/os/linux/raw.rs +++ b/src/libstd/os/linux/raw.rs @@ -17,6 +17,7 @@ crates.io should be used instead for the correct \ definitions")] #![allow(deprecated)] +#![allow(missing_debug_implementations)] use os::raw::c_ulong; diff --git a/src/libstd/os/macos/raw.rs b/src/libstd/os/macos/raw.rs index 8f9b29462c4f9..0b96295f9e69e 100644 --- a/src/libstd/os/macos/raw.rs +++ b/src/libstd/os/macos/raw.rs @@ -33,7 +33,7 @@ use os::raw::c_long; pub type pthread_t = usize; #[repr(C)] -#[derive(Clone)] +#[derive(Clone, Debug)] #[stable(feature = "raw_ext", since = "1.1.0")] pub struct stat { #[stable(feature = "raw_ext", since = "1.1.0")] diff --git a/src/libstd/os/raw.rs b/src/libstd/os/raw.rs index 2a918d8aeb7b8..cc154f7ab413b 100644 --- a/src/libstd/os/raw.rs +++ b/src/libstd/os/raw.rs @@ -12,6 +12,8 @@ #![stable(feature = "raw_os", since = "1.1.0")] +use fmt; + #[cfg(any(target_os = "android", target_os = "emscripten", all(target_os = "linux", any(target_arch = "aarch64", @@ -71,6 +73,13 @@ pub enum c_void { #[doc(hidden)] __variant2, } +#[stable(feature = "std_debug", since = "1.15.0")] +impl fmt::Debug for c_void { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.pad("c_void") + } +} + #[cfg(test)] #[allow(unused_imports)] mod tests { diff --git a/src/libstd/panic.rs b/src/libstd/panic.rs index a7e8c4fab3735..faf4949e86192 100644 --- a/src/libstd/panic.rs +++ b/src/libstd/panic.rs @@ -14,6 +14,7 @@ use any::Any; use cell::UnsafeCell; +use fmt; use ops::{Deref, DerefMut}; use panicking; use ptr::{Unique, Shared}; @@ -296,6 +297,15 @@ impl R> FnOnce<()> for AssertUnwindSafe { } } +#[stable(feature = "std_debug", since = "1.15.0")] +impl fmt::Debug for AssertUnwindSafe { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_tuple("AssertUnwindSafe") + .field(&self.0) + .finish() + } +} + /// 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 diff --git a/src/libstd/panicking.rs b/src/libstd/panicking.rs index 45a10d2452851..e5edea241e199 100644 --- a/src/libstd/panicking.rs +++ b/src/libstd/panicking.rs @@ -177,6 +177,7 @@ pub fn take_hook() -> Box { /// panic!("Normal panic"); /// ``` #[stable(feature = "panic_hooks", since = "1.10.0")] +#[derive(Debug)] pub struct PanicInfo<'a> { payload: &'a (Any + Send), location: Location<'a>, @@ -256,6 +257,7 @@ impl<'a> PanicInfo<'a> { /// /// panic!("Normal panic"); /// ``` +#[derive(Debug)] #[stable(feature = "panic_hooks", since = "1.10.0")] pub struct Location<'a> { file: &'a str, diff --git a/src/libstd/process.rs b/src/libstd/process.rs index 858537dd2de12..66373615a1cf4 100644 --- a/src/libstd/process.rs +++ b/src/libstd/process.rs @@ -114,6 +114,17 @@ impl IntoInner for Child { fn into_inner(self) -> imp::Process { self.handle } } +#[stable(feature = "std_debug", since = "1.15.0")] +impl fmt::Debug for Child { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("Child") + .field("stdin", &self.stdin) + .field("stdout", &self.stdout) + .field("stderr", &self.stderr) + .finish() + } +} + /// A handle to a child process's stdin. This struct is used in the [`stdin`] /// field on [`Child`]. /// @@ -149,6 +160,13 @@ impl FromInner for ChildStdin { } } +#[stable(feature = "std_debug", since = "1.15.0")] +impl fmt::Debug for ChildStdin { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.pad("ChildStdin { .. }") + } +} + /// A handle to a child process's stdout. This struct is used in the [`stdout`] /// field on [`Child`]. /// @@ -183,6 +201,13 @@ impl FromInner for ChildStdout { } } +#[stable(feature = "std_debug", since = "1.15.0")] +impl fmt::Debug for ChildStdout { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.pad("ChildStdout { .. }") + } +} + /// A handle to a child process's stderr. This struct is used in the [`stderr`] /// field on [`Child`]. /// @@ -217,6 +242,13 @@ impl FromInner for ChildStderr { } } +#[stable(feature = "std_debug", since = "1.15.0")] +impl fmt::Debug for ChildStderr { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.pad("ChildStderr { .. }") + } +} + /// A process builder, providing fine-grained control /// over how a new process should be spawned. /// @@ -622,6 +654,13 @@ impl FromInner for Stdio { } } +#[stable(feature = "std_debug", since = "1.15.0")] +impl fmt::Debug for Stdio { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.pad("Stdio { .. }") + } +} + /// Describes the result of a process after it has terminated. #[derive(PartialEq, Eq, Clone, Copy, Debug)] #[stable(feature = "process", since = "1.0.0")] diff --git a/src/libstd/rand/mod.rs b/src/libstd/rand/mod.rs index f48325218fb49..b853e83de5d6c 100644 --- a/src/libstd/rand/mod.rs +++ b/src/libstd/rand/mod.rs @@ -59,6 +59,7 @@ #![unstable(feature = "rand", issue = "0")] use cell::RefCell; +use fmt; use io; use mem; use rc::Rc; @@ -143,6 +144,12 @@ pub struct ThreadRng { rng: Rc>, } +impl fmt::Debug for ThreadRng { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.pad("ThreadRng { .. }") + } +} + /// Retrieve the lazily-initialized thread-local random number /// generator, seeded by the system. Intended to be used in method /// chaining style, e.g. `thread_rng().gen::()`. diff --git a/src/libstd/sync/barrier.rs b/src/libstd/sync/barrier.rs index f46eab6848463..b8e83dced8d4b 100644 --- a/src/libstd/sync/barrier.rs +++ b/src/libstd/sync/barrier.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use fmt; use sync::{Mutex, Condvar}; /// A barrier enables multiple threads to synchronize the beginning @@ -54,6 +55,13 @@ struct BarrierState { #[stable(feature = "rust1", since = "1.0.0")] pub struct BarrierWaitResult(bool); +#[stable(feature = "std_debug", since = "1.15.0")] +impl fmt::Debug for Barrier { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.pad("Barrier { .. }") + } +} + impl Barrier { /// Creates a new barrier that can block a given number of threads. /// @@ -102,6 +110,15 @@ impl Barrier { } } +#[stable(feature = "std_debug", since = "1.15.0")] +impl fmt::Debug for BarrierWaitResult { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("BarrierWaitResult") + .field("is_leader", &self.is_leader()) + .finish() + } +} + impl BarrierWaitResult { /// Returns whether this thread from `wait` is the "leader thread". /// diff --git a/src/libstd/sync/condvar.rs b/src/libstd/sync/condvar.rs index a983ae716a481..8ab30c51b282e 100644 --- a/src/libstd/sync/condvar.rs +++ b/src/libstd/sync/condvar.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use fmt; use sync::atomic::{AtomicUsize, Ordering}; use sync::{mutex, MutexGuard, PoisonError}; use sys_common::condvar as sys; @@ -239,6 +240,13 @@ impl Condvar { } } +#[stable(feature = "std_debug", since = "1.15.0")] +impl fmt::Debug for Condvar { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.pad("Condvar { .. }") + } +} + #[stable(feature = "condvar_default", since = "1.9.0")] impl Default for Condvar { /// Creates a `Condvar` which is ready to be waited on and notified. diff --git a/src/libstd/sync/mpsc/mod.rs b/src/libstd/sync/mpsc/mod.rs index 63745388eb67b..756d02b625f53 100644 --- a/src/libstd/sync/mpsc/mod.rs +++ b/src/libstd/sync/mpsc/mod.rs @@ -306,6 +306,7 @@ impl !Sync for Receiver { } /// whenever `next` is called, waiting for a new message, and `None` will be /// returned when the corresponding channel has hung up. #[stable(feature = "rust1", since = "1.0.0")] +#[derive(Debug)] pub struct Iter<'a, T: 'a> { rx: &'a Receiver } @@ -317,6 +318,7 @@ pub struct Iter<'a, T: 'a> { /// This Iterator will never block the caller in order to wait for data to /// become available. Instead, it will return `None`. #[stable(feature = "receiver_try_iter", since = "1.15.0")] +#[derive(Debug)] pub struct TryIter<'a, T: 'a> { rx: &'a Receiver } @@ -325,6 +327,7 @@ pub struct TryIter<'a, T: 'a> { /// whenever `next` is called, waiting for a new message, and `None` will be /// returned when the corresponding channel has hung up. #[stable(feature = "receiver_into_iter", since = "1.1.0")] +#[derive(Debug)] pub struct IntoIter { rx: Receiver } diff --git a/src/libstd/sync/mutex.rs b/src/libstd/sync/mutex.rs index df4a3746a49bd..f6dbe01d7bdbf 100644 --- a/src/libstd/sync/mutex.rs +++ b/src/libstd/sync/mutex.rs @@ -351,6 +351,15 @@ impl<'a, T: ?Sized> Drop for MutexGuard<'a, T> { } } +#[stable(feature = "std_debug", since = "1.15.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") + .field("lock", &self.__lock) + .finish() + } +} + pub fn guard_lock<'a, T: ?Sized>(guard: &MutexGuard<'a, T>) -> &'a sys::Mutex { &guard.__lock.inner } diff --git a/src/libstd/sync/once.rs b/src/libstd/sync/once.rs index 71e163321aea2..a9747639aacd7 100644 --- a/src/libstd/sync/once.rs +++ b/src/libstd/sync/once.rs @@ -64,6 +64,7 @@ // You'll find a few more details in the implementation, but that's the gist of // it! +use fmt; use marker; use ptr; use sync::atomic::{AtomicUsize, AtomicBool, Ordering}; @@ -103,6 +104,7 @@ unsafe impl Send for Once {} /// State yielded to the `call_once_force` method which can be used to query /// whether the `Once` was previously poisoned or not. #[unstable(feature = "once_poison", issue = "33577")] +#[derive(Debug)] pub struct OnceState { poisoned: bool, } @@ -328,6 +330,13 @@ impl Once { } } +#[stable(feature = "std_debug", since = "1.15.0")] +impl fmt::Debug for Once { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.pad("Once { .. }") + } +} + impl Drop for Finish { fn drop(&mut self) { // Swap out our state with however we finished. We should only ever see diff --git a/src/libstd/sync/rwlock.rs b/src/libstd/sync/rwlock.rs index f83cf7ba9c29e..0a11c71706b7e 100644 --- a/src/libstd/sync/rwlock.rs +++ b/src/libstd/sync/rwlock.rs @@ -362,6 +362,24 @@ impl<'rwlock, T: ?Sized> RwLockWriteGuard<'rwlock, T> { } } +#[stable(feature = "std_debug", since = "1.15.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") + .field("lock", &self.__lock) + .finish() + } +} + +#[stable(feature = "std_debug", since = "1.15.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") + .field("lock", &self.__lock) + .finish() + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl<'rwlock, T: ?Sized> Deref for RwLockReadGuard<'rwlock, T> { type Target = T; diff --git a/src/libstd/sys/unix/fast_thread_local.rs b/src/libstd/sys/unix/fast_thread_local.rs index 0c625e7add9d0..f4f73646e1b7e 100644 --- a/src/libstd/sys/unix/fast_thread_local.rs +++ b/src/libstd/sys/unix/fast_thread_local.rs @@ -12,6 +12,7 @@ #![unstable(feature = "thread_local_internals", issue = "0")] use cell::{Cell, UnsafeCell}; +use fmt; use intrinsics; use ptr; @@ -24,6 +25,12 @@ pub struct Key { dtor_running: Cell, } +impl fmt::Debug for Key { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.pad("Key { .. }") + } +} + unsafe impl ::marker::Sync for Key { } impl Key { diff --git a/src/libstd/sys/unix/fd.rs b/src/libstd/sys/unix/fd.rs index 61eb60da486c9..2384d959881a2 100644 --- a/src/libstd/sys/unix/fd.rs +++ b/src/libstd/sys/unix/fd.rs @@ -18,6 +18,7 @@ use sys::cvt; use sys_common::AsInner; use sys_common::io::read_to_end_uninitialized; +#[derive(Debug)] pub struct FileDesc { fd: c_int, } diff --git a/src/libstd/sys/unix/fs.rs b/src/libstd/sys/unix/fs.rs index 9ee0458b5da36..8b5c0c04276b1 100644 --- a/src/libstd/sys/unix/fs.rs +++ b/src/libstd/sys/unix/fs.rs @@ -66,7 +66,7 @@ pub struct DirEntry { name: Box<[u8]> } -#[derive(Clone)] +#[derive(Clone, Debug)] pub struct OpenOptions { // generic read: bool, @@ -86,6 +86,7 @@ pub struct FilePermissions { mode: mode_t } #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] pub struct FileType { mode: mode_t } +#[derive(Debug)] pub struct DirBuilder { mode: mode_t } impl FileAttr { diff --git a/src/libstd/sys/windows/fs.rs b/src/libstd/sys/windows/fs.rs index 7d7d78bbd8730..c410fcd1ee0ed 100644 --- a/src/libstd/sys/windows/fs.rs +++ b/src/libstd/sys/windows/fs.rs @@ -58,7 +58,7 @@ pub struct DirEntry { data: c::WIN32_FIND_DATAW, } -#[derive(Clone)] +#[derive(Clone, Debug)] pub struct OpenOptions { // generic read: bool, @@ -79,6 +79,7 @@ pub struct OpenOptions { #[derive(Clone, PartialEq, Eq, Debug)] pub struct FilePermissions { attrs: c::DWORD } +#[derive(Debug)] pub struct DirBuilder; impl fmt::Debug for ReadDir { diff --git a/src/libstd/thread/local.rs b/src/libstd/thread/local.rs index f74dd5924951c..01584979aabaa 100644 --- a/src/libstd/thread/local.rs +++ b/src/libstd/thread/local.rs @@ -13,6 +13,7 @@ #![unstable(feature = "thread_local_internals", issue = "0")] use cell::UnsafeCell; +use fmt; use mem; /// A thread local storage key which owns its contents. @@ -98,6 +99,13 @@ pub struct LocalKey { init: fn() -> T, } +#[stable(feature = "std_debug", since = "1.15.0")] +impl fmt::Debug for LocalKey { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.pad("LocalKey { .. }") + } +} + /// Declare a new thread local storage key of type `std::thread::LocalKey`. /// /// # Syntax @@ -184,7 +192,7 @@ macro_rules! __thread_local_inner { #[unstable(feature = "thread_local_state", reason = "state querying was recently added", issue = "27716")] -#[derive(Eq, PartialEq, Copy, Clone)] +#[derive(Debug, Eq, PartialEq, Copy, Clone)] pub enum LocalKeyState { /// All keys are in this state whenever a thread starts. Keys will /// transition to the `Valid` state once the first call to `with` happens @@ -313,6 +321,7 @@ impl LocalKey { #[doc(hidden)] pub mod os { use cell::{Cell, UnsafeCell}; + use fmt; use marker; use ptr; use sys_common::thread_local::StaticKey as OsStaticKey; @@ -323,6 +332,13 @@ pub mod os { marker: marker::PhantomData>, } + #[stable(feature = "std_debug", since = "1.15.0")] + impl fmt::Debug for Key { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.pad("Key { .. }") + } + } + unsafe impl ::marker::Sync for Key { } struct Value { diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs index 255cd2a9bc0f1..8cfa0200bf837 100644 --- a/src/libstd/thread/mod.rs +++ b/src/libstd/thread/mod.rs @@ -203,6 +203,7 @@ pub use self::local::{LocalKey, LocalKeyState}; /// Thread configuration. Provides detailed control over the properties /// and behavior of new threads. #[stable(feature = "rust1", since = "1.0.0")] +#[derive(Debug)] pub struct Builder { // A name for the thread-to-be, for identification in panic messages name: Option, @@ -573,6 +574,13 @@ impl ThreadId { } } +#[stable(feature = "std_debug", since = "1.15.0")] +impl fmt::Debug for ThreadId { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.pad("ThreadId { .. }") + } +} + //////////////////////////////////////////////////////////////////////////////// // Thread //////////////////////////////////////////////////////////////////////////////// @@ -788,6 +796,13 @@ impl IntoInner for JoinHandle { fn into_inner(self) -> imp::Thread { self.0.native.unwrap() } } +#[stable(feature = "std_debug", since = "1.15.0")] +impl fmt::Debug for JoinHandle { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.pad("JoinHandle { .. }") + } +} + fn _assert_sync_and_send() { fn _assert_both() {} _assert_both::>(); From b35c306b657c25f676c3981e2c78ea73f44ef378 Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Fri, 2 Dec 2016 23:10:44 +0000 Subject: [PATCH 39/73] Fix the path resolutions of glob imports. --- src/librustc_resolve/resolve_imports.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index 890891fd09018..64a8e21f9e0a1 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -708,10 +708,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { } // Record the destination of this import - if let Some(did) = module.def_id() { - let resolution = PathResolution::new(Def::Mod(did)); - self.def_map.insert(directive.id, resolution); - } + self.def_map.insert(directive.id, PathResolution::new(module.def().unwrap())); } // Miscellaneous post-processing, including recording reexports, reporting conflicts, From 83ab9f7faccddee23545e12d323791f9e2d06380 Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Tue, 29 Nov 2016 02:07:02 +0000 Subject: [PATCH 40/73] Remove some unused functions and fix formatting. --- src/libsyntax/attr.rs | 30 ------------------------------ src/libsyntax/ext/hygiene.rs | 12 ++++++------ 2 files changed, 6 insertions(+), 36 deletions(-) diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs index 45c120e0b95ca..c31bcfbd86992 100644 --- a/src/libsyntax/attr.rs +++ b/src/libsyntax/attr.rs @@ -29,7 +29,6 @@ use symbol::Symbol; use util::ThinVec; use std::cell::{RefCell, Cell}; -use std::collections::HashSet; thread_local! { static USED_ATTRS: RefCell> = RefCell::new(Vec::new()); @@ -372,16 +371,6 @@ pub fn mk_spanned_attr_outer(sp: Span, id: AttrId, item: MetaItem) -> Attribute } } -pub fn mk_doc_attr_outer(id: AttrId, item: MetaItem, is_sugared_doc: bool) -> Attribute { - Attribute { - id: id, - style: ast::AttrStyle::Outer, - value: item, - is_sugared_doc: is_sugared_doc, - span: DUMMY_SP, - } -} - pub fn mk_sugared_doc_attr(id: AttrId, text: Symbol, lo: BytePos, hi: BytePos) -> Attribute { let style = doc_comment_style(&text.as_str()); @@ -421,13 +410,6 @@ pub fn first_attr_value_str_by_name(attrs: &[Attribute], name: &str) -> Option Option { - items.iter() - .rev() - .find(|mi| mi.check_name(name)) - .and_then(|i| i.value_str()) -} - /* Higher-level applications */ pub fn find_crate_name(attrs: &[Attribute]) -> Option { @@ -856,18 +838,6 @@ pub fn find_deprecation(diagnostic: &Handler, attrs: &[Attribute], find_deprecation_generic(diagnostic, attrs.iter(), item_sp) } -pub fn require_unique_names(diagnostic: &Handler, metas: &[MetaItem]) { - let mut set = HashSet::new(); - for meta in metas { - let name = meta.name(); - - if !set.insert(name.clone()) { - panic!(diagnostic.span_fatal(meta.span, - &format!("duplicate meta item `{}`", name))); - } - } -} - /// Parse #[repr(...)] forms. /// diff --git a/src/libsyntax/ext/hygiene.rs b/src/libsyntax/ext/hygiene.rs index 0fd72277cca9f..8842cb55b1ea5 100644 --- a/src/libsyntax/ext/hygiene.rs +++ b/src/libsyntax/ext/hygiene.rs @@ -115,12 +115,12 @@ impl SyntaxContext { }) } - /// If `ident` is macro expanded, return the source ident from the macro definition - /// and the mark of the expansion that created the macro definition. - pub fn source(self) -> (Self /* source context */, Mark /* source macro */) { - let macro_def_ctxt = self.data().prev_ctxt.data(); - (macro_def_ctxt.prev_ctxt, macro_def_ctxt.outer_mark) - } + /// If `ident` is macro expanded, return the source ident from the macro definition + /// and the mark of the expansion that created the macro definition. + pub fn source(self) -> (Self /* source context */, Mark /* source macro */) { + let macro_def_ctxt = self.data().prev_ctxt.data(); + (macro_def_ctxt.prev_ctxt, macro_def_ctxt.outer_mark) + } } impl fmt::Debug for SyntaxContext { From 59de7f8f04d9122dd776f2edd73eb77a4fc94054 Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Tue, 29 Nov 2016 02:07:12 +0000 Subject: [PATCH 41/73] Add `ident.unhygienize()` and use `Ident` more instead of `Name` in `resolve`. --- src/librustc_resolve/build_reduced_graph.rs | 108 +++++++++---------- src/librustc_resolve/lib.rs | 51 +++++---- src/librustc_resolve/macros.rs | 23 ++-- src/librustc_resolve/resolve_imports.rs | 112 ++++++++++---------- src/libsyntax/ast.rs | 12 ++- 5 files changed, 156 insertions(+), 150 deletions(-) diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 25a37931ba31f..4aa04dc34feda 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -28,7 +28,7 @@ use rustc::ty; use std::cell::Cell; use std::rc::Rc; -use syntax::ast::Name; +use syntax::ast::{Name, Ident}; use syntax::attr; use syntax::ast::{self, Block, ForeignItem, ForeignItemKind, Item, ItemKind}; @@ -76,12 +76,12 @@ struct LegacyMacroImports { impl<'b> Resolver<'b> { /// Defines `name` in namespace `ns` of module `parent` to be `def` if it is not yet defined; /// otherwise, reports an error. - fn define(&mut self, parent: Module<'b>, name: Name, ns: Namespace, def: T) + fn define(&mut self, parent: Module<'b>, ident: Ident, ns: Namespace, def: T) where T: ToNameBinding<'b>, { let binding = def.to_name_binding(); - if let Err(old_binding) = self.try_define(parent, name, ns, binding.clone()) { - self.report_conflict(parent, name, ns, old_binding, &binding); + if let Err(old_binding) = self.try_define(parent, ident, ns, binding.clone()) { + self.report_conflict(parent, ident, ns, old_binding, &binding); } } @@ -102,7 +102,7 @@ impl<'b> Resolver<'b> { /// Constructs the reduced graph for one item. fn build_reduced_graph_for_item(&mut self, item: &Item, expansion: Mark) { let parent = self.current_module; - let name = item.ident.name; + let ident = item.ident; let sp = item.span; let vis = self.resolve_visibility(&item.vis); @@ -157,8 +157,8 @@ impl<'b> Resolver<'b> { } let subclass = SingleImport { - target: binding.name, - source: source.name, + target: binding, + source: source, result: self.per_ns(|_, _| Cell::new(Err(Undetermined))), }; self.add_import_directive( @@ -187,13 +187,13 @@ impl<'b> Resolver<'b> { for source_item in source_items { let node = source_item.node; - let (module_path, name, rename) = { + let (module_path, ident, rename) = { if node.name.name != keywords::SelfValue.name() { - let rename = node.rename.unwrap_or(node.name).name; - (module_path.clone(), node.name.name, rename) + let rename = node.rename.unwrap_or(node.name); + (module_path.clone(), node.name, rename) } else { - let name = match module_path.last() { - Some(ident) => ident.name, + let ident = match module_path.last() { + Some(&ident) => ident, None => { resolve_error( self, @@ -205,13 +205,13 @@ impl<'b> Resolver<'b> { } }; let module_path = module_path.split_last().unwrap().1; - let rename = node.rename.map(|i| i.name).unwrap_or(name); - (module_path.to_vec(), name, rename) + let rename = node.rename.unwrap_or(ident); + (module_path.to_vec(), ident, rename) } }; let subclass = SingleImport { target: rename, - source: name, + source: ident, result: self.per_ns(|_, _| Cell::new(Err(Undetermined))), }; let id = source_item.node.id; @@ -251,7 +251,7 @@ impl<'b> Resolver<'b> { expansion: expansion, }); let imported_binding = self.import(binding, directive); - self.define(parent, name, TypeNS, imported_binding); + self.define(parent, ident, TypeNS, imported_binding); self.populate_module_if_necessary(module); self.process_legacy_macro_imports(item, module, expansion); } @@ -265,9 +265,9 @@ impl<'b> Resolver<'b> { attr::contains_name(&item.attrs, "no_implicit_prelude") }, normal_ancestor_id: Some(item.id), - ..ModuleS::new(Some(parent), ModuleKind::Def(def, name)) + ..ModuleS::new(Some(parent), ModuleKind::Def(def, ident.name)) }); - self.define(parent, name, TypeNS, (module, vis, sp, expansion)); + self.define(parent, ident, TypeNS, (module, vis, sp, expansion)); self.module_map.insert(item.id, module); // Descend into the module. @@ -280,27 +280,27 @@ impl<'b> Resolver<'b> { ItemKind::Static(_, m, _) => { let mutbl = m == Mutability::Mutable; let def = Def::Static(self.definitions.local_def_id(item.id), mutbl); - self.define(parent, name, ValueNS, (def, vis, sp, expansion)); + self.define(parent, ident, ValueNS, (def, vis, sp, expansion)); } ItemKind::Const(..) => { let def = Def::Const(self.definitions.local_def_id(item.id)); - self.define(parent, name, ValueNS, (def, vis, sp, expansion)); + self.define(parent, ident, ValueNS, (def, vis, sp, expansion)); } ItemKind::Fn(..) => { let def = Def::Fn(self.definitions.local_def_id(item.id)); - self.define(parent, name, ValueNS, (def, vis, sp, expansion)); + self.define(parent, ident, ValueNS, (def, vis, sp, expansion)); } // These items live in the type namespace. ItemKind::Ty(..) => { let def = Def::TyAlias(self.definitions.local_def_id(item.id)); - self.define(parent, name, TypeNS, (def, vis, sp, expansion)); + self.define(parent, ident, TypeNS, (def, vis, sp, expansion)); } ItemKind::Enum(ref enum_definition, _) => { let def = Def::Enum(self.definitions.local_def_id(item.id)); - let module = self.new_module(parent, ModuleKind::Def(def, name), true); - self.define(parent, name, TypeNS, (module, vis, sp, expansion)); + let module = self.new_module(parent, ModuleKind::Def(def, ident.name), true); + self.define(parent, ident, TypeNS, (module, vis, sp, expansion)); for variant in &(*enum_definition).variants { self.build_reduced_graph_for_variant(variant, module, vis, expansion); @@ -311,14 +311,14 @@ impl<'b> Resolver<'b> { ItemKind::Struct(ref struct_def, _) => { // Define a name in the type namespace. let def = Def::Struct(self.definitions.local_def_id(item.id)); - self.define(parent, name, TypeNS, (def, vis, sp, expansion)); + self.define(parent, ident, TypeNS, (def, vis, sp, expansion)); // If this is a tuple or unit struct, define a name // in the value namespace as well. if !struct_def.is_struct() { let ctor_def = Def::StructCtor(self.definitions.local_def_id(struct_def.id()), CtorKind::from_ast(struct_def)); - self.define(parent, name, ValueNS, (ctor_def, vis, sp, expansion)); + self.define(parent, ident, ValueNS, (ctor_def, vis, sp, expansion)); } // Record field names for error reporting. @@ -332,7 +332,7 @@ impl<'b> Resolver<'b> { ItemKind::Union(ref vdata, _) => { let def = Def::Union(self.definitions.local_def_id(item.id)); - self.define(parent, name, TypeNS, (def, vis, sp, expansion)); + self.define(parent, ident, TypeNS, (def, vis, sp, expansion)); // Record field names for error reporting. let field_names = vdata.fields().iter().filter_map(|field| { @@ -350,8 +350,8 @@ impl<'b> Resolver<'b> { // Add all the items within to a new module. let module = - self.new_module(parent, ModuleKind::Def(Def::Trait(def_id), name), true); - self.define(parent, name, TypeNS, (module, vis, sp, expansion)); + self.new_module(parent, ModuleKind::Def(Def::Trait(def_id), ident.name), true); + self.define(parent, ident, TypeNS, (module, vis, sp, expansion)); self.current_module = module; } ItemKind::Mac(_) => panic!("unexpanded macro in resolve!"), @@ -365,26 +365,23 @@ impl<'b> Resolver<'b> { parent: Module<'b>, vis: ty::Visibility, expansion: Mark) { - let name = variant.node.name.name; + let ident = variant.node.name; let def_id = self.definitions.local_def_id(variant.node.data.id()); // Define a name in the type namespace. let def = Def::Variant(def_id); - self.define(parent, name, TypeNS, (def, vis, variant.span, expansion)); + self.define(parent, ident, TypeNS, (def, vis, variant.span, expansion)); // Define a constructor name in the value namespace. // Braced variants, unlike structs, generate unusable names in // value namespace, they are reserved for possible future use. let ctor_kind = CtorKind::from_ast(&variant.node.data); let ctor_def = Def::VariantCtor(def_id, ctor_kind); - self.define(parent, name, ValueNS, (ctor_def, vis, variant.span, expansion)); + self.define(parent, ident, ValueNS, (ctor_def, vis, variant.span, expansion)); } /// Constructs the reduced graph for one foreign item. fn build_reduced_graph_for_foreign_item(&mut self, item: &ForeignItem, expansion: Mark) { - let parent = self.current_module; - let name = item.ident.name; - let def = match item.node { ForeignItemKind::Fn(..) => { Def::Fn(self.definitions.local_def_id(item.id)) @@ -393,8 +390,9 @@ impl<'b> Resolver<'b> { Def::Static(self.definitions.local_def_id(item.id), m) } }; + let parent = self.current_module; let vis = self.resolve_visibility(&item.vis); - self.define(parent, name, ValueNS, (def, vis, item.span, expansion)); + self.define(parent, item.ident, ValueNS, (def, vis, item.span, expansion)); } fn build_reduced_graph_for_block(&mut self, block: &Block) { @@ -414,7 +412,7 @@ impl<'b> Resolver<'b> { /// Builds the reduced graph for a single item in an external crate. fn build_reduced_graph_for_external_crate_def(&mut self, parent: Module<'b>, child: Export) { - let name = child.name; + let ident = Ident::with_empty_ctxt(child.name); let def = child.def; let def_id = def.def_id(); let vis = match def { @@ -425,25 +423,25 @@ impl<'b> Resolver<'b> { match def { Def::Mod(..) | Def::Enum(..) => { - let module = self.new_module(parent, ModuleKind::Def(def, name), false); - self.define(parent, name, TypeNS, (module, vis, DUMMY_SP, Mark::root())); + let module = self.new_module(parent, ModuleKind::Def(def, ident.name), false); + self.define(parent, ident, TypeNS, (module, vis, DUMMY_SP, Mark::root())); } Def::Variant(..) => { - self.define(parent, name, TypeNS, (def, vis, DUMMY_SP, Mark::root())); + self.define(parent, ident, TypeNS, (def, vis, DUMMY_SP, Mark::root())); } Def::VariantCtor(..) => { - self.define(parent, name, ValueNS, (def, vis, DUMMY_SP, Mark::root())); + self.define(parent, ident, ValueNS, (def, vis, DUMMY_SP, Mark::root())); } Def::Fn(..) | Def::Static(..) | Def::Const(..) | Def::AssociatedConst(..) | Def::Method(..) => { - self.define(parent, name, ValueNS, (def, vis, DUMMY_SP, Mark::root())); + self.define(parent, ident, ValueNS, (def, vis, DUMMY_SP, Mark::root())); } Def::Trait(..) => { - let module = self.new_module(parent, ModuleKind::Def(def, name), false); - self.define(parent, name, TypeNS, (module, vis, DUMMY_SP, Mark::root())); + let module = self.new_module(parent, ModuleKind::Def(def, ident.name), false); + self.define(parent, ident, TypeNS, (module, vis, DUMMY_SP, Mark::root())); // If this is a trait, add all the trait item names to the trait info. let trait_item_def_ids = self.session.cstore.associated_item_def_ids(def_id); @@ -455,27 +453,27 @@ impl<'b> Resolver<'b> { } } Def::TyAlias(..) | Def::AssociatedTy(..) => { - self.define(parent, name, TypeNS, (def, vis, DUMMY_SP, Mark::root())); + self.define(parent, ident, TypeNS, (def, vis, DUMMY_SP, Mark::root())); } Def::Struct(..) => { - self.define(parent, name, TypeNS, (def, vis, DUMMY_SP, Mark::root())); + self.define(parent, ident, TypeNS, (def, vis, DUMMY_SP, Mark::root())); // Record field names for error reporting. let field_names = self.session.cstore.struct_field_names(def_id); self.insert_field_names(def_id, field_names); } Def::StructCtor(..) => { - self.define(parent, name, ValueNS, (def, vis, DUMMY_SP, Mark::root())); + self.define(parent, ident, ValueNS, (def, vis, DUMMY_SP, Mark::root())); } Def::Union(..) => { - self.define(parent, name, TypeNS, (def, vis, DUMMY_SP, Mark::root())); + self.define(parent, ident, TypeNS, (def, vis, DUMMY_SP, Mark::root())); // Record field names for error reporting. let field_names = self.session.cstore.struct_field_names(def_id); self.insert_field_names(def_id, field_names); } Def::Macro(..) => { - self.define(parent, name, MacroNS, (def, vis, DUMMY_SP, Mark::root())); + self.define(parent, ident, MacroNS, (def, vis, DUMMY_SP, Mark::root())); } Def::Local(..) | Def::PrimTy(..) | @@ -574,12 +572,13 @@ impl<'b> Resolver<'b> { } if let Some(span) = legacy_imports.import_all { - module.for_each_child(|name, ns, binding| if ns == MacroNS { - self.legacy_import_macro(name, binding, span, allow_shadowing); + module.for_each_child(|ident, ns, binding| if ns == MacroNS { + self.legacy_import_macro(ident.name, binding, span, allow_shadowing); }); } else { for (name, span) in legacy_imports.imports { - let result = self.resolve_name_in_module(module, name, MacroNS, false, None); + let ident = Ident::with_empty_ctxt(name); + let result = self.resolve_ident_in_module(module, ident, MacroNS, false, None); if let Ok(binding) = result { self.legacy_import_macro(name, binding, span, allow_shadowing); } else { @@ -591,7 +590,8 @@ impl<'b> Resolver<'b> { let krate = module.def_id().unwrap().krate; self.used_crates.insert(krate); self.session.cstore.export_macros(krate); - let result = self.resolve_name_in_module(module, name, MacroNS, false, None); + let ident = Ident::with_empty_ctxt(name); + let result = self.resolve_ident_in_module(module, ident, MacroNS, false, None); if let Ok(binding) = result { self.macro_exports.push(Export { name: name, def: binding.def() }); } else { @@ -759,7 +759,7 @@ impl<'a, 'b> Visitor<'a> for BuildReducedGraphVisitor<'a, 'b> { self.resolver.trait_item_map.insert((item.ident.name, def_id), is_static_method); let vis = ty::Visibility::Public; - self.resolver.define(parent, item.ident.name, ns, (def, vis, item.span, self.expansion)); + self.resolver.define(parent, item.ident, ns, (def, vis, item.span, self.expansion)); self.resolver.current_module = parent.parent.unwrap(); // nearest normal ancestor visit::walk_trait_item(self, item); diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 509ee704e2ea2..4d4f4629c7534 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -781,8 +781,8 @@ pub struct ModuleS<'a> { // The node id of the closest normal module (`mod`) ancestor (including this module). normal_ancestor_id: Option, - resolutions: RefCell>>>, - legacy_macro_resolutions: RefCell>, + resolutions: RefCell>>>, + legacy_macro_resolutions: RefCell>, macro_resolutions: RefCell, PathScope, Span)>>, // Macro invocations that can expand into items in this module. @@ -794,7 +794,7 @@ pub struct ModuleS<'a> { globs: RefCell>>, // Used to memoize the traits in this module for faster searches through all traits in scope. - traits: RefCell)]>>>, + traits: RefCell)]>>>, // Whether this module is populated. If not populated, any attempt to // access the children must be preceded with a @@ -822,9 +822,9 @@ impl<'a> ModuleS<'a> { } } - fn for_each_child)>(&self, mut f: F) { - for (&(name, ns), name_resolution) in self.resolutions.borrow().iter() { - name_resolution.borrow().binding.map(|binding| f(name, ns, binding)); + fn for_each_child)>(&self, mut f: F) { + for (&(ident, ns), name_resolution) in self.resolutions.borrow().iter() { + name_resolution.borrow().binding.map(|binding| f(ident, ns, binding)); } } @@ -1334,7 +1334,7 @@ impl<'a> Resolver<'a> { }) } - fn record_use(&mut self, name: Name, ns: Namespace, binding: &'a NameBinding<'a>, span: Span) + fn record_use(&mut self, ident: Ident, ns: Namespace, binding: &'a NameBinding<'a>, span: Span) -> bool /* true if an error was reported */ { // track extern crates for unused_extern_crate lint if let Some(DefId { krate, .. }) = binding.module().and_then(ModuleS::def_id) { @@ -1345,13 +1345,13 @@ impl<'a> Resolver<'a> { NameBindingKind::Import { directive, binding, ref used } if !used.get() => { used.set(true); self.used_imports.insert((directive.id, ns)); - self.add_to_glob_map(directive.id, name); - self.record_use(name, ns, binding, span) + self.add_to_glob_map(directive.id, ident); + self.record_use(ident, ns, binding, span) } NameBindingKind::Import { .. } => false, NameBindingKind::Ambiguity { b1, b2 } => { self.ambiguity_errors.push(AmbiguityError { - span: span, name: name, lexical: false, b1: b1, b2: b2, + span: span, name: ident.name, lexical: false, b1: b1, b2: b2, }); true } @@ -1359,9 +1359,9 @@ impl<'a> Resolver<'a> { } } - fn add_to_glob_map(&mut self, id: NodeId, name: Name) { + fn add_to_glob_map(&mut self, id: NodeId, ident: Ident) { if self.make_glob_map { - self.glob_map.entry(id).or_insert_with(FxHashSet).insert(name); + self.glob_map.entry(id).or_insert_with(FxHashSet).insert(ident.name); } } @@ -1388,7 +1388,7 @@ impl<'a> Resolver<'a> { record_used: Option) -> Option> { if ns == TypeNS { - ident = Ident::with_empty_ctxt(ident.name); + ident = ident.unhygienize(); } // Walk backwards up the ribs in scope. @@ -1403,8 +1403,7 @@ impl<'a> Resolver<'a> { } if let ModuleRibKind(module) = self.ribs[ns][i].kind { - let name = ident.name; - let item = self.resolve_name_in_module(module, name, ns, false, record_used); + let item = self.resolve_ident_in_module(module, ident, ns, false, record_used); if let Ok(binding) = item { // The ident resolves to an item. return Some(LexicalScopeBinding::Item(binding)); @@ -1413,7 +1412,7 @@ impl<'a> Resolver<'a> { if let ModuleKind::Block(..) = module.kind { // We can see through blocks } else if !module.no_implicit_prelude { return self.prelude.and_then(|prelude| { - self.resolve_name_in_module(prelude, name, ns, false, None).ok() + self.resolve_ident_in_module(prelude, ident, ns, false, None).ok() }).map(LexicalScopeBinding::Item) } else { return None; @@ -2183,8 +2182,7 @@ impl<'a> Resolver<'a> { Def::VariantCtor(_, CtorKind::Const) | Def::Const(..) if !always_binding => { // A unit struct/variant or constant pattern. - let name = ident.node.name; - self.record_use(name, ValueNS, binding.unwrap(), ident.span); + self.record_use(ident.node, ValueNS, binding.unwrap(), ident.span); Some(PathResolution::new(def)) } Def::StructCtor(..) | Def::VariantCtor(..) | @@ -2363,9 +2361,9 @@ impl<'a> Resolver<'a> { allow_super = false; let binding = if let Some(module) = module { - self.resolve_name_in_module(module, ident.name, ns, false, record_used) + self.resolve_ident_in_module(module, ident, ns, false, record_used) } else if opt_ns == Some(MacroNS) { - self.resolve_lexical_macro_path_segment(ident.name, ns, record_used) + self.resolve_lexical_macro_path_segment(ident, ns, record_used) } else { match self.resolve_ident_in_lexical_scope(ident, ns, record_used) { Some(LexicalScopeBinding::Item(binding)) => Ok(binding), @@ -2953,16 +2951,15 @@ impl<'a> Resolver<'a> { in_module_is_extern)) = worklist.pop() { self.populate_module_if_necessary(in_module); - in_module.for_each_child(|name, ns, name_binding| { + in_module.for_each_child(|ident, ns, name_binding| { // avoid imports entirely if name_binding.is_import() && !name_binding.is_extern_crate() { return; } // collect results based on the filter function - if name == lookup_name && ns == namespace { + if ident.name == lookup_name && ns == namespace { if filter_fn(name_binding.def()) { // create the path - let ident = Ident::with_empty_ctxt(name); let params = PathParameters::none(); let segment = PathSegment { identifier: ident, @@ -2994,7 +2991,7 @@ impl<'a> Resolver<'a> { // form the path let mut path_segments = path_segments.clone(); path_segments.push(PathSegment { - identifier: Ident::with_empty_ctxt(name), + identifier: ident, parameters: PathParameters::none(), }); @@ -3124,13 +3121,13 @@ impl<'a> Resolver<'a> { fn report_conflict(&mut self, parent: Module, - name: Name, + ident: Ident, ns: Namespace, binding: &NameBinding, old_binding: &NameBinding) { // Error on the second of two conflicting names if old_binding.span.lo > binding.span.lo { - return self.report_conflict(parent, name, ns, old_binding, binding); + return self.report_conflict(parent, ident, ns, old_binding, binding); } let container = match parent.kind { @@ -3145,7 +3142,7 @@ impl<'a> Resolver<'a> { false => ("defined", "definition"), }; - let span = binding.span; + let (name, span) = (ident.name, binding.span); if let Some(s) = self.name_already_seen.get(&name) { if s == &span { diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 6c02967672d84..b2e31d5490962 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -19,7 +19,7 @@ use rustc::hir::map::{self, DefCollector}; use rustc::ty; use std::cell::Cell; use std::rc::Rc; -use syntax::ast::{self, Name}; +use syntax::ast::{self, Name, Ident}; use syntax::errors::DiagnosticBuilder; use syntax::ext::base::{self, Determinacy, MultiModifier, MultiDecorator}; use syntax::ext::base::{NormalTT, SyntaxExtension}; @@ -246,7 +246,7 @@ impl<'a> base::Resolver for Resolver<'a> { let result = match self.resolve_legacy_scope(&invocation.legacy_scope, name, false) { Some(MacroBinding::Legacy(binding)) => Ok(binding.ext.clone()), Some(MacroBinding::Modern(binding)) => Ok(binding.get_macro(self)), - None => match self.resolve_lexical_macro_path_segment(name, MacroNS, None) { + None => match self.resolve_lexical_macro_path_segment(path[0], MacroNS, None) { Ok(binding) => Ok(binding.get_macro(self)), Err(Determinacy::Undetermined) if !force => return Err(Determinacy::Undetermined), _ => { @@ -260,7 +260,7 @@ impl<'a> base::Resolver for Resolver<'a> { }; if self.use_extern_macros { - self.current_module.legacy_macro_resolutions.borrow_mut().push((scope, name, span)); + self.current_module.legacy_macro_resolutions.borrow_mut().push((scope, path[0], span)); } result } @@ -269,7 +269,7 @@ impl<'a> base::Resolver for Resolver<'a> { impl<'a> Resolver<'a> { // Resolve the initial segment of a non-global macro path (e.g. `foo` in `foo::bar!();`) pub fn resolve_lexical_macro_path_segment(&mut self, - name: Name, + ident: Ident, ns: Namespace, record_used: Option) -> Result<&'a NameBinding<'a>, Determinacy> { @@ -278,7 +278,7 @@ impl<'a> Resolver<'a> { loop { // Since expanded macros may not shadow the lexical scope (enforced below), // we can ignore unresolved invocations (indicated by the penultimate argument). - match self.resolve_name_in_module(module, name, ns, true, record_used) { + match self.resolve_ident_in_module(module, ident, ns, true, record_used) { Ok(binding) => { let span = match record_used { Some(span) => span, @@ -286,6 +286,7 @@ impl<'a> Resolver<'a> { }; match potential_expanded_shadower { Some(shadower) if shadower.def() != binding.def() => { + let name = ident.name; self.ambiguity_errors.push(AmbiguityError { span: span, name: name, b1: shadower, b2: binding, lexical: true, }); @@ -383,10 +384,10 @@ impl<'a> Resolver<'a> { } } - for &(mark, name, span) in module.legacy_macro_resolutions.borrow().iter() { + for &(mark, ident, span) in module.legacy_macro_resolutions.borrow().iter() { let legacy_scope = &self.invocations[&mark].legacy_scope; - let legacy_resolution = self.resolve_legacy_scope(legacy_scope, name, true); - let resolution = self.resolve_lexical_macro_path_segment(name, MacroNS, Some(span)); + let legacy_resolution = self.resolve_legacy_scope(legacy_scope, ident.name, true); + let resolution = self.resolve_lexical_macro_path_segment(ident, MacroNS, Some(span)); let (legacy_resolution, resolution) = match (legacy_resolution, resolution) { (Some(legacy_resolution), Ok(resolution)) => (legacy_resolution, resolution), _ => continue, @@ -396,9 +397,9 @@ impl<'a> Resolver<'a> { MacroBinding::Modern(binding) => (binding.span, "imported"), MacroBinding::Legacy(binding) => (binding.span, "defined"), }; - let msg1 = format!("`{}` could resolve to the macro {} here", name, participle); - let msg2 = format!("`{}` could also resolve to the macro imported here", name); - self.session.struct_span_err(span, &format!("`{}` is ambiguous", name)) + let msg1 = format!("`{}` could resolve to the macro {} here", ident, participle); + let msg2 = format!("`{}` could also resolve to the macro imported here", ident); + self.session.struct_span_err(span, &format!("`{}` is ambiguous", ident)) .span_note(legacy_span, &msg1) .span_note(resolution.span, &msg2) .emit(); diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index 64a8e21f9e0a1..7c7908d24010b 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -21,7 +21,7 @@ use rustc::ty; use rustc::lint::builtin::PRIVATE_IN_PUBLIC; use rustc::hir::def::*; -use syntax::ast::{Ident, NodeId, Name}; +use syntax::ast::{Ident, NodeId}; use syntax::ext::base::Determinacy::{self, Determined, Undetermined}; use syntax::ext::hygiene::Mark; use syntax::symbol::keywords; @@ -35,8 +35,8 @@ use std::mem; #[derive(Clone, Debug)] pub enum ImportDirectiveSubclass<'a> { SingleImport { - target: Name, - source: Name, + target: Ident, + source: Ident, result: PerNS, Determinacy>>>, }, GlobImport { @@ -126,31 +126,32 @@ impl<'a> NameResolution<'a> { } impl<'a> Resolver<'a> { - fn resolution(&self, module: Module<'a>, name: Name, ns: Namespace) + fn resolution(&self, module: Module<'a>, ident: Ident, ns: Namespace) -> &'a RefCell> { - *module.resolutions.borrow_mut().entry((name, ns)) + *module.resolutions.borrow_mut().entry((ident, ns)) .or_insert_with(|| self.arenas.alloc_name_resolution()) } - /// Attempts to resolve the supplied name in the given module for the given namespace. - /// If successful, returns the binding corresponding to the name. + /// Attempts to resolve `ident` in namespaces `ns` of `module`. /// Invariant: if `record_used` is `Some`, import resolution must be complete. - pub fn resolve_name_in_module(&mut self, - module: Module<'a>, - name: Name, - ns: Namespace, - ignore_unresolved_invocations: bool, - record_used: Option) - -> Result<&'a NameBinding<'a>, Determinacy> { + pub fn resolve_ident_in_module(&mut self, + module: Module<'a>, + ident: Ident, + ns: Namespace, + ignore_unresolved_invocations: bool, + record_used: Option) + -> Result<&'a NameBinding<'a>, Determinacy> { + let ident = ident.unhygienize(); self.populate_module_if_necessary(module); - let resolution = self.resolution(module, name, ns) + let resolution = self.resolution(module, ident, ns) .try_borrow_mut() .map_err(|_| Determined)?; // This happens when there is a cycle of imports if let Some(span) = record_used { if let Some(binding) = resolution.binding { if let Some(shadowed_glob) = resolution.shadows_glob { + let name = ident.name; // If we ignore unresolved invocations, we must forbid // expanded shadowing to avoid time travel. if ignore_unresolved_invocations && @@ -162,11 +163,11 @@ impl<'a> Resolver<'a> { }); } } - if self.record_use(name, ns, binding, span) { + if self.record_use(ident, ns, binding, span) { return Ok(self.dummy_binding); } if !self.is_accessible(binding.vis) { - self.privacy_errors.push(PrivacyError(span, name, binding)); + self.privacy_errors.push(PrivacyError(span, ident.name, binding)); } } @@ -194,11 +195,11 @@ impl<'a> Resolver<'a> { Some(module) => module, None => return Err(Undetermined), }; - let name = match directive.subclass { + let ident = match directive.subclass { SingleImport { source, .. } => source, _ => unreachable!(), }; - match self.resolve_name_in_module(module, name, ns, false, None) { + match self.resolve_ident_in_module(module, ident, ns, false, None) { Err(Determined) => {} _ => return Err(Undetermined), } @@ -220,7 +221,7 @@ impl<'a> Resolver<'a> { for directive in module.globs.borrow().iter() { if self.is_accessible(directive.vis.get()) { if let Some(module) = directive.imported_module.get() { - let result = self.resolve_name_in_module(module, name, ns, false, None); + let result = self.resolve_ident_in_module(module, ident, ns, false, None); if let Err(Undetermined) = result { return Err(Undetermined); } @@ -299,12 +300,13 @@ impl<'a> Resolver<'a> { } // Define the name or return the existing binding if there is a collision. - pub fn try_define(&mut self, module: Module<'a>, name: Name, ns: Namespace, binding: T) + pub fn try_define(&mut self, module: Module<'a>, ident: Ident, ns: Namespace, binding: T) -> Result<(), &'a NameBinding<'a>> where T: ToNameBinding<'a> { + let ident = ident.unhygienize(); let binding = self.arenas.alloc_name_binding(binding.to_name_binding()); - self.update_resolution(module, name, ns, |this, resolution| { + self.update_resolution(module, ident, ns, |this, resolution| { if let Some(old_binding) = resolution.binding { if binding.is_glob_import() { if !old_binding.is_glob_import() && @@ -347,13 +349,14 @@ impl<'a> Resolver<'a> { // Use `f` to mutate the resolution of the name in the module. // If the resolution becomes a success, define it in the module's glob importers. - fn update_resolution(&mut self, module: Module<'a>, name: Name, ns: Namespace, f: F) -> T + fn update_resolution(&mut self, module: Module<'a>, ident: Ident, ns: Namespace, f: F) + -> T where F: FnOnce(&mut Resolver<'a>, &mut NameResolution<'a>) -> T { // Ensure that `resolution` isn't borrowed when defining in the module's glob importers, // during which the resolution might end up getting re-defined via a glob cycle. let (binding, t) = { - let mut resolution = &mut *self.resolution(module, name, ns).borrow_mut(); + let mut resolution = &mut *self.resolution(module, ident, ns).borrow_mut(); let old_binding = resolution.binding(); let t = f(self, resolution); @@ -372,7 +375,7 @@ impl<'a> Resolver<'a> { for directive in module.glob_importers.borrow_mut().iter() { if self.is_accessible_from(binding.vis, directive.parent) { let imported_binding = self.import(binding, directive); - let _ = self.try_define(directive.parent, name, ns, imported_binding); + let _ = self.try_define(directive.parent, ident, ns, imported_binding); } } @@ -508,7 +511,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { let mut indeterminate = false; self.per_ns(|this, ns| { if let Err(Undetermined) = result[ns].get() { - result[ns].set(this.resolve_name_in_module(module, source, ns, false, None)); + result[ns].set(this.resolve_ident_in_module(module, source, ns, false, None)); } else { return }; @@ -564,7 +567,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { _ => return None, }; - let (name, result) = match directive.subclass { + let (ident, result) = match directive.subclass { SingleImport { source, ref result, .. } => (source, result), GlobImport { .. } if module.def_id() == directive.parent.def_id() => { // Importing a module into itself is not allowed. @@ -586,8 +589,8 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { self.per_ns(|this, ns| { if let Ok(binding) = result[ns].get() { all_ns_err = false; - if this.record_use(name, ns, binding, directive.span) { - this.resolution(module, name, ns).borrow_mut().binding = + if this.record_use(ident, ns, binding, directive.span) { + this.resolution(module, ident, ns).borrow_mut().binding = Some(this.dummy_binding); } } @@ -596,7 +599,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { if all_ns_err { let mut all_ns_failed = true; self.per_ns(|this, ns| { - match this.resolve_name_in_module(module, name, ns, false, Some(span)) { + match this.resolve_ident_in_module(module, ident, ns, false, Some(span)) { Ok(_) => all_ns_failed = false, _ => {} } @@ -604,27 +607,28 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { return if all_ns_failed { let resolutions = module.resolutions.borrow(); - let names = resolutions.iter().filter_map(|(&(ref n, _), resolution)| { - if *n == name { return None; } // Never suggest the same name + let names = resolutions.iter().filter_map(|(&(ref i, _), resolution)| { + if *i == ident { return None; } // Never suggest the same name match *resolution.borrow() { - NameResolution { binding: Some(_), .. } => Some(n), + NameResolution { binding: Some(_), .. } => Some(&i.name), NameResolution { single_imports: SingleImports::None, .. } => None, - _ => Some(n), + _ => Some(&i.name), } }); - let lev_suggestion = match find_best_match_for_name(names, &name.as_str(), None) { - Some(name) => format!(". Did you mean to use `{}`?", name), - None => "".to_owned(), - }; + let lev_suggestion = + match find_best_match_for_name(names, &ident.name.as_str(), None) { + Some(name) => format!(". Did you mean to use `{}`?", name), + None => "".to_owned(), + }; let module_str = module_to_string(module); let msg = if &module_str == "???" { - format!("no `{}` in the root{}", name, lev_suggestion) + format!("no `{}` in the root{}", ident, lev_suggestion) } else { - format!("no `{}` in `{}`{}", name, module_str, lev_suggestion) + format!("no `{}` in `{}`{}", ident, module_str, lev_suggestion) }; Some(msg) } else { - // `resolve_name_in_module` reported a privacy error. + // `resolve_ident_in_module` reported a privacy error. self.import_dummy_binding(directive); None } @@ -649,18 +653,18 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { if ns == TypeNS && binding.is_extern_crate() { let msg = format!("extern crate `{}` is private, and cannot be reexported \ (error E0364), consider declaring with `pub`", - name); + ident); self.session.add_lint(PRIVATE_IN_PUBLIC, directive.id, directive.span, msg); } else if ns == TypeNS { struct_span_err!(self.session, directive.span, E0365, - "`{}` is private, and cannot be reexported", name) - .span_label(directive.span, &format!("reexport of private `{}`", name)) - .note(&format!("consider declaring type or module `{}` with `pub`", name)) + "`{}` is private, and cannot be reexported", ident) + .span_label(directive.span, &format!("reexport of private `{}`", ident)) + .note(&format!("consider declaring type or module `{}` with `pub`", ident)) .emit(); } else { - let msg = format!("`{}` is private, and cannot be reexported", name); + let msg = format!("`{}` is private, and cannot be reexported", ident); let note_msg = - format!("consider marking `{}` as `pub` in the imported module", name); + format!("consider marking `{}` as `pub` in the imported module", ident); struct_span_err!(self.session, directive.span, E0364, "{}", &msg) .span_note(directive.span, ¬e_msg) .emit(); @@ -697,13 +701,13 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { // Ensure that `resolutions` isn't borrowed during `try_define`, // since it might get updated via a glob cycle. - let bindings = module.resolutions.borrow().iter().filter_map(|(name, resolution)| { - resolution.borrow().binding().map(|binding| (*name, binding)) + let bindings = module.resolutions.borrow().iter().filter_map(|(&ident, resolution)| { + resolution.borrow().binding().map(|binding| (ident, binding)) }).collect::>(); - for ((name, ns), binding) in bindings { + for ((ident, ns), binding) in bindings { if binding.pseudo_vis() == ty::Visibility::Public || self.is_accessible(binding.vis) { let imported_binding = self.import(binding, directive); - let _ = self.try_define(directive.parent, name, ns, imported_binding); + let _ = self.try_define(directive.parent, ident, ns, imported_binding); } } @@ -722,7 +726,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { reexports = mem::replace(&mut self.macro_exports, Vec::new()); } - for (&(name, ns), resolution) in module.resolutions.borrow().iter() { + for (&(ident, ns), resolution) in module.resolutions.borrow().iter() { let resolution = resolution.borrow(); let binding = match resolution.binding { Some(binding) => binding, @@ -736,7 +740,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { if !def.def_id().is_local() { self.session.cstore.export_macros(def.def_id().krate); } - reexports.push(Export { name: name, def: def }); + reexports.push(Export { name: ident.name, def: def }); } } @@ -745,7 +749,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { !orig_binding.vis.is_at_least(binding.vis, self) { let msg = format!("variant `{}` is private, and cannot be reexported \ (error E0364), consider declaring its enum as `pub`", - name); + ident); self.session.add_lint(PRIVATE_IN_PUBLIC, directive.id, binding.span, msg); } } diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 2a911aceb9d94..2369cc5714ec1 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -47,10 +47,14 @@ impl Ident { Ident { name: name, ctxt: SyntaxContext::empty() } } - /// Maps a string to an identifier with an empty syntax context. - pub fn from_str(s: &str) -> Ident { - Ident::with_empty_ctxt(Symbol::intern(s)) - } + /// Maps a string to an identifier with an empty syntax context. + pub fn from_str(s: &str) -> Ident { + Ident::with_empty_ctxt(Symbol::intern(s)) + } + + pub fn unhygienize(&self) -> Ident { + Ident { name: self.name, ctxt: SyntaxContext::empty() } + } } impl fmt::Debug for Ident { From aa19274b72f0f1f2a4481cdf9114e30c1b5f336d Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Tue, 29 Nov 2016 02:53:00 +0000 Subject: [PATCH 42/73] De-genericize `try_define`. --- src/librustc_resolve/build_reduced_graph.rs | 23 ++++++++-------- src/librustc_resolve/lib.rs | 6 ++--- src/librustc_resolve/resolve_imports.rs | 29 +++++++++++---------- 3 files changed, 30 insertions(+), 28 deletions(-) diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 4aa04dc34feda..9401c77c7b8d5 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -16,7 +16,8 @@ use macros::{InvocationData, LegacyScope}; use resolve_imports::ImportDirective; use resolve_imports::ImportDirectiveSubclass::{self, GlobImport, SingleImport}; -use {Resolver, Module, ModuleS, ModuleKind, NameBinding, NameBindingKind, ToNameBinding}; +use {Module, ModuleS, ModuleKind, NameBinding, NameBindingKind, ToNameBinding}; +use {Resolver, ResolverArenas}; use Namespace::{self, TypeNS, ValueNS, MacroNS}; use {resolve_error, resolve_struct_error, ResolutionError}; @@ -45,24 +46,24 @@ use syntax::visit::{self, Visitor}; use syntax_pos::{Span, DUMMY_SP}; impl<'a> ToNameBinding<'a> for (Module<'a>, ty::Visibility, Span, Mark) { - fn to_name_binding(self) -> NameBinding<'a> { - NameBinding { + fn to_name_binding(self, arenas: &'a ResolverArenas<'a>) -> &'a NameBinding<'a> { + arenas.alloc_name_binding(NameBinding { kind: NameBindingKind::Module(self.0), vis: self.1, span: self.2, expansion: self.3, - } + }) } } impl<'a> ToNameBinding<'a> for (Def, ty::Visibility, Span, Mark) { - fn to_name_binding(self) -> NameBinding<'a> { - NameBinding { + fn to_name_binding(self, arenas: &'a ResolverArenas<'a>) -> &'a NameBinding<'a> { + arenas.alloc_name_binding(NameBinding { kind: NameBindingKind::Def(self.0), vis: self.1, span: self.2, expansion: self.3, - } + }) } } @@ -79,8 +80,8 @@ impl<'b> Resolver<'b> { fn define(&mut self, parent: Module<'b>, ident: Ident, ns: Namespace, def: T) where T: ToNameBinding<'b>, { - let binding = def.to_name_binding(); - if let Err(old_binding) = self.try_define(parent, ident, ns, binding.clone()) { + let binding = def.to_name_binding(self.arenas); + if let Err(old_binding) = self.try_define(parent, ident, ns, binding) { self.report_conflict(parent, ident, ns, old_binding, &binding); } } @@ -238,8 +239,8 @@ impl<'b> Resolver<'b> { // n.b. we don't need to look at the path option here, because cstore already did let crate_id = self.session.cstore.extern_mod_stmt_cnum(item.id).unwrap(); let module = self.get_extern_crate_root(crate_id); - let binding = (module, ty::Visibility::Public, sp, expansion).to_name_binding(); - let binding = self.arenas.alloc_name_binding(binding); + let binding = + (module, ty::Visibility::Public, sp, expansion).to_name_binding(self.arenas); let directive = self.arenas.alloc_import_directive(ImportDirective { id: item.id, parent: parent, diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 4d4f4629c7534..972fd8f570c08 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -875,11 +875,11 @@ pub struct NameBinding<'a> { } pub trait ToNameBinding<'a> { - fn to_name_binding(self) -> NameBinding<'a>; + fn to_name_binding(self, arenas: &'a ResolverArenas<'a>) -> &'a NameBinding<'a>; } -impl<'a> ToNameBinding<'a> for NameBinding<'a> { - fn to_name_binding(self) -> NameBinding<'a> { +impl<'a> ToNameBinding<'a> for &'a NameBinding<'a> { + fn to_name_binding(self, _: &'a ResolverArenas<'a>) -> &'a NameBinding<'a> { self } } diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index 7c7908d24010b..2c35d7ec4423f 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -12,7 +12,7 @@ use self::ImportDirectiveSubclass::*; use {AmbiguityError, Module, PerNS}; use Namespace::{self, TypeNS, MacroNS}; -use {NameBinding, NameBindingKind, PathResult, PathScope, PrivacyError, ToNameBinding}; +use {NameBinding, NameBindingKind, PathResult, PathScope, PrivacyError}; use Resolver; use {names_to_string, module_to_string}; use {resolve_error, ResolutionError}; @@ -273,7 +273,7 @@ impl<'a> Resolver<'a> { // Given a binding and an import directive that resolves to it, // return the corresponding binding defined by the import directive. pub fn import(&mut self, binding: &'a NameBinding<'a>, directive: &'a ImportDirective<'a>) - -> NameBinding<'a> { + -> &'a NameBinding<'a> { let vis = if binding.pseudo_vis().is_at_least(directive.vis.get(), self) || !directive.is_glob() && binding.is_extern_crate() { // c.f. `PRIVATE_IN_PUBLIC` directive.vis.get() @@ -287,7 +287,7 @@ impl<'a> Resolver<'a> { } } - NameBinding { + self.arenas.alloc_name_binding(NameBinding { kind: NameBindingKind::Import { binding: binding, directive: directive, @@ -296,16 +296,17 @@ impl<'a> Resolver<'a> { span: directive.span, vis: vis, expansion: directive.expansion, - } + }) } // Define the name or return the existing binding if there is a collision. - pub fn try_define(&mut self, module: Module<'a>, ident: Ident, ns: Namespace, binding: T) - -> Result<(), &'a NameBinding<'a>> - where T: ToNameBinding<'a> - { + pub fn try_define(&mut self, + module: Module<'a>, + ident: Ident, + ns: Namespace, + binding: &'a NameBinding<'a>) + -> Result<(), &'a NameBinding<'a>> { let ident = ident.unhygienize(); - let binding = self.arenas.alloc_name_binding(binding.to_name_binding()); self.update_resolution(module, ident, ns, |this, resolution| { if let Some(old_binding) = resolution.binding { if binding.is_glob_import() { @@ -389,7 +390,7 @@ impl<'a> Resolver<'a> { let dummy_binding = self.dummy_binding; let dummy_binding = self.import(dummy_binding, directive); self.per_ns(|this, ns| { - let _ = this.try_define(directive.parent, target, ns, dummy_binding.clone()); + let _ = this.try_define(directive.parent, target, ns, dummy_binding); }); } } @@ -516,10 +517,11 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { return }; + let parent = directive.parent; match result[ns].get() { Err(Undetermined) => indeterminate = true, Err(Determined) => { - this.update_resolution(directive.parent, target, ns, |_, resolution| { + this.update_resolution(parent, target, ns, |_, resolution| { resolution.single_imports.directive_failed() }); } @@ -534,10 +536,9 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { } Ok(binding) => { let imported_binding = this.import(binding, directive); - let conflict = this.try_define(directive.parent, target, ns, imported_binding); + let conflict = this.try_define(parent, target, ns, imported_binding); if let Err(old_binding) = conflict { - let binding = &this.import(binding, directive); - this.report_conflict(directive.parent, target, ns, binding, old_binding); + this.report_conflict(parent, target, ns, imported_binding, old_binding); } } } From 532b013b28adcaa6710f4ba263990debff50d860 Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Sat, 26 Nov 2016 12:47:52 +0000 Subject: [PATCH 43/73] Rename `ModuleS` -> `ModuleData`. --- src/librustc_resolve/build_reduced_graph.rs | 10 ++++---- src/librustc_resolve/lib.rs | 26 ++++++++++----------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 9401c77c7b8d5..2930e57422bfd 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -16,7 +16,7 @@ use macros::{InvocationData, LegacyScope}; use resolve_imports::ImportDirective; use resolve_imports::ImportDirectiveSubclass::{self, GlobImport, SingleImport}; -use {Module, ModuleS, ModuleKind, NameBinding, NameBindingKind, ToNameBinding}; +use {Module, ModuleData, ModuleKind, NameBinding, NameBindingKind, ToNameBinding}; use {Resolver, ResolverArenas}; use Namespace::{self, TypeNS, ValueNS, MacroNS}; use {resolve_error, resolve_struct_error, ResolutionError}; @@ -261,12 +261,12 @@ impl<'b> Resolver<'b> { ItemKind::Mod(..) => { let def = Def::Mod(self.definitions.local_def_id(item.id)); - let module = self.arenas.alloc_module(ModuleS { + let module = self.arenas.alloc_module(ModuleData { no_implicit_prelude: parent.no_implicit_prelude || { attr::contains_name(&item.attrs, "no_implicit_prelude") }, normal_ancestor_id: Some(item.id), - ..ModuleS::new(Some(parent), ModuleKind::Def(def, ident.name)) + ..ModuleData::new(Some(parent), ModuleKind::Def(def, ident.name)) }); self.define(parent, ident, TypeNS, (module, vis, sp, expansion)); self.module_map.insert(item.id, module); @@ -493,9 +493,9 @@ impl<'b> Resolver<'b> { let macros_only = self.session.cstore.dep_kind(cnum).macros_only(); let arenas = self.arenas; *self.extern_crate_roots.entry((cnum, macros_only)).or_insert_with(|| { - arenas.alloc_module(ModuleS { + arenas.alloc_module(ModuleData { populated: Cell::new(false), - ..ModuleS::new(None, ModuleKind::Def(Def::Mod(def_id), keywords::Invalid.name())) + ..ModuleData::new(None, ModuleKind::Def(Def::Mod(def_id), keywords::Invalid.name())) }) }) } diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 972fd8f570c08..d87e04f7b97f9 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -774,7 +774,7 @@ enum ModuleKind { } /// One node in the tree of modules. -pub struct ModuleS<'a> { +pub struct ModuleData<'a> { parent: Option>, kind: ModuleKind, @@ -802,11 +802,11 @@ pub struct ModuleS<'a> { populated: Cell, } -pub type Module<'a> = &'a ModuleS<'a>; +pub type Module<'a> = &'a ModuleData<'a>; -impl<'a> ModuleS<'a> { +impl<'a> ModuleData<'a> { fn new(parent: Option>, kind: ModuleKind) -> Self { - ModuleS { + ModuleData { parent: parent, kind: kind, normal_ancestor_id: None, @@ -859,7 +859,7 @@ impl<'a> ModuleS<'a> { } } -impl<'a> fmt::Debug for ModuleS<'a> { +impl<'a> fmt::Debug for ModuleData<'a> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{:?}", self.def()) } @@ -1116,7 +1116,7 @@ pub struct Resolver<'a> { } pub struct ResolverArenas<'a> { - modules: arena::TypedArena>, + modules: arena::TypedArena>, local_modules: RefCell>>, name_bindings: arena::TypedArena>, import_directives: arena::TypedArena>, @@ -1126,7 +1126,7 @@ pub struct ResolverArenas<'a> { } impl<'a> ResolverArenas<'a> { - fn alloc_module(&'a self, module: ModuleS<'a>) -> Module<'a> { + fn alloc_module(&'a self, module: ModuleData<'a>) -> Module<'a> { let module = self.modules.alloc(module); if module.def_id().map(|def_id| def_id.is_local()).unwrap_or(true) { self.local_modules.borrow_mut().push(module); @@ -1206,10 +1206,10 @@ impl<'a> Resolver<'a> { arenas: &'a ResolverArenas<'a>) -> Resolver<'a> { let root_def = Def::Mod(DefId::local(CRATE_DEF_INDEX)); - let graph_root = arenas.alloc_module(ModuleS { + let graph_root = arenas.alloc_module(ModuleData { normal_ancestor_id: Some(CRATE_NODE_ID), no_implicit_prelude: attr::contains_name(&krate.attrs, "no_implicit_prelude"), - ..ModuleS::new(None, ModuleKind::Def(root_def, keywords::Invalid.name())) + ..ModuleData::new(None, ModuleKind::Def(root_def, keywords::Invalid.name())) }); let mut module_map = NodeMap(); module_map.insert(CRATE_NODE_ID, graph_root); @@ -1327,17 +1327,17 @@ impl<'a> Resolver<'a> { } fn new_module(&self, parent: Module<'a>, kind: ModuleKind, local: bool) -> Module<'a> { - self.arenas.alloc_module(ModuleS { + self.arenas.alloc_module(ModuleData { normal_ancestor_id: if local { self.current_module.normal_ancestor_id } else { None }, populated: Cell::new(local), - ..ModuleS::new(Some(parent), kind) + ..ModuleData::new(Some(parent), kind) }) } fn record_use(&mut self, ident: Ident, ns: Namespace, binding: &'a NameBinding<'a>, span: Span) -> bool /* true if an error was reported */ { // track extern crates for unused_extern_crate lint - if let Some(DefId { krate, .. }) = binding.module().and_then(ModuleS::def_id) { + if let Some(DefId { krate, .. }) = binding.module().and_then(ModuleData::def_id) { self.used_crates.insert(krate); } @@ -2403,7 +2403,7 @@ impl<'a> Resolver<'a> { }); } } - let msg = if module.and_then(ModuleS::def) == self.graph_root.def() { + let msg = if module.and_then(ModuleData::def) == self.graph_root.def() { let is_mod = |def| match def { Def::Mod(..) => true, _ => false }; let mut candidates = self.lookup_candidates(ident.name, TypeNS, is_mod).candidates; From 4d638fd1131c3f909d6e328c20d88e361a444a99 Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Sat, 26 Nov 2016 12:48:46 +0000 Subject: [PATCH 44/73] Canonicalize lifetime names. --- src/librustc_resolve/build_reduced_graph.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 2930e57422bfd..02a4d8db0955a 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -74,11 +74,11 @@ struct LegacyMacroImports { reexports: Vec<(Name, Span)>, } -impl<'b> Resolver<'b> { +impl<'a> Resolver<'a> { /// Defines `name` in namespace `ns` of module `parent` to be `def` if it is not yet defined; /// otherwise, reports an error. - fn define(&mut self, parent: Module<'b>, ident: Ident, ns: Namespace, def: T) - where T: ToNameBinding<'b>, + fn define(&mut self, parent: Module<'a>, ident: Ident, ns: Namespace, def: T) + where T: ToNameBinding<'a>, { let binding = def.to_name_binding(self.arenas); if let Err(old_binding) = self.try_define(parent, ident, ns, binding) { @@ -363,7 +363,7 @@ impl<'b> Resolver<'b> { // type and value namespaces. fn build_reduced_graph_for_variant(&mut self, variant: &Variant, - parent: Module<'b>, + parent: Module<'a>, vis: ty::Visibility, expansion: Mark) { let ident = variant.node.name; @@ -412,7 +412,7 @@ impl<'b> Resolver<'b> { } /// Builds the reduced graph for a single item in an external crate. - fn build_reduced_graph_for_external_crate_def(&mut self, parent: Module<'b>, child: Export) { + fn build_reduced_graph_for_external_crate_def(&mut self, parent: Module<'a>, child: Export) { let ident = Ident::with_empty_ctxt(child.name); let def = child.def; let def_id = def.def_id(); @@ -488,7 +488,7 @@ impl<'b> Resolver<'b> { } } - fn get_extern_crate_root(&mut self, cnum: CrateNum) -> Module<'b> { + fn get_extern_crate_root(&mut self, cnum: CrateNum) -> Module<'a> { let def_id = DefId { krate: cnum, index: CRATE_DEF_INDEX }; let macros_only = self.session.cstore.dep_kind(cnum).macros_only(); let arenas = self.arenas; @@ -531,7 +531,7 @@ impl<'b> Resolver<'b> { /// Ensures that the reduced graph rooted at the given external module /// is built, building it if it is not. - pub fn populate_module_if_necessary(&mut self, module: Module<'b>) { + pub fn populate_module_if_necessary(&mut self, module: Module<'a>) { if module.populated.get() { return } for child in self.session.cstore.item_children(module.def_id().unwrap()) { self.build_reduced_graph_for_external_crate_def(module, child); @@ -541,7 +541,7 @@ impl<'b> Resolver<'b> { fn legacy_import_macro(&mut self, name: Name, - binding: &'b NameBinding<'b>, + binding: &'a NameBinding<'a>, span: Span, allow_shadowing: bool) { self.used_crates.insert(binding.def().def_id().krate); @@ -554,7 +554,7 @@ impl<'b> Resolver<'b> { } } - fn process_legacy_macro_imports(&mut self, item: &Item, module: Module<'b>, expansion: Mark) { + fn process_legacy_macro_imports(&mut self, item: &Item, module: Module<'a>, expansion: Mark) { let allow_shadowing = expansion == Mark::root(); let legacy_imports = self.legacy_macro_imports(&item.attrs); let cnum = module.def_id().unwrap().krate; From e80d1a8faf2da8df494828e2772e2d2043282fed Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Tue, 29 Nov 2016 23:36:27 +0000 Subject: [PATCH 45/73] Remove `MacroDef`'s fields `imported_from` and `allow_internal_unstable`, remove `export` argument of `resolver.add_macro()`. --- src/librustc/hir/intravisit.rs | 1 - src/librustc/hir/lowering.rs | 2 -- src/librustc/hir/mod.rs | 2 -- src/librustc/middle/stability.rs | 8 ++------ src/librustc_metadata/cstore_impl.rs | 2 -- src/librustc_resolve/macros.rs | 5 +++-- src/librustdoc/visit_ast.rs | 5 +++-- src/libsyntax/ast.rs | 2 -- src/libsyntax/ext/base.rs | 4 ++-- src/libsyntax/ext/tt/macro_rules.rs | 7 ++----- src/libsyntax/visit.rs | 1 - 11 files changed, 12 insertions(+), 27 deletions(-) diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs index 625bde2ca8b67..186d6f626509f 100644 --- a/src/librustc/hir/intravisit.rs +++ b/src/librustc/hir/intravisit.rs @@ -365,7 +365,6 @@ pub fn walk_crate<'v, V: Visitor<'v>>(visitor: &mut V, krate: &'v Crate) { pub fn walk_macro_def<'v, V: Visitor<'v>>(visitor: &mut V, macro_def: &'v MacroDef) { visitor.visit_id(macro_def.id); visitor.visit_name(macro_def.span, macro_def.name); - walk_opt_name(visitor, macro_def.span, macro_def.imported_from); walk_list!(visitor, visit_attribute, ¯o_def.attrs); } diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 74876eb59ee9a..f5773d3517804 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -987,8 +987,6 @@ impl<'a> LoweringContext<'a> { attrs: self.lower_attrs(&m.attrs), id: m.id, span: m.span, - imported_from: m.imported_from.map(|x| x.name), - allow_internal_unstable: m.allow_internal_unstable, body: m.body.clone().into(), } } diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 4fd8f96ba046a..f52ee35e17573 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -475,8 +475,6 @@ pub struct MacroDef { pub attrs: HirVec, pub id: NodeId, pub span: Span, - pub imported_from: Option, - pub allow_internal_unstable: bool, pub body: HirVec, } diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs index 3e32957aecfe0..f45e86f2f4b96 100644 --- a/src/librustc/middle/stability.rs +++ b/src/librustc/middle/stability.rs @@ -302,9 +302,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> { } fn visit_macro_def(&mut self, md: &'tcx hir::MacroDef) { - if md.imported_from.is_none() { - self.annotate(md.id, &md.attrs, md.span, AnnotationKind::Required, |_| {}); - } + self.annotate(md.id, &md.attrs, md.span, AnnotationKind::Required, |_| {}); } } @@ -373,9 +371,7 @@ impl<'a, 'tcx> Visitor<'tcx> for MissingStabilityAnnotations<'a, 'tcx> { } fn visit_macro_def(&mut self, md: &'tcx hir::MacroDef) { - if md.imported_from.is_none() { - self.check_missing_stability(md.id, md.span); - } + self.check_missing_stability(md.id, md.span); } } diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index 1a1bb1432eec1..ac830318ce9a3 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -418,8 +418,6 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { ident: ast::Ident::with_empty_ctxt(name), id: ast::DUMMY_NODE_ID, span: local_span, - imported_from: None, // FIXME - allow_internal_unstable: attr::contains_name(&attrs, "allow_internal_unstable"), attrs: attrs, body: body, }) diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index b2e31d5490962..5e356878ba800 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -20,6 +20,7 @@ use rustc::ty; use std::cell::Cell; use std::rc::Rc; use syntax::ast::{self, Name, Ident}; +use syntax::attr; use syntax::errors::DiagnosticBuilder; use syntax::ext::base::{self, Determinacy, MultiModifier, MultiDecorator}; use syntax::ext::base::{NormalTT, SyntaxExtension}; @@ -138,7 +139,7 @@ impl<'a> base::Resolver for Resolver<'a> { invocation.expansion.set(visitor.legacy_scope); } - fn add_macro(&mut self, scope: Mark, mut def: ast::MacroDef, export: bool) { + fn add_macro(&mut self, scope: Mark, mut def: ast::MacroDef) { if def.ident.name == "macro_rules" { self.session.span_err(def.span, "user-defined macros may not be named `macro_rules`"); } @@ -153,7 +154,7 @@ impl<'a> base::Resolver for Resolver<'a> { invocation.legacy_scope.set(LegacyScope::Binding(binding)); self.macro_names.insert(def.ident.name); - if export { + if attr::contains_name(&def.attrs, "macro_export") { def.id = self.next_node_id(); DefCollector::new(&mut self.definitions).with_parent(CRATE_DEF_INDEX, |collector| { collector.visit_macro_def(&def) diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index 4087b9a761f97..e5410c6341f84 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -201,6 +201,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { if def_id.krate == LOCAL_CRATE { continue // These are `krate.exported_macros`, handled in `self.visit()`. } + let imported_from = self.cx.sess().cstore.original_crate_name(def_id.krate); let def = match self.cx.sess().cstore.load_macro(def_id, self.cx.sess()) { LoadedMacro::MacroRules(macro_rules) => macro_rules, // FIXME(jseyfried): document proc macro reexports @@ -217,7 +218,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { matchers: matchers, stab: self.stability(def.id), depr: self.deprecation(def.id), - imported_from: def.imported_from.map(|ident| ident.name), + imported_from: Some(imported_from), }) } } @@ -525,7 +526,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { matchers: matchers, stab: self.stability(def.id), depr: self.deprecation(def.id), - imported_from: def.imported_from, + imported_from: None, } } } diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 2369cc5714ec1..39d78cd87761e 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -1972,8 +1972,6 @@ pub struct MacroDef { pub attrs: Vec, pub id: NodeId, pub span: Span, - pub imported_from: Option, - pub allow_internal_unstable: bool, pub body: Vec, } diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index ddbca47429d18..508c5eaed8cc1 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -520,7 +520,7 @@ pub trait Resolver { fn eliminate_crate_var(&mut self, item: P) -> P; fn visit_expansion(&mut self, mark: Mark, expansion: &Expansion); - fn add_macro(&mut self, scope: Mark, def: ast::MacroDef, export: bool); + fn add_macro(&mut self, scope: Mark, def: ast::MacroDef); fn add_ext(&mut self, ident: ast::Ident, ext: Rc); fn add_expansions_at_stmt(&mut self, id: ast::NodeId, macros: Vec); @@ -544,7 +544,7 @@ impl Resolver for DummyResolver { fn eliminate_crate_var(&mut self, item: P) -> P { item } fn visit_expansion(&mut self, _invoc: Mark, _expansion: &Expansion) {} - fn add_macro(&mut self, _scope: Mark, _def: ast::MacroDef, _export: bool) {} + fn add_macro(&mut self, _scope: Mark, _def: ast::MacroDef) {} fn add_ext(&mut self, _ident: ast::Ident, _ext: Rc) {} fn add_expansions_at_stmt(&mut self, _id: ast::NodeId, _macros: Vec) {} diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index ca18e580ecdfb..5a028594a2158 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -160,14 +160,11 @@ impl IdentMacroExpander for MacroRulesExpander { tts: Vec, attrs: Vec) -> Box { - let export = attr::contains_name(&attrs, "macro_export"); let def = ast::MacroDef { ident: ident, id: ast::DUMMY_NODE_ID, span: span, - imported_from: None, body: tts, - allow_internal_unstable: attr::contains_name(&attrs, "allow_internal_unstable"), attrs: attrs, }; @@ -178,7 +175,7 @@ impl IdentMacroExpander for MacroRulesExpander { MacEager::items(placeholders::macro_scope_placeholder().make_items()) }; - cx.resolver.add_macro(cx.current_expansion.mark, def, export); + cx.resolver.add_macro(cx.current_expansion.mark, def); result } } @@ -282,7 +279,7 @@ pub fn compile(sess: &ParseSess, def: &ast::MacroDef) -> SyntaxExtension { valid: valid, }); - NormalTT(exp, Some(def.span), def.allow_internal_unstable) + NormalTT(exp, Some(def.span), attr::contains_name(&def.attrs, "allow_internal_unstable")) } fn check_lhs_nt_follows(sess: &ParseSess, lhs: &TokenTree) -> bool { diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 3e0353d532d88..c1391d0b1c2f1 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -178,7 +178,6 @@ pub fn walk_crate<'a, V: Visitor<'a>>(visitor: &mut V, krate: &'a Crate) { pub fn walk_macro_def<'a, V: Visitor<'a>>(visitor: &mut V, macro_def: &'a MacroDef) { visitor.visit_ident(macro_def.span, macro_def.ident); - walk_opt_ident(visitor, macro_def.span, macro_def.imported_from); walk_list!(visitor, visit_attribute, ¯o_def.attrs); } From 421c5d11c1b4bb591bb429577c7b89cba59acefa Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Thu, 1 Dec 2016 11:20:04 +0000 Subject: [PATCH 46/73] Remove scope placeholders, remove method `add_macro` of `ext::base::Resolver`. --- src/librustc_resolve/build_reduced_graph.rs | 10 ++- src/librustc_resolve/macros.rs | 75 ++++++++++++--------- src/libsyntax/ext/base.rs | 2 - src/libsyntax/ext/expand.rs | 37 +++++----- src/libsyntax/ext/placeholders.rs | 50 ++++---------- src/libsyntax/ext/tt/macro_rules.rs | 34 +--------- src/libsyntax_ext/lib.rs | 5 +- 7 files changed, 91 insertions(+), 122 deletions(-) diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 02a4d8db0955a..9f85580b93ef8 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -697,9 +697,13 @@ impl<'a, 'b> Visitor<'a> for BuildReducedGraphVisitor<'a, 'b> { fn visit_item(&mut self, item: &'a Item) { let macro_use = match item.node { - ItemKind::Mac(..) if item.id == ast::DUMMY_NODE_ID => return, // Scope placeholder - ItemKind::Mac(..) => { - return self.legacy_scope = LegacyScope::Expansion(self.visit_invoc(item.id)); + ItemKind::Mac(ref mac) => { + if mac.node.path.segments.is_empty() { + self.legacy_scope = LegacyScope::Expansion(self.visit_invoc(item.id)); + } else { + self.resolver.define_macro(item, &mut self.legacy_scope); + } + return } ItemKind::Mod(..) => self.resolver.contains_macro_use(&item.attrs), _ => false, diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 5e356878ba800..ce92a4446f920 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -23,8 +23,8 @@ use syntax::ast::{self, Name, Ident}; use syntax::attr; use syntax::errors::DiagnosticBuilder; use syntax::ext::base::{self, Determinacy, MultiModifier, MultiDecorator}; -use syntax::ext::base::{NormalTT, SyntaxExtension}; -use syntax::ext::expand::Expansion; +use syntax::ext::base::{NormalTT, Resolver as SyntaxResolver, SyntaxExtension}; +use syntax::ext::expand::{Expansion, mark_tts}; use syntax::ext::hygiene::Mark; use syntax::ext::tt::macro_rules; use syntax::feature_gate::{emit_feature_err, GateIssue}; @@ -139,34 +139,6 @@ impl<'a> base::Resolver for Resolver<'a> { invocation.expansion.set(visitor.legacy_scope); } - fn add_macro(&mut self, scope: Mark, mut def: ast::MacroDef) { - if def.ident.name == "macro_rules" { - self.session.span_err(def.span, "user-defined macros may not be named `macro_rules`"); - } - - let invocation = self.invocations[&scope]; - let binding = self.arenas.alloc_legacy_binding(LegacyBinding { - parent: Cell::new(invocation.legacy_scope.get()), - name: def.ident.name, - ext: Rc::new(macro_rules::compile(&self.session.parse_sess, &def)), - span: def.span, - }); - invocation.legacy_scope.set(LegacyScope::Binding(binding)); - self.macro_names.insert(def.ident.name); - - if attr::contains_name(&def.attrs, "macro_export") { - def.id = self.next_node_id(); - DefCollector::new(&mut self.definitions).with_parent(CRATE_DEF_INDEX, |collector| { - collector.visit_macro_def(&def) - }); - self.macro_exports.push(Export { - name: def.ident.name, - def: Def::Macro(self.definitions.local_def_id(def.id)), - }); - self.exported_macros.push(def); - } - } - fn add_ext(&mut self, ident: ast::Ident, ext: Rc) { if let NormalTT(..) = *ext { self.macro_names.insert(ident.name); @@ -444,4 +416,47 @@ impl<'a> Resolver<'a> { expansion.visit_with(def_collector) }); } + + pub fn define_macro(&mut self, item: &ast::Item, legacy_scope: &mut LegacyScope<'a>) { + let tts = match item.node { + ast::ItemKind::Mac(ref mac) => &mac.node.tts, + _ => unreachable!(), + }; + + if item.ident.name == "macro_rules" { + self.session.span_err(item.span, "user-defined macros may not be named `macro_rules`"); + } + + let mark = Mark::from_placeholder_id(item.id); + let invocation = self.invocations[&mark]; + invocation.module.set(self.current_module); + + let mut def = ast::MacroDef { + ident: item.ident, + attrs: item.attrs.clone(), + id: ast::DUMMY_NODE_ID, + span: item.span, + body: mark_tts(tts, mark), + }; + + *legacy_scope = LegacyScope::Binding(self.arenas.alloc_legacy_binding(LegacyBinding { + parent: Cell::new(*legacy_scope), + name: def.ident.name, + ext: Rc::new(macro_rules::compile(&self.session.parse_sess, &def)), + span: def.span, + })); + self.macro_names.insert(def.ident.name); + + if attr::contains_name(&def.attrs, "macro_export") { + def.id = self.next_node_id(); + DefCollector::new(&mut self.definitions).with_parent(CRATE_DEF_INDEX, |collector| { + collector.visit_macro_def(&def) + }); + self.macro_exports.push(Export { + name: def.ident.name, + def: Def::Macro(self.definitions.local_def_id(def.id)), + }); + self.exported_macros.push(def); + } + } } diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 508c5eaed8cc1..f9364f39ab768 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -520,7 +520,6 @@ pub trait Resolver { fn eliminate_crate_var(&mut self, item: P) -> P; fn visit_expansion(&mut self, mark: Mark, expansion: &Expansion); - fn add_macro(&mut self, scope: Mark, def: ast::MacroDef); fn add_ext(&mut self, ident: ast::Ident, ext: Rc); fn add_expansions_at_stmt(&mut self, id: ast::NodeId, macros: Vec); @@ -544,7 +543,6 @@ impl Resolver for DummyResolver { fn eliminate_crate_var(&mut self, item: P) -> P { item } fn visit_expansion(&mut self, _invoc: Mark, _expansion: &Expansion) {} - fn add_macro(&mut self, _scope: Mark, _def: ast::MacroDef) {} fn add_ext(&mut self, _ident: ast::Ident, _ext: Rc) {} fn add_expansions_at_stmt(&mut self, _id: ast::NodeId, _macros: Vec) {} diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 19545e2e642b1..05501b5434a14 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -392,14 +392,6 @@ impl<'a, 'b> MacroExpander<'a, 'b> { }; let Mac_ { path, tts, .. } = mac.node; - // Detect use of feature-gated or invalid attributes on macro invoations - // since they will not be detected after macro expansion. - for attr in attrs.iter() { - feature_gate::check_attribute(&attr, &self.cx.parse_sess, - &self.cx.parse_sess.codemap(), - &self.cx.ecfg.features.unwrap()); - } - let extname = path.segments.last().unwrap().identifier.name; let ident = ident.unwrap_or(keywords::Invalid.ident()); let marked_tts = mark_tts(&tts, mark); @@ -601,6 +593,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { fn collect_bang( &mut self, mac: ast::Mac, attrs: Vec, span: Span, kind: ExpansionKind, ) -> Expansion { + self.check_attributes(&attrs); self.collect(kind, InvocationKind::Bang { attrs: attrs, mac: mac, ident: None, span: span }) } @@ -622,6 +615,16 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { fn configure(&mut self, node: T) -> Option { self.cfg.configure(node) } + + // Detect use of feature-gated or invalid attributes on macro invocations + // since they will not be detected after macro expansion. + fn check_attributes(&mut self, attrs: &[ast::Attribute]) { + let codemap = &self.cx.parse_sess.codemap(); + let features = self.cx.ecfg.features.unwrap(); + for attr in attrs.iter() { + feature_gate::check_attribute(&attr, &self.cx.parse_sess, codemap, features); + } + } } // These are pretty nasty. Ideally, we would keep the tokens around, linked from @@ -740,14 +743,18 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> { match item.node { ast::ItemKind::Mac(..) => { - if match item.node { - ItemKind::Mac(ref mac) => mac.node.path.segments.is_empty(), - _ => unreachable!(), - } { - return SmallVector::one(item); - } + self.check_attributes(&item.attrs); + let is_macro_def = if let ItemKind::Mac(ref mac) = item.node { + mac.node.path.segments[0].identifier.name == "macro_rules" + } else { + unreachable!() + }; - item.and_then(|item| match item.node { + item.and_then(|mut item| match item.node { + ItemKind::Mac(_) if is_macro_def => { + item.id = ast::NodeId::from_u32(Mark::fresh().as_u32()); + SmallVector::one(P(item)) + } ItemKind::Mac(mac) => { self.collect(ExpansionKind::Items, InvocationKind::Bang { mac: mac, diff --git a/src/libsyntax/ext/placeholders.rs b/src/libsyntax/ext/placeholders.rs index 4fe57a8345e94..eb4b6144c8d28 100644 --- a/src/libsyntax/ext/placeholders.rs +++ b/src/libsyntax/ext/placeholders.rs @@ -12,9 +12,10 @@ use ast; use codemap::{DUMMY_SP, dummy_spanned}; use ext::base::ExtCtxt; use ext::expand::{Expansion, ExpansionKind}; +use ext::hygiene::Mark; use fold::*; use ptr::P; -use symbol::{Symbol, keywords}; +use symbol::keywords; use util::move_map::MoveMap; use util::small_vector::SmallVector; @@ -68,10 +69,6 @@ pub fn placeholder(kind: ExpansionKind, id: ast::NodeId) -> Expansion { } } -pub fn macro_scope_placeholder() -> Expansion { - placeholder(ExpansionKind::Items, ast::DUMMY_NODE_ID) -} - pub struct PlaceholderExpander<'a, 'b: 'a> { expansions: HashMap, cx: &'a mut ExtCtxt<'b>, @@ -100,11 +97,12 @@ impl<'a, 'b> PlaceholderExpander<'a, 'b> { impl<'a, 'b> Folder for PlaceholderExpander<'a, 'b> { fn fold_item(&mut self, item: P) -> SmallVector> { match item.node { - // Scope placeholder - ast::ItemKind::Mac(_) if item.id == ast::DUMMY_NODE_ID => SmallVector::one(item), - ast::ItemKind::Mac(_) => self.remove(item.id).make_items(), - _ => noop_fold_item(item, self), + ast::ItemKind::Mac(ref mac) if !mac.node.path.segments.is_empty() => {} + ast::ItemKind::Mac(_) => return self.remove(item.id).make_items(), + _ => {} } + + noop_fold_item(item, self) } fn fold_trait_item(&mut self, item: ast::TraitItem) -> SmallVector { @@ -172,10 +170,10 @@ impl<'a, 'b> Folder for PlaceholderExpander<'a, 'b> { block.stmts = block.stmts.move_flat_map(|mut stmt| { remaining_stmts -= 1; - // Scope placeholder + // `macro_rules!` macro definition if let ast::StmtKind::Item(ref item) = stmt.node { - if let ast::ItemKind::Mac(..) = item.node { - macros.push(item.ident.ctxt.data().outer_mark); + if let ast::ItemKind::Mac(_) = item.node { + macros.push(Mark::from_placeholder_id(item.id)); return None; } } @@ -208,33 +206,13 @@ impl<'a, 'b> Folder for PlaceholderExpander<'a, 'b> { fn fold_mod(&mut self, module: ast::Mod) -> ast::Mod { let mut module = noop_fold_mod(module, self); module.items = module.items.move_flat_map(|item| match item.node { - ast::ItemKind::Mac(_) => None, // remove scope placeholders from modules + ast::ItemKind::Mac(_) if !self.cx.ecfg.keep_macs => None, // remove macro definitions _ => Some(item), }); module } -} -pub fn reconstructed_macro_rules(def: &ast::MacroDef) -> Expansion { - Expansion::Items(SmallVector::one(P(ast::Item { - ident: def.ident, - attrs: def.attrs.clone(), - id: ast::DUMMY_NODE_ID, - node: ast::ItemKind::Mac(ast::Mac { - span: def.span, - node: ast::Mac_ { - path: ast::Path { - span: DUMMY_SP, - global: false, - segments: vec![ast::PathSegment { - identifier: ast::Ident::with_empty_ctxt(Symbol::intern("macro_rules")), - parameters: ast::PathParameters::none(), - }], - }, - tts: def.body.clone(), - } - }), - vis: ast::Visibility::Inherited, - span: def.span, - }))) + fn fold_mac(&mut self, mac: ast::Mac) -> ast::Mac { + mac + } } diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index 5a028594a2158..3abd24b50ba9a 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -10,10 +10,9 @@ use {ast, attr}; use syntax_pos::{Span, DUMMY_SP}; -use ext::base::{DummyResult, ExtCtxt, MacEager, MacResult, SyntaxExtension}; -use ext::base::{IdentMacroExpander, NormalTT, TTMacroExpander}; +use ext::base::{DummyResult, ExtCtxt, MacResult, SyntaxExtension}; +use ext::base::{NormalTT, TTMacroExpander}; use ext::expand::{Expansion, ExpansionKind}; -use ext::placeholders; use ext::tt::macro_parser::{Success, Error, Failure}; use ext::tt::macro_parser::{MatchedSeq, MatchedNonterminal}; use ext::tt::macro_parser::{parse, parse_failure_msg}; @@ -151,35 +150,6 @@ fn generic_extension<'cx>(cx: &'cx ExtCtxt, cx.span_fatal(best_fail_spot.substitute_dummy(sp), &best_fail_msg); } -pub struct MacroRulesExpander; -impl IdentMacroExpander for MacroRulesExpander { - fn expand(&self, - cx: &mut ExtCtxt, - span: Span, - ident: ast::Ident, - tts: Vec, - attrs: Vec) - -> Box { - let def = ast::MacroDef { - ident: ident, - id: ast::DUMMY_NODE_ID, - span: span, - body: tts, - attrs: attrs, - }; - - // If keep_macs is true, expands to a MacEager::items instead. - let result = if cx.ecfg.keep_macs { - MacEager::items(placeholders::reconstructed_macro_rules(&def).make_items()) - } else { - MacEager::items(placeholders::macro_scope_placeholder().make_items()) - }; - - cx.resolver.add_macro(cx.current_expansion.mark, def); - result - } -} - // Note that macro-by-example's input is also matched against a token tree: // $( $lhs:tt => $rhs:tt );+ // diff --git a/src/libsyntax_ext/lib.rs b/src/libsyntax_ext/lib.rs index 66d6c0570ace7..e31b29d5cc1b4 100644 --- a/src/libsyntax_ext/lib.rs +++ b/src/libsyntax_ext/lib.rs @@ -50,8 +50,7 @@ pub mod deriving; use std::rc::Rc; use syntax::ast; -use syntax::ext::base::{MacroExpanderFn, NormalTT, IdentTT, MultiModifier, NamedSyntaxExtension}; -use syntax::ext::tt::macro_rules::MacroRulesExpander; +use syntax::ext::base::{MacroExpanderFn, NormalTT, MultiModifier, NamedSyntaxExtension}; use syntax::symbol::Symbol; pub fn register_builtins(resolver: &mut syntax::ext::base::Resolver, @@ -61,8 +60,6 @@ pub fn register_builtins(resolver: &mut syntax::ext::base::Resolver, resolver.add_ext(ast::Ident::with_empty_ctxt(name), Rc::new(ext)); }; - register(Symbol::intern("macro_rules"), IdentTT(Box::new(MacroRulesExpander), None, false)); - macro_rules! register { ($( $name:ident: $f:expr, )*) => { $( register(Symbol::intern(stringify!($name)), From 6f040b48ef3f8bce0706d838f5672ca8a3e07880 Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Thu, 1 Dec 2016 11:54:01 +0000 Subject: [PATCH 47/73] Avoid including attributes in bang macro invocations. --- src/libsyntax/ext/base.rs | 6 ++---- src/libsyntax/ext/expand.rs | 38 +++++++++++++++++-------------------- 2 files changed, 19 insertions(+), 25 deletions(-) diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index f9364f39ab768..8e63f73fdaa7a 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -217,8 +217,7 @@ pub trait IdentMacroExpander { cx: &'cx mut ExtCtxt, sp: Span, ident: ast::Ident, - token_tree: Vec, - attrs: Vec) + token_tree: Vec) -> Box; } @@ -234,8 +233,7 @@ impl IdentMacroExpander for F cx: &'cx mut ExtCtxt, sp: Span, ident: ast::Ident, - token_tree: Vec, - _attrs: Vec) + token_tree: Vec) -> Box { (*self)(cx, sp, ident, token_tree) diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 05501b5434a14..e6782884f384e 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -158,7 +158,6 @@ pub struct Invocation { pub enum InvocationKind { Bang { - attrs: Vec, mac: ast::Mac, ident: Option, span: Span, @@ -386,8 +385,8 @@ impl<'a, 'b> MacroExpander<'a, 'b> { /// Expand a macro invocation. Returns the result of expansion. fn expand_bang_invoc(&mut self, invoc: Invocation, ext: Rc) -> Expansion { let (mark, kind) = (invoc.expansion_data.mark, invoc.expansion_kind); - let (attrs, mac, ident, span) = match invoc.kind { - InvocationKind::Bang { attrs, mac, ident, span } => (attrs, mac, ident, span), + let (mac, ident, span) = match invoc.kind { + InvocationKind::Bang { mac, ident, span } => (mac, ident, span), _ => unreachable!(), }; let Mac_ { path, tts, .. } = mac.node; @@ -432,7 +431,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { } }); - kind.make_from(expander.expand(self.cx, span, ident, marked_tts, attrs)) + kind.make_from(expander.expand(self.cx, span, ident, marked_tts)) } MultiDecorator(..) | MultiModifier(..) | SyntaxExtension::AttrProcMacro(..) => { @@ -590,11 +589,8 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { placeholder(expansion_kind, ast::NodeId::from_u32(mark.as_u32())) } - fn collect_bang( - &mut self, mac: ast::Mac, attrs: Vec, span: Span, kind: ExpansionKind, - ) -> Expansion { - self.check_attributes(&attrs); - self.collect(kind, InvocationKind::Bang { attrs: attrs, mac: mac, ident: None, span: span }) + fn collect_bang(&mut self, mac: ast::Mac, span: Span, kind: ExpansionKind) -> Expansion { + self.collect(kind, InvocationKind::Bang { mac: mac, ident: None, span: span }) } fn collect_attr(&mut self, attr: ast::Attribute, item: Annotatable, kind: ExpansionKind) @@ -663,7 +659,8 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> { expr.node = self.cfg.configure_expr_kind(expr.node); if let ast::ExprKind::Mac(mac) = expr.node { - self.collect_bang(mac, expr.attrs.into(), expr.span, ExpansionKind::Expr).make_expr() + self.check_attributes(&expr.attrs); + self.collect_bang(mac, expr.span, ExpansionKind::Expr).make_expr() } else { P(noop_fold_expr(expr, self)) } @@ -674,8 +671,8 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> { expr.node = self.cfg.configure_expr_kind(expr.node); if let ast::ExprKind::Mac(mac) = expr.node { - self.collect_bang(mac, expr.attrs.into(), expr.span, ExpansionKind::OptExpr) - .make_opt_expr() + self.check_attributes(&expr.attrs); + self.collect_bang(mac, expr.span, ExpansionKind::OptExpr).make_opt_expr() } else { Some(P(noop_fold_expr(expr, self))) } @@ -688,8 +685,7 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> { } pat.and_then(|pat| match pat.node { - PatKind::Mac(mac) => - self.collect_bang(mac, Vec::new(), pat.span, ExpansionKind::Pat).make_pat(), + PatKind::Mac(mac) => self.collect_bang(mac, pat.span, ExpansionKind::Pat).make_pat(), _ => unreachable!(), }) } @@ -710,8 +706,8 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> { }).collect() }; - let mut placeholder = - self.collect_bang(mac, attrs.into(), stmt.span, ExpansionKind::Stmts).make_stmts(); + self.check_attributes(&attrs); + let mut placeholder = self.collect_bang(mac, stmt.span, ExpansionKind::Stmts).make_stmts(); // If this is a macro invocation with a semicolon, then apply that // semicolon to the final statement produced by expansion. @@ -758,7 +754,6 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> { ItemKind::Mac(mac) => { self.collect(ExpansionKind::Items, InvocationKind::Bang { mac: mac, - attrs: item.attrs, ident: Some(item.ident), span: item.span, }).make_items() @@ -830,7 +825,8 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> { match item.node { ast::TraitItemKind::Macro(mac) => { let ast::TraitItem { attrs, span, .. } = item; - self.collect_bang(mac, attrs, span, ExpansionKind::TraitItems).make_trait_items() + self.check_attributes(&attrs); + self.collect_bang(mac, span, ExpansionKind::TraitItems).make_trait_items() } _ => fold::noop_fold_trait_item(item, self), } @@ -848,7 +844,8 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> { match item.node { ast::ImplItemKind::Macro(mac) => { let ast::ImplItem { attrs, span, .. } = item; - self.collect_bang(mac, attrs, span, ExpansionKind::ImplItems).make_impl_items() + self.check_attributes(&attrs); + self.collect_bang(mac, span, ExpansionKind::ImplItems).make_impl_items() } _ => fold::noop_fold_impl_item(item, self), } @@ -861,8 +858,7 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> { }; match ty.node { - ast::TyKind::Mac(mac) => - self.collect_bang(mac, Vec::new(), ty.span, ExpansionKind::Ty).make_ty(), + ast::TyKind::Mac(mac) => self.collect_bang(mac, ty.span, ExpansionKind::Ty).make_ty(), _ => unreachable!(), } } From 745ddf2aa78e4515d6a41e34a301d97afbde33ba Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Thu, 1 Dec 2016 22:49:32 +0000 Subject: [PATCH 48/73] Refactor out `mark.as_placeholder_id()`. --- src/libsyntax/ext/expand.rs | 8 ++++---- src/libsyntax/ext/hygiene.rs | 6 +++++- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index e6782884f384e..5d62175fbf23a 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -275,7 +275,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { if expansions.len() < depth { expansions.push(Vec::new()); } - expansions[depth - 1].push((mark.as_u32(), expansion)); + expansions[depth - 1].push((mark, expansion)); if !self.cx.ecfg.single_step { invocations.extend(new_invocations.into_iter().rev()); } @@ -286,7 +286,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { let mut placeholder_expander = PlaceholderExpander::new(self.cx, self.monotonic); while let Some(expansions) = expansions.pop() { for (mark, expansion) in expansions.into_iter().rev() { - placeholder_expander.add(ast::NodeId::from_u32(mark), expansion); + placeholder_expander.add(mark.as_placeholder_id(), expansion); } } @@ -586,7 +586,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { ..self.cx.current_expansion.clone() }, }); - placeholder(expansion_kind, ast::NodeId::from_u32(mark.as_u32())) + placeholder(expansion_kind, mark.as_placeholder_id()) } fn collect_bang(&mut self, mac: ast::Mac, span: Span, kind: ExpansionKind) -> Expansion { @@ -748,7 +748,7 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> { item.and_then(|mut item| match item.node { ItemKind::Mac(_) if is_macro_def => { - item.id = ast::NodeId::from_u32(Mark::fresh().as_u32()); + item.id = Mark::fresh().as_placeholder_id(); SmallVector::one(P(item)) } ItemKind::Mac(mac) => { diff --git a/src/libsyntax/ext/hygiene.rs b/src/libsyntax/ext/hygiene.rs index 8842cb55b1ea5..2af5c2ea9995e 100644 --- a/src/libsyntax/ext/hygiene.rs +++ b/src/libsyntax/ext/hygiene.rs @@ -51,7 +51,11 @@ impl Mark { Mark(id.as_u32()) } - pub fn as_u32(&self) -> u32 { + pub fn as_placeholder_id(self) -> NodeId { + NodeId::from_u32(self.0) + } + + pub fn as_u32(self) -> u32 { self.0 } } From dcae8bfb409c6b4f67b57a52b36bcecd4eafa3a4 Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Tue, 6 Dec 2016 06:25:41 +0000 Subject: [PATCH 49/73] Give extern crates' root modules a better name. --- src/librustc_resolve/build_reduced_graph.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 9f85580b93ef8..cd2a276797914 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -490,12 +490,13 @@ impl<'a> Resolver<'a> { fn get_extern_crate_root(&mut self, cnum: CrateNum) -> Module<'a> { let def_id = DefId { krate: cnum, index: CRATE_DEF_INDEX }; + let name = self.session.cstore.crate_name(cnum); let macros_only = self.session.cstore.dep_kind(cnum).macros_only(); let arenas = self.arenas; *self.extern_crate_roots.entry((cnum, macros_only)).or_insert_with(|| { arenas.alloc_module(ModuleData { populated: Cell::new(false), - ..ModuleData::new(None, ModuleKind::Def(Def::Mod(def_id), keywords::Invalid.name())) + ..ModuleData::new(None, ModuleKind::Def(Def::Mod(def_id), name)) }) }) } From bd85a6dbe71807774764e52600aa5429ac878b1d Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Sun, 18 Dec 2016 22:25:46 -0500 Subject: [PATCH 50/73] target spec: add an asm-args field to pass arguments to the external .. assembler --- src/librustc_back/target/mod.rs | 6 ++++++ src/librustc_trans/back/write.rs | 4 ++++ 2 files changed, 10 insertions(+) diff --git a/src/librustc_back/target/mod.rs b/src/librustc_back/target/mod.rs index 351d469ea2809..13333be66f570 100644 --- a/src/librustc_back/target/mod.rs +++ b/src/librustc_back/target/mod.rs @@ -267,6 +267,9 @@ pub struct TargetOptions { /// user-defined libraries. pub post_link_args: Vec, + /// Extra arguments to pass to the external assembler (when used) + pub asm_args: Vec, + /// Default CPU to pass to LLVM. Corresponds to `llc -mcpu=$cpu`. Defaults /// to "generic". pub cpu: String, @@ -394,6 +397,7 @@ impl Default for TargetOptions { ar: option_env!("CFG_DEFAULT_AR").unwrap_or("ar").to_string(), pre_link_args: Vec::new(), post_link_args: Vec::new(), + asm_args: Vec::new(), cpu: "generic".to_string(), features: "".to_string(), dynamic_linking: false, @@ -561,6 +565,7 @@ impl Target { key!(late_link_args, list); key!(post_link_objects, list); key!(post_link_args, list); + key!(asm_args, list); key!(cpu); key!(features); key!(dynamic_linking, bool); @@ -723,6 +728,7 @@ impl ToJson for Target { target_option_val!(late_link_args); target_option_val!(post_link_objects); target_option_val!(post_link_args); + target_option_val!(asm_args); target_option_val!(cpu); target_option_val!(features); target_option_val!(dynamic_linking); diff --git a/src/librustc_trans/back/write.rs b/src/librustc_trans/back/write.rs index ffab0bde7abde..de8814f143e04 100644 --- a/src/librustc_trans/back/write.rs +++ b/src/librustc_trans/back/write.rs @@ -1085,6 +1085,10 @@ fn run_work_multithreaded(sess: &Session, pub fn run_assembler(sess: &Session, outputs: &OutputFilenames) { let (pname, mut cmd, _) = get_linker(sess); + for arg in &sess.target.target.options.asm_args { + cmd.arg(arg); + } + cmd.arg("-c").arg("-o").arg(&outputs.path(OutputType::Object)) .arg(&outputs.temp_path(OutputType::Assembly, None)); debug!("{:?}", cmd); From 5049ad22ec3fff948ed6e568336e055402b5a246 Mon Sep 17 00:00:00 2001 From: Clar Charr Date: Fri, 2 Dec 2016 12:18:01 -0500 Subject: [PATCH 51/73] From<[u16; 8]> for Ipv6Addr. --- src/libstd/net/ip.rs | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/src/libstd/net/ip.rs b/src/libstd/net/ip.rs index c1e610f33fb70..6aab7486004f8 100644 --- a/src/libstd/net/ip.rs +++ b/src/libstd/net/ip.rs @@ -1068,6 +1068,14 @@ impl From<[u8; 16]> for Ipv6Addr { } } +#[stable(feature = "ipv6_from_segments", since = "1.15.0")] +impl From<[u16; 8]> for Ipv6Addr { + fn from(segments: [u16; 8]) -> Ipv6Addr { + let [a, b, c, d, e, f, g, h] = segments; + Ipv6Addr::new(a, b, c, d, e, f, g, h) + } +} + // Tests for this module #[cfg(all(test, not(target_os = "emscripten")))] mod tests { @@ -1413,10 +1421,28 @@ mod tests { } #[test] - fn ipv4_from_u32_slice() { + fn ipv4_from_octets() { assert_eq!(Ipv4Addr::from([127, 0, 0, 1]), Ipv4Addr::new(127, 0, 0, 1)) } + #[test] + fn ipv6_from_segments() { + let from_u16s = Ipv6Addr::from([0x0011, 0x2233, 0x4455, 0x6677, + 0x8899, 0xaabb, 0xccdd, 0xeeff]); + let new = Ipv6Addr::new(0x0011, 0x2233, 0x4455, 0x6677, + 0x8899, 0xaabb, 0xccdd, 0xeeff); + assert_eq!(new, from_u16s); + } + + #[test] + fn ipv6_from_octets() { + let from_u16s = Ipv6Addr::from([0x0011, 0x2233, 0x4455, 0x6677, + 0x8899, 0xaabb, 0xccdd, 0xeeff]); + let from_u8s = Ipv6Addr::from([0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff]); + assert_eq!(from_u16s, from_u8s); + } + #[test] fn ord() { assert!(Ipv4Addr::new(100, 64, 3, 3) < Ipv4Addr::new(192, 0, 2, 2)); From 3a82b0da3d501f5b7f532e26b4738ac0e53fab13 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Mon, 19 Dec 2016 14:24:33 -0500 Subject: [PATCH 52/73] Don't try get local DefId of imported macro in rustdoc. --- src/librustdoc/clean/mod.rs | 2 +- src/librustdoc/doctree.rs | 4 +++- src/librustdoc/visit_ast.rs | 8 ++++---- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 28ca92f5db6f6..123516dc89d74 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2801,7 +2801,7 @@ impl Clean for doctree::Macro { visibility: Some(Public), stability: self.stab.clean(cx), deprecation: self.depr.clean(cx), - def_id: cx.tcx.map.local_def_id(self.id), + def_id: self.def_id, inner: MacroItem(Macro { source: format!("macro_rules! {} {{\n{}}}", name, diff --git a/src/librustdoc/doctree.rs b/src/librustdoc/doctree.rs index 21fc135eaadae..31e10fbd3b7d3 100644 --- a/src/librustdoc/doctree.rs +++ b/src/librustdoc/doctree.rs @@ -233,9 +233,11 @@ pub struct DefaultImpl { pub whence: Span, } +// For Macro we store the DefId instead of the NodeId, since we also create +// these imported macro_rules (which only have a DUMMY_NODE_ID). pub struct Macro { pub name: Name, - pub id: ast::NodeId, + pub def_id: hir::def_id::DefId, pub attrs: hir::HirVec, pub whence: Span, pub matchers: hir::HirVec, diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index 4087b9a761f97..29e874c5ab526 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -85,7 +85,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { None); // attach the crate's exported macros to the top-level module: let macro_exports: Vec<_> = - krate.exported_macros.iter().map(|def| self.visit_macro(def)).collect(); + krate.exported_macros.iter().map(|def| self.visit_local_macro(def)).collect(); self.module.macros.extend(macro_exports); self.module.is_crate = true; } @@ -210,7 +210,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { // FIXME(jseyfried) merge with `self.visit_macro()` let matchers = def.body.chunks(4).map(|arm| arm[0].get_span()).collect(); om.macros.push(Macro { - id: def.id, + def_id: def_id, attrs: def.attrs.clone().into(), name: def.ident.name, whence: def.span, @@ -513,12 +513,12 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { } // convert each exported_macro into a doc item - fn visit_macro(&self, def: &hir::MacroDef) -> Macro { + fn visit_local_macro(&self, def: &hir::MacroDef) -> Macro { // Extract the spans of all matchers. They represent the "interface" of the macro. let matchers = def.body.chunks(4).map(|arm| arm[0].get_span()).collect(); Macro { - id: def.id, + def_id: self.cx.tcx.map.local_def_id(def.id), attrs: def.attrs.clone(), name: def.name, whence: def.span, From 488359eba184ed8b7a58f30c9ce24e13e2af394c Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 19 Dec 2016 11:40:36 -0800 Subject: [PATCH 53/73] travis: Fix the cargotest bot Recently the Cargo revision running on cargotest was updated in #38051, and the updated version of Cargo pulls in the openssl-sys 0.9 crate instead of the old openssl-sys 0.7 crate. The 0.9 release of openssl-sys has slightly different requirements and logic for detecting OpenSSL, namely it requires `pkg-config` to be present on Linux typically. This commit fixes this problem by installing pkg-config in the cargotest container that's running on the bots. This in turn should hopefully fix the build script and allow it to find the already-installed local OpenSSL libraries. --- src/ci/docker/x86_64-gnu-cargotest/Dockerfile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ci/docker/x86_64-gnu-cargotest/Dockerfile b/src/ci/docker/x86_64-gnu-cargotest/Dockerfile index 0d9835e86d2a7..2c3db87d9fb1f 100644 --- a/src/ci/docker/x86_64-gnu-cargotest/Dockerfile +++ b/src/ci/docker/x86_64-gnu-cargotest/Dockerfile @@ -12,7 +12,8 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ ccache \ libssl-dev \ sudo \ - xz-utils + xz-utils \ + pkg-config ENV SCCACHE_DIGEST=7237e38e029342fa27b7ac25412cb9d52554008b12389727320bd533fd7f05b6a96d55485f305caf95e5c8f5f97c3313e10012ccad3e752aba2518f3522ba783 RUN curl -L https://api.pub.build.mozilla.org/tooltool/sha512/$SCCACHE_DIGEST | \ From cae98cae4f1045cd30239f2a62a77ab81fa2dec7 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 19 Dec 2016 11:59:44 -0800 Subject: [PATCH 54/73] travis: Support local sccache if not on bots This commit configures local sccache directory to get used if you're running builds locally to enjoy the benefits of caching when running inside the containers. --- src/ci/docker/run.sh | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/ci/docker/run.sh b/src/ci/docker/run.sh index ce8b49a92dce5..8c2c8d2a9db5a 100755 --- a/src/ci/docker/run.sh +++ b/src/ci/docker/run.sh @@ -28,15 +28,23 @@ docker \ mkdir -p $HOME/.cargo mkdir -p $root_dir/obj +args= +if [ "$SCCACHE_BUCKET" != "" ]; then + args="$args --env SCCACHE_BUCKET=$SCCACHE_BUCKET" + args="$args --env AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID" + args="$args --env AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY" +else + mkdir -p $HOME/.cache/sccache + args="$args --env SCCACHE_DIR=/sccache --volume $HOME/.cache/sccache:/sccache" +fi + exec docker \ run \ --volume "$root_dir:/checkout:ro" \ --volume "$root_dir/obj:/checkout/obj" \ --workdir /checkout/obj \ --env SRC=/checkout \ - --env SCCACHE_BUCKET=$SCCACHE_BUCKET \ - --env AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID \ - --env AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY \ + $args \ --env CARGO_HOME=/cargo \ --env LOCAL_USER_ID=`id -u` \ --volume "$HOME/.cargo:/cargo" \ From 8e61ff25d85dcdc81c55f51ba2a777e13e561a25 Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Sat, 10 Dec 2016 06:45:58 +0000 Subject: [PATCH 55/73] Optimize `ast::PathSegment`. --- src/librustc/hir/lowering.rs | 18 +++-- src/librustc_passes/ast_validation.rs | 4 +- src/librustc_resolve/lib.rs | 14 +--- src/librustc_resolve/macros.rs | 4 +- src/libsyntax/ast.rs | 97 +++++---------------------- src/libsyntax/ext/build.rs | 31 ++++----- src/libsyntax/fold.rs | 2 +- src/libsyntax/parse/mod.rs | 53 +++------------ src/libsyntax/parse/parser.rs | 40 ++++------- src/libsyntax/print/pprust.rs | 13 ++-- src/libsyntax/std_inject.rs | 5 +- src/libsyntax/test.rs | 5 +- src/libsyntax/visit.rs | 4 +- src/libsyntax_ext/concat_idents.rs | 6 +- 14 files changed, 86 insertions(+), 210 deletions(-) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index f5773d3517804..e8c3492705a3f 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -433,13 +433,19 @@ impl<'a> LoweringContext<'a> { segment: &PathSegment, param_mode: ParamMode) -> hir::PathSegment { - let parameters = match segment.parameters { - PathParameters::AngleBracketed(ref data) => { - let data = self.lower_angle_bracketed_parameter_data(data, param_mode); - hir::AngleBracketedParameters(data) + let parameters = if let Some(ref parameters) = segment.parameters { + match **parameters { + PathParameters::AngleBracketed(ref data) => { + let data = self.lower_angle_bracketed_parameter_data(data, param_mode); + hir::AngleBracketedParameters(data) + } + PathParameters::Parenthesized(ref data) => { + hir::ParenthesizedParameters(self.lower_parenthesized_parameter_data(data)) + } } - PathParameters::Parenthesized(ref data) => - hir::ParenthesizedParameters(self.lower_parenthesized_parameter_data(data)), + } else { + let data = self.lower_angle_bracketed_parameter_data(&Default::default(), param_mode); + hir::AngleBracketedParameters(data) }; hir::PathSegment { diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs index 2d0f0864752ab..bc150b847786f 100644 --- a/src/librustc_passes/ast_validation.rs +++ b/src/librustc_passes/ast_validation.rs @@ -171,7 +171,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { match item.node { ItemKind::Use(ref view_path) => { let path = view_path.node.path(); - if !path.segments.iter().all(|segment| segment.parameters.is_empty()) { + if path.segments.iter().any(|segment| segment.parameters.is_some()) { self.err_handler() .span_err(path.span, "type or lifetime parameters in import path"); } @@ -275,7 +275,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { fn visit_vis(&mut self, vis: &'a Visibility) { match *vis { Visibility::Restricted { ref path, .. } => { - if !path.segments.iter().all(|segment| segment.parameters.is_empty()) { + if !path.segments.iter().all(|segment| segment.parameters.is_none()) { self.err_handler() .span_err(path.span, "type or lifetime parameters in visibility path"); } diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index d87e04f7b97f9..821820df8388b 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -62,7 +62,7 @@ use syntax::ast::{Arm, BindingMode, Block, Crate, Expr, ExprKind}; use syntax::ast::{FnDecl, ForeignItem, ForeignItemKind, Generics}; use syntax::ast::{Item, ItemKind, ImplItem, ImplItemKind}; use syntax::ast::{Local, Mutability, Pat, PatKind, Path}; -use syntax::ast::{PathSegment, PathParameters, QSelf, TraitItemKind, TraitRef, Ty, TyKind}; +use syntax::ast::{QSelf, TraitItemKind, TraitRef, Ty, TyKind}; use syntax_pos::{Span, DUMMY_SP}; use errors::DiagnosticBuilder; @@ -2960,14 +2960,9 @@ impl<'a> Resolver<'a> { if ident.name == lookup_name && ns == namespace { if filter_fn(name_binding.def()) { // create the path - let params = PathParameters::none(); - let segment = PathSegment { - identifier: ident, - parameters: params, - }; let span = name_binding.span; let mut segms = path_segments.clone(); - segms.push(segment); + segms.push(ident.into()); let path = Path { span: span, global: false, @@ -2990,10 +2985,7 @@ impl<'a> Resolver<'a> { if let Some(module) = name_binding.module() { // form the path let mut path_segments = path_segments.clone(); - path_segments.push(PathSegment { - identifier: ident, - parameters: PathParameters::none(), - }); + path_segments.push(ident.into()); if !in_module_is_extern || name_binding.vis == ty::Visibility::Public { // add the module to the lookup diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index ce92a4446f920..6399a266fcf38 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -183,9 +183,9 @@ impl<'a> base::Resolver for Resolver<'a> { fn resolve_macro(&mut self, scope: Mark, path: &ast::Path, force: bool) -> Result, Determinacy> { let ast::Path { ref segments, global, span } = *path; - if segments.iter().any(|segment| !segment.parameters.is_empty()) { + if segments.iter().any(|segment| segment.parameters.is_some()) { let kind = - if segments.last().unwrap().parameters.is_empty() { "module" } else { "macro" }; + if segments.last().unwrap().parameters.is_some() { "macro" } else { "module" }; let msg = format!("type parameters are not allowed on {}s", kind); self.session.span_err(path.span, &msg); return Err(Determinacy::Determined); diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 39d78cd87761e..fdd82225b9747 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -137,12 +137,7 @@ impl Path { Path { span: s, global: false, - segments: vec![ - PathSegment { - identifier: identifier, - parameters: PathParameters::none() - } - ], + segments: vec![identifier.into()], } } } @@ -160,7 +155,15 @@ pub struct PathSegment { /// this is more than just simple syntactic sugar; the use of /// parens affects the region binding rules, so we preserve the /// distinction. - pub parameters: PathParameters, + /// The `Option>` wrapper is purely a size optimization; + /// `None` is used to represent both `Path` and `Path<>`. + pub parameters: Option>, +} + +impl From for PathSegment { + fn from(id: Ident) -> Self { + PathSegment { identifier: id, parameters: None } + } } /// Parameters of a path segment. @@ -174,79 +177,8 @@ pub enum PathParameters { Parenthesized(ParenthesizedParameterData), } -impl PathParameters { - pub fn none() -> PathParameters { - PathParameters::AngleBracketed(AngleBracketedParameterData { - lifetimes: Vec::new(), - types: P::new(), - bindings: P::new(), - }) - } - - pub fn is_empty(&self) -> bool { - match *self { - PathParameters::AngleBracketed(ref data) => data.is_empty(), - - // Even if the user supplied no types, something like - // `X()` is equivalent to `X<(),()>`. - PathParameters::Parenthesized(..) => false, - } - } - - pub fn has_lifetimes(&self) -> bool { - match *self { - PathParameters::AngleBracketed(ref data) => !data.lifetimes.is_empty(), - PathParameters::Parenthesized(_) => false, - } - } - - pub fn has_types(&self) -> bool { - match *self { - PathParameters::AngleBracketed(ref data) => !data.types.is_empty(), - PathParameters::Parenthesized(..) => true, - } - } - - /// Returns the types that the user wrote. Note that these do not necessarily map to the type - /// parameters in the parenthesized case. - pub fn types(&self) -> Vec<&P> { - match *self { - PathParameters::AngleBracketed(ref data) => { - data.types.iter().collect() - } - PathParameters::Parenthesized(ref data) => { - data.inputs.iter() - .chain(data.output.iter()) - .collect() - } - } - } - - pub fn lifetimes(&self) -> Vec<&Lifetime> { - match *self { - PathParameters::AngleBracketed(ref data) => { - data.lifetimes.iter().collect() - } - PathParameters::Parenthesized(_) => { - Vec::new() - } - } - } - - pub fn bindings(&self) -> Vec<&TypeBinding> { - match *self { - PathParameters::AngleBracketed(ref data) => { - data.bindings.iter().collect() - } - PathParameters::Parenthesized(_) => { - Vec::new() - } - } - } -} - /// A path like `Foo<'a, T>` -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] +#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Default)] pub struct AngleBracketedParameterData { /// The lifetime parameters for this path segment. pub lifetimes: Vec, @@ -258,9 +190,10 @@ pub struct AngleBracketedParameterData { pub bindings: P<[TypeBinding]>, } -impl AngleBracketedParameterData { - fn is_empty(&self) -> bool { - self.lifetimes.is_empty() && self.types.is_empty() && self.bindings.is_empty() +impl Into>> for AngleBracketedParameterData { + fn into(self) -> Option> { + let empty = self.lifetimes.is_empty() && self.types.is_empty() && self.bindings.is_empty(); + if empty { None } else { Some(P(PathParameters::AngleBracketed(self))) } } } diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index a208b934d79e1..c0dfb90024006 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -322,21 +322,17 @@ impl<'a> AstBuilder for ExtCtxt<'a> { bindings: Vec ) -> ast::Path { let last_identifier = idents.pop().unwrap(); - let mut segments: Vec = idents.into_iter() - .map(|ident| { - ast::PathSegment { - identifier: ident, - parameters: ast::PathParameters::none(), - } - }).collect(); - segments.push(ast::PathSegment { - identifier: last_identifier, - parameters: ast::PathParameters::AngleBracketed(ast::AngleBracketedParameterData { + let mut segments: Vec = idents.into_iter().map(Into::into).collect(); + let parameters = if lifetimes.is_empty() && types.is_empty() && bindings.is_empty() { + None + } else { + Some(P(ast::PathParameters::AngleBracketed(ast::AngleBracketedParameterData { lifetimes: lifetimes, types: P::from_vec(types), bindings: P::from_vec(bindings), - }) - }); + }))) + }; + segments.push(ast::PathSegment { identifier: last_identifier, parameters: parameters }); ast::Path { span: sp, global: global, @@ -367,13 +363,14 @@ impl<'a> AstBuilder for ExtCtxt<'a> { bindings: Vec) -> (ast::QSelf, ast::Path) { let mut path = trait_path; + let parameters = ast::AngleBracketedParameterData { + lifetimes: lifetimes, + types: P::from_vec(types), + bindings: P::from_vec(bindings), + }; path.segments.push(ast::PathSegment { identifier: ident, - parameters: ast::PathParameters::AngleBracketed(ast::AngleBracketedParameterData { - lifetimes: lifetimes, - types: P::from_vec(types), - bindings: P::from_vec(bindings), - }) + parameters: Some(P(ast::PathParameters::AngleBracketed(parameters))), }); (ast::QSelf { diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 6af8efb2a195c..b3753e3e977e3 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -438,7 +438,7 @@ pub fn noop_fold_path(Path {global, segments, span}: Path, fld: &mut global: global, segments: segments.move_map(|PathSegment {identifier, parameters}| PathSegment { identifier: fld.fold_ident(identifier), - parameters: fld.fold_path_parameters(parameters), + parameters: parameters.map(|ps| ps.map(|ps| fld.fold_path_parameters(ps))), }), span: fld.new_span(span) } diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index c982205f0ecef..b9e6605639ead 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -634,12 +634,7 @@ mod tests { node: ast::ExprKind::Path(None, ast::Path { span: sp(0, 1), global: false, - segments: vec![ - ast::PathSegment { - identifier: Ident::from_str("a"), - parameters: ast::PathParameters::none(), - } - ], + segments: vec![Ident::from_str("a").into()], }), span: sp(0, 1), attrs: ThinVec::new(), @@ -651,19 +646,10 @@ mod tests { P(ast::Expr { id: ast::DUMMY_NODE_ID, node: ast::ExprKind::Path(None, ast::Path { - span: sp(0, 6), - global: true, - segments: vec![ - ast::PathSegment { - identifier: Ident::from_str("a"), - parameters: ast::PathParameters::none(), - }, - ast::PathSegment { - identifier: Ident::from_str("b"), - parameters: ast::PathParameters::none(), - } - ] - }), + span: sp(0, 6), + global: true, + segments: vec![Ident::from_str("a").into(), Ident::from_str("b").into()], + }), span: sp(0, 6), attrs: ThinVec::new(), })) @@ -772,12 +758,7 @@ mod tests { node:ast::ExprKind::Path(None, ast::Path{ span: sp(7, 8), global: false, - segments: vec![ - ast::PathSegment { - identifier: Ident::from_str("d"), - parameters: ast::PathParameters::none(), - } - ], + segments: vec![Ident::from_str("d").into()], }), span:sp(7,8), attrs: ThinVec::new(), @@ -795,12 +776,7 @@ mod tests { node: ast::ExprKind::Path(None, ast::Path { span:sp(0,1), global:false, - segments: vec![ - ast::PathSegment { - identifier: Ident::from_str("b"), - parameters: ast::PathParameters::none(), - } - ], + segments: vec![Ident::from_str("b").into()], }), span: sp(0,1), attrs: ThinVec::new()})), @@ -842,12 +818,7 @@ mod tests { node: ast::TyKind::Path(None, ast::Path{ span:sp(10,13), global:false, - segments: vec![ - ast::PathSegment { - identifier: Ident::from_str("i32"), - parameters: ast::PathParameters::none(), - } - ], + segments: vec![Ident::from_str("i32").into()], }), span:sp(10,13) }), @@ -890,13 +861,7 @@ mod tests { ast::Path{ span:sp(17,18), global:false, - segments: vec![ - ast::PathSegment { - identifier: Ident::from_str("b"), - parameters: - ast::PathParameters::none(), - } - ], + segments: vec![Ident::from_str("b").into()], }), span: sp(17,18), attrs: ThinVec::new()})), diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index a1d4ad9d629c9..72462b74e686c 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -1705,12 +1705,11 @@ impl<'a> Parser<'a> { // Parse types, optionally. let parameters = if self.eat_lt() { let (lifetimes, types, bindings) = self.parse_generic_values_after_lt()?; - - ast::PathParameters::AngleBracketed(ast::AngleBracketedParameterData { + ast::AngleBracketedParameterData { lifetimes: lifetimes, types: P::from_vec(types), bindings: P::from_vec(bindings), - }) + }.into() } else if self.eat(&token::OpenDelim(token::Paren)) { let lo = self.prev_span.lo; @@ -1727,18 +1726,17 @@ impl<'a> Parser<'a> { let hi = self.prev_span.hi; - ast::PathParameters::Parenthesized(ast::ParenthesizedParameterData { + Some(P(ast::PathParameters::Parenthesized(ast::ParenthesizedParameterData { span: mk_sp(lo, hi), inputs: inputs, output: output_ty, - }) + }))) } else { - ast::PathParameters::none() + None }; // Assemble and push the result. - segments.push(ast::PathSegment { identifier: identifier, - parameters: parameters }); + segments.push(ast::PathSegment { identifier: identifier, parameters: parameters }); // Continue only if we see a `::` if !self.eat(&token::ModSep) { @@ -1757,10 +1755,7 @@ impl<'a> Parser<'a> { // If we do not see a `::`, stop. if !self.eat(&token::ModSep) { - segments.push(ast::PathSegment { - identifier: identifier, - parameters: ast::PathParameters::none() - }); + segments.push(identifier.into()); return Ok(segments); } @@ -1768,14 +1763,13 @@ impl<'a> Parser<'a> { if self.eat_lt() { // Consumed `a::b::<`, go look for types let (lifetimes, types, bindings) = self.parse_generic_values_after_lt()?; - let parameters = ast::AngleBracketedParameterData { - lifetimes: lifetimes, - types: P::from_vec(types), - bindings: P::from_vec(bindings), - }; segments.push(ast::PathSegment { identifier: identifier, - parameters: ast::PathParameters::AngleBracketed(parameters), + parameters: ast::AngleBracketedParameterData { + lifetimes: lifetimes, + types: P::from_vec(types), + bindings: P::from_vec(bindings), + }.into(), }); // Consumed `a::b::`, check for `::` before proceeding @@ -1784,10 +1778,7 @@ impl<'a> Parser<'a> { } } else { // Consumed `a::`, go look for `b` - segments.push(ast::PathSegment { - identifier: identifier, - parameters: ast::PathParameters::none(), - }); + segments.push(identifier.into()); } } } @@ -1802,10 +1793,7 @@ impl<'a> Parser<'a> { let identifier = self.parse_path_segment_ident()?; // Assemble and push the result. - segments.push(ast::PathSegment { - identifier: identifier, - parameters: ast::PathParameters::none() - }); + segments.push(identifier.into()); // If we do not see a `::` or see `::{`/`::*`, stop. if !self.check(&token::ModSep) || self.is_import_coupler() { diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index c28b9d00501b7..22e8391de93ed 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -2349,7 +2349,9 @@ impl<'a> State<'a> { try!(self.print_ident(segment.identifier)); - try!(self.print_path_parameters(&segment.parameters, colons_before_params)); + if let Some(ref parameters) = segment.parameters { + try!(self.print_path_parameters(parameters, colons_before_params)) + } } Ok(()) @@ -2373,7 +2375,10 @@ impl<'a> State<'a> { try!(word(&mut self.s, "::")); let item_segment = path.segments.last().unwrap(); try!(self.print_ident(item_segment.identifier)); - self.print_path_parameters(&item_segment.parameters, colons_before_params) + match item_segment.parameters { + Some(ref parameters) => self.print_path_parameters(parameters, colons_before_params), + None => Ok(()), + } } fn print_path_parameters(&mut self, @@ -2381,10 +2386,6 @@ impl<'a> State<'a> { colons_before_params: bool) -> io::Result<()> { - if parameters.is_empty() { - return Ok(()); - } - if colons_before_params { try!(word(&mut self.s, "::")) } diff --git a/src/libsyntax/std_inject.rs b/src/libsyntax/std_inject.rs index 6a291ad9c408a..4ad760a3cafe4 100644 --- a/src/libsyntax/std_inject.rs +++ b/src/libsyntax/std_inject.rs @@ -81,9 +81,8 @@ pub fn maybe_inject_crates_ref(sess: &ParseSess, vis: ast::Visibility::Inherited, node: ast::ItemKind::Use(P(codemap::dummy_spanned(ast::ViewPathGlob(ast::Path { global: false, - segments: vec![name, "prelude", "v1"].into_iter().map(|name| ast::PathSegment { - identifier: ast::Ident::from_str(name), - parameters: ast::PathParameters::none(), + segments: vec![name, "prelude", "v1"].into_iter().map(|name| { + ast::Ident::from_str(name).into() }).collect(), span: span, })))), diff --git a/src/libsyntax/test.rs b/src/libsyntax/test.rs index fca89e265e4ed..7709d3bd1cf1c 100644 --- a/src/libsyntax/test.rs +++ b/src/libsyntax/test.rs @@ -580,10 +580,7 @@ fn path_node(ids: Vec) -> ast::Path { ast::Path { span: DUMMY_SP, global: false, - segments: ids.into_iter().map(|identifier| ast::PathSegment { - identifier: identifier, - parameters: ast::PathParameters::none(), - }).collect() + segments: ids.into_iter().map(Into::into).collect(), } } diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index c1391d0b1c2f1..ad29cb50a84c8 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -383,7 +383,9 @@ pub fn walk_path_segment<'a, V: Visitor<'a>>(visitor: &mut V, path_span: Span, segment: &'a PathSegment) { visitor.visit_ident(path_span, segment.identifier); - visitor.visit_path_parameters(path_span, &segment.parameters); + if let Some(ref parameters) = segment.parameters { + visitor.visit_path_parameters(path_span, parameters); + } } pub fn walk_path_parameters<'a, V>(visitor: &mut V, diff --git a/src/libsyntax_ext/concat_idents.rs b/src/libsyntax_ext/concat_idents.rs index b26e33eb384dc..1381490efa194 100644 --- a/src/libsyntax_ext/concat_idents.rs +++ b/src/libsyntax_ext/concat_idents.rs @@ -59,14 +59,10 @@ pub fn expand_syntax_ext<'cx>(cx: &'cx mut ExtCtxt, impl Result { fn path(&self) -> ast::Path { - let segment = ast::PathSegment { - identifier: self.ident, - parameters: ast::PathParameters::none(), - }; ast::Path { span: self.span, global: false, - segments: vec![segment], + segments: vec![self.ident.into()], } } } From 51f25b3cfcb8137e7a95e35a89e5b3a7f33858b2 Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Mon, 12 Dec 2016 08:17:47 +0000 Subject: [PATCH 56/73] resolve: clean up diagnostics for name conflicts. --- src/librustc_resolve/lib.rs | 37 ++++--------------- src/test/compile-fail/E0259.rs | 2 +- .../compile-fail/blind-item-item-shadow.rs | 2 +- src/test/compile-fail/issue-19498.rs | 6 +-- src/test/compile-fail/issue-24081.rs | 10 ++--- .../resolve-conflict-item-vs-import.rs | 2 +- 6 files changed, 19 insertions(+), 40 deletions(-) diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 821820df8388b..3535aab9a1bd9 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -3156,40 +3156,19 @@ impl<'a> Resolver<'a> { }; let mut err = match (old_binding.is_extern_crate(), binding.is_extern_crate()) { - (true, true) => { - let mut e = struct_span_err!(self.session, span, E0259, "{}", msg); - e.span_label(span, &format!("`{}` was already imported", name)); - e - }, - (true, _) | (_, true) if binding.is_import() && old_binding.is_import() => { - let mut e = struct_span_err!(self.session, span, E0254, "{}", msg); - e.span_label(span, &"already imported"); - e - }, - (true, _) | (_, true) => { - let mut e = struct_span_err!(self.session, span, E0260, "{}", msg); - e.span_label(span, &format!("`{}` already imported", name)); - e + (true, true) => struct_span_err!(self.session, span, E0259, "{}", msg), + (true, _) | (_, true) => match binding.is_import() && old_binding.is_import() { + true => struct_span_err!(self.session, span, E0254, "{}", msg), + false => struct_span_err!(self.session, span, E0260, "{}", msg), }, _ => match (old_binding.is_import(), binding.is_import()) { - (false, false) => { - let mut e = struct_span_err!(self.session, span, E0428, "{}", msg); - e.span_label(span, &format!("already defined")); - e - }, - (true, true) => { - let mut e = struct_span_err!(self.session, span, E0252, "{}", msg); - e.span_label(span, &format!("already imported")); - e - }, - _ => { - let mut e = struct_span_err!(self.session, span, E0255, "{}", msg); - e.span_label(span, &format!("`{}` was already imported", name)); - e - } + (false, false) => struct_span_err!(self.session, span, E0428, "{}", msg), + (true, true) => struct_span_err!(self.session, span, E0252, "{}", msg), + _ => struct_span_err!(self.session, span, E0255, "{}", msg), }, }; + err.span_label(span, &format!("`{}` already {}", name, participle)); if old_binding.span != syntax_pos::DUMMY_SP { err.span_label(old_binding.span, &format!("previous {} of `{}` here", noun, name)); } diff --git a/src/test/compile-fail/E0259.rs b/src/test/compile-fail/E0259.rs index 95be48b5ff1b3..b2129902ef9c3 100644 --- a/src/test/compile-fail/E0259.rs +++ b/src/test/compile-fail/E0259.rs @@ -15,6 +15,6 @@ extern crate collections; extern crate libc as collections; //~^ ERROR E0259 -//~| NOTE `collections` was already imported +//~| NOTE `collections` already imported fn main() {} diff --git a/src/test/compile-fail/blind-item-item-shadow.rs b/src/test/compile-fail/blind-item-item-shadow.rs index 853282ff01436..e9df8868a1ed9 100644 --- a/src/test/compile-fail/blind-item-item-shadow.rs +++ b/src/test/compile-fail/blind-item-item-shadow.rs @@ -12,6 +12,6 @@ mod foo { pub mod foo { } } //~ NOTE previous definition of `foo` here use foo::foo; //~^ ERROR a module named `foo` has already been defined in this module -//~| was already imported +//~| `foo` already defined fn main() {} diff --git a/src/test/compile-fail/issue-19498.rs b/src/test/compile-fail/issue-19498.rs index 2e2115b71103a..88e804fb8aa08 100644 --- a/src/test/compile-fail/issue-19498.rs +++ b/src/test/compile-fail/issue-19498.rs @@ -11,13 +11,13 @@ use self::A; //~ NOTE previous import of `A` here use self::B; //~ NOTE previous import of `B` here mod A {} //~ ERROR a module named `A` has already been imported in this module -//~| `A` was already imported +//~| `A` already imported pub mod B {} //~ ERROR a module named `B` has already been imported in this module -//~| `B` was already imported +//~| `B` already imported mod C { use C::D; //~ NOTE previous import of `D` here mod D {} //~ ERROR a module named `D` has already been imported in this module - //~| `D` was already imported + //~| `D` already imported } fn main() {} diff --git a/src/test/compile-fail/issue-24081.rs b/src/test/compile-fail/issue-24081.rs index 188716c5e93f5..26bb72b862f2c 100644 --- a/src/test/compile-fail/issue-24081.rs +++ b/src/test/compile-fail/issue-24081.rs @@ -15,14 +15,14 @@ use std::ops::Div; //~ NOTE previous import use std::ops::Rem; //~ NOTE previous import type Add = bool; //~ ERROR a trait named `Add` has already been imported in this module -//~| was already imported +//~| `Add` already imported struct Sub { x: f32 } //~ ERROR a trait named `Sub` has already been imported in this module -//~| was already imported +//~| `Sub` already imported enum Mul { A, B } //~ ERROR a trait named `Mul` has already been imported in this module -//~| was already imported +//~| `Mul` already imported mod Div { } //~ ERROR a trait named `Div` has already been imported in this module -//~| was already imported +//~| `Div` already imported trait Rem { } //~ ERROR a trait named `Rem` has already been imported in this module -//~| was already imported +//~| `Rem` already imported fn main() {} diff --git a/src/test/compile-fail/resolve-conflict-item-vs-import.rs b/src/test/compile-fail/resolve-conflict-item-vs-import.rs index 5a068ce42142f..2083d98e09d31 100644 --- a/src/test/compile-fail/resolve-conflict-item-vs-import.rs +++ b/src/test/compile-fail/resolve-conflict-item-vs-import.rs @@ -13,6 +13,6 @@ use std::mem::transmute; fn transmute() {} //~^ ERROR a value named `transmute` has already been imported in this module -//~| was already imported +//~| `transmute` already imported fn main() { } From 8d9ba291f54e45cb4d12a066850680241efa25f5 Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Mon, 12 Dec 2016 10:09:22 +0000 Subject: [PATCH 57/73] Minor bugfix for macro invocation path resolution. --- src/librustc_resolve/macros.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 6399a266fcf38..dfeb66e1d8c76 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -205,7 +205,10 @@ impl<'a> base::Resolver for Resolver<'a> { } let ext = match self.resolve_path(&path, path_scope, Some(MacroNS), None) { - PathResult::NonModule(path_res) => Ok(self.get_macro(path_res.base_def)), + PathResult::NonModule(path_res) => match path_res.base_def { + Def::Err => Err(Determinacy::Determined), + def @ _ => Ok(self.get_macro(def)), + }, PathResult::Module(..) => unreachable!(), PathResult::Indeterminate if !force => return Err(Determinacy::Undetermined), _ => Err(Determinacy::Determined), From 39e6ae2dccdea270ef70aa7eecdd87252a5c36f2 Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Wed, 14 Dec 2016 09:59:41 +0000 Subject: [PATCH 58/73] Clean up `get_traits_containing_item`. --- src/librustc_resolve/lib.rs | 92 +++++++++++++++++-------------------- 1 file changed, 42 insertions(+), 50 deletions(-) diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 3535aab9a1bd9..fb28b45d20e5a 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -2863,72 +2863,64 @@ impl<'a> Resolver<'a> { fn get_traits_containing_item(&mut self, name: Name) -> Vec { debug!("(getting traits containing item) looking for '{}'", name); - fn add_trait_info(found_traits: &mut Vec, - trait_def_id: DefId, - import_id: Option, - name: Name) { - debug!("(adding trait info) found trait {:?} for method '{}'", - trait_def_id, - name); - found_traits.push(TraitCandidate { - def_id: trait_def_id, - import_id: import_id, - }); - } - let mut found_traits = Vec::new(); // Look for the current trait. if let Some((trait_def_id, _)) = self.current_trait_ref { if self.trait_item_map.contains_key(&(name, trait_def_id)) { - add_trait_info(&mut found_traits, trait_def_id, None, name); + found_traits.push(TraitCandidate { def_id: trait_def_id, import_id: None }); } } let mut search_module = self.current_module; loop { - // Look for trait children. - let mut search_in_module = |this: &mut Self, module: Module<'a>| { - let mut traits = module.traits.borrow_mut(); - if traits.is_none() { - let mut collected_traits = Vec::new(); - module.for_each_child(|name, ns, binding| { - if ns != TypeNS { return } - if let Def::Trait(_) = binding.def() { - collected_traits.push((name, binding)); - } - }); - *traits = Some(collected_traits.into_boxed_slice()); - } - - for &(trait_name, binding) in traits.as_ref().unwrap().iter() { - let trait_def_id = binding.def().def_id(); - if this.trait_item_map.contains_key(&(name, trait_def_id)) { - let mut import_id = None; - if let NameBindingKind::Import { directive, .. } = binding.kind { - let id = directive.id; - this.maybe_unused_trait_imports.insert(id); - this.add_to_glob_map(id, trait_name); - import_id = Some(id); - } - add_trait_info(&mut found_traits, trait_def_id, import_id, name); - } - } - }; - search_in_module(self, search_module); + self.get_traits_in_module_containing_item(name, search_module, &mut found_traits); + match search_module.kind { + ModuleKind::Block(..) => search_module = search_module.parent.unwrap(), + _ => break, + } + } - if let ModuleKind::Block(..) = search_module.kind { - search_module = search_module.parent.unwrap(); - } else { - if !search_module.no_implicit_prelude { - self.prelude.map(|prelude| search_in_module(self, prelude)); - } - break; + if let Some(prelude) = self.prelude { + if !search_module.no_implicit_prelude { + self.get_traits_in_module_containing_item(name, prelude, &mut found_traits); } } found_traits } + fn get_traits_in_module_containing_item(&mut self, + name: Name, + module: Module, + found_traits: &mut Vec) { + let mut traits = module.traits.borrow_mut(); + if traits.is_none() { + let mut collected_traits = Vec::new(); + module.for_each_child(|name, ns, binding| { + if ns != TypeNS { return } + if let Def::Trait(_) = binding.def() { + collected_traits.push((name, binding)); + } + }); + *traits = Some(collected_traits.into_boxed_slice()); + } + + for &(trait_name, binding) in traits.as_ref().unwrap().iter() { + let trait_def_id = binding.def().def_id(); + if self.trait_item_map.contains_key(&(name, trait_def_id)) { + let import_id = match binding.kind { + NameBindingKind::Import { directive, .. } => { + self.maybe_unused_trait_imports.insert(directive.id); + self.add_to_glob_map(directive.id, trait_name); + Some(directive.id) + } + _ => None, + }; + found_traits.push(TraitCandidate { def_id: trait_def_id, import_id: import_id }); + } + } + } + /// When name resolution fails, this method can be used to look up candidate /// entities with the expected name. It allows filtering them using the /// supplied predicate (which should be used to only accept the types of From f705c69bf641b271828f37adb525cafc618237d8 Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Thu, 15 Dec 2016 11:13:24 +0000 Subject: [PATCH 59/73] Simplify `TyCtxt::create_and_enter`. --- src/librustc/ty/context.rs | 10 ++++------ src/librustc/ty/mod.rs | 9 ++++++++- src/librustc_driver/driver.rs | 16 +++------------- src/librustc_driver/pretty.rs | 5 ++--- src/librustc_driver/test.rs | 4 +--- 5 files changed, 18 insertions(+), 26 deletions(-) diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 4854a14f733f5..20405398effd7 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -762,11 +762,9 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { /// reference to the context, to allow formatting values that need it. pub fn create_and_enter(s: &'tcx Session, arenas: &'tcx CtxtArenas<'tcx>, - trait_map: TraitMap, + resolutions: ty::Resolutions, named_region_map: resolve_lifetime::NamedRegionMap, map: ast_map::Map<'tcx>, - freevars: FreevarMap, - maybe_unused_trait_imports: NodeSet, region_maps: RegionMaps, lang_items: middle::lang_items::LanguageItems, stability: stability::Index<'tcx>, @@ -790,7 +788,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { item_variance_map: RefCell::new(DepTrackingMap::new(dep_graph.clone())), variance_computed: Cell::new(false), sess: s, - trait_map: trait_map, + trait_map: resolutions.trait_map, tables: RefCell::new(Tables::empty()), impl_trait_refs: RefCell::new(DepTrackingMap::new(dep_graph.clone())), trait_defs: RefCell::new(DepTrackingMap::new(dep_graph.clone())), @@ -802,8 +800,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { fulfilled_predicates: RefCell::new(fulfilled_predicates), map: map, mir_map: RefCell::new(DepTrackingMap::new(dep_graph.clone())), - freevars: RefCell::new(freevars), - maybe_unused_trait_imports: maybe_unused_trait_imports, + freevars: RefCell::new(resolutions.freevars), + maybe_unused_trait_imports: resolutions.maybe_unused_trait_imports, item_types: RefCell::new(DepTrackingMap::new(dep_graph.clone())), rcache: RefCell::new(FxHashMap()), tc_cache: RefCell::new(FxHashMap()), diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index df12c252907a5..8f478435efd90 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -17,7 +17,7 @@ pub use self::LvaluePreference::*; pub use self::fold::TypeFoldable; use dep_graph::{self, DepNode}; -use hir::map as ast_map; +use hir::{map as ast_map, FreevarMap, TraitMap}; use middle; use hir::def::{Def, CtorKind, ExportMap}; use hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE}; @@ -112,6 +112,13 @@ pub struct CrateAnalysis<'tcx> { pub hir_ty_to_ty: NodeMap>, } +#[derive(Clone)] +pub struct Resolutions { + pub freevars: FreevarMap, + pub trait_map: TraitMap, + pub maybe_unused_trait_imports: NodeSet, +} + #[derive(Copy, Clone)] pub enum DtorKind { NoDtor, diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index ace00f031859d..360933c6b6695 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -8,8 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use rustc::hir; -use rustc::hir::{map as hir_map, FreevarMap, TraitMap}; +use rustc::hir::{self, map as hir_map}; use rustc::hir::lowering::lower_crate; use rustc_data_structures::stable_hasher::StableHasher; use rustc_mir as mir; @@ -20,7 +19,7 @@ use rustc::session::search_paths::PathKind; use rustc::lint; use rustc::middle::{self, dependency_format, stability, reachable}; use rustc::middle::privacy::AccessLevels; -use rustc::ty::{self, TyCtxt}; +use rustc::ty::{self, TyCtxt, Resolutions}; use rustc::util::common::time; use rustc::util::nodemap::{NodeSet, NodeMap}; use rustc_borrowck as borrowck; @@ -59,13 +58,6 @@ use syntax_ext; use derive_registrar; -#[derive(Clone)] -pub struct Resolutions { - pub freevars: FreevarMap, - pub trait_map: TraitMap, - pub maybe_unused_trait_imports: NodeSet, -} - pub fn compile_input(sess: &Session, cstore: &CStore, input: &Input, @@ -864,11 +856,9 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session, TyCtxt::create_and_enter(sess, arenas, - resolutions.trait_map, + resolutions, named_region_map, hir_map, - resolutions.freevars, - resolutions.maybe_unused_trait_imports, region_map, lang_items, index, diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs index b055b043723e4..74df1e52bde43 100644 --- a/src/librustc_driver/pretty.rs +++ b/src/librustc_driver/pretty.rs @@ -15,10 +15,9 @@ pub use self::PpSourceMode::*; pub use self::PpMode::*; use self::NodesMatchingUII::*; -use abort_on_err; -use driver::{self, Resolutions}; +use {abort_on_err, driver}; -use rustc::ty::{self, TyCtxt}; +use rustc::ty::{self, TyCtxt, Resolutions}; use rustc::cfg; use rustc::cfg::graphviz::LabelledCFG; use rustc::dep_graph::DepGraph; diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs index 2f8550e5acda7..cbab39c390829 100644 --- a/src/librustc_driver/test.rs +++ b/src/librustc_driver/test.rs @@ -138,11 +138,9 @@ fn test_env(source_string: &str, let index = stability::Index::new(&ast_map); TyCtxt::create_and_enter(&sess, &arenas, - resolutions.trait_map, + resolutions, named_region_map.unwrap(), ast_map, - resolutions.freevars, - resolutions.maybe_unused_trait_imports, region_map, lang_items, index, From 2dc2f5fafb17c5bb406ef2187332ebaf2dd8d35d Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Mon, 19 Dec 2016 21:57:43 +0000 Subject: [PATCH 60/73] Bump version to 1.16 --- mk/main.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mk/main.mk b/mk/main.mk index 49fdfc4118df5..d01ec07b4244e 100644 --- a/mk/main.mk +++ b/mk/main.mk @@ -13,7 +13,7 @@ ###################################################################### # The version number -CFG_RELEASE_NUM=1.15.0 +CFG_RELEASE_NUM=1.16.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 From 0a014c684140c8df32aea55801f006a1b8aa973c Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 19 Dec 2016 15:49:57 -0700 Subject: [PATCH 61/73] Move prefix to [install] section --- src/bootstrap/config.rs | 14 ++++++++++++-- src/bootstrap/config.toml.example | 11 ++++++++--- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index beb62ef20744c..942555274057e 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -113,6 +113,7 @@ pub struct Target { #[derive(RustcDecodable, Default)] struct TomlConfig { build: Option, + install: Option, llvm: Option, rust: Option, target: Option>, @@ -126,7 +127,6 @@ struct Build { target: Vec, cargo: Option, rustc: Option, - prefix: Option, compiler_docs: Option, docs: Option, submodules: Option, @@ -136,6 +136,12 @@ struct Build { python: Option, } +/// TOML representation of various global install decisions. +#[derive(RustcDecodable, Default, Clone)] +struct Install { + prefix: Option, +} + /// TOML representation of how the LLVM build is configured. #[derive(RustcDecodable, Default)] struct Llvm { @@ -239,7 +245,6 @@ impl Config { } config.rustc = build.rustc.map(PathBuf::from); config.cargo = build.cargo.map(PathBuf::from); - config.prefix = build.prefix; config.nodejs = build.nodejs.map(PathBuf::from); config.gdb = build.gdb.map(PathBuf::from); config.python = build.python.map(PathBuf::from); @@ -248,6 +253,10 @@ impl Config { set(&mut config.submodules, build.submodules); set(&mut config.vendor, build.vendor); + if let Some(ref install) = toml.install { + config.prefix = install.prefix.clone(); + } + if let Some(ref llvm) = toml.llvm { set(&mut config.ccache, llvm.ccache); set(&mut config.ninja, llvm.ninja); @@ -257,6 +266,7 @@ impl Config { set(&mut config.llvm_version_check, llvm.version_check); set(&mut config.llvm_static_stdcpp, llvm.static_libstdcpp); } + if let Some(ref rust) = toml.rust { set(&mut config.rust_debug_assertions, rust.debug_assertions); set(&mut config.rust_debuginfo, rust.debuginfo); diff --git a/src/bootstrap/config.toml.example b/src/bootstrap/config.toml.example index 76fcfebdb9456..4a08d66d8d9a0 100644 --- a/src/bootstrap/config.toml.example +++ b/src/bootstrap/config.toml.example @@ -70,9 +70,6 @@ # specified, use this rustc binary instead as the stage0 snapshot compiler. #rustc = "/path/to/bin/rustc" -# Instead of installing to /usr/local, install to this path instead. -#prefix = "/path/to/install" - # Flag to specify whether any documentation is built. If false, rustdoc and # friends will still be compiled but they will not be used to generate any # documentation. @@ -101,6 +98,14 @@ # Indicate whether the vendored sources are used for Rust dependencies or not #vendor = false +# ============================================================================= +# General install configuration options +# ============================================================================= +[install] + +# Instead of installing to /usr/local, install to this path instead. +#prefix = "/path/to/install" + # ============================================================================= # Options for compiling Rust code itself # ============================================================================= From 228e495e7f7fb89ca4047847a5118c5e224a0958 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 19 Dec 2016 17:42:07 -0700 Subject: [PATCH 62/73] Remove trailing whitespace --- src/bootstrap/config.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index 942555274057e..c38f860141fc7 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -266,7 +266,7 @@ impl Config { set(&mut config.llvm_version_check, llvm.version_check); set(&mut config.llvm_static_stdcpp, llvm.static_libstdcpp); } - + if let Some(ref rust) = toml.rust { set(&mut config.rust_debug_assertions, rust.debug_assertions); set(&mut config.rust_debuginfo, rust.debuginfo); From f5e7d92129f34b3da9b9049a2e5b7a9f81383ca7 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 19 Dec 2016 09:45:42 -0800 Subject: [PATCH 63/73] rustbuild: Update Cargo download location I updated the beta compiler used to bootstrap the master branch in #38438 with the intention of fixing Travis OSX linkage issues but I mistakenly forgot that the PR only updated rustc, not Cargo itself. Cargo has a new release process with downloads in a different location, so this commit updates rustbuild to download from this new location by tracking revisions instead of Cargo nightly dates. --- src/bootstrap/bootstrap.py | 22 +++++++++------------- src/stage0.txt | 2 +- 2 files changed, 10 insertions(+), 14 deletions(-) diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 5f16542ed2f2b..89d297760e286 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -81,7 +81,7 @@ def verify(path, sha_path, verbose): with open(path, "rb") as f: found = hashlib.sha256(f.read()).hexdigest() with open(sha_path, "r") as f: - expected, _ = f.readline().split() + expected = f.readline().split()[0] verified = found == expected if not verified: print("invalid checksum:\n" @@ -146,7 +146,7 @@ class RustBuild(object): def download_stage0(self): cache_dst = os.path.join(self.build_dir, "cache") rustc_cache = os.path.join(cache_dst, self.stage0_rustc_date()) - cargo_cache = os.path.join(cache_dst, self.stage0_cargo_date()) + cargo_cache = os.path.join(cache_dst, self.stage0_cargo_rev()) if not os.path.exists(rustc_cache): os.makedirs(rustc_cache) if not os.path.exists(cargo_cache): @@ -179,21 +179,17 @@ def download_stage0(self): if self.cargo().startswith(self.bin_root()) and \ (not os.path.exists(self.cargo()) or self.cargo_out_of_date()): self.print_what_it_means_to_bootstrap() - channel = self.stage0_cargo_channel() - filename = "cargo-{}-{}.tar.gz".format(channel, self.build) - url = "https://static.rust-lang.org/cargo-dist/" + self.stage0_cargo_date() + filename = "cargo-nightly-{}.tar.gz".format(self.build) + url = "https://s3.amazonaws.com/rust-lang-ci/cargo-builds/" + self.stage0_cargo_rev() tarball = os.path.join(cargo_cache, filename) if not os.path.exists(tarball): get("{}/{}".format(url, filename), tarball, verbose=self.verbose) unpack(tarball, self.bin_root(), match="cargo", verbose=self.verbose) with open(self.cargo_stamp(), 'w') as f: - f.write(self.stage0_cargo_date()) + f.write(self.stage0_cargo_rev()) - def stage0_cargo_date(self): - return self._cargo_date - - def stage0_cargo_channel(self): - return self._cargo_channel + def stage0_cargo_rev(self): + return self._cargo_rev def stage0_rustc_date(self): return self._rustc_date @@ -217,7 +213,7 @@ def cargo_out_of_date(self): if not os.path.exists(self.cargo_stamp()) or self.clean: return True with open(self.cargo_stamp(), 'r') as f: - return self.stage0_cargo_date() != f.read() + return self.stage0_cargo_rev() != f.read() def bin_root(self): return os.path.join(self.build_dir, self.build, "stage0") @@ -469,7 +465,7 @@ def main(): data = stage0_data(rb.rust_root) rb._rustc_channel, rb._rustc_date = data['rustc'].split('-', 1) - rb._cargo_channel, rb._cargo_date = data['cargo'].split('-', 1) + rb._cargo_rev = data['cargo'] start_time = time() diff --git a/src/stage0.txt b/src/stage0.txt index 4fbd70835dd2b..187c56d7889ea 100644 --- a/src/stage0.txt +++ b/src/stage0.txt @@ -13,4 +13,4 @@ # released on `$date` rustc: beta-2016-12-16 -cargo: nightly-2016-11-16 +cargo: fbeea902d2c9a5be6d99cc35681565d8f7832592 From e1d8806efd702ee396992677cd04ab40c329d5d7 Mon Sep 17 00:00:00 2001 From: Austin Hicks Date: Mon, 19 Dec 2016 21:14:27 -0500 Subject: [PATCH 64/73] Fix closure debuginfo. --- src/librustc_trans/mir/mod.rs | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/librustc_trans/mir/mod.rs b/src/librustc_trans/mir/mod.rs index 12cbfcef7d26b..94dc9a5fdb489 100644 --- a/src/librustc_trans/mir/mod.rs +++ b/src/librustc_trans/mir/mod.rs @@ -10,14 +10,13 @@ use libc::c_uint; use llvm::{self, ValueRef}; -use rustc::ty; +use rustc::ty::{self, layout}; use rustc::mir; use rustc::mir::tcx::LvalueTy; use session::config::FullDebugInfo; use base; use common::{self, Block, BlockAndBuilder, CrateContext, FunctionContext, C_null}; use debuginfo::{self, declare_local, DebugLoc, VariableAccess, VariableKind, FunctionDebugContext}; -use machine; use type_of; use syntax_pos::{DUMMY_SP, NO_EXPANSION, COMMAND_LINE_EXPN, BytePos}; @@ -494,10 +493,15 @@ fn arg_local_refs<'bcx, 'tcx>(bcx: &BlockAndBuilder<'bcx, 'tcx>, llval }; - let llclosurety = type_of::type_of(bcx.ccx(), closure_ty); + let layout = bcx.ccx().layout_of(closure_ty); + let offsets = match *layout { + layout::Univariant { ref variant, .. } => &variant.offsets[..], + _ => bug!("Closures are only supposed to be Univariant") + }; + for (i, (decl, ty)) in mir.upvar_decls.iter().zip(upvar_tys).enumerate() { - let byte_offset_of_var_in_env = - machine::llelement_offset(bcx.ccx(), llclosurety, i); + let byte_offset_of_var_in_env = offsets[i].bytes(); + let ops = unsafe { [llvm::LLVMRustDIBuilderCreateOpDeref(), From 54f75c95722c12da32ca63301fe8548322018a97 Mon Sep 17 00:00:00 2001 From: est31 Date: Tue, 20 Dec 2016 03:34:36 +0100 Subject: [PATCH 65/73] Add regression test for #38458 --- src/test/compile-fail/issue-38458.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 src/test/compile-fail/issue-38458.rs diff --git a/src/test/compile-fail/issue-38458.rs b/src/test/compile-fail/issue-38458.rs new file mode 100644 index 0000000000000..56eb5f874cd61 --- /dev/null +++ b/src/test/compile-fail/issue-38458.rs @@ -0,0 +1,15 @@ +// 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. + +const x: () = { + return; //~ ERROR return statement outside of function body +}; + +fn main() {} From 73877a0bc882abc2a88fe9c0d4fb95d49c1ba492 Mon Sep 17 00:00:00 2001 From: Seo Sanghyeon Date: Tue, 20 Dec 2016 19:48:14 +0900 Subject: [PATCH 66/73] Find FileCheck using llvm-config --- src/bootstrap/lib.rs | 3 ++- src/bootstrap/sanity.rs | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index f6db6e786db81..128e03fe8f888 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -721,7 +721,8 @@ impl Build { fn llvm_filecheck(&self, target: &str) -> PathBuf { let target_config = self.config.target_config.get(target); if let Some(s) = target_config.and_then(|c| c.llvm_config.as_ref()) { - s.parent().unwrap().join(exe("FileCheck", target)) + let llvm_bindir = output(Command::new(s).arg("--bindir")); + Path::new(llvm_bindir.trim()).join(exe("FileCheck", target)) } else { let base = self.llvm_out(&self.config.build).join("build"); let exe = exe("FileCheck", target); diff --git a/src/bootstrap/sanity.rs b/src/bootstrap/sanity.rs index 2992099687d9a..5d543419fc9b6 100644 --- a/src/bootstrap/sanity.rs +++ b/src/bootstrap/sanity.rs @@ -143,7 +143,7 @@ pub fn check(build: &mut Build) { // Externally configured LLVM requires FileCheck to exist let filecheck = build.llvm_filecheck(&build.config.build); if !filecheck.starts_with(&build.out) && !filecheck.exists() && build.config.codegen_tests { - panic!("filecheck executable {:?} does not exist", filecheck); + panic!("FileCheck executable {:?} does not exist", filecheck); } for target in build.config.target.iter() { From 46d74eac236c7b58c848a471d81f9d5c59362513 Mon Sep 17 00:00:00 2001 From: Wang Xuerui Date: Mon, 19 Dec 2016 15:30:14 +0800 Subject: [PATCH 67/73] rustbuild: only plan from build triple for dist We only want to package each host/target once for `dist`. The obvious solution takes the form of step dependency, which is implemented at least for the `dist-rustc` step. Unfortunately since the steps are created from `hosts x targets` during planning and *not* de-duplicated afterwards, the problem still persists. We therefore move the check inside `plan()` instead, to avoid creating the duplicate steps in the first place. --- src/bootstrap/step.rs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/step.rs b/src/bootstrap/step.rs index 35eb98e4723f2..def06ee698353 100644 --- a/src/bootstrap/step.rs +++ b/src/bootstrap/step.rs @@ -822,7 +822,16 @@ invalid rule dependency graph detected, was a rule added and maybe typo'd? let hosts = if self.build.flags.host.len() > 0 { &self.build.flags.host } else { - &self.build.config.host + if kind == Kind::Dist { + // For 'dist' steps we only distribute artifacts built from + // the build platform, so only consider that in the hosts + // array. + // NOTE: This relies on the fact that the build triple is + // always placed first, as done in `config.rs`. + &self.build.config.host[..1] + } else { + &self.build.config.host + } }; let targets = if self.build.flags.target.len() > 0 { &self.build.flags.target From 8e38b2de42dda1752400524b69f76051586d469b Mon Sep 17 00:00:00 2001 From: Wang Xuerui Date: Mon, 19 Dec 2016 16:39:19 +0800 Subject: [PATCH 68/73] rustbuild: package src only once for build triple --- src/bootstrap/dist.rs | 8 +++++++- src/bootstrap/step.rs | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index be51a6753fb62..6e3174ed2f6d0 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -346,8 +346,14 @@ pub fn analysis(build: &Build, compiler: &Compiler, target: &str) { } /// Creates the `rust-src` installer component and the plain source tarball -pub fn rust_src(build: &Build) { +pub fn rust_src(build: &Build, host: &str) { println!("Dist src"); + + if host != build.config.build { + println!("\tskipping, not a build host"); + return + } + let plain_name = format!("rustc-{}-src", package_vers(build)); let name = format!("rust-src-{}", package_vers(build)); let image = tmpdir(build).join(format!("{}-image", name)); diff --git a/src/bootstrap/step.rs b/src/bootstrap/step.rs index def06ee698353..719fb82a56dce 100644 --- a/src/bootstrap/step.rs +++ b/src/bootstrap/step.rs @@ -499,7 +499,7 @@ pub fn build_rules(build: &Build) -> Rules { rules.dist("dist-src", "src") .default(true) .host(true) - .run(move |_| dist::rust_src(build)); + .run(move |s| dist::rust_src(build, s.target)); rules.dist("dist-docs", "src/doc") .default(true) .dep(|s| s.name("default:doc")) From 57cf2ab31cb443721d0481ac5989dfdd17a1a251 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 20 Dec 2016 09:38:13 -0800 Subject: [PATCH 69/73] rustbuild: Deny and fix warnings Turned out this lint uncovered an actual bug! Closes #38484 --- src/bootstrap/bin/rustc.rs | 2 ++ src/bootstrap/bin/rustdoc.rs | 2 ++ src/bootstrap/flags.rs | 2 +- src/bootstrap/lib.rs | 2 ++ 4 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/bin/rustc.rs b/src/bootstrap/bin/rustc.rs index 2fa4363e658a4..9cab6c423f5f9 100644 --- a/src/bootstrap/bin/rustc.rs +++ b/src/bootstrap/bin/rustc.rs @@ -25,6 +25,8 @@ //! switching compilers for the bootstrap and for build scripts will probably //! never get replaced. +#![deny(warnings)] + extern crate bootstrap; use std::env; diff --git a/src/bootstrap/bin/rustdoc.rs b/src/bootstrap/bin/rustdoc.rs index 67358e540dad0..a53bbe22eb94c 100644 --- a/src/bootstrap/bin/rustdoc.rs +++ b/src/bootstrap/bin/rustdoc.rs @@ -12,6 +12,8 @@ //! //! See comments in `src/bootstrap/rustc.rs` for more information. +#![deny(warnings)] + extern crate bootstrap; use std::env; diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs index e5ace62406a2b..b2412fbb3c844 100644 --- a/src/bootstrap/flags.rs +++ b/src/bootstrap/flags.rs @@ -280,7 +280,7 @@ To learn more about a subcommand, run `./x.py -h` Flags { verbose: m.opt_count("v"), - stage: m.opt_str("stage").map(|j| j.parse().unwrap()), + stage: stage, keep_stage: m.opt_str("keep-stage").map(|j| j.parse().unwrap()), build: m.opt_str("build").unwrap_or_else(|| { env::var("BUILD").unwrap() diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index f6db6e786db81..b2f40ab9e9bdf 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -64,6 +64,8 @@ //! More documentation can be found in each respective module below, and you can //! also check out the `src/bootstrap/README.md` file for more information. +#![deny(warnings)] + extern crate build_helper; extern crate cmake; extern crate filetime; From 49546cc6bb8af8c0450d62f5584325d65872b885 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 20 Dec 2016 10:19:02 -0800 Subject: [PATCH 70/73] rustbuild: Actually test musl on the musl bot A typo unfortunately meant that we haven't been testing musl for a bit, so now it's time to discover if we accidentally introduced a regression! --- src/bootstrap/mk/Makefile.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bootstrap/mk/Makefile.in b/src/bootstrap/mk/Makefile.in index cbcd85fb6b0d8..0d83a79cf32d9 100644 --- a/src/bootstrap/mk/Makefile.in +++ b/src/bootstrap/mk/Makefile.in @@ -66,7 +66,7 @@ tidy: check-stage2-T-arm-linux-androideabi-H-x86_64-unknown-linux-gnu: $(Q)$(BOOTSTRAP) test --target arm-linux-androideabi check-stage2-T-x86_64-unknown-linux-musl-H-x86_64-unknown-linux-gnu: - $(Q)$(BOOTSTRAP) test --target x86_64-unknown-linux-gnu + $(Q)$(BOOTSTRAP) test --target x86_64-unknown-linux-musl .PHONY: dist From 70ef94db2278da1b46d249c6fc6b3eac3dc324ae Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 19 Dec 2016 10:42:04 -0800 Subject: [PATCH 71/73] rustbuild: Run debuginfo tests by default This fixes an accidental regression in rustbuild which stopped running debuginfo tests by default. Here we flag the test suites as `default(true)` to ensure that they're run on bots, for example. --- src/bootstrap/step.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/bootstrap/step.rs b/src/bootstrap/step.rs index 95882cf8126cb..7647f2a2780d4 100644 --- a/src/bootstrap/step.rs +++ b/src/bootstrap/step.rs @@ -267,16 +267,18 @@ pub fn build_rules(build: &Build) -> Rules { // nothing to do for debuginfo tests } else if build.config.build.contains("apple") { rules.test("check-debuginfo", "src/test/debuginfo") + .default(true) .dep(|s| s.name("libtest")) - .dep(|s| s.name("tool-compiletest").host(s.host)) + .dep(|s| s.name("tool-compiletest").target(s.host)) .dep(|s| s.name("test-helpers")) .dep(|s| s.name("debugger-scripts")) .run(move |s| check::compiletest(build, &s.compiler(), s.target, "debuginfo-lldb", "debuginfo")); } else { rules.test("check-debuginfo", "src/test/debuginfo") + .default(true) .dep(|s| s.name("libtest")) - .dep(|s| s.name("tool-compiletest").host(s.host)) + .dep(|s| s.name("tool-compiletest").target(s.host)) .dep(|s| s.name("test-helpers")) .dep(|s| s.name("debugger-scripts")) .run(move |s| check::compiletest(build, &s.compiler(), s.target, From fe0d0927f7c01b491a3f247bf2618b64e201bc43 Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Tue, 6 Dec 2016 15:47:33 -1000 Subject: [PATCH 72/73] Indicate that `BTreeSet::iter` returns values in ascending order. Fixes https://github.com/rust-lang/rust/issues/38204. --- src/libcollections/btree/set.rs | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/libcollections/btree/set.rs b/src/libcollections/btree/set.rs index ffd5d7a919271..34674e3a0bd30 100644 --- a/src/libcollections/btree/set.rs +++ b/src/libcollections/btree/set.rs @@ -173,7 +173,7 @@ impl BTreeSet { } impl BTreeSet { - /// Gets an iterator over the `BTreeSet`'s contents. + /// Gets an iterator that visits the values in the `BTreeSet` in ascending order. /// /// # Examples /// @@ -187,6 +187,19 @@ impl BTreeSet { /// assert_eq!(set_iter.next(), Some(&3)); /// assert_eq!(set_iter.next(), None); /// ``` + /// + /// Values returned by the iterator are returned in ascending order: + /// + /// ``` + /// use std::collections::BTreeSet; + /// + /// let set: BTreeSet = [3, 1, 2].iter().cloned().collect(); + /// let mut set_iter = set.iter(); + /// assert_eq!(set_iter.next(), Some(&1)); + /// assert_eq!(set_iter.next(), Some(&2)); + /// assert_eq!(set_iter.next(), Some(&3)); + /// assert_eq!(set_iter.next(), None); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn iter(&self) -> Iter { Iter { iter: self.map.keys() } From 214a6c61666202ab073fceaeab13885027c8c3f2 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 20 Dec 2016 12:18:55 -0800 Subject: [PATCH 73/73] Fix compile errors and such --- src/librustc_resolve/lib.rs | 2 +- src/libstd/os/macos/raw.rs | 2 +- src/libstd/os/mod.rs | 2 +- src/libstd/sys/mod.rs | 2 ++ src/libstd/sys/unix/ext/net.rs | 7 +++---- src/libstd/sys_common/mod.rs | 1 + 6 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 18d7499e75189..f73227681c5e1 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -1358,7 +1358,7 @@ impl<'a> Resolver<'a> { span: span, name: ident.name, lexical: false, b1: b1, b2: b2, legacy: legacy, }); if legacy { - self.record_use(name, ns, b1, span); + self.record_use(ident, ns, b1, span); } !legacy } diff --git a/src/libstd/os/macos/raw.rs b/src/libstd/os/macos/raw.rs index 0b96295f9e69e..8f9b29462c4f9 100644 --- a/src/libstd/os/macos/raw.rs +++ b/src/libstd/os/macos/raw.rs @@ -33,7 +33,7 @@ use os::raw::c_long; pub type pthread_t = usize; #[repr(C)] -#[derive(Clone, Debug)] +#[derive(Clone)] #[stable(feature = "raw_ext", since = "1.1.0")] pub struct stat { #[stable(feature = "raw_ext", since = "1.1.0")] diff --git a/src/libstd/os/mod.rs b/src/libstd/os/mod.rs index 58f1604de1c5c..e45af86705582 100644 --- a/src/libstd/os/mod.rs +++ b/src/libstd/os/mod.rs @@ -11,7 +11,7 @@ //! OS-specific functionality. #![stable(feature = "os", since = "1.0.0")] -#![allow(missing_docs, bad_style)] +#![allow(missing_docs, bad_style, missing_debug_implementations)] #[cfg(any(target_os = "redox", unix))] #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libstd/sys/mod.rs b/src/libstd/sys/mod.rs index e4b0d980c921a..14da376efa998 100644 --- a/src/libstd/sys/mod.rs +++ b/src/libstd/sys/mod.rs @@ -30,6 +30,8 @@ //! inter-dependencies within `std` that will be a challenging goal to //! achieve. +#![allow(missing_debug_implementations)] + pub use self::imp::*; #[cfg(target_os = "redox")] diff --git a/src/libstd/sys/unix/ext/net.rs b/src/libstd/sys/unix/ext/net.rs index e822488c01851..1ba4a104e515c 100644 --- a/src/libstd/sys/unix/ext/net.rs +++ b/src/libstd/sys/unix/ext/net.rs @@ -141,7 +141,7 @@ impl SocketAddr { /// /// A named address: /// - /// ``` + /// ```no_run /// use std::os::unix::net::UnixListener; /// /// let socket = UnixListener::bind("/tmp/sock").unwrap(); @@ -173,7 +173,7 @@ impl SocketAddr { /// /// With a pathname: /// - /// ``` + /// ```no_run /// use std::os::unix::net::UnixListener; /// use std::path::Path; /// @@ -186,7 +186,6 @@ impl SocketAddr { /// /// ``` /// use std::os::unix::net::UnixDatagram; - /// use std::path::Path; /// /// let socket = UnixDatagram::unbound().unwrap(); /// let addr = socket.local_addr().expect("Couldn't get local address"); @@ -624,7 +623,7 @@ impl UnixListener { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::os::unix::net::UnixListener; /// /// let listener = match UnixListener::bind("/path/to/the/socket") { diff --git a/src/libstd/sys_common/mod.rs b/src/libstd/sys_common/mod.rs index 5c07e36508c69..634d6258885e8 100644 --- a/src/libstd/sys_common/mod.rs +++ b/src/libstd/sys_common/mod.rs @@ -23,6 +23,7 @@ //! `std::sys` from the standard library. #![allow(missing_docs)] +#![allow(missing_debug_implementations)] use sync::Once; use sys;