about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock4
-rw-r--r--compiler/rustc_const_eval/src/transform/validate.rs2
-rw-r--r--compiler/rustc_hir_pretty/src/lib.rs6
-rw-r--r--library/core/src/cell.rs44
-rw-r--r--library/core/src/mem/maybe_uninit.rs37
-rw-r--r--src/librustdoc/html/static/js/settings.js4
-rw-r--r--src/test/pretty/issue-85089.pp20
-rw-r--r--src/test/pretty/issue-85089.rs16
-rw-r--r--src/test/rustdoc-gui/settings.goml11
9 files changed, 137 insertions, 7 deletions
diff --git a/Cargo.lock b/Cargo.lock
index f393a918094..d5acab8139c 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"
diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs
index 87b7c55bf7f..fbb129f9724 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
                         )
                     )
diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs
index 729139adc2d..da27554a229 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/library/core/src/cell.rs b/library/core/src/cell.rs
index 4474b673a95..3451a25504e 100644
--- a/library/core/src/cell.rs
+++ b/library/core/src/cell.rs
@@ -1816,6 +1816,50 @@ impl<T: ?Sized + fmt::Display> fmt::Display for RefMut<'_, T> {
 ///
 /// [`.get_mut()`]: `UnsafeCell::get_mut`
 ///
+/// `UnsafeCell<T>` 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<T>`.
+/// Special care has to be taken when converting a nested `T` inside of an `Outer<T>` type
+/// to an `Outer<UnsafeCell<T>>` type: this is not sound when the `Outer<T>` type enables [niche]
+/// optimizations. For example, the type `Option<NonNull<u8>>` is typically 8 bytes large on
+/// 64-bit platforms, but the type `Option<UnsafeCell<NonNull<u8>>>` takes up 16 bytes of space.
+/// Therefore this is not a valid conversion, despite `NonNull<u8>` and `UnsafeCell<NonNull<u8>>>`
+/// 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<T>` 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<T>`, e.g.:
+///
+/// ```rust
+/// use std::cell::UnsafeCell;
+///
+/// let mut x: UnsafeCell<u32> = UnsafeCell::new(5);
+/// let shared: &UnsafeCell<u32> = &x;
+/// // using `.get()` is okay:
+/// unsafe {
+///     // SAFETY: there exist no other references to the contents of `x`
+///     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 exclusive: &mut u32 = &mut *UnsafeCell::raw_get(shared as *const _);
+/// };
+/// // using `.get_mut()` is always safe:
+/// 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<u32>`
+///     let shared: &UnsafeCell<u32> = &*(exclusive as *mut _ as *const UnsafeCell<u32>);
+///     // 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
 ///
 /// Here is an example showcasing how to soundly mutate the contents of an `UnsafeCell<_>` despite
diff --git a/library/core/src/mem/maybe_uninit.rs b/library/core/src/mem/maybe_uninit.rs
index e2ae39fbab3..2ae96367628 100644
--- a/library/core/src/mem/maybe_uninit.rs
+++ b/library/core/src/mem/maybe_uninit.rs
@@ -1284,3 +1284,40 @@ impl<T> MaybeUninit<T> {
         }
     }
 }
+
+impl<T, const N: usize> MaybeUninit<[T; N]> {
+    /// Transposes a `MaybeUninit<[T; N]>` into a `[MaybeUninit<T>; N]`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(maybe_uninit_uninit_array_transpose)]
+    /// # use std::mem::MaybeUninit;
+    ///
+    /// let data: [MaybeUninit<u8>; 1000] = MaybeUninit::uninit().transpose();
+    /// ```
+    #[unstable(feature = "maybe_uninit_uninit_array_transpose", issue = "96097")]
+    pub fn transpose(self) -> [MaybeUninit<T>; N] {
+        // SAFETY: T and MaybeUninit<T> have the same layout
+        unsafe { super::transmute_copy(&ManuallyDrop::new(self)) }
+    }
+}
+
+impl<T, const N: usize> [MaybeUninit<T>; N] {
+    /// Transposes a `[MaybeUninit<T>; N]` into a `MaybeUninit<[T; N]>`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(maybe_uninit_uninit_array_transpose)]
+    /// # use std::mem::MaybeUninit;
+    ///
+    /// let data = [MaybeUninit::<u8>::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<T> have the same layout
+        unsafe { super::transmute_copy(&ManuallyDrop::new(self)) }
+    }
+}
diff --git a/src/librustdoc/html/static/js/settings.js b/src/librustdoc/html/static/js/settings.js
index 1c5d33e2127..5e1c7e6f03e 100644
--- a/src/librustdoc/html/static/js/settings.js
+++ b/src/librustdoc/html/static/js/settings.js
@@ -216,7 +216,9 @@
         const innerHTML = `<div class="settings">${buildSettingsPageSections(settings)}</div>`;
         const el = document.createElement(elementKind);
         el.id = "settings";
-        el.className = "popover";
+        if (!isSettingsPage) {
+            el.className = "popover";
+        }
         el.innerHTML = innerHTML;
 
         if (isSettingsPage) {
diff --git a/src/test/pretty/issue-85089.pp b/src/test/pretty/issue-85089.pp
new file mode 100644
index 00000000000..f84e9df04a2
--- /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 00000000000..eb45d473119
--- /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> {}
diff --git a/src/test/rustdoc-gui/settings.goml b/src/test/rustdoc-gui/settings.goml
index dfbf1d38e0e..ed4e9c2516b 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"