From bebcb9da216ab439a8628219f8021b1770134a35 Mon Sep 17 00:00:00 2001 From: clubby789 Date: Mon, 12 May 2025 14:49:12 +0000 Subject: [PATCH 01/13] Add test for Ord impl for Option::NonZero --- tests/codegen/option-niche-eq.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/tests/codegen/option-niche-eq.rs b/tests/codegen/option-niche-eq.rs index 9c5ed9ce57a5e..2be9e2bc48927 100644 --- a/tests/codegen/option-niche-eq.rs +++ b/tests/codegen/option-niche-eq.rs @@ -24,6 +24,18 @@ pub fn non_zero_signed_eq(l: Option>, r: Option>) -> b l == r } +// Test for #49892 +// This currently relies on a manual implementation of `PartialOrd`/`Ord` for `Option` +// Once LLVM is better able to optimize this pattern, we can return to using a derive. +// CHECK-LABEL: @non_zero_ord +#[no_mangle] +pub fn non_zero_ord(a: Option>, b: Option>) -> bool { + // CHECK: start: + // CHECK-NEXT: icmp ult i32 + // CHECK-NEXT: ret i1 + a < b +} + // CHECK-LABEL: @non_null_eq #[no_mangle] pub fn non_null_eq(l: Option>, r: Option>) -> bool { From 5eb47eeb851d4428642197cea3a566bcfa5f726a Mon Sep 17 00:00:00 2001 From: clubby789 Date: Mon, 12 May 2025 15:09:32 +0000 Subject: [PATCH 02/13] Add failing tests for some Option optimizations --- tests/codegen/option-niche-eq.rs | 13 ++-------- .../option-niche-unfixed/option-bool-eq.rs | 15 ++++++++++++ .../option-niche-unfixed/option-nonzero-eq.rs | 24 +++++++++++++++++++ 3 files changed, 41 insertions(+), 11 deletions(-) create mode 100644 tests/codegen/option-niche-unfixed/option-bool-eq.rs create mode 100644 tests/codegen/option-niche-unfixed/option-nonzero-eq.rs diff --git a/tests/codegen/option-niche-eq.rs b/tests/codegen/option-niche-eq.rs index 2be9e2bc48927..a39e2870a0f4f 100644 --- a/tests/codegen/option-niche-eq.rs +++ b/tests/codegen/option-niche-eq.rs @@ -1,3 +1,4 @@ +//@ min-llvm-version: 20 //@ compile-flags: -Copt-level=3 -Zmerge-functions=disabled #![crate_type = "lib"] @@ -24,7 +25,7 @@ pub fn non_zero_signed_eq(l: Option>, r: Option>) -> b l == r } -// Test for #49892 +// FIXME(#49892) // This currently relies on a manual implementation of `PartialOrd`/`Ord` for `Option` // Once LLVM is better able to optimize this pattern, we can return to using a derive. // CHECK-LABEL: @non_zero_ord @@ -73,13 +74,3 @@ pub fn niche_eq(l: Option, r: Option) -> bool { // CHECK-NEXT: ret i1 l == r } - -// FIXME: This should work too -// // FIXME-CHECK-LABEL: @bool_eq -// #[no_mangle] -// pub fn bool_eq(l: Option, r: Option) -> bool { -// // FIXME-CHECK: start: -// // FIXME-CHECK-NEXT: icmp eq i8 -// // FIXME-CHECK-NEXT: ret i1 -// l == r -// } diff --git a/tests/codegen/option-niche-unfixed/option-bool-eq.rs b/tests/codegen/option-niche-unfixed/option-bool-eq.rs new file mode 100644 index 0000000000000..fa0e7836afb9e --- /dev/null +++ b/tests/codegen/option-niche-unfixed/option-bool-eq.rs @@ -0,0 +1,15 @@ +//@ should-fail +//@ compile-flags: -Copt-level=3 -Zmerge-functions=disabled +//! FIXME(#49892) +//! Tests that LLVM does not fully optimize comparisons of `Option`. +//! If this starts passing, it can be moved to `tests/codegen/option-niche-eq.rs` +#![crate_type = "lib"] + +// CHECK-LABEL: @bool_eq +#[no_mangle] +pub fn bool_eq(l: Option, r: Option) -> bool { + // CHECK: start: + // CHECK-NEXT: icmp eq i8 + // CHECK-NEXT: ret i1 + l == r +} diff --git a/tests/codegen/option-niche-unfixed/option-nonzero-eq.rs b/tests/codegen/option-niche-unfixed/option-nonzero-eq.rs new file mode 100644 index 0000000000000..308856cfb7e9d --- /dev/null +++ b/tests/codegen/option-niche-unfixed/option-nonzero-eq.rs @@ -0,0 +1,24 @@ +//@ should-fail +//@ compile-flags: -Copt-level=3 -Zmerge-functions=disabled +//! FIXME(#49892) +//! Test that the derived implementation of `PartialEq` for `Option` is not fully +//! optimized by LLVM. If this starts passing, the test and manual impl should +//! be removed. +#![crate_type = "lib"] + +use std::num::NonZero; + +#[derive(Copy, Clone, PartialEq, Eq)] +pub enum Option { + None, + Some(T), +} + +// CHECK-LABEL: @non_zero_eq +#[no_mangle] +pub fn non_zero_eq(l: Option>, r: Option>) -> bool { + // CHECK: start: + // CHECK-NEXT: icmp eq i32 + // CHECK-NEXT: ret i1 + l == r +} From 5326fc9bc78ca44e04d4583a8ced3a23768815e6 Mon Sep 17 00:00:00 2001 From: binarycat Date: Mon, 14 Apr 2025 19:01:38 -0500 Subject: [PATCH 03/13] rustdoc: on mobile, make the sidebar full width and linewrap this is because the mobile sidebar cannot be resized, unlike on desktop. --- src/librustdoc/html/static/css/rustdoc.css | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index a81d5c9c49b4b..7be83b65fbfaf 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -2527,9 +2527,12 @@ in src-script.js and main.js z-index: 11; /* Reduce height slightly to account for mobile topbar. */ height: calc(100vh - 45px); - width: 200px; /* resize indicator: hide this when on touch or mobile */ border-right: none; + width: 100%; + } + .sidebar-elems .block li a { + white-space: wrap; } /* The source view uses a different design for the sidebar toggle, and doesn't have a topbar, From d29d1a332bc44b461859ccc756d53cbd81cbea0e Mon Sep 17 00:00:00 2001 From: Paul Mabileau Date: Sat, 17 May 2025 02:09:06 +0200 Subject: [PATCH 04/13] Docs(lib/alloc/vec): Add the missing `an` to `extract_if`'s first sentence As inspired by the equivalent methods from other collection types. Signed-off-by: Paul Mabileau --- library/alloc/src/vec/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 59879f23d7850..4d03ca63ec8ad 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -3648,7 +3648,7 @@ impl Vec { Splice { drain: self.drain(range), replace_with: replace_with.into_iter() } } - /// Creates an iterator which uses a closure to determine if element in the range should be removed. + /// Creates an iterator which uses a closure to determine if an element in the range should be removed. /// /// If the closure returns true, then the element is removed and yielded. /// If the closure returns false, the element will remain in the vector and will not be yielded From cd5772e396361c72e4662655687a462aee6c6aea Mon Sep 17 00:00:00 2001 From: Paul Mabileau Date: Sat, 17 May 2025 02:14:55 +0200 Subject: [PATCH 05/13] Docs(lib/coll/hm): Reword `extract_if` to use `element` instead of `value` A minor change, but it seemed interesting to unify this one's description, especially considering all the other equivalents use `element` as well. Signed-off-by: Paul Mabileau --- library/std/src/collections/hash/set.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/library/std/src/collections/hash/set.rs b/library/std/src/collections/hash/set.rs index 8514dfd9a984d..5043d1bd1df7c 100644 --- a/library/std/src/collections/hash/set.rs +++ b/library/std/src/collections/hash/set.rs @@ -276,10 +276,10 @@ impl HashSet { Drain { base: self.base.drain() } } - /// Creates an iterator which uses a closure to determine if a value should be removed. + /// Creates an iterator which uses a closure to determine if an element should be removed. /// - /// If the closure returns true, then the value is removed and yielded. - /// If the closure returns false, the value will remain in the list and will not be yielded + /// If the closure returns true, then the element is removed and yielded. + /// If the closure returns false, the element will remain in the list and will not be yielded /// by the iterator. /// /// If the returned `ExtractIf` is not exhausted, e.g. because it is dropped without iterating From 35f847363729b16332eab1a85900617218495757 Mon Sep 17 00:00:00 2001 From: Paul Mabileau Date: Sat, 17 May 2025 02:22:13 +0200 Subject: [PATCH 06/13] Docs(lib/coll/btm): Split `extract_if`'s first sentence from the following ones This also seems like a small mistake: the first main sentence is put in the same paragraph as the other two following ones while other equivalents all have it split. Therefore, do the same here. Signed-off-by: Paul Mabileau --- library/alloc/src/collections/btree/map.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/library/alloc/src/collections/btree/map.rs b/library/alloc/src/collections/btree/map.rs index 5ca32ed741af8..ea81645aa6491 100644 --- a/library/alloc/src/collections/btree/map.rs +++ b/library/alloc/src/collections/btree/map.rs @@ -1398,10 +1398,12 @@ impl BTreeMap { } /// Creates an iterator that visits all elements (key-value pairs) in - /// ascending key order and uses a closure to determine if an element should - /// be removed. If the closure returns `true`, the element is removed from - /// the map and yielded. If the closure returns `false`, or panics, the - /// element remains in the map and will not be yielded. + /// ascending key order and uses a closure to determine if an element + /// should be removed. + /// + /// If the closure returns `true`, the element is removed from the map and + /// yielded. If the closure returns `false`, or panics, the element remains + /// in the map and will not be yielded. /// /// The iterator also lets you mutate the value of each element in the /// closure, regardless of whether you choose to keep or remove it. From 9205ee27a815e5b356cfce6269d9ded1d1c098f7 Mon Sep 17 00:00:00 2001 From: Paul Mabileau Date: Sat, 17 May 2025 02:36:08 +0200 Subject: [PATCH 07/13] Docs(lib/extract_if): Unify paragraph about closure actions Also fixes `HashSet`'s that incorrectly designated itself as a `list`. Signed-off-by: Paul Mabileau --- library/alloc/src/collections/linked_list.rs | 6 +++--- library/alloc/src/vec/mod.rs | 6 +++--- library/std/src/collections/hash/map.rs | 6 +++--- library/std/src/collections/hash/set.rs | 6 +++--- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/library/alloc/src/collections/linked_list.rs b/library/alloc/src/collections/linked_list.rs index 00e2805d11f61..1890a114d3cb2 100644 --- a/library/alloc/src/collections/linked_list.rs +++ b/library/alloc/src/collections/linked_list.rs @@ -1124,9 +1124,9 @@ impl LinkedList { /// Creates an iterator which uses a closure to determine if an element should be removed. /// - /// If the closure returns true, then the element is removed and yielded. - /// If the closure returns false, the element will remain in the list and will not be yielded - /// by the iterator. + /// If the closure returns `true`, the element is removed from the list and + /// yielded. If the closure returns `false`, or panics, the element remains + /// in the list and will not be yielded. /// /// If the returned `ExtractIf` is not exhausted, e.g. because it is dropped without iterating /// or the iteration short-circuits, then the remaining elements will be retained. diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 4d03ca63ec8ad..e5f2c9468e386 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -3650,9 +3650,9 @@ impl Vec { /// Creates an iterator which uses a closure to determine if an element in the range should be removed. /// - /// If the closure returns true, then the element is removed and yielded. - /// If the closure returns false, the element will remain in the vector and will not be yielded - /// by the iterator. + /// If the closure returns `true`, the element is removed from the vector + /// and yielded. If the closure returns `false`, or panics, the element + /// remains in the vector and will not be yielded. /// /// Only elements that fall in the provided range are considered for extraction, but any elements /// after the range will still have to be moved if any element has been extracted. diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs index 3530f890f5294..9732d2c2d5ce9 100644 --- a/library/std/src/collections/hash/map.rs +++ b/library/std/src/collections/hash/map.rs @@ -650,9 +650,9 @@ impl HashMap { /// Creates an iterator which uses a closure to determine if an element should be removed. /// - /// If the closure returns true, the element is removed from the map and yielded. - /// If the closure returns false, or panics, the element remains in the map and will not be - /// yielded. + /// If the closure returns `true`, the element is removed from the map and + /// yielded. If the closure returns `false`, or panics, the element remains + /// in the map and will not be yielded. /// /// Note that `extract_if` lets you mutate every value in the filter closure, regardless of /// whether you choose to keep or remove it. diff --git a/library/std/src/collections/hash/set.rs b/library/std/src/collections/hash/set.rs index 5043d1bd1df7c..482d57b47f677 100644 --- a/library/std/src/collections/hash/set.rs +++ b/library/std/src/collections/hash/set.rs @@ -278,9 +278,9 @@ impl HashSet { /// Creates an iterator which uses a closure to determine if an element should be removed. /// - /// If the closure returns true, then the element is removed and yielded. - /// If the closure returns false, the element will remain in the list and will not be yielded - /// by the iterator. + /// If the closure returns `true`, the element is removed from the set and + /// yielded. If the closure returns `false`, or panics, the element remains + /// in the set and will not be yielded. /// /// If the returned `ExtractIf` is not exhausted, e.g. because it is dropped without iterating /// or the iteration short-circuits, then the remaining elements will be retained. From 014434e96f4f42e06b6c2dfc00110209b121040e Mon Sep 17 00:00:00 2001 From: Paul Mabileau Date: Sat, 17 May 2025 02:45:56 +0200 Subject: [PATCH 08/13] Docs(lib/extract_if): Unify paragraph about elements mutation Take the one from `BTreeMap` that seems the best-worded and most precise among the available variations. Signed-off-by: Paul Mabileau --- library/alloc/src/collections/linked_list.rs | 4 ++-- library/alloc/src/vec/mod.rs | 4 ++-- library/std/src/collections/hash/map.rs | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/library/alloc/src/collections/linked_list.rs b/library/alloc/src/collections/linked_list.rs index 1890a114d3cb2..0e365ebd3080a 100644 --- a/library/alloc/src/collections/linked_list.rs +++ b/library/alloc/src/collections/linked_list.rs @@ -1132,8 +1132,8 @@ impl LinkedList { /// or the iteration short-circuits, then the remaining elements will be retained. /// Use `extract_if().for_each(drop)` if you do not need the returned iterator. /// - /// Note that `extract_if` lets you mutate every element in the filter closure, regardless of - /// whether you choose to keep or remove it. + /// The iterator also lets you mutate the value of each element in the + /// closure, regardless of whether you choose to keep or remove it. /// /// # Examples /// diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index e5f2c9468e386..3ea5f160666bc 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -3692,8 +3692,8 @@ impl Vec { /// But `extract_if` is easier to use. `extract_if` is also more efficient, /// because it can backshift the elements of the array in bulk. /// - /// Note that `extract_if` also lets you mutate the elements passed to the filter closure, - /// regardless of whether you choose to keep or remove them. + /// The iterator also lets you mutate the value of each element in the + /// closure, regardless of whether you choose to keep or remove it. /// /// # Panics /// diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs index 9732d2c2d5ce9..5e053d3644856 100644 --- a/library/std/src/collections/hash/map.rs +++ b/library/std/src/collections/hash/map.rs @@ -654,8 +654,8 @@ impl HashMap { /// yielded. If the closure returns `false`, or panics, the element remains /// in the map and will not be yielded. /// - /// Note that `extract_if` lets you mutate every value in the filter closure, regardless of - /// whether you choose to keep or remove it. + /// The iterator also lets you mutate the value of each element in the + /// closure, regardless of whether you choose to keep or remove it. /// /// If the returned `ExtractIf` is not exhausted, e.g. because it is dropped without iterating /// or the iteration short-circuits, then the remaining elements will be retained. From a9330dd0e9fbc1698b69ac82e138d9dcef31bc33 Mon Sep 17 00:00:00 2001 From: Paul Mabileau Date: Sat, 17 May 2025 02:49:57 +0200 Subject: [PATCH 09/13] Docs(lib/coll/hm): Add kv pair to `extract_if`'s first sentence Make it consistent in this regard with `BTreeMap`'s. Signed-off-by: Paul Mabileau --- library/std/src/collections/hash/map.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs index 5e053d3644856..edbdd0411457f 100644 --- a/library/std/src/collections/hash/map.rs +++ b/library/std/src/collections/hash/map.rs @@ -648,7 +648,7 @@ impl HashMap { Drain { base: self.base.drain() } } - /// Creates an iterator which uses a closure to determine if an element should be removed. + /// Creates an iterator which uses a closure to determine if an element (key-value pair) should be removed. /// /// If the closure returns `true`, the element is removed from the map and /// yielded. If the closure returns `false`, or panics, the element remains From b1d7480acbc6bcc01f0eef98feaccdf53b387cd3 Mon Sep 17 00:00:00 2001 From: Paul Mabileau Date: Sat, 17 May 2025 02:54:21 +0200 Subject: [PATCH 10/13] Docs(lib/extract_if): Unify example description Signed-off-by: Paul Mabileau --- library/alloc/src/collections/linked_list.rs | 2 +- library/alloc/src/vec/mod.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/library/alloc/src/collections/linked_list.rs b/library/alloc/src/collections/linked_list.rs index 0e365ebd3080a..d03c1969b5b70 100644 --- a/library/alloc/src/collections/linked_list.rs +++ b/library/alloc/src/collections/linked_list.rs @@ -1137,7 +1137,7 @@ impl LinkedList { /// /// # Examples /// - /// Splitting a list into evens and odds, reusing the original list: + /// Splitting a list into even and odd values, reusing the original list: /// /// ``` /// use std::collections::LinkedList; diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 3ea5f160666bc..ce7321544b6b9 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -3701,7 +3701,7 @@ impl Vec { /// /// # Examples /// - /// Splitting an array into evens and odds, reusing the original allocation: + /// Splitting a vector into even and odd values, reusing the original vector: /// /// ``` /// let mut numbers = vec![1, 2, 3, 4, 5, 6, 8, 9, 11, 13, 14, 15]; From 1eba1b56e33f196e6b48cad2efb41b9b9ab7452f Mon Sep 17 00:00:00 2001 From: binarycat Date: Thu, 22 May 2025 16:05:52 -0500 Subject: [PATCH 11/13] rustdoc: rip out all the gui tests for <100% width mobile sidebar stuff like "clicking the settings menu closes the mobile sidebar" is now impossible for users to observe, since the mobile sidebar will always cover the settings menu due to being full-width, which is good because that behavior is also now impossible for our testing framework to observe. --- tests/rustdoc-gui/notable-trait.goml | 4 ---- tests/rustdoc-gui/pocket-menu.goml | 13 ------------- tests/rustdoc-gui/sidebar-mobile.goml | 7 +++++-- 3 files changed, 5 insertions(+), 19 deletions(-) diff --git a/tests/rustdoc-gui/notable-trait.goml b/tests/rustdoc-gui/notable-trait.goml index 4624fb80b3779..7fc70e0675df4 100644 --- a/tests/rustdoc-gui/notable-trait.goml +++ b/tests/rustdoc-gui/notable-trait.goml @@ -244,10 +244,6 @@ click: ".sidebar-menu-toggle" assert: "//*[@class='sidebar shown']" assert-count: ("//*[@class='tooltip popover']", 0) assert-false: "#method\.create_an_iterator_from_read .tooltip:focus" -// Clicking a notable trait tooltip popover should close the sidebar. -click: "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']" -assert-count: ("//*[@class='tooltip popover']", 1) -assert-false: "//*[@class='sidebar shown']" // Also check the focus handling for the settings button. set-window-size: (1100, 600) diff --git a/tests/rustdoc-gui/pocket-menu.goml b/tests/rustdoc-gui/pocket-menu.goml index 4a062fec7516d..073172dd8a791 100644 --- a/tests/rustdoc-gui/pocket-menu.goml +++ b/tests/rustdoc-gui/pocket-menu.goml @@ -68,16 +68,3 @@ assert-css: ("#settings-menu .popover", {"display": "block"}) click: ".sidebar-menu-toggle" assert: "//*[@class='sidebar shown']" assert-css: ("#settings-menu .popover", {"display": "none"}) -// Opening the settings popover should close the sidebar. -click: "#settings-menu a" -assert-css: ("#settings-menu .popover", {"display": "block"}) -assert-false: "//*[@class='sidebar shown']" - -// Opening the settings popover at start (which async loads stuff) should also close. -reload: -click: ".sidebar-menu-toggle" -assert: "//*[@class='sidebar shown']" -assert-false: "#settings-menu .popover" -click: "#settings-menu a" -assert-false: "//*[@class='sidebar shown']" -wait-for: "#settings-menu .popover" diff --git a/tests/rustdoc-gui/sidebar-mobile.goml b/tests/rustdoc-gui/sidebar-mobile.goml index 4ada4837a5774..0596f84317481 100644 --- a/tests/rustdoc-gui/sidebar-mobile.goml +++ b/tests/rustdoc-gui/sidebar-mobile.goml @@ -32,8 +32,8 @@ assert-css: ( {"display": "block"} ) -// Click elsewhere. -click: "body" +// Click the toggle to close it +click: ".sidebar-menu-toggle" assert-css: (".sidebar", {"display": "block", "left": "-1000px"}) // Open the sidebar menu, and make sure pressing Escape closes it. @@ -57,6 +57,7 @@ scroll-to: ".block.keyword li:nth-child(1)" compare-elements-position-near: (".block.keyword li:nth-child(1)", ".mobile-topbar", {"y": 544}) // Now checking the background color of the sidebar. +reload: show-text: true define-function: ( @@ -72,6 +73,8 @@ define-function: ( "background-color": |background|, "color": |color|, }) + // Close the sidebar menu. + press-key: "Escape" }, ) From 89a8abc4bea115c3508ee5ac4eb9ac3a55920316 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Wed, 21 May 2025 19:18:31 +0200 Subject: [PATCH 12/13] use `cfg_select!` to select the right `VaListImpl` definition --- library/core/src/ffi/va_list.rs | 311 ++++++++++++++------------------ 1 file changed, 136 insertions(+), 175 deletions(-) diff --git a/library/core/src/ffi/va_list.rs b/library/core/src/ffi/va_list.rs index f12bd289f27aa..8f7c090bc1ba2 100644 --- a/library/core/src/ffi/va_list.rs +++ b/library/core/src/ffi/va_list.rs @@ -5,148 +5,120 @@ use crate::ffi::c_void; #[allow(unused_imports)] use crate::fmt; -use crate::marker::PhantomData; +use crate::marker::{PhantomData, PhantomInvariantLifetime}; use crate::ops::{Deref, DerefMut}; -/// Basic implementation of a `va_list`. // The name is WIP, using `VaListImpl` for now. -#[cfg(any( +// +// Most targets explicitly specify the layout of `va_list`, this layout is matched here. +crate::cfg_select! { all( - not(target_arch = "aarch64"), - not(target_arch = "powerpc"), - not(target_arch = "s390x"), - not(target_arch = "xtensa"), - not(target_arch = "x86_64") - ), - all(target_arch = "aarch64", target_vendor = "apple"), - target_family = "wasm", - target_os = "uefi", - windows, -))] -#[repr(transparent)] -#[lang = "va_list"] -pub struct VaListImpl<'f> { - ptr: *mut c_void, - - // Invariant over `'f`, so each `VaListImpl<'f>` object is tied to - // the region of the function it's defined in - _marker: PhantomData<&'f mut &'f c_void>, -} - -#[cfg(any( - all( - not(target_arch = "aarch64"), - not(target_arch = "powerpc"), - not(target_arch = "s390x"), - not(target_arch = "xtensa"), - not(target_arch = "x86_64") - ), - all(target_arch = "aarch64", target_vendor = "apple"), - target_family = "wasm", - target_os = "uefi", - windows, -))] -impl<'f> fmt::Debug for VaListImpl<'f> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "va_list* {:p}", self.ptr) + target_arch = "aarch64", + not(target_vendor = "apple"), + not(target_os = "uefi"), + not(windows), + ) => { + /// AArch64 ABI implementation of a `va_list`. See the + /// [AArch64 Procedure Call Standard] for more details. + /// + /// [AArch64 Procedure Call Standard]: + /// http://infocenter.arm.com/help/topic/com.arm.doc.ihi0055b/IHI0055B_aapcs64.pdf + #[cfg_attr(not(doc), repr(C))] // work around https://github.com/rust-lang/rust/issues/66401 + #[derive(Debug)] + #[lang = "va_list"] + pub struct VaListImpl<'f> { + stack: *mut c_void, + gr_top: *mut c_void, + vr_top: *mut c_void, + gr_offs: i32, + vr_offs: i32, + _marker: PhantomInvariantLifetime<'f>, + } + } + all(target_arch = "powerpc", not(target_os = "uefi"), not(windows)) => { + /// PowerPC ABI implementation of a `va_list`. + #[cfg_attr(not(doc), repr(C))] // work around https://github.com/rust-lang/rust/issues/66401 + #[derive(Debug)] + #[lang = "va_list"] + pub struct VaListImpl<'f> { + gpr: u8, + fpr: u8, + reserved: u16, + overflow_arg_area: *mut c_void, + reg_save_area: *mut c_void, + _marker: PhantomInvariantLifetime<'f>, + } + } + target_arch = "s390x" => { + /// s390x ABI implementation of a `va_list`. + #[cfg_attr(not(doc), repr(C))] // work around https://github.com/rust-lang/rust/issues/66401 + #[derive(Debug)] + #[lang = "va_list"] + pub struct VaListImpl<'f> { + gpr: i64, + fpr: i64, + overflow_arg_area: *mut c_void, + reg_save_area: *mut c_void, + _marker: PhantomInvariantLifetime<'f>, + } + } + all(target_arch = "x86_64", not(target_os = "uefi"), not(windows)) => { + /// x86_64 ABI implementation of a `va_list`. + #[cfg_attr(not(doc), repr(C))] // work around https://github.com/rust-lang/rust/issues/66401 + #[derive(Debug)] + #[lang = "va_list"] + pub struct VaListImpl<'f> { + gp_offset: i32, + fp_offset: i32, + overflow_arg_area: *mut c_void, + reg_save_area: *mut c_void, + _marker: PhantomInvariantLifetime<'f>, + } + } + target_arch = "xtensa" => { + /// Xtensa ABI implementation of a `va_list`. + #[repr(C)] + #[derive(Debug)] + #[lang = "va_list"] + pub struct VaListImpl<'f> { + stk: *mut i32, + reg: *mut i32, + ndx: i32, + _marker: PhantomInvariantLifetime<'f>, + } } -} - -/// AArch64 ABI implementation of a `va_list`. See the -/// [AArch64 Procedure Call Standard] for more details. -/// -/// [AArch64 Procedure Call Standard]: -/// http://infocenter.arm.com/help/topic/com.arm.doc.ihi0055b/IHI0055B_aapcs64.pdf -#[cfg(all( - target_arch = "aarch64", - not(target_vendor = "apple"), - not(target_os = "uefi"), - not(windows), -))] -#[cfg_attr(not(doc), repr(C))] // work around https://github.com/rust-lang/rust/issues/66401 -#[derive(Debug)] -#[lang = "va_list"] -pub struct VaListImpl<'f> { - stack: *mut c_void, - gr_top: *mut c_void, - vr_top: *mut c_void, - gr_offs: i32, - vr_offs: i32, - _marker: PhantomData<&'f mut &'f c_void>, -} - -/// PowerPC ABI implementation of a `va_list`. -#[cfg(all(target_arch = "powerpc", not(target_os = "uefi"), not(windows)))] -#[cfg_attr(not(doc), repr(C))] // work around https://github.com/rust-lang/rust/issues/66401 -#[derive(Debug)] -#[lang = "va_list"] -pub struct VaListImpl<'f> { - gpr: u8, - fpr: u8, - reserved: u16, - overflow_arg_area: *mut c_void, - reg_save_area: *mut c_void, - _marker: PhantomData<&'f mut &'f c_void>, -} - -/// s390x ABI implementation of a `va_list`. -#[cfg(target_arch = "s390x")] -#[cfg_attr(not(doc), repr(C))] // work around https://github.com/rust-lang/rust/issues/66401 -#[derive(Debug)] -#[lang = "va_list"] -pub struct VaListImpl<'f> { - gpr: i64, - fpr: i64, - overflow_arg_area: *mut c_void, - reg_save_area: *mut c_void, - _marker: PhantomData<&'f mut &'f c_void>, -} -/// x86_64 ABI implementation of a `va_list`. -#[cfg(all(target_arch = "x86_64", not(target_os = "uefi"), not(windows)))] -#[cfg_attr(not(doc), repr(C))] // work around https://github.com/rust-lang/rust/issues/66401 -#[derive(Debug)] -#[lang = "va_list"] -pub struct VaListImpl<'f> { - gp_offset: i32, - fp_offset: i32, - overflow_arg_area: *mut c_void, - reg_save_area: *mut c_void, - _marker: PhantomData<&'f mut &'f c_void>, -} + // The fallback implementation, used for: + // + // - apple aarch64 (see https://github.com/rust-lang/rust/pull/56599) + // - windows + // - uefi + // - any other target for which we don't specify the `VaListImpl` above + // + // In this implementation the `va_list` type is just an alias for an opaque pointer. + // That pointer is probably just the next variadic argument on the caller's stack. + _ => { + /// Basic implementation of a `va_list`. + #[repr(transparent)] + #[lang = "va_list"] + pub struct VaListImpl<'f> { + ptr: *mut c_void, + + // Invariant over `'f`, so each `VaListImpl<'f>` object is tied to + // the region of the function it's defined in + _marker: PhantomInvariantLifetime<'f>, + } -/// Xtensa ABI implementation of a `va_list`. -#[cfg(target_arch = "xtensa")] -#[repr(C)] -#[derive(Debug)] -#[lang = "va_list"] -pub struct VaListImpl<'f> { - stk: *mut i32, - reg: *mut i32, - ndx: i32, - _marker: PhantomData<&'f mut &'f c_void>, + impl<'f> fmt::Debug for VaListImpl<'f> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "va_list* {:p}", self.ptr) + } + } + } } -/// A wrapper for a `va_list` -#[repr(transparent)] -#[derive(Debug)] -pub struct VaList<'a, 'f: 'a> { - #[cfg(any( - all( - not(target_arch = "aarch64"), - not(target_arch = "powerpc"), - not(target_arch = "s390x"), - not(target_arch = "x86_64") - ), - target_arch = "xtensa", - all(target_arch = "aarch64", target_vendor = "apple"), - target_family = "wasm", - target_os = "uefi", - windows, - ))] - inner: VaListImpl<'f>, - - #[cfg(all( +crate::cfg_select! { + all( any( target_arch = "aarch64", target_arch = "powerpc", @@ -158,52 +130,41 @@ pub struct VaList<'a, 'f: 'a> { not(target_family = "wasm"), not(target_os = "uefi"), not(windows), - ))] - inner: &'a mut VaListImpl<'f>, + ) => { + /// A wrapper for a `va_list` + #[repr(transparent)] + #[derive(Debug)] + pub struct VaList<'a, 'f: 'a> { + inner: &'a mut VaListImpl<'f>, + _marker: PhantomData<&'a mut VaListImpl<'f>>, + } - _marker: PhantomData<&'a mut VaListImpl<'f>>, -} -#[cfg(any( - all( - not(target_arch = "aarch64"), - not(target_arch = "powerpc"), - not(target_arch = "s390x"), - not(target_arch = "x86_64") - ), - target_arch = "xtensa", - all(target_arch = "aarch64", target_vendor = "apple"), - target_family = "wasm", - target_os = "uefi", - windows, -))] -impl<'f> VaListImpl<'f> { - /// Converts a `VaListImpl` into a `VaList` that is binary-compatible with C's `va_list`. - #[inline] - pub fn as_va_list<'a>(&'a mut self) -> VaList<'a, 'f> { - VaList { inner: VaListImpl { ..*self }, _marker: PhantomData } + impl<'f> VaListImpl<'f> { + /// Converts a [`VaListImpl`] into a [`VaList`] that is binary-compatible with C's `va_list`. + #[inline] + pub fn as_va_list<'a>(&'a mut self) -> VaList<'a, 'f> { + VaList { inner: self, _marker: PhantomData } + } + } } -} -#[cfg(all( - any( - target_arch = "aarch64", - target_arch = "powerpc", - target_arch = "s390x", - target_arch = "xtensa", - target_arch = "x86_64" - ), - not(target_arch = "xtensa"), - any(not(target_arch = "aarch64"), not(target_vendor = "apple")), - not(target_family = "wasm"), - not(target_os = "uefi"), - not(windows), -))] -impl<'f> VaListImpl<'f> { - /// Converts a `VaListImpl` into a `VaList` that is binary-compatible with C's `va_list`. - #[inline] - pub fn as_va_list<'a>(&'a mut self) -> VaList<'a, 'f> { - VaList { inner: self, _marker: PhantomData } + _ => { + /// A wrapper for a `va_list` + #[repr(transparent)] + #[derive(Debug)] + pub struct VaList<'a, 'f: 'a> { + inner: VaListImpl<'f>, + _marker: PhantomData<&'a mut VaListImpl<'f>>, + } + + impl<'f> VaListImpl<'f> { + /// Converts a [`VaListImpl`] into a [`VaList`] that is binary-compatible with C's `va_list`. + #[inline] + pub fn as_va_list<'a>(&'a mut self) -> VaList<'a, 'f> { + VaList { inner: VaListImpl { ..*self }, _marker: PhantomData } + } + } } } From bcca611b359c74b71e798c2ee30f4695c6218bbf Mon Sep 17 00:00:00 2001 From: binarycat Date: Fri, 23 May 2025 17:43:19 -0500 Subject: [PATCH 13/13] rustdoc-gui test: apply suggestions from code review --- tests/rustdoc-gui/sidebar-mobile.goml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/rustdoc-gui/sidebar-mobile.goml b/tests/rustdoc-gui/sidebar-mobile.goml index 0596f84317481..6ddc07c6481c1 100644 --- a/tests/rustdoc-gui/sidebar-mobile.goml +++ b/tests/rustdoc-gui/sidebar-mobile.goml @@ -57,7 +57,8 @@ scroll-to: ".block.keyword li:nth-child(1)" compare-elements-position-near: (".block.keyword li:nth-child(1)", ".mobile-topbar", {"y": 544}) // Now checking the background color of the sidebar. -reload: +// Close the sidebar menu. +press-key: "Escape" show-text: true define-function: ( @@ -73,6 +74,8 @@ define-function: ( "background-color": |background|, "color": |color|, }) + // Make sure the sidebar is full width + compare-elements-size: (".sidebar", "body", ["width"]) // Close the sidebar menu. press-key: "Escape" },