From 7ce8e289db72471c41b53664a214ed0e00458f07 Mon Sep 17 00:00:00 2001 From: ltdk Date: Wed, 13 Aug 2025 12:38:11 -0400 Subject: [PATCH 01/10] Add `Path::has_trailing_sep` and related methods --- library/std/src/path.rs | 187 +++++++++++++++++++++++++++++++++++++- library/std/tests/path.rs | 38 +++++++- 2 files changed, 221 insertions(+), 4 deletions(-) diff --git a/library/std/src/path.rs b/library/std/src/path.rs index 19663e4a9df62..943c40220b848 100644 --- a/library/std/src/path.rs +++ b/library/std/src/path.rs @@ -1412,6 +1412,99 @@ impl PathBuf { } } + /// Sets whether the path has a trailing [separator](MAIN_SEPARATOR). + /// + /// The value returned by [`has_trailing_sep`](Path::has_trailing_sep) will be equivalent to + /// the provided value if possible. + /// + /// # Examples + /// + /// ``` + /// #![feature(path_trailing_sep)] + /// use std::path::PathBuf; + /// + /// let mut p = PathBuf::from("dir"); + /// + /// assert!(!p.has_trailing_sep()); + /// p.set_trailing_sep(false); + /// assert!(!p.has_trailing_sep()); + /// p.set_trailing_sep(true); + /// assert!(p.has_trailing_sep()); + /// p.set_trailing_sep(false); + /// assert!(!p.has_trailing_sep()); + /// + /// p = PathBuf::from("/"); + /// assert!(p.has_trailing_sep()); + /// p.set_trailing_sep(false); + /// assert!(p.has_trailing_sep()); + /// ``` + #[unstable(feature = "path_trailing_sep", issue = "142503")] + pub fn set_trailing_sep(&mut self, trailing_sep: bool) { + if trailing_sep { self.push_trailing_sep() } else { self.pop_trailing_sep() } + } + + /// Adds a trailing [separator](MAIN_SEPARATOR) to the path. + /// + /// This acts similarly to [`Path::with_trailing_sep`], but mutates the underlying `PathBuf`. + /// + /// # Examples + /// + /// ``` + /// #![feature(path_trailing_sep)] + /// use std::ffi::OsStr; + /// use std::path::PathBuf; + /// + /// let mut p = PathBuf::from("dir"); + /// + /// assert!(!p.has_trailing_sep()); + /// p.push_trailing_sep(); + /// assert!(p.has_trailing_sep()); + /// p.push_trailing_sep(); + /// assert!(p.has_trailing_sep()); + /// + /// p = PathBuf::from("dir/"); + /// p.push_trailing_sep(); + /// assert_eq!(p.as_os_str(), OsStr::new("dir/")); + /// ``` + #[unstable(feature = "path_trailing_sep", issue = "142503")] + pub fn push_trailing_sep(&mut self) { + if !self.has_trailing_sep() { + self.push(""); + } + } + + /// Removes a trailing [separator](MAIN_SEPARATOR) from the path, if possible. + /// + /// This acts similarly to [`Path::trim_trailing_sep`], but mutates the underlying `PathBuf`. + /// + /// # Examples + /// + /// ``` + /// #![feature(path_trailing_sep)] + /// use std::ffi::OsStr; + /// use std::path::PathBuf; + /// + /// let mut p = PathBuf::from("dir//"); + /// + /// assert!(p.has_trailing_sep()); + /// assert_eq!(p.as_os_str(), OsStr::new("dir//")); + /// p.pop_trailing_sep(); + /// assert!(!p.has_trailing_sep()); + /// assert_eq!(p.as_os_str(), OsStr::new("dir")); + /// p.pop_trailing_sep(); + /// assert!(!p.has_trailing_sep()); + /// assert_eq!(p.as_os_str(), OsStr::new("dir")); + /// + /// p = PathBuf::from("/"); + /// assert!(p.has_trailing_sep()); + /// p.pop_trailing_sep(); + /// assert!(p.has_trailing_sep()); + /// ``` + #[unstable(feature = "path_trailing_sep", issue = "142503")] + pub fn pop_trailing_sep(&mut self) { + self.inner.truncate(self.trim_trailing_sep().as_os_str().len()); + } + /// Updates [`self.file_name`] to `file_name`. /// /// If [`self.file_name`] was [`None`], this is equivalent to pushing @@ -1610,7 +1703,7 @@ impl PathBuf { let new = extension.as_encoded_bytes(); if !new.is_empty() { // truncate until right after the file name - // this is necessary for trimming the trailing slash + // this is necessary for trimming the trailing separator let end_file_name = file_name[file_name.len()..].as_ptr().addr(); let start = self.inner.as_encoded_bytes().as_ptr().addr(); self.inner.truncate(end_file_name.wrapping_sub(start)); @@ -2755,6 +2848,94 @@ impl Path { self.file_name().map(rsplit_file_at_dot).and_then(|(before, after)| before.and(after)) } + /// Checks whether the path ends in a trailing [separator](MAIN_SEPARATOR). + /// + /// This is generally done to ensure that a path is treated as a directory, not a file, + /// although it does not actually guarantee that such a path is a directory on the underlying + /// file system. + /// + /// Despite this behavior, two paths are still considered the same in Rust whether they have a + /// trailing separator or not. + /// + /// # Examples + /// + /// ``` + /// #![feature(path_trailing_sep)] + /// use std::path::Path; + /// + /// assert!(Path::new("dir/").has_trailing_sep()); + /// assert!(!Path::new("file.rs").has_trailing_sep()); + /// ``` + #[unstable(feature = "path_trailing_sep", issue = "142503")] + #[must_use] + #[inline] + pub fn has_trailing_sep(&self) -> bool { + self.as_os_str().as_encoded_bytes().last().copied().is_some_and(is_sep_byte) + } + + /// Ensures that a path has a trailing [separator](MAIN_SEPARATOR), + /// allocating a [`PathBuf`] if necessary. + /// + /// The resulting path will return true for [`has_trailing_sep`](Self::has_trailing_sep). + /// + /// # Examples + /// + /// ``` + /// #![feature(path_trailing_sep)] + /// use std::ffi::OsStr; + /// use std::path::Path; + /// + /// assert_eq!(Path::new("dir//").with_trailing_sep().as_os_str(), OsStr::new("dir//")); + /// assert_eq!(Path::new("dir/").with_trailing_sep().as_os_str(), OsStr::new("dir/")); + /// assert!(!Path::new("dir").has_trailing_sep()); + /// assert!(Path::new("dir").with_trailing_sep().has_trailing_sep()); + /// ``` + #[unstable(feature = "path_trailing_sep", issue = "142503")] + #[must_use] + #[inline] + pub fn with_trailing_sep(&self) -> Cow<'_, Path> { + if self.has_trailing_sep() { Cow::Borrowed(self) } else { Cow::Owned(self.join("")) } + } + + /// Trims a trailing [separator](MAIN_SEPARATOR) from a path, if possible. + /// + /// The resulting path will return false for [`has_trailing_sep`](Self::has_trailing_sep) for + /// most paths. + /// + /// Some paths, like `/`, cannot be trimmed in this way. + /// + /// # Examples + /// + /// ``` + /// #![feature(path_trailing_sep)] + /// use std::ffi::OsStr; + /// use std::path::Path; + /// + /// assert_eq!(Path::new("dir//").trim_trailing_sep().as_os_str(), OsStr::new("dir")); + /// assert_eq!(Path::new("dir/").trim_trailing_sep().as_os_str(), OsStr::new("dir")); + /// assert_eq!(Path::new("dir").trim_trailing_sep().as_os_str(), OsStr::new("dir")); + /// assert_eq!(Path::new("/").trim_trailing_sep().as_os_str(), OsStr::new("/")); + /// assert_eq!(Path::new("//").trim_trailing_sep().as_os_str(), OsStr::new("//")); + /// ``` + #[unstable(feature = "path_trailing_sep", issue = "142503")] + #[must_use] + #[inline] + pub fn trim_trailing_sep(&self) -> &Path { + if self.has_trailing_sep() && (!self.has_root() || self.parent().is_some()) { + let mut bytes = self.inner.as_encoded_bytes(); + while let Some((last, init)) = bytes.split_last() + && is_sep_byte(*last) + { + bytes = init; + } + + // SAFETY: Trimming trailing ASCII bytes will retain the validity of the string. + Path::new(unsafe { OsStr::from_encoded_bytes_unchecked(bytes) }) + } else { + self + } + } + /// Creates an owned [`PathBuf`] with `path` adjoined to `self`. /// /// If `path` is absolute, it replaces the current path. @@ -2907,7 +3088,7 @@ impl Path { /// `a/b` all have `a` and `b` as components, but `./a/b` starts with /// an additional [`CurDir`] component. /// - /// * A trailing slash is normalized away, `/a/b` and `/a/b/` are equivalent. + /// * Trailing separators are normalized away, so `/a/b` and `/a/b/` are equivalent. /// /// Note that no other normalization takes place; in particular, `a/c` /// and `a/b/../c` are distinct, to account for the possibility that `b` @@ -3710,7 +3891,7 @@ impl Error for NormalizeError {} /// /// On POSIX platforms, the path is resolved using [POSIX semantics][posix-semantics], /// except that it stops short of resolving symlinks. This means it will keep `..` -/// components and trailing slashes. +/// components and trailing separators. /// /// On Windows, for verbatim paths, this will simply return the path as given. For other /// paths, this is currently equivalent to calling diff --git a/library/std/tests/path.rs b/library/std/tests/path.rs index fa76c50597b05..1d3337ff935a8 100644 --- a/library/std/tests/path.rs +++ b/library/std/tests/path.rs @@ -1,4 +1,9 @@ -#![feature(clone_to_uninit, maybe_uninit_slice, normalize_lexically)] +// tidy-alphabetical-start +#![feature(clone_to_uninit)] +#![feature(maybe_uninit_slice)] +#![feature(normalize_lexically)] +#![feature(path_trailing_sep)] +// tidy-alphabetical-end use std::clone::CloneToUninit; use std::ffi::OsStr; @@ -2532,3 +2537,34 @@ fn normalize_lexically() { fn compare_path_to_str() { assert!(&PathBuf::from("x") == "x"); } + +#[test] +fn test_trim_trailing_sep() { + assert_eq!(Path::new("/").trim_trailing_sep().as_os_str(), OsStr::new("/")); + assert_eq!(Path::new("//").trim_trailing_sep().as_os_str(), OsStr::new("//")); + assert_eq!(Path::new("").trim_trailing_sep().as_os_str(), OsStr::new("")); + assert_eq!(Path::new(".").trim_trailing_sep().as_os_str(), OsStr::new(".")); + assert_eq!(Path::new("./").trim_trailing_sep().as_os_str(), OsStr::new(".")); + assert_eq!(Path::new(".//").trim_trailing_sep().as_os_str(), OsStr::new(".")); + assert_eq!(Path::new("..").trim_trailing_sep().as_os_str(), OsStr::new("..")); + assert_eq!(Path::new("../").trim_trailing_sep().as_os_str(), OsStr::new("..")); + assert_eq!(Path::new("..//").trim_trailing_sep().as_os_str(), OsStr::new("..")); + + #[cfg(any(windows, target_os = "cygwin"))] + { + assert_eq!(Path::new("\\").trim_trailing_sep().as_os_str(), OsStr::new("\\")); + assert_eq!(Path::new("\\\\").trim_trailing_sep().as_os_str(), OsStr::new("\\\\")); + assert_eq!(Path::new("c:/").trim_trailing_sep().as_os_str(), OsStr::new("c:/")); + assert_eq!(Path::new("c://").trim_trailing_sep().as_os_str(), OsStr::new("c://")); + assert_eq!(Path::new("c:./").trim_trailing_sep().as_os_str(), OsStr::new("c:.")); + assert_eq!(Path::new("c:.//").trim_trailing_sep().as_os_str(), OsStr::new("c:.")); + assert_eq!(Path::new("c:../").trim_trailing_sep().as_os_str(), OsStr::new("c:..")); + assert_eq!(Path::new("c:..//").trim_trailing_sep().as_os_str(), OsStr::new("c:..")); + assert_eq!(Path::new("c:\\").trim_trailing_sep().as_os_str(), OsStr::new("c:\\")); + assert_eq!(Path::new("c:\\\\").trim_trailing_sep().as_os_str(), OsStr::new("c:\\\\")); + assert_eq!(Path::new("c:.\\").trim_trailing_sep().as_os_str(), OsStr::new("c:.")); + assert_eq!(Path::new("c:.\\\\").trim_trailing_sep().as_os_str(), OsStr::new("c:.")); + assert_eq!(Path::new("c:..\\").trim_trailing_sep().as_os_str(), OsStr::new("c:..")); + assert_eq!(Path::new("c:..\\\\").trim_trailing_sep().as_os_str(), OsStr::new("c:..")); + } +} From 9bb4081fb0977c1a8923fff6ebe60fc882bcac1d Mon Sep 17 00:00:00 2001 From: cyrgani Date: Mon, 29 Sep 2025 23:42:01 +0200 Subject: [PATCH 02/10] remove `reverse_{encode, decode}!` --- library/proc_macro/src/bridge/client.rs | 2 +- library/proc_macro/src/bridge/mod.rs | 20 -------------------- library/proc_macro/src/bridge/server.rs | 2 +- 3 files changed, 2 insertions(+), 22 deletions(-) diff --git a/library/proc_macro/src/bridge/client.rs b/library/proc_macro/src/bridge/client.rs index e7d547966a5d5..4e519e56a1ed4 100644 --- a/library/proc_macro/src/bridge/client.rs +++ b/library/proc_macro/src/bridge/client.rs @@ -144,7 +144,7 @@ macro_rules! define_client_side { buf.clear(); api_tags::Method::$name(api_tags::$name::$method).encode(&mut buf, &mut ()); - reverse_encode!(buf; $($arg),*); + $($arg.encode(&mut buf, &mut ());)* buf = bridge.dispatch.call(buf); diff --git a/library/proc_macro/src/bridge/mod.rs b/library/proc_macro/src/bridge/mod.rs index d60a76fff5dc5..7fd67ba465ef4 100644 --- a/library/proc_macro/src/bridge/mod.rs +++ b/library/proc_macro/src/bridge/mod.rs @@ -119,26 +119,6 @@ macro_rules! with_api_handle_types { }; } -// FIXME(eddyb) this calls `encode` for each argument, but in reverse, -// to match the ordering in `reverse_decode`. -macro_rules! reverse_encode { - ($writer:ident;) => {}; - ($writer:ident; $first:ident $(, $rest:ident)*) => { - reverse_encode!($writer; $($rest),*); - $first.encode(&mut $writer, &mut ()); - } -} - -// FIXME(eddyb) this calls `decode` for each argument, but in reverse, -// to avoid borrow conflicts from borrows started by `&mut` arguments. -macro_rules! reverse_decode { - ($reader:ident, $s:ident;) => {}; - ($reader:ident, $s:ident; $first:ident: $first_ty:ty $(, $rest:ident: $rest_ty:ty)*) => { - reverse_decode!($reader, $s; $($rest: $rest_ty),*); - let $first = <$first_ty>::decode(&mut $reader, $s); - } -} - #[allow(unsafe_code)] mod arena; #[allow(unsafe_code)] diff --git a/library/proc_macro/src/bridge/server.rs b/library/proc_macro/src/bridge/server.rs index 5beda7c3c96e5..724ccbd96c59b 100644 --- a/library/proc_macro/src/bridge/server.rs +++ b/library/proc_macro/src/bridge/server.rs @@ -178,7 +178,7 @@ macro_rules! define_dispatcher_impl { $(api_tags::Method::$name(m) => match m { $(api_tags::$name::$method => { let mut call_method = || { - reverse_decode!(reader, handle_store; $($arg: $arg_ty),*); + $(let $arg = <$arg_ty>::decode(&mut reader, handle_store);)* $name::$method(server, $($arg),*) }; // HACK(eddyb) don't use `panic::catch_unwind` in a panic. From 23f340061395300415d551fdac92d28ca2f2fbfb Mon Sep 17 00:00:00 2001 From: cyrgani Date: Tue, 30 Sep 2025 00:01:17 +0200 Subject: [PATCH 03/10] remove unused `#![feature(stmt_expr_attributes)]` --- library/proc_macro/src/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/library/proc_macro/src/lib.rs b/library/proc_macro/src/lib.rs index 162b4fdcc8ae2..613abd7024e3f 100644 --- a/library/proc_macro/src/lib.rs +++ b/library/proc_macro/src/lib.rs @@ -27,7 +27,6 @@ #![feature(panic_can_unwind)] #![feature(restricted_std)] #![feature(rustc_attrs)] -#![feature(stmt_expr_attributes)] #![feature(extend_one)] #![recursion_limit = "256"] #![allow(internal_features)] From d7773f6b1c220d43946bce8010847837ad334b74 Mon Sep 17 00:00:00 2001 From: cyrgani Date: Tue, 30 Sep 2025 00:09:12 +0200 Subject: [PATCH 04/10] explicitly implement `!Send` and `!Sync` --- library/proc_macro/src/bridge/client.rs | 17 ++++++----------- library/proc_macro/src/bridge/closure.rs | 4 +--- library/proc_macro/src/bridge/mod.rs | 8 +++----- library/proc_macro/src/bridge/server.rs | 14 ++------------ 4 files changed, 12 insertions(+), 31 deletions(-) diff --git a/library/proc_macro/src/bridge/client.rs b/library/proc_macro/src/bridge/client.rs index 4e519e56a1ed4..92558f2b7d9cc 100644 --- a/library/proc_macro/src/bridge/client.rs +++ b/library/proc_macro/src/bridge/client.rs @@ -26,18 +26,16 @@ macro_rules! define_client_handles { $( pub(crate) struct $oty { handle: handle::Handle, - // Prevent Send and Sync impls. `!Send`/`!Sync` is the usual - // way of doing this, but that requires unstable features. - // rust-analyzer uses this code and avoids unstable features. - _marker: PhantomData<*mut ()>, } + impl !Send for $oty {} + impl !Sync for $oty {} + // Forward `Drop::drop` to the inherent `drop` method. impl Drop for $oty { fn drop(&mut self) { $oty { handle: self.handle, - _marker: PhantomData, }.drop(); } } @@ -64,7 +62,6 @@ macro_rules! define_client_handles { fn decode(r: &mut Reader<'_>, s: &mut S) -> Self { $oty { handle: handle::Handle::decode(r, s), - _marker: PhantomData, } } } @@ -74,12 +71,11 @@ macro_rules! define_client_handles { #[derive(Copy, Clone, PartialEq, Eq, Hash)] pub(crate) struct $ity { handle: handle::Handle, - // Prevent Send and Sync impls. `!Send`/`!Sync` is the usual - // way of doing this, but that requires unstable features. - // rust-analyzer uses this code and avoids unstable features. - _marker: PhantomData<*mut ()>, } + impl !Send for $ity {} + impl !Sync for $ity {} + impl Encode for $ity { fn encode(self, w: &mut Writer, s: &mut S) { self.handle.encode(w, s); @@ -90,7 +86,6 @@ macro_rules! define_client_handles { fn decode(r: &mut Reader<'_>, s: &mut S) -> Self { $ity { handle: handle::Handle::decode(r, s), - _marker: PhantomData, } } } diff --git a/library/proc_macro/src/bridge/closure.rs b/library/proc_macro/src/bridge/closure.rs index e0e688434dce5..e5133907854b2 100644 --- a/library/proc_macro/src/bridge/closure.rs +++ b/library/proc_macro/src/bridge/closure.rs @@ -6,9 +6,7 @@ use std::marker::PhantomData; pub(super) struct Closure<'a, A, R> { call: unsafe extern "C" fn(*mut Env, A) -> R, env: *mut Env, - // Prevent Send and Sync impls. `!Send`/`!Sync` is the usual way of doing - // this, but that requires unstable features. rust-analyzer uses this code - // and avoids unstable features. + // Prevent Send and Sync impls. // // The `'a` lifetime parameter represents the lifetime of `Env`. _marker: PhantomData<*mut &'a mut ()>, diff --git a/library/proc_macro/src/bridge/mod.rs b/library/proc_macro/src/bridge/mod.rs index 7fd67ba465ef4..1b09deb6bfe60 100644 --- a/library/proc_macro/src/bridge/mod.rs +++ b/library/proc_macro/src/bridge/mod.rs @@ -160,13 +160,11 @@ pub struct BridgeConfig<'a> { /// If 'true', always invoke the default panic hook force_show_panics: bool, - - // Prevent Send and Sync impls. `!Send`/`!Sync` is the usual way of doing - // this, but that requires unstable features. rust-analyzer uses this code - // and avoids unstable features. - _marker: marker::PhantomData<*mut ()>, } +impl !Send for BridgeConfig<'_> {} +impl !Sync for BridgeConfig<'_> {} + #[forbid(unsafe_code)] #[allow(non_camel_case_types)] mod api_tags { diff --git a/library/proc_macro/src/bridge/server.rs b/library/proc_macro/src/bridge/server.rs index 724ccbd96c59b..0bb30698aa1d7 100644 --- a/library/proc_macro/src/bridge/server.rs +++ b/library/proc_macro/src/bridge/server.rs @@ -295,12 +295,7 @@ impl ExecutionStrategy for SameThread { let mut dispatch = |buf| dispatcher.dispatch(buf); - run_client(BridgeConfig { - input, - dispatch: (&mut dispatch).into(), - force_show_panics, - _marker: marker::PhantomData, - }) + run_client(BridgeConfig { input, dispatch: (&mut dispatch).into(), force_show_panics }) } } @@ -331,12 +326,7 @@ where client.recv().expect("server died while client waiting for reply") }; - run_client(BridgeConfig { - input, - dispatch: (&mut dispatch).into(), - force_show_panics, - _marker: marker::PhantomData, - }) + run_client(BridgeConfig { input, dispatch: (&mut dispatch).into(), force_show_panics }) }); while let Some(b) = server.recv() { From cd40bbfe2965a42ae8336ebd70fc7fb9c81d22e0 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Mon, 29 Sep 2025 20:53:06 +1000 Subject: [PATCH 05/10] Move `MetadataKindId` into its own submodule --- compiler/rustc_codegen_llvm/src/llvm/ffi.rs | 11 +---------- .../rustc_codegen_llvm/src/llvm/metadata_kind.rs | 13 +++++++++++++ compiler/rustc_codegen_llvm/src/llvm/mod.rs | 2 ++ 3 files changed, 16 insertions(+), 10 deletions(-) create mode 100644 compiler/rustc_codegen_llvm/src/llvm/metadata_kind.rs diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index afd2991a09c3a..83867cc2dce66 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -29,6 +29,7 @@ use super::debuginfo::{ DITemplateTypeParameter, DIType, DebugEmissionKind, DebugNameTableKind, }; use crate::llvm; +use crate::llvm::MetadataKindId; /// In the LLVM-C API, boolean values are passed as `typedef int LLVMBool`, /// which has a different ABI from Rust or C++ `bool`. @@ -1035,16 +1036,6 @@ pub(crate) type GetSymbolsCallback = unsafe extern "C" fn(*mut c_void, *const c_char) -> *mut c_void; pub(crate) type GetSymbolsErrorCallback = unsafe extern "C" fn(*const c_char) -> *mut c_void; -#[derive(Copy, Clone)] -#[repr(transparent)] -pub(crate) struct MetadataKindId(c_uint); - -impl From for MetadataKindId { - fn from(value: MetadataType) -> Self { - Self(value as c_uint) - } -} - unsafe extern "C" { // Create and destroy contexts. pub(crate) fn LLVMContextDispose(C: &'static mut Context); diff --git a/compiler/rustc_codegen_llvm/src/llvm/metadata_kind.rs b/compiler/rustc_codegen_llvm/src/llvm/metadata_kind.rs new file mode 100644 index 0000000000000..926eb78935205 --- /dev/null +++ b/compiler/rustc_codegen_llvm/src/llvm/metadata_kind.rs @@ -0,0 +1,13 @@ +use libc::c_uint; + +use crate::llvm::MetadataType; + +#[derive(Copy, Clone)] +#[repr(transparent)] +pub(crate) struct MetadataKindId(c_uint); + +impl From for MetadataKindId { + fn from(value: MetadataType) -> Self { + Self(value as c_uint) + } +} diff --git a/compiler/rustc_codegen_llvm/src/llvm/mod.rs b/compiler/rustc_codegen_llvm/src/llvm/mod.rs index 1115d82fa85d3..2333fbe7a7656 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/mod.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/mod.rs @@ -13,11 +13,13 @@ pub(crate) use self::CallConv::*; pub(crate) use self::CodeGenOptSize::*; pub(crate) use self::MetadataType::*; pub(crate) use self::ffi::*; +pub(crate) use self::metadata_kind::MetadataKindId; use crate::common::AsCCharPtr; pub(crate) mod diagnostic; pub(crate) mod enzyme_ffi; mod ffi; +mod metadata_kind; pub(crate) use self::enzyme_ffi::*; From 906bf49ade52d7485a6c8a0756f020ade3a342b6 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Mon, 29 Sep 2025 20:21:33 +1000 Subject: [PATCH 06/10] Declare all "fixed" metadata kinds as `MetadataKindId` --- .../src/llvm/metadata_kind.rs | 64 +++++++++++++++++++ .../rustc_llvm/llvm-wrapper/RustWrapper.cpp | 52 +++++++++++++++ 2 files changed, 116 insertions(+) diff --git a/compiler/rustc_codegen_llvm/src/llvm/metadata_kind.rs b/compiler/rustc_codegen_llvm/src/llvm/metadata_kind.rs index 926eb78935205..4d00356c61627 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/metadata_kind.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/metadata_kind.rs @@ -11,3 +11,67 @@ impl From for MetadataKindId { Self(value as c_uint) } } + +macro_rules! declare_fixed_metadata_kinds { + ( + $( + FIXED_MD_KIND($variant:ident, $value:literal) + )* + ) => { + // Use a submodule to group all declarations into one `#[expect(..)]`. + #[expect(dead_code)] + mod fixed_kinds { + use super::MetadataKindId; + $( + #[expect(non_upper_case_globals)] + pub(crate) const $variant: MetadataKindId = MetadataKindId($value); + )* + } + }; +} + +// Must be kept in sync with the corresponding static assertions in `RustWrapper.cpp`. +declare_fixed_metadata_kinds! { + FIXED_MD_KIND(MD_dbg, 0) + FIXED_MD_KIND(MD_tbaa, 1) + FIXED_MD_KIND(MD_prof, 2) + FIXED_MD_KIND(MD_fpmath, 3) + FIXED_MD_KIND(MD_range, 4) + FIXED_MD_KIND(MD_tbaa_struct, 5) + FIXED_MD_KIND(MD_invariant_load, 6) + FIXED_MD_KIND(MD_alias_scope, 7) + FIXED_MD_KIND(MD_noalias, 8) + FIXED_MD_KIND(MD_nontemporal, 9) + FIXED_MD_KIND(MD_mem_parallel_loop_access, 10) + FIXED_MD_KIND(MD_nonnull, 11) + FIXED_MD_KIND(MD_dereferenceable, 12) + FIXED_MD_KIND(MD_dereferenceable_or_null, 13) + FIXED_MD_KIND(MD_make_implicit, 14) + FIXED_MD_KIND(MD_unpredictable, 15) + FIXED_MD_KIND(MD_invariant_group, 16) + FIXED_MD_KIND(MD_align, 17) + FIXED_MD_KIND(MD_loop, 18) + FIXED_MD_KIND(MD_type, 19) + FIXED_MD_KIND(MD_section_prefix, 20) + FIXED_MD_KIND(MD_absolute_symbol, 21) + FIXED_MD_KIND(MD_associated, 22) + FIXED_MD_KIND(MD_callees, 23) + FIXED_MD_KIND(MD_irr_loop, 24) + FIXED_MD_KIND(MD_access_group, 25) + FIXED_MD_KIND(MD_callback, 26) + FIXED_MD_KIND(MD_preserve_access_index, 27) + FIXED_MD_KIND(MD_vcall_visibility, 28) + FIXED_MD_KIND(MD_noundef, 29) + FIXED_MD_KIND(MD_annotation, 30) + FIXED_MD_KIND(MD_nosanitize, 31) + FIXED_MD_KIND(MD_func_sanitize, 32) + FIXED_MD_KIND(MD_exclude, 33) + FIXED_MD_KIND(MD_memprof, 34) + FIXED_MD_KIND(MD_callsite, 35) + FIXED_MD_KIND(MD_kcfi_type, 36) + FIXED_MD_KIND(MD_pcsections, 37) + FIXED_MD_KIND(MD_DIAssignID, 38) + FIXED_MD_KIND(MD_coro_outside_frame, 39) + FIXED_MD_KIND(MD_mmra, 40) + FIXED_MD_KIND(MD_noalias_addrspace, 41) +} diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp index 4a77812591893..2b83ea24ac61c 100644 --- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp @@ -1824,3 +1824,55 @@ extern "C" size_t LLVMRustEnzymeGetMaxTypeDepth() { return 6; // Default fallback depth } #endif + +// Statically assert that the fixed metadata kind IDs declared in +// `metadata_kind.rs` match the ones actually used by LLVM. +#define FIXED_MD_KIND(VARIANT, VALUE) \ + static_assert(::llvm::LLVMContext::VARIANT == VALUE); +// Must be kept in sync with the corresponding list in `metadata_kind.rs`. +FIXED_MD_KIND(MD_dbg, 0) +FIXED_MD_KIND(MD_tbaa, 1) +FIXED_MD_KIND(MD_prof, 2) +FIXED_MD_KIND(MD_fpmath, 3) +FIXED_MD_KIND(MD_range, 4) +FIXED_MD_KIND(MD_tbaa_struct, 5) +FIXED_MD_KIND(MD_invariant_load, 6) +FIXED_MD_KIND(MD_alias_scope, 7) +FIXED_MD_KIND(MD_noalias, 8) +FIXED_MD_KIND(MD_nontemporal, 9) +FIXED_MD_KIND(MD_mem_parallel_loop_access, 10) +FIXED_MD_KIND(MD_nonnull, 11) +FIXED_MD_KIND(MD_dereferenceable, 12) +FIXED_MD_KIND(MD_dereferenceable_or_null, 13) +FIXED_MD_KIND(MD_make_implicit, 14) +FIXED_MD_KIND(MD_unpredictable, 15) +FIXED_MD_KIND(MD_invariant_group, 16) +FIXED_MD_KIND(MD_align, 17) +FIXED_MD_KIND(MD_loop, 18) +FIXED_MD_KIND(MD_type, 19) +FIXED_MD_KIND(MD_section_prefix, 20) +FIXED_MD_KIND(MD_absolute_symbol, 21) +FIXED_MD_KIND(MD_associated, 22) +FIXED_MD_KIND(MD_callees, 23) +FIXED_MD_KIND(MD_irr_loop, 24) +FIXED_MD_KIND(MD_access_group, 25) +FIXED_MD_KIND(MD_callback, 26) +FIXED_MD_KIND(MD_preserve_access_index, 27) +FIXED_MD_KIND(MD_vcall_visibility, 28) +FIXED_MD_KIND(MD_noundef, 29) +FIXED_MD_KIND(MD_annotation, 30) +FIXED_MD_KIND(MD_nosanitize, 31) +FIXED_MD_KIND(MD_func_sanitize, 32) +FIXED_MD_KIND(MD_exclude, 33) +FIXED_MD_KIND(MD_memprof, 34) +FIXED_MD_KIND(MD_callsite, 35) +FIXED_MD_KIND(MD_kcfi_type, 36) +FIXED_MD_KIND(MD_pcsections, 37) +FIXED_MD_KIND(MD_DIAssignID, 38) +FIXED_MD_KIND(MD_coro_outside_frame, 39) +FIXED_MD_KIND(MD_mmra, 40) +FIXED_MD_KIND(MD_noalias_addrspace, 41) +// If some fixed metadata kinds are not present and consistent in all supported +// LLVM versions, it's fine to omit them from this list; in that case Rust-side +// code cannot declare them as fixed IDs and must look them up by name instead. +#undef FIXED_MD_KIND From cc6329a9bcd78c4531e9713775e2936fe223e601 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Tue, 30 Sep 2025 20:05:23 +1000 Subject: [PATCH 07/10] Replace `MetadataType` with the `MetadataKindId` constants --- compiler/rustc_codegen_llvm/src/context.rs | 6 ++-- .../src/debuginfo/metadata.rs | 8 ++--- compiler/rustc_codegen_llvm/src/llvm/ffi.rs | 33 ++++--------------- .../src/llvm/metadata_kind.rs | 8 +---- compiler/rustc_codegen_llvm/src/llvm/mod.rs | 3 +- compiler/rustc_codegen_llvm/src/type_.rs | 8 ++--- 6 files changed, 17 insertions(+), 49 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index aa5c17269fb84..b1da6f7c74061 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -34,7 +34,7 @@ use smallvec::SmallVec; use crate::back::write::to_llvm_code_model; use crate::callee::get_fn; use crate::debuginfo::metadata::apply_vcall_visibility_metadata; -use crate::llvm::Metadata; +use crate::llvm::{Metadata, MetadataKindId}; use crate::type_::Type; use crate::value::Value; use crate::{attributes, common, coverageinfo, debuginfo, llvm, llvm_util}; @@ -1006,11 +1006,11 @@ impl<'ll, CX: Borrow>> GenericCx<'ll, CX> { pub(crate) fn set_metadata<'a>( &self, val: &'a Value, - kind_id: impl Into, + kind_id: MetadataKindId, md: &'ll Metadata, ) { let node = self.get_metadata_value(md); - llvm::LLVMSetMetadata(val, kind_id.into(), node); + llvm::LLVMSetMetadata(val, kind_id, node); } } diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs index 1e4ace4ca922c..bc20c75941349 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -1611,16 +1611,12 @@ pub(crate) fn apply_vcall_visibility_metadata<'ll, 'tcx>( let v = [llvm::LLVMValueAsMetadata(cx.const_usize(0)), typeid]; llvm::LLVMRustGlobalAddMetadata( vtable, - llvm::MD_type as c_uint, + llvm::MD_type, llvm::LLVMMDNodeInContext2(cx.llcx, v.as_ptr(), v.len()), ); let vcall_visibility = llvm::LLVMValueAsMetadata(cx.const_u64(vcall_visibility as u64)); let vcall_visibility_metadata = llvm::LLVMMDNodeInContext2(cx.llcx, &vcall_visibility, 1); - llvm::LLVMGlobalSetMetadata( - vtable, - llvm::MetadataType::MD_vcall_visibility as c_uint, - vcall_visibility_metadata, - ); + llvm::LLVMGlobalSetMetadata(vtable, llvm::MD_vcall_visibility, vcall_visibility_metadata); } } diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 83867cc2dce66..f17de168ca434 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -514,31 +514,6 @@ pub(crate) enum FileType { ObjectFile, } -/// LLVMMetadataType -#[derive(Copy, Clone)] -#[repr(C)] -#[expect(dead_code, reason = "Some variants are unused, but are kept to match LLVM-C")] -pub(crate) enum MetadataType { - MD_dbg = 0, - MD_tbaa = 1, - MD_prof = 2, - MD_fpmath = 3, - MD_range = 4, - MD_tbaa_struct = 5, - MD_invariant_load = 6, - MD_alias_scope = 7, - MD_noalias = 8, - MD_nontemporal = 9, - MD_mem_parallel_loop_access = 10, - MD_nonnull = 11, - MD_unpredictable = 15, - MD_align = 17, - MD_type = 19, - MD_vcall_visibility = 28, - MD_noundef = 29, - MD_kcfi_type = 36, -} - /// Must match the layout of `LLVMInlineAsmDialect`. #[derive(Copy, Clone, PartialEq)] #[repr(C)] @@ -1130,7 +1105,11 @@ unsafe extern "C" { pub(crate) fn LLVMSetValueName2(Val: &Value, Name: *const c_char, NameLen: size_t); pub(crate) fn LLVMReplaceAllUsesWith<'a>(OldVal: &'a Value, NewVal: &'a Value); pub(crate) safe fn LLVMSetMetadata<'a>(Val: &'a Value, KindID: MetadataKindId, Node: &'a Value); - pub(crate) fn LLVMGlobalSetMetadata<'a>(Val: &'a Value, KindID: c_uint, Metadata: &'a Metadata); + pub(crate) fn LLVMGlobalSetMetadata<'a>( + Val: &'a Value, + KindID: MetadataKindId, + Metadata: &'a Metadata, + ); pub(crate) safe fn LLVMValueAsMetadata(Node: &Value) -> &Metadata; // Operations on constants of any type @@ -2050,7 +2029,7 @@ unsafe extern "C" { // Operations on all values pub(crate) fn LLVMRustGlobalAddMetadata<'a>( Val: &'a Value, - KindID: c_uint, + KindID: MetadataKindId, Metadata: &'a Metadata, ); pub(crate) fn LLVMRustIsNonGVFunctionPointerTy(Val: &Value) -> bool; diff --git a/compiler/rustc_codegen_llvm/src/llvm/metadata_kind.rs b/compiler/rustc_codegen_llvm/src/llvm/metadata_kind.rs index 4d00356c61627..a8a671b5c85f1 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/metadata_kind.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/metadata_kind.rs @@ -1,17 +1,11 @@ use libc::c_uint; -use crate::llvm::MetadataType; +pub(crate) use self::fixed_kinds::*; #[derive(Copy, Clone)] #[repr(transparent)] pub(crate) struct MetadataKindId(c_uint); -impl From for MetadataKindId { - fn from(value: MetadataType) -> Self { - Self(value as c_uint) - } -} - macro_rules! declare_fixed_metadata_kinds { ( $( diff --git a/compiler/rustc_codegen_llvm/src/llvm/mod.rs b/compiler/rustc_codegen_llvm/src/llvm/mod.rs index 2333fbe7a7656..9a53dacb1dfdd 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/mod.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/mod.rs @@ -11,9 +11,8 @@ use rustc_llvm::RustString; pub(crate) use self::CallConv::*; pub(crate) use self::CodeGenOptSize::*; -pub(crate) use self::MetadataType::*; pub(crate) use self::ffi::*; -pub(crate) use self::metadata_kind::MetadataKindId; +pub(crate) use self::metadata_kind::*; use crate::common::AsCCharPtr; pub(crate) mod diagnostic; diff --git a/compiler/rustc_codegen_llvm/src/type_.rs b/compiler/rustc_codegen_llvm/src/type_.rs index 9ecaf5f24fe15..5b97898a4b888 100644 --- a/compiler/rustc_codegen_llvm/src/type_.rs +++ b/compiler/rustc_codegen_llvm/src/type_.rs @@ -306,7 +306,7 @@ impl<'ll, 'tcx> TypeMembershipCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> { let v = [llvm::LLVMValueAsMetadata(self.const_usize(0)), typeid_metadata]; llvm::LLVMRustGlobalAddMetadata( function, - llvm::MD_type as c_uint, + llvm::MD_type, llvm::LLVMMDNodeInContext2(self.llcx, v.as_ptr(), v.len()), ) } @@ -318,7 +318,7 @@ impl<'ll, 'tcx> TypeMembershipCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> { let v = [llvm::LLVMValueAsMetadata(self.const_usize(0)), typeid_metadata]; llvm::LLVMGlobalSetMetadata( function, - llvm::MD_type as c_uint, + llvm::MD_type, llvm::LLVMMDNodeInContext2(self.llcx, v.as_ptr(), v.len()), ) } @@ -333,7 +333,7 @@ impl<'ll, 'tcx> TypeMembershipCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> { unsafe { llvm::LLVMRustGlobalAddMetadata( function, - llvm::MD_kcfi_type as c_uint, + llvm::MD_kcfi_type, llvm::LLVMMDNodeInContext2( self.llcx, &llvm::LLVMValueAsMetadata(kcfi_type_metadata), @@ -348,7 +348,7 @@ impl<'ll, 'tcx> TypeMembershipCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> { unsafe { llvm::LLVMGlobalSetMetadata( function, - llvm::MD_kcfi_type as c_uint, + llvm::MD_kcfi_type, llvm::LLVMMDNodeInContext2( self.llcx, &llvm::LLVMValueAsMetadata(kcfi_type_metadata), From 198777a08e74e2b7a59ed9b7a8b2561eaddc160e Mon Sep 17 00:00:00 2001 From: lcnr Date: Tue, 30 Sep 2025 15:03:40 +0200 Subject: [PATCH 08/10] remove unnecessary test directives --- .../trait-upcasting/illegal-upcast-to-impl-opaque.rs | 7 ------- 1 file changed, 7 deletions(-) diff --git a/tests/ui/traits/trait-upcasting/illegal-upcast-to-impl-opaque.rs b/tests/ui/traits/trait-upcasting/illegal-upcast-to-impl-opaque.rs index 2760c1696b56d..f603ff1ec80ec 100644 --- a/tests/ui/traits/trait-upcasting/illegal-upcast-to-impl-opaque.rs +++ b/tests/ui/traits/trait-upcasting/illegal-upcast-to-impl-opaque.rs @@ -1,12 +1,5 @@ //@ revisions: current next //@[next] compile-flags: -Znext-solver -//@[next] failure-status: 101 -//@[next] known-bug: unknown -//@[next] normalize-stderr: "note: .*\n\n" -> "" -//@[next] normalize-stderr: "thread 'rustc' panicked.*\n.*\n" -> "" -//@[next] normalize-stderr: "(error: internal compiler error: [^:]+):\d+:\d+: " -> "$1:LL:CC: " -//@[next] normalize-stderr: "delayed at .*" -> "" -//@[next] rustc-env:RUST_BACKTRACE=0 //@ check-pass trait Super { From 9e79fac0354b2a87515c30e94754413ef99b3675 Mon Sep 17 00:00:00 2001 From: Taiki Endo Date: Tue, 30 Sep 2025 22:39:10 +0900 Subject: [PATCH 09/10] Add repr(align(2)) to RcInner and ArcInner --- library/alloc/src/rc.rs | 4 +++- library/alloc/src/sync.rs | 16 +++++++++------- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index fcb466778a3fb..e8527b18f0706 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -277,7 +277,9 @@ use crate::vec::Vec; // This is repr(C) to future-proof against possible field-reordering, which // would interfere with otherwise safe [into|from]_raw() of transmutable // inner types. -#[repr(C)] +// repr(align(2)) (forcing alignment to at least 2) is required because usize +// has 1-byte alignment on AVR. +#[repr(C, align(2))] struct RcInner { strong: Cell, weak: Cell, diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index 32396cccb8fca..6bab3b7056f67 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -341,7 +341,7 @@ pub struct Weak< // but it is not necessarily a valid pointer. // `Weak::new` sets this to `usize::MAX` so that it doesn’t need // to allocate space on the heap. That's not a value a real pointer - // will ever have because RcInner has alignment at least 2. + // will ever have because ArcInner has alignment at least 2. ptr: NonNull>, alloc: A, } @@ -366,7 +366,9 @@ impl fmt::Debug for Weak { // This is repr(C) to future-proof against possible field-reordering, which // would interfere with otherwise safe [into|from]_raw() of transmutable // inner types. -#[repr(C)] +// Unlike RcInner, repr(align(2)) is not strictly required because atomic types +// have the alignment same as its size, but we use it for consistency and clarity. +#[repr(C, align(2))] struct ArcInner { strong: Atomic, @@ -1622,9 +1624,9 @@ impl Arc { pub fn as_ptr(this: &Self) -> *const T { let ptr: *mut ArcInner = NonNull::as_ptr(this.ptr); - // SAFETY: This cannot go through Deref::deref or RcInnerPtr::inner because + // SAFETY: This cannot go through Deref::deref or ArcInnerPtr::inner because // this is required to retain raw/mut provenance such that e.g. `get_mut` can - // write through the pointer after the Rc is recovered through `from_raw`. + // write through the pointer after the Arc is recovered through `from_raw`. unsafe { &raw mut (*ptr).data } } @@ -2459,7 +2461,7 @@ impl Arc { /// If any other `Arc` or [`Weak`] pointers to the same allocation exist, then /// they must not be dereferenced or have active borrows for the duration /// of the returned borrow, and their inner type must be exactly the same as the - /// inner type of this Rc (including lifetimes). This is trivially the case if no + /// inner type of this Arc (including lifetimes). This is trivially the case if no /// such pointers exist, for example immediately after `Arc::new`. /// /// # Examples @@ -3031,7 +3033,7 @@ impl Weak { // Otherwise, we're guaranteed the pointer came from a nondangling Weak. // SAFETY: data_offset is safe to call, as ptr references a real (potentially dropped) T. let offset = unsafe { data_offset(ptr) }; - // Thus, we reverse the offset to get the whole RcInner. + // Thus, we reverse the offset to get the whole ArcInner. // SAFETY: the pointer originated from a Weak, so this offset is safe. unsafe { ptr.byte_sub(offset) as *mut ArcInner } }; @@ -4024,7 +4026,7 @@ impl Unpin for Arc {} /// valid instance of T, but the T is allowed to be dropped. unsafe fn data_offset(ptr: *const T) -> usize { // Align the unsized value to the end of the ArcInner. - // Because RcInner is repr(C), it will always be the last field in memory. + // Because ArcInner is repr(C), it will always be the last field in memory. // SAFETY: since the only unsized types possible are slices, trait objects, // and extern types, the input safety requirement is currently enough to // satisfy the requirements of align_of_val_raw; this is an implementation From ba13b6ec6f919430412d99a3d50ff87042a787a7 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Mon, 29 Sep 2025 21:02:52 -0700 Subject: [PATCH 10/10] bootstrap: build bootstrap docs with in-tree rustdoc All of the docs need to be built with the same rustdoc. Otherwise, any change to the search index breaks everything, because the two rustdocs don't agree on the format. --- src/bootstrap/src/core/build_steps/doc.rs | 21 +++++++++++---------- src/bootstrap/src/core/builder/tests.rs | 18 ++++++++++-------- 2 files changed, 21 insertions(+), 18 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/doc.rs b/src/bootstrap/src/core/build_steps/doc.rs index 7865b68565930..37462c63f1b09 100644 --- a/src/bootstrap/src/core/build_steps/doc.rs +++ b/src/bootstrap/src/core/build_steps/doc.rs @@ -1024,12 +1024,9 @@ macro_rules! tool_doc { run.builder.ensure(Rustc::from_build_compiler(run.builder, compilers.build_compiler(), target)); compilers.build_compiler() } - Mode::ToolBootstrap => { - // bootstrap/host tools should be documented with the stage 0 compiler - prepare_doc_compiler(run.builder, run.builder.host_target, 1) - } Mode::ToolTarget => { - // target tools should be documented with the in-tree compiler + // when shipping multiple docs together in one folder, + // they all need to use the same rustdoc version prepare_doc_compiler(run.builder, run.builder.host_target, run.builder.top_stage) } _ => { @@ -1132,7 +1129,11 @@ macro_rules! tool_doc { tool_doc!( BuildHelper, "src/build_helper", - mode = Mode::ToolBootstrap, + // ideally, this would use ToolBootstrap, + // but we distribute these docs together in the same folder + // as a bunch of stage1 tools, and you can't mix rustdoc versions + // because that breaks cross-crate data (particularly search) + mode = Mode::ToolTarget, is_library = true, crates = ["build_helper"] ); @@ -1175,25 +1176,25 @@ tool_doc!( // "specialization" feature in its build script when it detects a nightly toolchain. allow_features: "specialization" ); -tool_doc!(Tidy, "src/tools/tidy", mode = Mode::ToolBootstrap, crates = ["tidy"]); +tool_doc!(Tidy, "src/tools/tidy", mode = Mode::ToolTarget, crates = ["tidy"]); tool_doc!( Bootstrap, "src/bootstrap", - mode = Mode::ToolBootstrap, + mode = Mode::ToolTarget, is_library = true, crates = ["bootstrap"] ); tool_doc!( RunMakeSupport, "src/tools/run-make-support", - mode = Mode::ToolBootstrap, + mode = Mode::ToolTarget, is_library = true, crates = ["run_make_support"] ); tool_doc!( Compiletest, "src/tools/compiletest", - mode = Mode::ToolBootstrap, + mode = Mode::ToolTarget, is_library = true, crates = ["compiletest"] ); diff --git a/src/bootstrap/src/core/builder/tests.rs b/src/bootstrap/src/core/builder/tests.rs index 88df469e9a099..3306435758b45 100644 --- a/src/bootstrap/src/core/builder/tests.rs +++ b/src/bootstrap/src/core/builder/tests.rs @@ -1158,13 +1158,12 @@ mod snapshot { [doc] embedded-book (book) [doc] edition-guide (book) [doc] style-guide (book) - [build] rustdoc 0 - [doc] rustc 0 -> Tidy 1 - [doc] rustc 0 -> Bootstrap 1 + [doc] rustc 1 -> Tidy 2 + [doc] rustc 1 -> Bootstrap 2 [doc] rustc 1 -> releases 2 - [doc] rustc 0 -> RunMakeSupport 1 - [doc] rustc 0 -> BuildHelper 1 - [doc] rustc 0 -> Compiletest 1 + [doc] rustc 1 -> RunMakeSupport 2 + [doc] rustc 1 -> BuildHelper 2 + [doc] rustc 1 -> Compiletest 2 [build] rustc 0 -> RustInstaller 1 " ); @@ -2686,8 +2685,11 @@ mod snapshot { .path("src/tools/compiletest") .stage(2) .render_steps(), @r" - [build] rustdoc 0 - [doc] rustc 0 -> Compiletest 1 + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustc 1 -> std 1 + [build] rustdoc 1 + [doc] rustc 1 -> Compiletest 2 "); }