From 302e33fde2785874c6b85aa9760e8e6be2e7dad4 Mon Sep 17 00:00:00 2001 From: Pointerbender Date: Mon, 12 Sep 2022 11:12:28 +0200 Subject: [PATCH 01/10] add description of the memory layout for `UnsafeCell` --- library/core/src/cell.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index fb4454c94cb33..cce4e5a594672 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -1811,6 +1811,8 @@ impl fmt::Display for RefMut<'_, T> { /// /// [`.get_mut()`]: `UnsafeCell::get_mut` /// +/// `UnsafeCell` has the same in-memory representation as its inner type `T`. +/// /// # Examples /// /// Here is an example showcasing how to soundly mutate the contents of an `UnsafeCell<_>` despite From 13bc0996ddb64919feefb256ad9468087333121d Mon Sep 17 00:00:00 2001 From: Pointerbender Date: Wed, 14 Sep 2022 10:10:18 +0200 Subject: [PATCH 02/10] expand documentation on type conversion w.r.t. `UnsafeCell` --- library/core/src/cell.rs | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index cce4e5a594672..b730e13dcb887 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -1811,7 +1811,36 @@ impl fmt::Display for RefMut<'_, T> { /// /// [`.get_mut()`]: `UnsafeCell::get_mut` /// -/// `UnsafeCell` has the same in-memory representation as its inner type `T`. +/// `UnsafeCell` has the same in-memory representation as its inner type `T`. A consequence +/// of this guarantee is that it is possible to convert between `T` and `UnsafeCell`. +/// However, it is only valid to obtain a `*mut T` pointer or `&mut T` reference to the +/// contents of an `UnsafeCell` through [`.get()`], [`.raw_get()`] or [`.get_mut()`], e.g.: +/// +/// ```rust +/// use std::cell::UnsafeCell; +/// +/// let mut x: UnsafeCell = UnsafeCell::new(5); +/// let p1: &UnsafeCell = &x; +/// // using `.get()` is okay: +/// unsafe { +/// // SAFETY: there exist no other references to the contents of `x` +/// let p2: &mut u32 = &mut *p1.get(); +/// }; +/// // using `.raw_get()` is also okay: +/// unsafe { +/// // SAFETY: there exist no other references to the contents of `x` in this scope +/// let p2: &mut u32 = &mut *UnsafeCell::raw_get(p1 as *const _); +/// }; +/// // using `.get_mut()` is always safe: +/// let p2: &mut u32 = x.get_mut(); +/// // but the following is not allowed! +/// // let p2: &mut u32 = unsafe { +/// // let t: *mut u32 = &x as *const _ as *mut u32; +/// // &mut *t +/// // }; +/// ``` +/// +/// [`.raw_get()`]: `UnsafeCell::raw_get` /// /// # Examples /// From 9c37c801ad737006c494f6b3bd97ff59764573ae Mon Sep 17 00:00:00 2001 From: Pointerbender Date: Sun, 9 Oct 2022 22:32:23 +0200 Subject: [PATCH 03/10] expand documentation on type conversion w.r.t. `UnsafeCell` --- library/core/src/cell.rs | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index b730e13dcb887..be1017e584286 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -1811,35 +1811,43 @@ impl fmt::Display for RefMut<'_, T> { /// /// [`.get_mut()`]: `UnsafeCell::get_mut` /// -/// `UnsafeCell` has the same in-memory representation as its inner type `T`. A consequence -/// of this guarantee is that it is possible to convert between `T` and `UnsafeCell`. -/// However, it is only valid to obtain a `*mut T` pointer or `&mut T` reference to the -/// contents of an `UnsafeCell` through [`.get()`], [`.raw_get()`] or [`.get_mut()`], e.g.: +/// `UnsafeCell` has the same in-memory representation as its inner type `T` if and only if +/// the type `T` does not contain a [niche] (e.g. the type `Option>` is typically +/// 8 bytes large on 64-bit platforms, but the type `Option>>` takes +/// up 16 bytes of space). A consequence of this guarantee is that it is possible to convert +/// between `T` and `UnsafeCell` when `T` has no niches. However, it is only valid to obtain +/// a `*mut T` pointer to the contents of a _shared_ `UnsafeCell` through [`.get()`] or +/// [`.raw_get()`]. A `&mut T` reference can be obtained by either dereferencing this pointer +/// or by calling [`.get_mut()`] on an _exclusive_ `UnsafeCell`, e.g.: /// /// ```rust /// use std::cell::UnsafeCell; /// /// let mut x: UnsafeCell = UnsafeCell::new(5); -/// let p1: &UnsafeCell = &x; +/// let shared: &UnsafeCell = &x; /// // using `.get()` is okay: /// unsafe { /// // SAFETY: there exist no other references to the contents of `x` -/// let p2: &mut u32 = &mut *p1.get(); +/// let exclusive: &mut u32 = &mut *shared.get(); /// }; /// // using `.raw_get()` is also okay: /// unsafe { /// // SAFETY: there exist no other references to the contents of `x` in this scope -/// let p2: &mut u32 = &mut *UnsafeCell::raw_get(p1 as *const _); +/// let exclusive: &mut u32 = &mut *UnsafeCell::raw_get(shared as *const _); /// }; /// // using `.get_mut()` is always safe: -/// let p2: &mut u32 = x.get_mut(); -/// // but the following is not allowed! -/// // let p2: &mut u32 = unsafe { -/// // let t: *mut u32 = &x as *const _ as *mut u32; -/// // &mut *t -/// // }; +/// let exclusive: &mut u32 = x.get_mut(); +/// +/// // when we have exclusive access, we can convert it to a shared `&UnsafeCell`: +/// unsafe { +/// // SAFETY: `u32` has no niche, therefore it has the same layout as `UnsafeCell` +/// let shared: &UnsafeCell = &*(exclusive as *mut _ as *const UnsafeCell); +/// // SAFETY: there exist no other *active* references to the contents of `x` in this scope +/// let exclusive: &mut u32 = &mut *shared.get(); +/// } /// ``` /// +/// [niche]: https://rust-lang.github.io/unsafe-code-guidelines/glossary.html#niche /// [`.raw_get()`]: `UnsafeCell::raw_get` /// /// # Examples From ddd119b2fed57eb6b19c44c18108de95c564a48d Mon Sep 17 00:00:00 2001 From: Pointerbender Date: Wed, 12 Oct 2022 23:34:13 +0200 Subject: [PATCH 04/10] expand documentation on type conversion w.r.t. `UnsafeCell` --- library/core/src/cell.rs | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index be1017e584286..4dee386f8879e 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -1811,14 +1811,19 @@ impl fmt::Display for RefMut<'_, T> { /// /// [`.get_mut()`]: `UnsafeCell::get_mut` /// -/// `UnsafeCell` has the same in-memory representation as its inner type `T` if and only if -/// the type `T` does not contain a [niche] (e.g. the type `Option>` is typically -/// 8 bytes large on 64-bit platforms, but the type `Option>>` takes -/// up 16 bytes of space). A consequence of this guarantee is that it is possible to convert -/// between `T` and `UnsafeCell` when `T` has no niches. However, it is only valid to obtain -/// a `*mut T` pointer to the contents of a _shared_ `UnsafeCell` through [`.get()`] or -/// [`.raw_get()`]. A `&mut T` reference can be obtained by either dereferencing this pointer -/// or by calling [`.get_mut()`] on an _exclusive_ `UnsafeCell`, e.g.: +/// `UnsafeCell` has the same in-memory representation as its inner type `T`. A consequence +/// of this guarantee is that it is possible to convert between `T` and `UnsafeCell`. +/// Special care has to be taken when converting a nested `T` inside of an `Outer` type +/// to an `Outer>` type: this is not sound when the `Outer` type enables [niche] +/// optimizations. For example, the type `Option>` is typically 8 bytes large on +/// 64-bit platforms, but the type `Option>>` takes up 16 bytes of space. +/// Therefore this is not a valid conversion, despite `NonNull` and `UnsafeCell>>` +/// having the same memory layout. This is because `UnsafeCell` disables niche optimizations in +/// order to avoid its interior mutability property from spreading from `T` into the `Outer` type, +/// thus this can cause distortions in the type size in these cases. Furthermore, it is only valid +/// to obtain a `*mut T` pointer to the contents of a _shared_ `UnsafeCell` through [`.get()`] +/// or [`.raw_get()`]. A `&mut T` reference can be obtained by either dereferencing this pointer or +/// by calling [`.get_mut()`] on an _exclusive_ `UnsafeCell`, e.g.: /// /// ```rust /// use std::cell::UnsafeCell; From b3b6fbc8341a008347cad370af1210aa4efa3080 Mon Sep 17 00:00:00 2001 From: Alyssa Ross Date: Fri, 14 Oct 2022 01:42:23 +0000 Subject: [PATCH 05/10] Update pkg-config --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0cc7f8a1c7ce3..9f7cc44d160bf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2652,9 +2652,9 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "pkg-config" -version = "0.3.18" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d36492546b6af1463394d46f0c834346f31548646f6ba10849802c9c9a27ac33" +checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae" [[package]] name = "polonius-engine" From 49f34bd8147a84229cc6641f2d386f09ee12c7e5 Mon Sep 17 00:00:00 2001 From: Gimgim <93856041+gimbles@users.noreply.github.com> Date: Sat, 15 Oct 2022 15:28:29 +0530 Subject: [PATCH 06/10] Surround type with backticks --- compiler/rustc_const_eval/src/transform/validate.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs index 87b7c55bf7fb5..fbb129f97247e 100644 --- a/compiler/rustc_const_eval/src/transform/validate.rs +++ b/compiler/rustc_const_eval/src/transform/validate.rs @@ -284,7 +284,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { this.fail( location, format!( - "Field projection `{:?}.{:?}` specified type `{:?}`, but actual type is {:?}", + "Field projection `{:?}.{:?}` specified type `{:?}`, but actual type is `{:?}`", parent, f, ty, f_ty ) ) From e14d2efba3a43ca5f02ce69f978f64323c471abb Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 15 Oct 2022 15:59:00 +0200 Subject: [PATCH 07/10] Fix display of settings page --- src/librustdoc/html/static/js/settings.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/librustdoc/html/static/js/settings.js b/src/librustdoc/html/static/js/settings.js index 1c5d33e212754..5e1c7e6f03e75 100644 --- a/src/librustdoc/html/static/js/settings.js +++ b/src/librustdoc/html/static/js/settings.js @@ -216,7 +216,9 @@ const innerHTML = `
${buildSettingsPageSections(settings)}
`; const el = document.createElement(elementKind); el.id = "settings"; - el.className = "popover"; + if (!isSettingsPage) { + el.className = "popover"; + } el.innerHTML = innerHTML; if (isSettingsPage) { From 11a40ec5ffc68dc44e8ac1b122d46c919b35aff5 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 15 Oct 2022 15:59:11 +0200 Subject: [PATCH 08/10] Add more GUI tests for settings page --- src/test/rustdoc-gui/settings.goml | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/test/rustdoc-gui/settings.goml b/src/test/rustdoc-gui/settings.goml index dfbf1d38e0e11..ed4e9c2516b0b 100644 --- a/src/test/rustdoc-gui/settings.goml +++ b/src/test/rustdoc-gui/settings.goml @@ -1,4 +1,5 @@ -// This test ensures that the settings menu display is working as expected. +// This test ensures that the settings menu display is working as expected and that +// the settings page is also rendered as expected. goto: "file://" + |DOC_PATH| + "/test_docs/index.html" show-text: true // needed when we check for colors below. // First, we check that the settings page doesn't exist. @@ -140,7 +141,13 @@ assert-css: ("#settings-menu .popover", {"display": "none"}) // Now we go to the settings page to check that the CSS is loaded as expected. goto: "file://" + |DOC_PATH| + "/settings.html" wait-for: "#settings" -assert-css: (".setting-line .toggle .slider", {"width": "45px", "margin-right": "20px"}) +assert-css: ( + ".setting-line .toggle .slider", + {"width": "45px", "margin-right": "20px", "border": "0px none rgb(0, 0, 0)"}, +) + +assert-attribute-false: ("#settings", {"class": "popover"}, CONTAINS) +compare-elements-position: (".sub-container", "#settings", ("x")) // We now check the display with JS disabled. assert-false: "noscript section" From 7334526c3803d9d9a5a9b017618aa95d618f687a Mon Sep 17 00:00:00 2001 From: Yutaro Ohno Date: Fri, 14 Oct 2022 17:53:09 +0900 Subject: [PATCH 09/10] pretty: fix to print some lifetimes on HIR pretty-print --- compiler/rustc_hir_pretty/src/lib.rs | 6 +++++- src/test/pretty/issue-85089.pp | 20 ++++++++++++++++++++ src/test/pretty/issue-85089.rs | 16 ++++++++++++++++ 3 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 src/test/pretty/issue-85089.pp create mode 100644 src/test/pretty/issue-85089.rs diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 729139adc2de8..da27554a2292b 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -1687,7 +1687,11 @@ impl<'a> State<'a> { let mut nonelided_generic_args: bool = false; let elide_lifetimes = generic_args.args.iter().all(|arg| match arg { - GenericArg::Lifetime(lt) => lt.is_elided(), + GenericArg::Lifetime(lt) if lt.is_elided() => true, + GenericArg::Lifetime(_) => { + nonelided_generic_args = true; + false + } _ => { nonelided_generic_args = true; true diff --git a/src/test/pretty/issue-85089.pp b/src/test/pretty/issue-85089.pp new file mode 100644 index 0000000000000..f84e9df04a2ac --- /dev/null +++ b/src/test/pretty/issue-85089.pp @@ -0,0 +1,20 @@ +#[prelude_import] +use ::std::prelude::rust_2015::*; +#[macro_use] +extern crate std; +// Test to print lifetimes on HIR pretty-printing. + +// pretty-compare-only +// pretty-mode:hir +// pp-exact:issue-85089.pp + +trait A<'x> { } +trait B<'x> { } + +struct Foo<'b> { + bar: &'b dyn for<'a> A<'a>, +} + +impl <'a> B<'a> for dyn for<'b> A<'b> { } + +impl <'a> A<'a> for Foo<'a> { } diff --git a/src/test/pretty/issue-85089.rs b/src/test/pretty/issue-85089.rs new file mode 100644 index 0000000000000..eb45d473119d4 --- /dev/null +++ b/src/test/pretty/issue-85089.rs @@ -0,0 +1,16 @@ +// Test to print lifetimes on HIR pretty-printing. + +// pretty-compare-only +// pretty-mode:hir +// pp-exact:issue-85089.pp + +trait A<'x> {} +trait B<'x> {} + +struct Foo<'b> { + pub bar: &'b dyn for<'a> A<'a>, +} + +impl<'a> B<'a> for dyn for<'b> A<'b> {} + +impl<'a> A<'a> for Foo<'a> {} From 393434c29eee2aa939dddfb8db0a4d692bcb96c0 Mon Sep 17 00:00:00 2001 From: Alex Saveau Date: Sat, 15 Oct 2022 15:57:19 -0700 Subject: [PATCH 10/10] Add MaybeUninit array transpose impls Signed-off-by: Alex Saveau --- library/core/src/mem/maybe_uninit.rs | 37 ++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/library/core/src/mem/maybe_uninit.rs b/library/core/src/mem/maybe_uninit.rs index e2ae39fbab335..2ae9636762813 100644 --- a/library/core/src/mem/maybe_uninit.rs +++ b/library/core/src/mem/maybe_uninit.rs @@ -1284,3 +1284,40 @@ impl MaybeUninit { } } } + +impl MaybeUninit<[T; N]> { + /// Transposes a `MaybeUninit<[T; N]>` into a `[MaybeUninit; N]`. + /// + /// # Examples + /// + /// ``` + /// #![feature(maybe_uninit_uninit_array_transpose)] + /// # use std::mem::MaybeUninit; + /// + /// let data: [MaybeUninit; 1000] = MaybeUninit::uninit().transpose(); + /// ``` + #[unstable(feature = "maybe_uninit_uninit_array_transpose", issue = "96097")] + pub fn transpose(self) -> [MaybeUninit; N] { + // SAFETY: T and MaybeUninit have the same layout + unsafe { super::transmute_copy(&ManuallyDrop::new(self)) } + } +} + +impl [MaybeUninit; N] { + /// Transposes a `[MaybeUninit; N]` into a `MaybeUninit<[T; N]>`. + /// + /// # Examples + /// + /// ``` + /// #![feature(maybe_uninit_uninit_array_transpose)] + /// # use std::mem::MaybeUninit; + /// + /// let data = [MaybeUninit::::uninit(); 1000]; + /// let data: MaybeUninit<[u8; 1000]> = data.transpose(); + /// ``` + #[unstable(feature = "maybe_uninit_uninit_array_transpose", issue = "96097")] + pub fn transpose(self) -> MaybeUninit<[T; N]> { + // SAFETY: T and MaybeUninit have the same layout + unsafe { super::transmute_copy(&ManuallyDrop::new(self)) } + } +}