From ca42a1bece0494a86b80713c6d0f8dbc3db667fa Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Tue, 1 Feb 2022 13:46:05 -0800 Subject: [PATCH 01/17] Update the documentation for `{As,Into,From}Raw{Fd,Handle,Socket}`. This change weakens the descriptions of the `{as,into,from}_raw_{fd,handle,socket}` descriptions from saying that they *do* express ownership relations to say that they are *typically used* in ways that express ownership relations. This needed needed since, for example, std's own [`RawFd`] implements `{As,From,Into}Fd` without any of the ownership relationships. This adds proper `# Safety` comments to `from_raw_{fd,handle,socket}`, adds the requirement that raw handles be not opened with the `FILE_FLAG_OVERLAPPED` flag, and merges the `OwnedHandle::from_raw_handle` comment into the main `FromRawHandle::from_raw_handle` comment. And, this changes `HandleOrNull` and `HandleOrInvalid` to not implement `FromRawHandle`, since they are intended for limited use in FFI situations, and not for generic use, and they have constraints that are stronger than the those of `FromRawHandle`. [`RawFd`]: https://doc.rust-lang.org/stable/std/os/unix/io/type.RawFd.html --- library/std/src/os/fd/raw.rs | 38 ++++++---- library/std/src/os/windows/io/handle.rs | 34 +++------ library/std/src/os/windows/io/raw.rs | 92 ++++++++++++++++++------- 3 files changed, 101 insertions(+), 63 deletions(-) diff --git a/library/std/src/os/fd/raw.rs b/library/std/src/os/fd/raw.rs index f874cf0b42d..6925269c8f1 100644 --- a/library/std/src/os/fd/raw.rs +++ b/library/std/src/os/fd/raw.rs @@ -24,9 +24,14 @@ pub type RawFd = raw::c_int; pub trait AsRawFd { /// Extracts the raw file descriptor. /// - /// This method does **not** pass ownership of the raw file descriptor - /// to the caller. The descriptor is only guaranteed to be valid while - /// the original object has not yet been destroyed. + /// This function is typically used to **borrow** an owned file descriptor. + /// When used in this way, this method does **not** pass ownership of the + /// raw file descriptor to the caller, and the file descriptor is only + /// guaranteed to be valid while the original object has not yet been + /// destroyed. + /// + /// However, borrowing is not strictly required. See [`AsFd::as_fd`] + /// for an API which strictly borrows a handle. /// /// # Example /// @@ -55,15 +60,17 @@ pub trait FromRawFd { /// Constructs a new instance of `Self` from the given raw file /// descriptor. /// - /// This function **consumes ownership** of the specified file - /// descriptor. The returned object will take responsibility for closing - /// it when the object goes out of scope. + /// This function is typically used to **consume ownership** of the + /// specified file descriptor. When used in this way, the returned object + /// will take responsibility for closing it when the object goes out of + /// scope. /// - /// This function is also unsafe as the primitives currently returned - /// have the contract that they are the sole owner of the file - /// descriptor they are wrapping. Usage of this function could - /// accidentally allow violating this contract which can cause memory - /// unsafety in code that relies on it being true. + /// However, consuming ownership is not strictly required. See + /// [`FromFd::from_fd`] for an API which strictly consumes ownership. + /// + /// # Safety + /// + /// The `fd` passed in must be a valid an open file descriptor. /// /// # Example /// @@ -94,9 +101,12 @@ pub trait FromRawFd { pub trait IntoRawFd { /// Consumes this object, returning the raw underlying file descriptor. /// - /// This function **transfers ownership** of the underlying file descriptor - /// to the caller. Callers are then the unique owners of the file descriptor - /// and must close the descriptor once it's no longer needed. + /// This function is typically used to **transfer ownership** of the underlying + /// file descriptor to the caller. When used in this way, callers are then the unique + /// owners of the file descriptor and must close it once it's no longer needed. + /// + /// However, transferring ownership is not strictly required. See + /// [`IntoFd::into_fd`] for an API which strictly transfers ownership. /// /// # Example /// diff --git a/library/std/src/os/windows/io/handle.rs b/library/std/src/os/windows/io/handle.rs index e37ce633a12..b9951a4249f 100644 --- a/library/std/src/os/windows/io/handle.rs +++ b/library/std/src/os/windows/io/handle.rs @@ -210,29 +210,13 @@ impl IntoRawHandle for OwnedHandle { } impl FromRawHandle for OwnedHandle { - /// Constructs a new instance of `Self` from the given raw handle. - /// - /// # Safety - /// - /// The resource pointed to by `handle` must be open and suitable for - /// assuming ownership. The resource must not require any cleanup other - /// than `CloseHandle`. - /// - /// In particular, it must not be used with handles to open registry - /// keys which need to be closed with [`RegCloseKey`] instead. - /// - /// Note that it *may* have the value `INVALID_HANDLE_VALUE` (-1), which is - /// sometimes a valid handle value. See [here] for the full story. - /// - /// [`RegCloseKey`]: https://docs.microsoft.com/en-us/windows/win32/api/winreg/nf-winreg-regclosekey - /// [here]: https://devblogs.microsoft.com/oldnewthing/20040302-00/?p=40443 #[inline] unsafe fn from_raw_handle(handle: RawHandle) -> Self { Self { handle } } } -impl FromRawHandle for HandleOrNull { +impl HandleOrNull { /// Constructs a new instance of `Self` from the given `RawHandle` returned /// from a Windows API that uses null to indicate failure, such as /// `CreateThread`. @@ -242,9 +226,9 @@ impl FromRawHandle for HandleOrNull { /// /// # Safety /// - /// The resource pointed to by `handle` must be either open and otherwise - /// unowned, or null. Note that not all Windows APIs use null for errors; - /// see [here] for the full story. + /// The passed `handle` value must either satisfy the safety requirements + /// of [`FromRawHandle::from_raw_handle`], or be null. Note that not all + /// Windows APIs use null for errors; see [here] for the full story. /// /// [here]: https://devblogs.microsoft.com/oldnewthing/20040302-00/?p=40443 #[inline] @@ -253,7 +237,7 @@ impl FromRawHandle for HandleOrNull { } } -impl FromRawHandle for HandleOrInvalid { +impl HandleOrInvalid { /// Constructs a new instance of `Self` from the given `RawHandle` returned /// from a Windows API that uses `INVALID_HANDLE_VALUE` to indicate /// failure, such as `CreateFileW`. @@ -263,10 +247,10 @@ impl FromRawHandle for HandleOrInvalid { /// /// # Safety /// - /// The resource pointed to by `handle` must be either open and otherwise - /// unowned, null, or equal to `INVALID_HANDLE_VALUE` (-1). Note that not - /// all Windows APIs use `INVALID_HANDLE_VALUE` for errors; see [here] for - /// the full story. + /// The passed `handle` value must either satisfy the safety requirements + /// of [`FromRawHandle::from_raw_handle`], or be + /// `INVALID_HANDLE_VALUE` (-1). Note that not all Windows APIs use + /// `INVALID_HANDLE_VALUE` for errors; see [here] for the full story. /// /// [here]: https://devblogs.microsoft.com/oldnewthing/20040302-00/?p=40443 #[inline] diff --git a/library/std/src/os/windows/io/raw.rs b/library/std/src/os/windows/io/raw.rs index c7f122048a1..580ebfe92d7 100644 --- a/library/std/src/os/windows/io/raw.rs +++ b/library/std/src/os/windows/io/raw.rs @@ -22,7 +22,15 @@ pub type RawSocket = raw::SOCKET; /// Extracts raw handles. #[stable(feature = "rust1", since = "1.0.0")] pub trait AsRawHandle { - /// Extracts the raw handle, without taking any ownership. + /// Extracts the raw handle. + /// + /// This function is typically used to **borrow** an owned handle. + /// When used in this way, this method does **not** pass ownership of the + /// raw handle to the caller, and the handle is only guaranteed + /// to be valid while the original object has not yet been destroyed. + /// + /// However, borrowing is not strictly required. See [`AsHandle::as_handle`] + /// for an API which strictly borrows a handle. #[stable(feature = "rust1", since = "1.0.0")] fn as_raw_handle(&self) -> RawHandle; } @@ -32,15 +40,29 @@ pub trait AsRawHandle { pub trait FromRawHandle { /// Constructs a new I/O object from the specified raw handle. /// - /// This function will **consume ownership** of the handle given, - /// passing responsibility for closing the handle to the returned - /// object. + /// This function is typically used to **consume ownership** of the handle + /// given, passing responsibility for closing the handle to the returned + /// object. When used in this way, the returned object + /// will take responsibility for closing it when the object goes out of + /// scope. /// - /// This function is also unsafe as the primitives currently returned - /// have the contract that they are the sole owner of the file - /// descriptor they are wrapping. Usage of this function could - /// accidentally allow violating this contract which can cause memory - /// unsafety in code that relies on it being true. + /// However, consuming ownership is not strictly required. See + /// [`FromHandle::from_handle`] for an API which strictly consumes ownership. + /// + /// # Safety + /// + /// The `handle` passed in must: + /// - be a valid an open handle, + /// - be a handle opened for synchronous I/O, *without* the + /// `FILE_FLAG_OVERLAPPED` flag, and + /// - be a handle for a resource that may be freed via [`CloseHandle`] + /// (as opposed to `RegCloseKey` or other close functions). + /// + /// Note that the handle *may* have the value `INVALID_HANDLE_VALUE` (-1), + /// which is sometimes a valid handle value. See [here] for the full story. + /// + /// [`CloseHandle`]: https://docs.microsoft.com/en-us/windows/win32/api/handleapi/nf-handleapi-closehandle + /// [here]: https://devblogs.microsoft.com/oldnewthing/20040302-00/?p=40443 #[stable(feature = "from_raw_os", since = "1.1.0")] unsafe fn from_raw_handle(handle: RawHandle) -> Self; } @@ -51,9 +73,12 @@ pub trait FromRawHandle { pub trait IntoRawHandle { /// Consumes this object, returning the raw underlying handle. /// - /// This function **transfers ownership** of the underlying handle to the - /// caller. Callers are then the unique owners of the handle and must close - /// it once it's no longer needed. + /// This function is typically used to **transfer ownership** of the underlying + /// handle to the caller. When used in this way, callers are then the unique + /// owners of the handle and must close it once it's no longer needed. + /// + /// However, transferring ownership is not strictly required. See + /// [`IntoHandle::into_handle`] for an API which strictly transfers ownership. #[stable(feature = "into_raw_os", since = "1.4.0")] fn into_raw_handle(self) -> RawHandle; } @@ -130,7 +155,15 @@ impl IntoRawHandle for fs::File { /// Extracts raw sockets. #[stable(feature = "rust1", since = "1.0.0")] pub trait AsRawSocket { - /// Extracts the underlying raw socket from this object. + /// Extracts the raw socket. + /// + /// This function is typically used to **borrow** an owned socket. + /// When used in this way, this method does **not** pass ownership of the + /// raw socket to the caller, and the socket is only guaranteed + /// to be valid while the original object has not yet been destroyed. + /// + /// However, borrowing is not strictly required. See [`AsSocket::as_socket`] + /// for an API which strictly borrows a socket. #[stable(feature = "rust1", since = "1.0.0")] fn as_raw_socket(&self) -> RawSocket; } @@ -138,16 +171,24 @@ pub trait AsRawSocket { /// Creates I/O objects from raw sockets. #[stable(feature = "from_raw_os", since = "1.1.0")] pub trait FromRawSocket { - /// Creates a new I/O object from the given raw socket. + /// Constructs a new I/O object from the specified raw socket. /// - /// This function will **consume ownership** of the socket provided and - /// it will be closed when the returned object goes out of scope. + /// This function is typically used to **consume ownership** of the socket + /// given, passing responsibility for closing the socket to the returned + /// object. When used in this way, the returned object + /// will take responsibility for closing it when the object goes out of + /// scope. /// - /// This function is also unsafe as the primitives currently returned - /// have the contract that they are the sole owner of the file - /// descriptor they are wrapping. Usage of this function could - /// accidentally allow violating this contract which can cause memory - /// unsafety in code that relies on it being true. + /// However, consuming ownership is not strictly required. See + /// [`FromSocket::from_socket`] for an API which strictly consumes ownership. + /// + /// # Safety + /// + /// The `socket` passed in must: + /// - be a valid an open socket, + /// - be a handle for a resource that may be freed via [`closesocket`]. + /// + /// [`closesocket`]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-closesocket #[stable(feature = "from_raw_os", since = "1.1.0")] unsafe fn from_raw_socket(sock: RawSocket) -> Self; } @@ -158,9 +199,12 @@ pub trait FromRawSocket { pub trait IntoRawSocket { /// Consumes this object, returning the raw underlying socket. /// - /// This function **transfers ownership** of the underlying socket to the - /// caller. Callers are then the unique owners of the socket and must close - /// it once it's no longer needed. + /// This function is typically used to **transfer ownership** of the underlying + /// socket to the caller. When used in this way, callers are then the unique + /// owners of the socket and must close it once it's no longer needed. + /// + /// However, transferring ownership is not strictly required. See + /// [`IntoSocket::into_socket`] for an API which strictly transfers ownership. #[stable(feature = "into_raw_os", since = "1.4.0")] fn into_raw_socket(self) -> RawSocket; } From 713bb19ca3a838356324a447ad46d88e5ff002a2 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Tue, 1 Feb 2022 14:23:03 -0800 Subject: [PATCH 02/17] Add missing `pub` keywords. --- library/std/src/os/windows/io/handle.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/std/src/os/windows/io/handle.rs b/library/std/src/os/windows/io/handle.rs index b9951a4249f..117ba0b4ec6 100644 --- a/library/std/src/os/windows/io/handle.rs +++ b/library/std/src/os/windows/io/handle.rs @@ -232,7 +232,7 @@ impl HandleOrNull { /// /// [here]: https://devblogs.microsoft.com/oldnewthing/20040302-00/?p=40443 #[inline] - unsafe fn from_raw_handle(handle: RawHandle) -> Self { + pub unsafe fn from_raw_handle(handle: RawHandle) -> Self { Self(OwnedHandle::from_raw_handle(handle)) } } @@ -254,7 +254,7 @@ impl HandleOrInvalid { /// /// [here]: https://devblogs.microsoft.com/oldnewthing/20040302-00/?p=40443 #[inline] - unsafe fn from_raw_handle(handle: RawHandle) -> Self { + pub unsafe fn from_raw_handle(handle: RawHandle) -> Self { Self(OwnedHandle::from_raw_handle(handle)) } } From 8516895170a12710dbe68ed3ad4bf8273f7f375a Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Tue, 1 Feb 2022 14:27:54 -0800 Subject: [PATCH 03/17] Fix two copy+pastos. --- library/std/src/os/fd/raw.rs | 2 +- library/std/src/os/windows/io/raw.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/library/std/src/os/fd/raw.rs b/library/std/src/os/fd/raw.rs index 6925269c8f1..4af1c9bd8d7 100644 --- a/library/std/src/os/fd/raw.rs +++ b/library/std/src/os/fd/raw.rs @@ -31,7 +31,7 @@ pub trait AsRawFd { /// destroyed. /// /// However, borrowing is not strictly required. See [`AsFd::as_fd`] - /// for an API which strictly borrows a handle. + /// for an API which strictly borrows a file descriptor. /// /// # Example /// diff --git a/library/std/src/os/windows/io/raw.rs b/library/std/src/os/windows/io/raw.rs index 580ebfe92d7..240d14236e5 100644 --- a/library/std/src/os/windows/io/raw.rs +++ b/library/std/src/os/windows/io/raw.rs @@ -186,7 +186,7 @@ pub trait FromRawSocket { /// /// The `socket` passed in must: /// - be a valid an open socket, - /// - be a handle for a resource that may be freed via [`closesocket`]. + /// - be a socket that may be freed via [`closesocket`]. /// /// [`closesocket`]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-closesocket #[stable(feature = "from_raw_os", since = "1.1.0")] From 6ef7ee36c2103113d572a1ff6e8de68809639649 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Tue, 1 Feb 2022 14:37:15 -0800 Subject: [PATCH 04/17] Fix unresolved doc links. --- library/std/src/os/fd/raw.rs | 4 ++++ library/std/src/os/windows/io/raw.rs | 2 ++ 2 files changed, 6 insertions(+) diff --git a/library/std/src/os/fd/raw.rs b/library/std/src/os/fd/raw.rs index 4af1c9bd8d7..192ada4a255 100644 --- a/library/std/src/os/fd/raw.rs +++ b/library/std/src/os/fd/raw.rs @@ -7,6 +7,10 @@ use crate::io; use crate::os::raw; #[cfg(unix)] use crate::os::unix::io::OwnedFd; +#[all(cfg(doc), unix)] +use crate::os::unix::io::{AsFd, FromFd, IntoFd}; +#[all(cfg(doc), target_os = "wasi")] +use crate::os::unix::io::{AsFd, FromFd, IntoFd}; #[cfg(target_os = "wasi")] use crate::os::wasi::io::OwnedFd; use crate::sys_common::{AsInner, IntoInner}; diff --git a/library/std/src/os/windows/io/raw.rs b/library/std/src/os/windows/io/raw.rs index 240d14236e5..6ecffcb8a17 100644 --- a/library/std/src/os/windows/io/raw.rs +++ b/library/std/src/os/windows/io/raw.rs @@ -5,6 +5,8 @@ use crate::fs; use crate::io; use crate::net; +#[all(cfg(doc), unix)] +use crate::os::windows::io::{AsHandle, AsSocket, FromHandle, FromSocket, IntoHandle, IntoSocket}; use crate::os::windows::io::{OwnedHandle, OwnedSocket}; use crate::os::windows::raw; use crate::sys; From 89544e900125aed4899706c78e8bbce5cb5f1023 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Tue, 1 Feb 2022 14:38:23 -0800 Subject: [PATCH 05/17] Fix errors. --- library/std/src/os/fd/raw.rs | 4 ++-- library/std/src/os/windows/io/raw.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/library/std/src/os/fd/raw.rs b/library/std/src/os/fd/raw.rs index 192ada4a255..bc3007da86a 100644 --- a/library/std/src/os/fd/raw.rs +++ b/library/std/src/os/fd/raw.rs @@ -7,9 +7,9 @@ use crate::io; use crate::os::raw; #[cfg(unix)] use crate::os::unix::io::OwnedFd; -#[all(cfg(doc), unix)] +#[cfg(all(doc, unix))] use crate::os::unix::io::{AsFd, FromFd, IntoFd}; -#[all(cfg(doc), target_os = "wasi")] +#[cfg(all(doc, target_os = "wasi"))] use crate::os::unix::io::{AsFd, FromFd, IntoFd}; #[cfg(target_os = "wasi")] use crate::os::wasi::io::OwnedFd; diff --git a/library/std/src/os/windows/io/raw.rs b/library/std/src/os/windows/io/raw.rs index 6ecffcb8a17..285802c6a9e 100644 --- a/library/std/src/os/windows/io/raw.rs +++ b/library/std/src/os/windows/io/raw.rs @@ -5,7 +5,7 @@ use crate::fs; use crate::io; use crate::net; -#[all(cfg(doc), unix)] +#[cfg(doc)] use crate::os::windows::io::{AsHandle, AsSocket, FromHandle, FromSocket, IntoHandle, IntoSocket}; use crate::os::windows::io::{OwnedHandle, OwnedSocket}; use crate::os::windows::raw; From 656d2a3a12746d624b8ee9dada8a70d708e1526c Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Tue, 1 Feb 2022 14:57:31 -0800 Subject: [PATCH 06/17] Use `From`/`Into` rather than the traits they replaced. --- library/std/src/os/fd/raw.rs | 14 ++++++++------ library/std/src/os/windows/io/raw.rs | 22 +++++++++++++--------- 2 files changed, 21 insertions(+), 15 deletions(-) diff --git a/library/std/src/os/fd/raw.rs b/library/std/src/os/fd/raw.rs index bc3007da86a..6feea737f3b 100644 --- a/library/std/src/os/fd/raw.rs +++ b/library/std/src/os/fd/raw.rs @@ -8,9 +8,9 @@ use crate::os::raw; #[cfg(unix)] use crate::os::unix::io::OwnedFd; #[cfg(all(doc, unix))] -use crate::os::unix::io::{AsFd, FromFd, IntoFd}; +use crate::os::unix::io::AsFd; #[cfg(all(doc, target_os = "wasi"))] -use crate::os::unix::io::{AsFd, FromFd, IntoFd}; +use crate::os::unix::io::AsFd; #[cfg(target_os = "wasi")] use crate::os::wasi::io::OwnedFd; use crate::sys_common::{AsInner, IntoInner}; @@ -69,8 +69,9 @@ pub trait FromRawFd { /// will take responsibility for closing it when the object goes out of /// scope. /// - /// However, consuming ownership is not strictly required. See - /// [`FromFd::from_fd`] for an API which strictly consumes ownership. + /// However, consuming ownership is not strictly required. Use a + /// [`From::from`] implementation for an API which strictly + /// consumes ownership. /// /// # Safety /// @@ -109,8 +110,9 @@ pub trait IntoRawFd { /// file descriptor to the caller. When used in this way, callers are then the unique /// owners of the file descriptor and must close it once it's no longer needed. /// - /// However, transferring ownership is not strictly required. See - /// [`IntoFd::into_fd`] for an API which strictly transfers ownership. + /// However, transferring ownership is not strictly required. Use a + /// [`Into::into`] implementation for an API which strictly + /// transfers ownership. /// /// # Example /// diff --git a/library/std/src/os/windows/io/raw.rs b/library/std/src/os/windows/io/raw.rs index 285802c6a9e..dc84a38156a 100644 --- a/library/std/src/os/windows/io/raw.rs +++ b/library/std/src/os/windows/io/raw.rs @@ -6,7 +6,7 @@ use crate::fs; use crate::io; use crate::net; #[cfg(doc)] -use crate::os::windows::io::{AsHandle, AsSocket, FromHandle, FromSocket, IntoHandle, IntoSocket}; +use crate::os::windows::io::{AsHandle, AsSocket}; use crate::os::windows::io::{OwnedHandle, OwnedSocket}; use crate::os::windows::raw; use crate::sys; @@ -48,8 +48,9 @@ pub trait FromRawHandle { /// will take responsibility for closing it when the object goes out of /// scope. /// - /// However, consuming ownership is not strictly required. See - /// [`FromHandle::from_handle`] for an API which strictly consumes ownership. + /// However, consuming ownership is not strictly required. Use a + /// `From::from` implementation for an API which strictly + /// consumes ownership. /// /// # Safety /// @@ -79,8 +80,9 @@ pub trait IntoRawHandle { /// handle to the caller. When used in this way, callers are then the unique /// owners of the handle and must close it once it's no longer needed. /// - /// However, transferring ownership is not strictly required. See - /// [`IntoHandle::into_handle`] for an API which strictly transfers ownership. + /// However, transferring ownership is not strictly required. Use a + /// `Into::into` implementation for an API which strictly + /// transfers ownership. #[stable(feature = "into_raw_os", since = "1.4.0")] fn into_raw_handle(self) -> RawHandle; } @@ -181,8 +183,9 @@ pub trait FromRawSocket { /// will take responsibility for closing it when the object goes out of /// scope. /// - /// However, consuming ownership is not strictly required. See - /// [`FromSocket::from_socket`] for an API which strictly consumes ownership. + /// However, consuming ownership is not strictly required. Use a + /// `From::from` implementation for an API which strictly + /// consumes ownership. /// /// # Safety /// @@ -205,8 +208,9 @@ pub trait IntoRawSocket { /// socket to the caller. When used in this way, callers are then the unique /// owners of the socket and must close it once it's no longer needed. /// - /// However, transferring ownership is not strictly required. See - /// [`IntoSocket::into_socket`] for an API which strictly transfers ownership. + /// However, transferring ownership is not strictly required. Use a + /// `Into::into` implementation for an API which strictly + /// transfers ownership. #[stable(feature = "into_raw_os", since = "1.4.0")] fn into_raw_socket(self) -> RawSocket; } From f88fb2a9a5d5f3acf5ff284c411022e14c28207b Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Tue, 1 Feb 2022 15:10:59 -0800 Subject: [PATCH 07/17] x.py fmt --- library/std/src/os/fd/raw.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/std/src/os/fd/raw.rs b/library/std/src/os/fd/raw.rs index 6feea737f3b..35b8b950372 100644 --- a/library/std/src/os/fd/raw.rs +++ b/library/std/src/os/fd/raw.rs @@ -5,12 +5,12 @@ use crate::fs; use crate::io; use crate::os::raw; -#[cfg(unix)] -use crate::os::unix::io::OwnedFd; #[cfg(all(doc, unix))] use crate::os::unix::io::AsFd; #[cfg(all(doc, target_os = "wasi"))] use crate::os::unix::io::AsFd; +#[cfg(unix)] +use crate::os::unix::io::OwnedFd; #[cfg(target_os = "wasi")] use crate::os::wasi::io::OwnedFd; use crate::sys_common::{AsInner, IntoInner}; From ba6050f7421bb6a1f00b6633257ce60cd25089b7 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Wed, 2 Feb 2022 16:23:23 -0800 Subject: [PATCH 08/17] Remove the documentation comment for `OwnedSocket::from_raw_socket`. This function is documented in more detail in the `FromRawSocket` trait. --- library/std/src/os/windows/io/socket.rs | 7 ------- 1 file changed, 7 deletions(-) diff --git a/library/std/src/os/windows/io/socket.rs b/library/std/src/os/windows/io/socket.rs index 26b569bcdd3..c1bdef29f53 100644 --- a/library/std/src/os/windows/io/socket.rs +++ b/library/std/src/os/windows/io/socket.rs @@ -168,13 +168,6 @@ impl IntoRawSocket for OwnedSocket { } impl FromRawSocket for OwnedSocket { - /// Constructs a new instance of `Self` from the given raw socket. - /// - /// # Safety - /// - /// The resource pointed to by `socket` must be open and suitable for - /// assuming ownership. The resource must not require cleanup other than - /// `closesocket`. #[inline] unsafe fn from_raw_socket(socket: RawSocket) -> Self { debug_assert_ne!(socket, c::INVALID_SOCKET as RawSocket); From 547509e15e5157e900582ecb6bf1d4a3a44a5b44 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Thu, 17 Feb 2022 14:25:43 -0700 Subject: [PATCH 09/17] rustdoc: add test cases for hidden enum variants --- src/test/rustdoc/strip-enum-variant.rs | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 src/test/rustdoc/strip-enum-variant.rs diff --git a/src/test/rustdoc/strip-enum-variant.rs b/src/test/rustdoc/strip-enum-variant.rs new file mode 100644 index 00000000000..12e57610071 --- /dev/null +++ b/src/test/rustdoc/strip-enum-variant.rs @@ -0,0 +1,9 @@ +// @has strip_enum_variant/enum.MyThing.html +// @has - '//code' 'Shown' +// @!has - '//code' 'NotShown' +// @has - '//code' '// some variants omitted' +pub enum MyThing { + Shown, + #[doc(hidden)] + NotShown, +} From bc31b3e5efd7500f25681dcaad2f41a6c3ead6d0 Mon Sep 17 00:00:00 2001 From: Thiago Trannin <51510921+thinety@users.noreply.github.com> Date: Wed, 2 Mar 2022 10:09:02 -0300 Subject: [PATCH 10/17] Remove out-of-context line at end of E0284 message --- compiler/rustc_error_codes/src/error_codes/E0284.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/compiler/rustc_error_codes/src/error_codes/E0284.md b/compiler/rustc_error_codes/src/error_codes/E0284.md index 82598aeec02..5a92f8352d2 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0284.md +++ b/compiler/rustc_error_codes/src/error_codes/E0284.md @@ -30,5 +30,3 @@ fn main() { d = d + m; } ``` - -Note that the type of `v` can now be inferred from the type of `temp`. From 9aed829fe6cdf5eaf278c6c3972f7acd0830887d Mon Sep 17 00:00:00 2001 From: bstrie <865233+bstrie@users.noreply.github.com> Date: Wed, 2 Mar 2022 13:52:31 -0500 Subject: [PATCH 11/17] Re-export core::ffi types from std::ffi --- library/std/src/ffi/mod.rs | 9 +++++++++ library/std/src/lib.rs | 1 + 2 files changed, 10 insertions(+) diff --git a/library/std/src/ffi/mod.rs b/library/std/src/ffi/mod.rs index 019b64c395e..13e3dacc30d 100644 --- a/library/std/src/ffi/mod.rs +++ b/library/std/src/ffi/mod.rs @@ -159,6 +159,15 @@ pub use self::os_str::{OsStr, OsString}; #[stable(feature = "core_c_void", since = "1.30.0")] pub use core::ffi::c_void; +#[unstable(feature = "core_ffi_c", issue = "94501")] +pub use core::ffi::{ + c_char, c_double, c_float, c_int, c_long, c_longlong, c_schar, c_short, c_uchar, c_uint, + c_ulong, c_ulonglong, c_ushort, +}; + +#[unstable(feature = "c_size_t", issue = "88345")] +pub use core::ffi::{c_ptrdiff_t, c_size_t, c_ssize_t}; + #[unstable( feature = "c_variadic", reason = "the `c_variadic` feature has not been properly tested on \ diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 4603b5aae20..10fec8e1152 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -261,6 +261,7 @@ #![feature(const_socketaddr)] #![feature(const_trait_impl)] #![feature(container_error_extra)] +#![feature(c_size_t)] #![feature(core_ffi_c)] #![feature(core_intrinsics)] #![feature(core_panic)] From 658ff942b04d288b346a7e89ac425216688fac78 Mon Sep 17 00:00:00 2001 From: Caio Date: Wed, 2 Mar 2022 16:02:37 -0300 Subject: [PATCH 12/17] 8 - Make more use of `let_chains` --- .../src/infer/error_reporting/mod.rs | 77 ++++++++-------- .../infer/error_reporting/need_type_info.rs | 89 +++++++++---------- .../nice_region_error/static_impl_trait.rs | 47 +++++----- .../trait_impl_difference.rs | 64 ++++++------- compiler/rustc_infer/src/infer/fudge.rs | 10 +-- .../src/infer/lexical_region_resolve/mod.rs | 12 +-- .../rustc_infer/src/infer/nll_relate/mod.rs | 6 +- .../src/infer/region_constraints/mod.rs | 6 +- compiler/rustc_infer/src/lib.rs | 11 +-- .../src/traits/error_reporting/mod.rs | 10 +-- 10 files changed, 146 insertions(+), 186 deletions(-) diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index edb2b11c039..bf4882d4595 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -606,17 +606,16 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { // don't show type `_` err.span_label(span, format!("this expression has type `{}`", ty)); } - if let Some(ty::error::ExpectedFound { found, .. }) = exp_found { - if ty.is_box() && ty.boxed_ty() == found { - if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) { - err.span_suggestion( - span, - "consider dereferencing the boxed value", - format!("*{}", snippet), - Applicability::MachineApplicable, - ); - } - } + if let Some(ty::error::ExpectedFound { found, .. }) = exp_found + && ty.is_box() && ty.boxed_ty() == found + && let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) + { + err.span_suggestion( + span, + "consider dereferencing the boxed value", + format!("*{}", snippet), + Applicability::MachineApplicable, + ); } } ObligationCauseCode::Pattern { origin_expr: false, span: Some(span), .. } => { @@ -1748,13 +1747,12 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { self.check_and_note_conflicting_crates(diag, terr); self.tcx.note_and_explain_type_err(diag, terr, cause, span, body_owner_def_id.to_def_id()); - if let Some(ValuePairs::PolyTraitRefs(exp_found)) = values { - if let ty::Closure(def_id, _) = exp_found.expected.skip_binder().self_ty().kind() { - if let Some(def_id) = def_id.as_local() { - let span = self.tcx.def_span(def_id); - diag.span_note(span, "this closure does not fulfill the lifetime requirements"); - } - } + if let Some(ValuePairs::PolyTraitRefs(exp_found)) = values + && let ty::Closure(def_id, _) = exp_found.expected.skip_binder().self_ty().kind() + && let Some(def_id) = def_id.as_local() + { + let span = self.tcx.def_span(def_id); + diag.span_note(span, "this closure does not fulfill the lifetime requirements"); } // It reads better to have the error origin as the final @@ -2046,19 +2044,16 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { // containing a single character, perhaps the user meant to write `'c'` to // specify a character literal (issue #92479) (ty::Char, ty::Ref(_, r, _)) if r.is_str() => { - if let Ok(code) = self.tcx.sess().source_map().span_to_snippet(span) { - if let Some(code) = - code.strip_prefix('"').and_then(|s| s.strip_suffix('"')) - { - if code.chars().count() == 1 { - err.span_suggestion( - span, - "if you meant to write a `char` literal, use single quotes", - format!("'{}'", code), - Applicability::MachineApplicable, - ); - } - } + if let Ok(code) = self.tcx.sess().source_map().span_to_snippet(span) + && let Some(code) = code.strip_prefix('"').and_then(|s| s.strip_suffix('"')) + && code.chars().count() == 1 + { + err.span_suggestion( + span, + "if you meant to write a `char` literal, use single quotes", + format!("'{}'", code), + Applicability::MachineApplicable, + ); } } // If a string was expected and the found expression is a character literal, @@ -2080,18 +2075,16 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { _ => {} } } - if let MatchExpressionArm(box MatchExpressionArmCause { source, .. }) = - *trace.cause.code() + let code = trace.cause.code(); + if let &MatchExpressionArm(box MatchExpressionArmCause { source, .. }) = code + && let hir::MatchSource::TryDesugar = source + && let Some((expected_ty, found_ty)) = self.values_str(trace.values) { - if let hir::MatchSource::TryDesugar = source { - if let Some((expected_ty, found_ty)) = self.values_str(trace.values) { - err.note(&format!( - "`?` operator cannot convert from `{}` to `{}`", - found_ty.content(), - expected_ty.content(), - )); - } - } + err.note(&format!( + "`?` operator cannot convert from `{}` to `{}`", + found_ty.content(), + expected_ty.content(), + )); } err } diff --git a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs index 8ff0eed71ed..3bc30f0220d 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs @@ -114,28 +114,25 @@ impl<'a, 'tcx> Visitor<'tcx> for FindHirNodeVisitor<'a, 'tcx> { } fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) { - if let ExprKind::Match(scrutinee, [_, arm], MatchSource::ForLoopDesugar) = expr.kind { - if let Some(pat) = arm.pat.for_loop_some() { - if let Some(ty) = self.node_ty_contains_target(pat.hir_id) { - self.found_for_loop_iter = Some(scrutinee); - self.found_node_ty = Some(ty); - return; - } - } + if let ExprKind::Match(scrutinee, [_, arm], MatchSource::ForLoopDesugar) = expr.kind + && let Some(pat) = arm.pat.for_loop_some() + && let Some(ty) = self.node_ty_contains_target(pat.hir_id) + { + self.found_for_loop_iter = Some(scrutinee); + self.found_node_ty = Some(ty); + return; } - if let ExprKind::MethodCall(segment, exprs, _) = expr.kind { - if segment.ident.span == self.target_span - && Some(self.target) - == self.infcx.in_progress_typeck_results.and_then(|typeck_results| { - typeck_results - .borrow() - .node_type_opt(exprs.first().unwrap().hir_id) - .map(Into::into) - }) - { - self.found_exact_method_call = Some(&expr); - return; - } + if let ExprKind::MethodCall(segment, exprs, _) = expr.kind + && segment.ident.span == self.target_span + && Some(self.target) == self.infcx.in_progress_typeck_results.and_then(|typeck_results| { + typeck_results + .borrow() + .node_type_opt(exprs.first().unwrap().hir_id) + .map(Into::into) + }) + { + self.found_exact_method_call = Some(&expr); + return; } // FIXME(const_generics): Currently, any uninferred `const` generics arguments @@ -602,10 +599,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { ); let use_diag = local_visitor.found_use_diagnostic.as_ref(); - if let Some(use_diag) = use_diag { - if use_diag.applies_to(err_span) { - use_diag.attach_note(&mut err); - } + if let Some(use_diag) = use_diag && use_diag.applies_to(err_span) { + use_diag.attach_note(&mut err); } let param_type = arg_data.kind.descr(); @@ -736,29 +731,27 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { // | help: specify type like: `>::into(foo_impl)` // | // = note: cannot satisfy `Impl: Into<_>` - if !impl_candidates.is_empty() && e.span.contains(span) { - if let Some(expr) = exprs.first() { - if let ExprKind::Path(hir::QPath::Resolved(_, path)) = expr.kind { - if let [path_segment] = path.segments { - let candidate_len = impl_candidates.len(); - let suggestions = impl_candidates.iter().map(|candidate| { - format!( - "{}::{}({})", - candidate, segment.ident, path_segment.ident - ) - }); - err.span_suggestions( - e.span, - &format!( - "use the fully qualified path for the potential candidate{}", - pluralize!(candidate_len), - ), - suggestions, - Applicability::MaybeIncorrect, - ); - } - } - }; + if !impl_candidates.is_empty() && e.span.contains(span) + && let Some(expr) = exprs.first() + && let ExprKind::Path(hir::QPath::Resolved(_, path)) = expr.kind + && let [path_segment] = path.segments + { + let candidate_len = impl_candidates.len(); + let suggestions = impl_candidates.iter().map(|candidate| { + format!( + "{}::{}({})", + candidate, segment.ident, path_segment.ident + ) + }); + err.span_suggestions( + e.span, + &format!( + "use the fully qualified path for the potential candidate{}", + pluralize!(candidate_len), + ), + suggestions, + Applicability::MaybeIncorrect, + ); } // Suggest specifying type params or point out the return type of the call: // diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs index a6de0c3d9fb..99dd418015b 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs @@ -223,35 +223,32 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { let fn_returns = tcx.return_type_impl_or_dyn_traits(anon_reg_sup.def_id); let mut override_error_code = None; - if let SubregionOrigin::Subtype(box TypeTrace { cause, .. }) = &sup_origin { - if let ObligationCauseCode::UnifyReceiver(ctxt) = cause.code() { - // Handle case of `impl Foo for dyn Bar { fn qux(&self) {} }` introducing a - // `'static` lifetime when called as a method on a binding: `bar.qux()`. - if self.find_impl_on_dyn_trait(&mut err, param.param_ty, &ctxt) { - override_error_code = Some(ctxt.assoc_item.name); - } - } + if let SubregionOrigin::Subtype(box TypeTrace { cause, .. }) = &sup_origin + && let ObligationCauseCode::UnifyReceiver(ctxt) = cause.code() + // Handle case of `impl Foo for dyn Bar { fn qux(&self) {} }` introducing a + // `'static` lifetime when called as a method on a binding: `bar.qux()`. + && self.find_impl_on_dyn_trait(&mut err, param.param_ty, &ctxt) + { + override_error_code = Some(ctxt.assoc_item.name); } - if let SubregionOrigin::Subtype(box TypeTrace { cause, .. }) = &sub_origin { - let code = match cause.code() { + + if let SubregionOrigin::Subtype(box TypeTrace { cause, .. }) = &sub_origin + && let code = match cause.code() { ObligationCauseCode::MatchImpl(parent, ..) => parent.code(), _ => cause.code(), - }; - if let (ObligationCauseCode::ItemObligation(item_def_id), None) = - (code, override_error_code) + } + && let (ObligationCauseCode::ItemObligation(item_def_id), None) = (code, override_error_code) + { + // Same case of `impl Foo for dyn Bar { fn qux(&self) {} }` introducing a `'static` + // lifetime as above, but called using a fully-qualified path to the method: + // `Foo::qux(bar)`. + let mut v = TraitObjectVisitor(FxHashSet::default()); + v.visit_ty(param.param_ty); + if let Some((ident, self_ty)) = + self.get_impl_ident_and_self_ty_from_trait(*item_def_id, &v.0) + && self.suggest_constrain_dyn_trait_in_impl(&mut err, &v.0, ident, self_ty) { - // Same case of `impl Foo for dyn Bar { fn qux(&self) {} }` introducing a `'static` - // lifetime as above, but called using a fully-qualified path to the method: - // `Foo::qux(bar)`. - let mut v = TraitObjectVisitor(FxHashSet::default()); - v.visit_ty(param.param_ty); - if let Some((ident, self_ty)) = - self.get_impl_ident_and_self_ty_from_trait(*item_def_id, &v.0) - { - if self.suggest_constrain_dyn_trait_in_impl(&mut err, &v.0, ident, self_ty) { - override_error_code = Some(ident.name); - } - } + override_error_code = Some(ident.name); } } if let (Some(ident), true) = (override_error_code, fn_returns.is_empty()) { diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs index 673c112163e..3f0f50bb75a 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs @@ -23,51 +23,39 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { let error = self.error.as_ref()?; debug!("try_report_impl_not_conforming_to_trait {:?}", error); if let RegionResolutionError::SubSupConflict( - _, - var_origin, - sub_origin, - _sub, - sup_origin, - _sup, - _, - ) = error.clone() + _, var_origin, sub_origin, _sub, sup_origin, _sup, _, + ) = error.clone() + && let (&Subtype(ref sup_trace), &Subtype(ref sub_trace)) = (&sup_origin, &sub_origin) + && let ( + sub_expected_found @ Some((sub_expected, sub_found)), + sup_expected_found @ Some(_), + CompareImplMethodObligation { trait_item_def_id, .. }, + ) = (sub_trace.values.ty(), sup_trace.values.ty(), sub_trace.cause.code()) + && sup_expected_found == sub_expected_found { - if let (&Subtype(ref sup_trace), &Subtype(ref sub_trace)) = (&sup_origin, &sub_origin) { - if let ( - sub_expected_found @ Some((sub_expected, sub_found)), - sup_expected_found @ Some(_), - CompareImplMethodObligation { trait_item_def_id, .. }, - ) = (&sub_trace.values.ty(), &sup_trace.values.ty(), sub_trace.cause.code()) - { - if sup_expected_found == sub_expected_found { - self.emit_err( - var_origin.span(), - *sub_expected, - *sub_found, - *trait_item_def_id, - ); - return Some(ErrorGuaranteed); - } - } - } + self.emit_err( + var_origin.span(), + sub_expected, + sub_found, + *trait_item_def_id, + ); + return Some(ErrorGuaranteed); } if let RegionResolutionError::ConcreteFailure(origin, _, _) - | RegionResolutionError::GenericBoundFailure(origin, _, _) = error.clone() - { - if let SubregionOrigin::CompareImplTypeObligation { + | RegionResolutionError::GenericBoundFailure(origin, _, _) = error.clone() + && let SubregionOrigin::CompareImplTypeObligation { span, impl_item_def_id, trait_item_def_id, } = origin - { - self.emit_associated_type_err( - span, - self.infcx.tcx.item_name(impl_item_def_id), - impl_item_def_id, - trait_item_def_id, - ); - return Some(ErrorGuaranteed); - } + { + self.emit_associated_type_err( + span, + self.infcx.tcx.item_name(impl_item_def_id), + impl_item_def_id, + trait_item_def_id, + ); + return Some(ErrorGuaranteed); } None } diff --git a/compiler/rustc_infer/src/infer/fudge.rs b/compiler/rustc_infer/src/infer/fudge.rs index c5c131a5b79..c5b90f79dc2 100644 --- a/compiler/rustc_infer/src/infer/fudge.rs +++ b/compiler/rustc_infer/src/infer/fudge.rs @@ -220,12 +220,10 @@ impl<'a, 'tcx> TypeFolder<'tcx> for InferenceFudger<'a, 'tcx> { } fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { - if let ty::ReVar(vid) = *r { - if self.region_vars.0.contains(&vid) { - let idx = vid.index() - self.region_vars.0.start.index(); - let origin = self.region_vars.1[idx]; - return self.infcx.next_region_var(origin); - } + if let ty::ReVar(vid) = *r && self.region_vars.0.contains(&vid) { + let idx = vid.index() - self.region_vars.0.start.index(); + let origin = self.region_vars.1[idx]; + return self.infcx.next_region_var(origin); } r } diff --git a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs index c7b4a96fb78..0f341a947ad 100644 --- a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs +++ b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs @@ -304,10 +304,8 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> { // check below for a common case, here purely as an // optimization. let b_universe = self.var_infos[b_vid].universe; - if let ReEmpty(a_universe) = *a_region { - if a_universe == b_universe { - return false; - } + if let ReEmpty(a_universe) = *a_region && a_universe == b_universe { + return false; } let mut lub = self.lub_concrete_regions(a_region, cur_region); @@ -324,10 +322,8 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> { // tighter bound than `'static`. // // (This might e.g. arise from being asked to prove `for<'a> { 'b: 'a }`.) - if let ty::RePlaceholder(p) = *lub { - if b_universe.cannot_name(p.universe) { - lub = self.tcx().lifetimes.re_static; - } + if let ty::RePlaceholder(p) = *lub && b_universe.cannot_name(p.universe) { + lub = self.tcx().lifetimes.re_static; } debug!("Expanding value of {:?} from {:?} to {:?}", b_vid, cur_region, lub); diff --git a/compiler/rustc_infer/src/infer/nll_relate/mod.rs b/compiler/rustc_infer/src/infer/nll_relate/mod.rs index 60f776d8c1f..69db6509b79 100644 --- a/compiler/rustc_infer/src/infer/nll_relate/mod.rs +++ b/compiler/rustc_infer/src/infer/nll_relate/mod.rs @@ -963,10 +963,8 @@ where ) -> RelateResult<'tcx, ty::Region<'tcx>> { debug!("TypeGeneralizer::regions(a={:?})", a); - if let ty::ReLateBound(debruijn, _) = *a { - if debruijn < self.first_free_index { - return Ok(a); - } + if let ty::ReLateBound(debruijn, _) = *a && debruijn < self.first_free_index { + return Ok(a); } // For now, we just always create a fresh region variable to diff --git a/compiler/rustc_infer/src/infer/region_constraints/mod.rs b/compiler/rustc_infer/src/infer/region_constraints/mod.rs index a5bd3b15c8d..6966f501446 100644 --- a/compiler/rustc_infer/src/infer/region_constraints/mod.rs +++ b/compiler/rustc_infer/src/infer/region_constraints/mod.rs @@ -470,10 +470,8 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> { debug!("RegionConstraintCollector: add_verify({:?})", verify); // skip no-op cases known to be satisfied - if let VerifyBound::AllBounds(ref bs) = verify.bound { - if bs.is_empty() { - return; - } + if let VerifyBound::AllBounds(ref bs) = verify.bound && bs.is_empty() { + return; } let index = self.data.verifys.len(); diff --git a/compiler/rustc_infer/src/lib.rs b/compiler/rustc_infer/src/lib.rs index 4960630051f..08e005364ce 100644 --- a/compiler/rustc_infer/src/lib.rs +++ b/compiler/rustc_infer/src/lib.rs @@ -12,18 +12,19 @@ //! //! This API is completely unstable and subject to change. +#![allow(rustc::potential_query_instability)] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![feature(bool_to_option)] #![feature(box_patterns)] +#![feature(control_flow_enum)] #![feature(derive_default_enum)] #![feature(extend_one)] -#![feature(let_else)] -#![feature(never_type)] -#![feature(control_flow_enum)] -#![feature(min_specialization)] #![feature(label_break_value)] +#![feature(let_chains)] +#![feature(let_else)] +#![feature(min_specialization)] +#![feature(never_type)] #![recursion_limit = "512"] // For rustdoc -#![allow(rustc::potential_query_instability)] #[macro_use] extern crate rustc_macros; diff --git a/compiler/rustc_infer/src/traits/error_reporting/mod.rs b/compiler/rustc_infer/src/traits/error_reporting/mod.rs index 5e93c002168..c8ef08f48b6 100644 --- a/compiler/rustc_infer/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/traits/error_reporting/mod.rs @@ -60,12 +60,10 @@ pub fn report_object_safety_error<'tcx>( let mut multi_span = vec![]; let mut messages = vec![]; for violation in violations { - if let ObjectSafetyViolation::SizedSelf(sp) = &violation { - if !sp.is_empty() { - // Do not report `SizedSelf` without spans pointing at `SizedSelf` obligations - // with a `Span`. - reported_violations.insert(ObjectSafetyViolation::SizedSelf(vec![].into())); - } + if let ObjectSafetyViolation::SizedSelf(sp) = &violation && !sp.is_empty() { + // Do not report `SizedSelf` without spans pointing at `SizedSelf` obligations + // with a `Span`. + reported_violations.insert(ObjectSafetyViolation::SizedSelf(vec![].into())); } if reported_violations.insert(violation.clone()) { let spans = violation.spans(); From af642bb466722a9afc84f5e131b7bdd3ed90ad16 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Wed, 2 Mar 2022 12:39:36 -0800 Subject: [PATCH 13/17] Fix a broken doc link on Windows. --- library/std/src/os/fd/raw.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/library/std/src/os/fd/raw.rs b/library/std/src/os/fd/raw.rs index 35b8b950372..f9c883dd6bf 100644 --- a/library/std/src/os/fd/raw.rs +++ b/library/std/src/os/fd/raw.rs @@ -5,9 +5,7 @@ use crate::fs; use crate::io; use crate::os::raw; -#[cfg(all(doc, unix))] -use crate::os::unix::io::AsFd; -#[cfg(all(doc, target_os = "wasi"))] +#[cfg(doc)] use crate::os::unix::io::AsFd; #[cfg(unix)] use crate::os::unix::io::OwnedFd; From 76f0305f8301b2b05a67f8534b1697c1bcc9acfe Mon Sep 17 00:00:00 2001 From: flip1995 Date: Tue, 15 Feb 2022 10:54:38 +0100 Subject: [PATCH 14/17] Move transmute_undefined_repr back to nursery There's still open discussion if this lint is ready to be enabled by default. We want to give us more time to figure this out and prevent this lint from getting to stable as an enabled-by-default lint. --- src/tools/clippy/clippy_lints/src/lib.register_all.rs | 1 - src/tools/clippy/clippy_lints/src/lib.register_correctness.rs | 1 - src/tools/clippy/clippy_lints/src/lib.register_nursery.rs | 1 + src/tools/clippy/clippy_lints/src/transmute/mod.rs | 2 +- 4 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/tools/clippy/clippy_lints/src/lib.register_all.rs b/src/tools/clippy/clippy_lints/src/lib.register_all.rs index f6d467941e3..abfb4603537 100644 --- a/src/tools/clippy/clippy_lints/src/lib.register_all.rs +++ b/src/tools/clippy/clippy_lints/src/lib.register_all.rs @@ -281,7 +281,6 @@ store.register_group(true, "clippy::all", Some("clippy_all"), vec![ LintId::of(transmute::TRANSMUTE_INT_TO_FLOAT), LintId::of(transmute::TRANSMUTE_NUM_TO_BYTES), LintId::of(transmute::TRANSMUTE_PTR_TO_REF), - LintId::of(transmute::TRANSMUTE_UNDEFINED_REPR), LintId::of(transmute::UNSOUND_COLLECTION_TRANSMUTE), LintId::of(transmute::WRONG_TRANSMUTE), LintId::of(transmuting_null::TRANSMUTING_NULL), diff --git a/src/tools/clippy/clippy_lints/src/lib.register_correctness.rs b/src/tools/clippy/clippy_lints/src/lib.register_correctness.rs index 35b1e644a8a..d7bf91eb692 100644 --- a/src/tools/clippy/clippy_lints/src/lib.register_correctness.rs +++ b/src/tools/clippy/clippy_lints/src/lib.register_correctness.rs @@ -58,7 +58,6 @@ store.register_group(true, "clippy::correctness", Some("clippy_correctness"), ve LintId::of(serde_api::SERDE_API_MISUSE), LintId::of(size_of_in_element_count::SIZE_OF_IN_ELEMENT_COUNT), LintId::of(swap::ALMOST_SWAPPED), - LintId::of(transmute::TRANSMUTE_UNDEFINED_REPR), LintId::of(transmute::UNSOUND_COLLECTION_TRANSMUTE), LintId::of(transmute::WRONG_TRANSMUTE), LintId::of(transmuting_null::TRANSMUTING_NULL), diff --git a/src/tools/clippy/clippy_lints/src/lib.register_nursery.rs b/src/tools/clippy/clippy_lints/src/lib.register_nursery.rs index a7353790100..8d4dde42bbe 100644 --- a/src/tools/clippy/clippy_lints/src/lib.register_nursery.rs +++ b/src/tools/clippy/clippy_lints/src/lib.register_nursery.rs @@ -26,6 +26,7 @@ store.register_group(true, "clippy::nursery", Some("clippy_nursery"), vec![ LintId::of(strings::STRING_LIT_AS_BYTES), LintId::of(suspicious_operation_groupings::SUSPICIOUS_OPERATION_GROUPINGS), LintId::of(trailing_empty_array::TRAILING_EMPTY_ARRAY), + LintId::of(transmute::TRANSMUTE_UNDEFINED_REPR), LintId::of(transmute::USELESS_TRANSMUTE), LintId::of(use_self::USE_SELF), ]) diff --git a/src/tools/clippy/clippy_lints/src/transmute/mod.rs b/src/tools/clippy/clippy_lints/src/transmute/mod.rs index 22a8c53a585..1da3b765904 100644 --- a/src/tools/clippy/clippy_lints/src/transmute/mod.rs +++ b/src/tools/clippy/clippy_lints/src/transmute/mod.rs @@ -377,7 +377,7 @@ declare_clippy_lint! { /// ``` #[clippy::version = "1.60.0"] pub TRANSMUTE_UNDEFINED_REPR, - correctness, + nursery, "transmute to or from a type with an undefined representation" } From fe78bd49207ec302cdb1898cdb56bc4194aa24fb Mon Sep 17 00:00:00 2001 From: est31 Date: Wed, 2 Mar 2022 22:10:35 +0100 Subject: [PATCH 15/17] Use ? operator in one instance instead of manual match --- src/librustdoc/doctest.rs | 91 +++++++++++++++++++-------------------- 1 file changed, 44 insertions(+), 47 deletions(-) diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs index dad04588703..63a8e85f7c5 100644 --- a/src/librustdoc/doctest.rs +++ b/src/librustdoc/doctest.rs @@ -111,58 +111,55 @@ crate fn run(options: RustdocOptions) -> Result<(), ErrorGuaranteed> { let externs = options.externs.clone(); let json_unused_externs = options.json_unused_externs; - let res = interface::run_compiler(config, |compiler| { - compiler.enter(|queries| { - let mut global_ctxt = queries.global_ctxt()?.take(); + let (tests, unused_extern_reports, compiling_test_count) = + interface::run_compiler(config, |compiler| { + compiler.enter(|queries| { + let mut global_ctxt = queries.global_ctxt()?.take(); - let collector = global_ctxt.enter(|tcx| { - let crate_attrs = tcx.hir().attrs(CRATE_HIR_ID); + let collector = global_ctxt.enter(|tcx| { + let crate_attrs = tcx.hir().attrs(CRATE_HIR_ID); - let opts = scrape_test_config(crate_attrs); - let enable_per_target_ignores = options.enable_per_target_ignores; - let mut collector = Collector::new( - tcx.crate_name(LOCAL_CRATE), - options, - false, - opts, - Some(compiler.session().parse_sess.clone_source_map()), - None, - enable_per_target_ignores, - ); + let opts = scrape_test_config(crate_attrs); + let enable_per_target_ignores = options.enable_per_target_ignores; + let mut collector = Collector::new( + tcx.crate_name(LOCAL_CRATE), + options, + false, + opts, + Some(compiler.session().parse_sess.clone_source_map()), + None, + enable_per_target_ignores, + ); - let mut hir_collector = HirCollector { - sess: compiler.session(), - collector: &mut collector, - map: tcx.hir(), - codes: ErrorCodes::from( - compiler.session().opts.unstable_features.is_nightly_build(), - ), - tcx, - }; - hir_collector.visit_testable( - "".to_string(), - CRATE_HIR_ID, - tcx.hir().span(CRATE_HIR_ID), - |this| tcx.hir().walk_toplevel_module(this), - ); + let mut hir_collector = HirCollector { + sess: compiler.session(), + collector: &mut collector, + map: tcx.hir(), + codes: ErrorCodes::from( + compiler.session().opts.unstable_features.is_nightly_build(), + ), + tcx, + }; + hir_collector.visit_testable( + "".to_string(), + CRATE_HIR_ID, + tcx.hir().span(CRATE_HIR_ID), + |this| tcx.hir().walk_toplevel_module(this), + ); - collector - }); - if compiler.session().diagnostic().has_errors_or_lint_errors() { - FatalError.raise(); - } + collector + }); + if compiler.session().diagnostic().has_errors_or_lint_errors() { + FatalError.raise(); + } - let unused_extern_reports = collector.unused_extern_reports.clone(); - let compiling_test_count = collector.compiling_test_count.load(Ordering::SeqCst); - let ret: Result<_, ErrorGuaranteed> = - Ok((collector.tests, unused_extern_reports, compiling_test_count)); - ret - }) - }); - let (tests, unused_extern_reports, compiling_test_count) = match res { - Ok(res) => res, - Err(ErrorGuaranteed) => return Err(ErrorGuaranteed), - }; + let unused_extern_reports = collector.unused_extern_reports.clone(); + let compiling_test_count = collector.compiling_test_count.load(Ordering::SeqCst); + let ret: Result<_, ErrorGuaranteed> = + Ok((collector.tests, unused_extern_reports, compiling_test_count)); + ret + }) + })?; run_tests(test_args, nocapture, tests); From 8253cfef7aa346c894259471e1e38a34df65cb58 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Wed, 2 Mar 2022 16:25:31 -0800 Subject: [PATCH 16/17] Remove the comment about `FILE_FLAG_OVERLAPPED`. There may eventually be something to say about `FILE_FLAG_OVERLAPPED` here, however this appears to be independent of the other changes in this PR, so remove them from this PR so that it can be discussed separately. --- library/std/src/os/windows/io/raw.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/library/std/src/os/windows/io/raw.rs b/library/std/src/os/windows/io/raw.rs index dc84a38156a..48c5fd358d9 100644 --- a/library/std/src/os/windows/io/raw.rs +++ b/library/std/src/os/windows/io/raw.rs @@ -56,8 +56,6 @@ pub trait FromRawHandle { /// /// The `handle` passed in must: /// - be a valid an open handle, - /// - be a handle opened for synchronous I/O, *without* the - /// `FILE_FLAG_OVERLAPPED` flag, and /// - be a handle for a resource that may be freed via [`CloseHandle`] /// (as opposed to `RegCloseKey` or other close functions). /// From 88b99224c1f59bef4f62aab5120f08dbd3c011c9 Mon Sep 17 00:00:00 2001 From: mark Date: Wed, 2 Mar 2022 21:33:43 -0600 Subject: [PATCH 17/17] add some examples to comments in mbe code --- compiler/rustc_expand/src/mbe/macro_parser.rs | 32 +++++++++++++++++++ compiler/rustc_expand/src/mbe/transcribe.rs | 6 ++++ 2 files changed, 38 insertions(+) diff --git a/compiler/rustc_expand/src/mbe/macro_parser.rs b/compiler/rustc_expand/src/mbe/macro_parser.rs index dd82add08dd..a419612e315 100644 --- a/compiler/rustc_expand/src/mbe/macro_parser.rs +++ b/compiler/rustc_expand/src/mbe/macro_parser.rs @@ -345,6 +345,38 @@ fn initial_matcher_pos<'root, 'tt>(ms: &'tt [TokenTree]) -> MatcherPos<'root, 't /// token tree. The depth of the `NamedMatch` structure will therefore depend /// only on the nesting depth of `ast::TTSeq`s in the originating /// token tree it was derived from. +/// +/// In layman's terms: `NamedMatch` will form a tree representing nested matches of a particular +/// meta variable. For example, if we are matching the following macro against the following +/// invocation... +/// +/// ```rust +/// macro_rules! foo { +/// ($($($x:ident),+);+) => {} +/// } +/// +/// foo!(a, b, c, d; a, b, c, d, e); +/// ``` +/// +/// Then, the tree will have the following shape: +/// +/// ```rust +/// MatchedSeq([ +/// MatchedSeq([ +/// MatchedNonterminal(a), +/// MatchedNonterminal(b), +/// MatchedNonterminal(c), +/// MatchedNonterminal(d), +/// ]), +/// MatchedSeq([ +/// MatchedNonterminal(a), +/// MatchedNonterminal(b), +/// MatchedNonterminal(c), +/// MatchedNonterminal(d), +/// MatchedNonterminal(e), +/// ]) +/// ]) +/// ``` #[derive(Debug, Clone)] crate enum NamedMatch { MatchedSeq(Lrc), diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs index 01a7f726617..54000527c15 100644 --- a/compiler/rustc_expand/src/mbe/transcribe.rs +++ b/compiler/rustc_expand/src/mbe/transcribe.rs @@ -358,6 +358,12 @@ impl LockstepIterSize { /// Note that if `repeats` does not match the exact correct depth of a meta-var, /// `lookup_cur_matched` will return `None`, which is why this still works even in the presence of /// multiple nested matcher sequences. +/// +/// Example: `$($($x $y)+*);+` -- we need to make sure that `x` and `y` repeat the same amount as +/// each other at the given depth when the macro was invoked. If they don't it might mean they were +/// declared at unequal depths or there was a compile bug. For example, if we have 3 repetitions of +/// the outer sequence and 4 repetitions of the inner sequence for `x`, we should have the same for +/// `y`; otherwise, we can't transcribe them both at the given depth. fn lockstep_iter_size( tree: &mbe::TokenTree, interpolations: &FxHashMap,