Auto merge of #131012 - GuillaumeGomez:rollup-e9ovh3a, r=GuillaumeGomez

Rollup of 5 pull requests

Successful merges:

 - #130383 (check if it's rust-lang/rust CI job in `llvm::is_ci_llvm_modified`)
 - #130416 (resolve #130122: reword 'sort-by' edge-conditions documentation)
 - #130537 (rustdoc: add doc comment to DocVisitor)
 - #130743 (Clarifications for set_nonblocking methods)
 - #131010 (extend comment in global_llvm_features regarding target-cpu=native)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2024-09-29 10:44:16 +00:00
commit 2da3cb9cab
9 changed files with 104 additions and 37 deletions

View File

@ -536,6 +536,11 @@ pub(crate) fn global_llvm_features(
// -Ctarget-cpu=native // -Ctarget-cpu=native
match sess.opts.cg.target_cpu { match sess.opts.cg.target_cpu {
Some(ref s) if s == "native" => { Some(ref s) if s == "native" => {
// We have already figured out the actual CPU name with `LLVMRustGetHostCPUName` and set
// that for LLVM, so the features implied by that CPU name will be available everywhere.
// However, that is not sufficient: e.g. `skylake` alone is not sufficient to tell if
// some of the instructions are available or not. So we have to also explicitly ask for
// the exact set of features available on the host, and enable all of them.
let features_string = unsafe { let features_string = unsafe {
let ptr = llvm::LLVMGetHostCPUFeatures(); let ptr = llvm::LLVMGetHostCPUFeatures();
let features_string = if !ptr.is_null() { let features_string = if !ptr.is_null() {

View File

@ -180,10 +180,9 @@ impl<T> [T] {
/// This sort is stable (i.e., does not reorder equal elements) and *O*(*n* \* log(*n*)) /// This sort is stable (i.e., does not reorder equal elements) and *O*(*n* \* log(*n*))
/// worst-case. /// worst-case.
/// ///
/// If the implementation of [`Ord`] for `T` does not implement a [total order] the resulting /// If the implementation of [`Ord`] for `T` does not implement a [total order], the function
/// order of elements in the slice is unspecified. All original elements will remain in the /// may panic; even if the function exits normally, the resulting order of elements in the slice
/// slice and any possible modifications via interior mutability are observed in the input. Same /// is unspecified. See also the note on panicking below.
/// is true if the implementation of [`Ord`] for `T` panics.
/// ///
/// When applicable, unstable sorting is preferred because it is generally faster than stable /// When applicable, unstable sorting is preferred because it is generally faster than stable
/// sorting and it doesn't allocate auxiliary memory. See /// sorting and it doesn't allocate auxiliary memory. See
@ -212,7 +211,15 @@ impl<T> [T] {
/// ///
/// # Panics /// # Panics
/// ///
/// May panic if the implementation of [`Ord`] for `T` does not implement a [total order]. /// May panic if the implementation of [`Ord`] for `T` does not implement a [total order], or if
/// the [`Ord`] implementation itself panics.
///
/// All safe functions on slices preserve the invariant that even if the function panics, all
/// original elements will remain in the slice and any possible modifications via interior
/// mutability are observed in the input. This ensures that recovery code (for instance inside
/// of a `Drop` or following a `catch_unwind`) will still have access to all the original
/// elements. For instance, if the slice belongs to a `Vec`, the `Vec::drop` method will be able
/// to dispose of all contained elements.
/// ///
/// # Examples /// # Examples
/// ///
@ -241,10 +248,9 @@ pub fn sort(&mut self)
/// This sort is stable (i.e., does not reorder equal elements) and *O*(*n* \* log(*n*)) /// This sort is stable (i.e., does not reorder equal elements) and *O*(*n* \* log(*n*))
/// worst-case. /// worst-case.
/// ///
/// If the comparison function `compare` does not implement a [total order] the resulting order /// If the comparison function `compare` does not implement a [total order], the function may
/// of elements in the slice is unspecified. All original elements will remain in the slice and /// panic; even if the function exits normally, the resulting order of elements in the slice is
/// any possible modifications via interior mutability are observed in the input. Same is true /// unspecified. See also the note on panicking below.
/// if `compare` panics.
/// ///
/// For example `|a, b| (a - b).cmp(a)` is a comparison function that is neither transitive nor /// For example `|a, b| (a - b).cmp(a)` is a comparison function that is neither transitive nor
/// reflexive nor total, `a < b < c < a` with `a = 1, b = 2, c = 3`. For more information and /// reflexive nor total, `a < b < c < a` with `a = 1, b = 2, c = 3`. For more information and
@ -263,7 +269,14 @@ pub fn sort(&mut self)
/// ///
/// # Panics /// # Panics
/// ///
/// May panic if `compare` does not implement a [total order]. /// May panic if `compare` does not implement a [total order], or if `compare` itself panics.
///
/// All safe functions on slices preserve the invariant that even if the function panics, all
/// original elements will remain in the slice and any possible modifications via interior
/// mutability are observed in the input. This ensures that recovery code (for instance inside
/// of a `Drop` or following a `catch_unwind`) will still have access to all the original
/// elements. For instance, if the slice belongs to a `Vec`, the `Vec::drop` method will be able
/// to dispose of all contained elements.
/// ///
/// # Examples /// # Examples
/// ///
@ -295,10 +308,9 @@ pub fn sort_by<F>(&mut self, mut compare: F)
/// This sort is stable (i.e., does not reorder equal elements) and *O*(*m* \* *n* \* log(*n*)) /// This sort is stable (i.e., does not reorder equal elements) and *O*(*m* \* *n* \* log(*n*))
/// worst-case, where the key function is *O*(*m*). /// worst-case, where the key function is *O*(*m*).
/// ///
/// If the implementation of [`Ord`] for `K` does not implement a [total order] the resulting /// If the implementation of [`Ord`] for `K` does not implement a [total order], the function
/// order of elements in the slice is unspecified. All original elements will remain in the /// may panic; even if the function exits normally, the resulting order of elements in the slice
/// slice and any possible modifications via interior mutability are observed in the input. Same /// is unspecified. See also the note on panicking below.
/// is true if the implementation of [`Ord`] for `K` panics.
/// ///
/// # Current implementation /// # Current implementation
/// ///
@ -313,7 +325,15 @@ pub fn sort_by<F>(&mut self, mut compare: F)
/// ///
/// # Panics /// # Panics
/// ///
/// May panic if the implementation of [`Ord`] for `K` does not implement a [total order]. /// May panic if the implementation of [`Ord`] for `K` does not implement a [total order], or if
/// the [`Ord`] implementation or the key-function `f` panics.
///
/// All safe functions on slices preserve the invariant that even if the function panics, all
/// original elements will remain in the slice and any possible modifications via interior
/// mutability are observed in the input. This ensures that recovery code (for instance inside
/// of a `Drop` or following a `catch_unwind`) will still have access to all the original
/// elements. For instance, if the slice belongs to a `Vec`, the `Vec::drop` method will be able
/// to dispose of all contained elements.
/// ///
/// # Examples /// # Examples
/// ///
@ -347,10 +367,9 @@ pub fn sort_by_key<K, F>(&mut self, mut f: F)
/// storage to remember the results of key evaluation. The order of calls to the key function is /// storage to remember the results of key evaluation. The order of calls to the key function is
/// unspecified and may change in future versions of the standard library. /// unspecified and may change in future versions of the standard library.
/// ///
/// If the implementation of [`Ord`] for `K` does not implement a [total order] the resulting /// If the implementation of [`Ord`] for `K` does not implement a [total order], the function
/// order of elements in the slice is unspecified. All original elements will remain in the /// may panic; even if the function exits normally, the resulting order of elements in the slice
/// slice and any possible modifications via interior mutability are observed in the input. Same /// is unspecified. See also the note on panicking below.
/// is true if the implementation of [`Ord`] for `K` panics.
/// ///
/// For simple key functions (e.g., functions that are property accesses or basic operations), /// For simple key functions (e.g., functions that are property accesses or basic operations),
/// [`sort_by_key`](slice::sort_by_key) is likely to be faster. /// [`sort_by_key`](slice::sort_by_key) is likely to be faster.
@ -369,7 +388,15 @@ pub fn sort_by_key<K, F>(&mut self, mut f: F)
/// ///
/// # Panics /// # Panics
/// ///
/// May panic if the implementation of [`Ord`] for `K` does not implement a [total order]. /// May panic if the implementation of [`Ord`] for `K` does not implement a [total order], or if
/// the [`Ord`] implementation panics.
///
/// All safe functions on slices preserve the invariant that even if the function panics, all
/// original elements will remain in the slice and any possible modifications via interior
/// mutability are observed in the input. This ensures that recovery code (for instance inside
/// of a `Drop` or following a `catch_unwind`) will still have access to all the original
/// elements. For instance, if the slice belongs to a `Vec`, the `Vec::drop` method will be able
/// to dispose of all contained elements.
/// ///
/// # Examples /// # Examples
/// ///

View File

@ -561,7 +561,7 @@ pub fn take_error(&self) -> io::Result<Option<io::Error>> {
/// Moves this TCP stream into or out of nonblocking mode. /// Moves this TCP stream into or out of nonblocking mode.
/// ///
/// This will result in `read`, `write`, `recv` and `send` operations /// This will result in `read`, `write`, `recv` and `send` system operations
/// becoming nonblocking, i.e., immediately returning from their calls. /// becoming nonblocking, i.e., immediately returning from their calls.
/// If the IO operation is successful, `Ok` is returned and no further /// If the IO operation is successful, `Ok` is returned and no further
/// action is required. If the IO operation could not be completed and needs /// action is required. If the IO operation could not be completed and needs

View File

@ -764,7 +764,7 @@ pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> {
/// Moves this UDP socket into or out of nonblocking mode. /// Moves this UDP socket into or out of nonblocking mode.
/// ///
/// This will result in `recv`, `recv_from`, `send`, and `send_to` /// This will result in `recv`, `recv_from`, `send`, and `send_to` system
/// operations becoming nonblocking, i.e., immediately returning from their /// operations becoming nonblocking, i.e., immediately returning from their
/// calls. If the IO operation is successful, `Ok` is returned and no /// calls. If the IO operation is successful, `Ok` is returned and no
/// further action is required. If the IO operation could not be completed /// further action is required. If the IO operation could not be completed

View File

@ -242,7 +242,7 @@ pub(crate) fn is_ci_llvm_available(config: &Config, asserts: bool) -> bool {
/// Returns true if we're running in CI with modified LLVM (and thus can't download it) /// Returns true if we're running in CI with modified LLVM (and thus can't download it)
pub(crate) fn is_ci_llvm_modified(config: &Config) -> bool { pub(crate) fn is_ci_llvm_modified(config: &Config) -> bool {
CiEnv::is_ci() && config.rust_info.is_managed_git_subrepository() && { CiEnv::is_rust_lang_managed_ci_job() && config.rust_info.is_managed_git_subrepository() && {
// We assume we have access to git, so it's okay to unconditionally pass // We assume we have access to git, so it's okay to unconditionally pass
// `true` here. // `true` here.
let llvm_sha = detect_llvm_sha(config, true); let llvm_sha = detect_llvm_sha(config, true);

View File

@ -343,6 +343,15 @@ pub struct Config {
pub out: PathBuf, pub out: PathBuf,
pub rust_info: channel::GitInfo, pub rust_info: channel::GitInfo,
pub cargo_info: channel::GitInfo,
pub rust_analyzer_info: channel::GitInfo,
pub clippy_info: channel::GitInfo,
pub miri_info: channel::GitInfo,
pub rustfmt_info: channel::GitInfo,
pub enzyme_info: channel::GitInfo,
pub in_tree_llvm_info: channel::GitInfo,
pub in_tree_gcc_info: channel::GitInfo,
// These are either the stage0 downloaded binaries or the locally installed ones. // These are either the stage0 downloaded binaries or the locally installed ones.
pub initial_cargo: PathBuf, pub initial_cargo: PathBuf,
pub initial_rustc: PathBuf, pub initial_rustc: PathBuf,
@ -1796,6 +1805,19 @@ fn get_table(option: &str) -> Result<TomlConfig, toml::de::Error> {
config.omit_git_hash = omit_git_hash.unwrap_or(default); config.omit_git_hash = omit_git_hash.unwrap_or(default);
config.rust_info = GitInfo::new(config.omit_git_hash, &config.src); config.rust_info = GitInfo::new(config.omit_git_hash, &config.src);
config.cargo_info = GitInfo::new(config.omit_git_hash, &config.src.join("src/tools/cargo"));
config.rust_analyzer_info =
GitInfo::new(config.omit_git_hash, &config.src.join("src/tools/rust-analyzer"));
config.clippy_info =
GitInfo::new(config.omit_git_hash, &config.src.join("src/tools/clippy"));
config.miri_info = GitInfo::new(config.omit_git_hash, &config.src.join("src/tools/miri"));
config.rustfmt_info =
GitInfo::new(config.omit_git_hash, &config.src.join("src/tools/rustfmt"));
config.enzyme_info =
GitInfo::new(config.omit_git_hash, &config.src.join("src/tools/enzyme"));
config.in_tree_llvm_info = GitInfo::new(false, &config.src.join("src/llvm-project"));
config.in_tree_gcc_info = GitInfo::new(false, &config.src.join("src/gcc"));
// We need to override `rust.channel` if it's manually specified when using the CI rustc. // We need to override `rust.channel` if it's manually specified when using the CI rustc.
// This is because if the compiler uses a different channel than the one specified in config.toml, // This is because if the compiler uses a different channel than the one specified in config.toml,
// tests may fail due to using a different channel than the one used by the compiler during tests. // tests may fail due to using a different channel than the one used by the compiler during tests.

View File

@ -305,18 +305,15 @@ pub fn new(mut config: Config) -> Build {
#[cfg(not(unix))] #[cfg(not(unix))]
let is_sudo = false; let is_sudo = false;
let omit_git_hash = config.omit_git_hash; let rust_info = config.rust_info.clone();
let rust_info = GitInfo::new(omit_git_hash, &src); let cargo_info = config.cargo_info.clone();
let cargo_info = GitInfo::new(omit_git_hash, &src.join("src/tools/cargo")); let rust_analyzer_info = config.rust_analyzer_info.clone();
let rust_analyzer_info = GitInfo::new(omit_git_hash, &src.join("src/tools/rust-analyzer")); let clippy_info = config.clippy_info.clone();
let clippy_info = GitInfo::new(omit_git_hash, &src.join("src/tools/clippy")); let miri_info = config.miri_info.clone();
let miri_info = GitInfo::new(omit_git_hash, &src.join("src/tools/miri")); let rustfmt_info = config.rustfmt_info.clone();
let rustfmt_info = GitInfo::new(omit_git_hash, &src.join("src/tools/rustfmt")); let enzyme_info = config.enzyme_info.clone();
let enzyme_info = GitInfo::new(omit_git_hash, &src.join("src/tools/enzyme")); let in_tree_llvm_info = config.in_tree_llvm_info.clone();
let in_tree_gcc_info = config.in_tree_gcc_info.clone();
// we always try to use git for LLVM builds
let in_tree_llvm_info = GitInfo::new(false, &src.join("src/llvm-project"));
let in_tree_gcc_info = GitInfo::new(false, &src.join("src/gcc"));
let initial_target_libdir_str = if config.dry_run() { let initial_target_libdir_str = if config.dry_run() {
"/dummy/lib/path/to/lib/".to_string() "/dummy/lib/path/to/lib/".to_string()

View File

@ -1,11 +1,17 @@
use crate::clean::*; use crate::clean::*;
/// Allows a type to traverse the cleaned ast of a crate.
///
/// Note that like [`rustc_ast::visit::Visitor`], but
/// unlike [`rustc_lint::EarlyLintPass`], if you override a
/// `visit_*` method, you will need to manually recurse into
/// its contents.
pub(crate) trait DocVisitor<'a>: Sized { pub(crate) trait DocVisitor<'a>: Sized {
fn visit_item(&mut self, item: &'a Item) { fn visit_item(&mut self, item: &'a Item) {
self.visit_item_recur(item) self.visit_item_recur(item)
} }
/// don't override! /// Don't override!
fn visit_inner_recur(&mut self, kind: &'a ItemKind) { fn visit_inner_recur(&mut self, kind: &'a ItemKind) {
match kind { match kind {
StrippedItem(..) => unreachable!(), StrippedItem(..) => unreachable!(),
@ -46,7 +52,7 @@ fn visit_inner_recur(&mut self, kind: &'a ItemKind) {
} }
} }
/// don't override! /// Don't override!
fn visit_item_recur(&mut self, item: &'a Item) { fn visit_item_recur(&mut self, item: &'a Item) {
match &item.kind { match &item.kind {
StrippedItem(i) => self.visit_inner_recur(&*i), StrippedItem(i) => self.visit_inner_recur(&*i),
@ -58,6 +64,7 @@ fn visit_mod(&mut self, m: &'a Module) {
m.items.iter().for_each(|i| self.visit_item(i)) m.items.iter().for_each(|i| self.visit_item(i))
} }
/// This is the main entrypoint of [`DocVisitor`].
fn visit_crate(&mut self, c: &'a Crate) { fn visit_crate(&mut self, c: &'a Crate) {
self.visit_item(&c.module); self.visit_item(&c.module);

View File

@ -19,6 +19,15 @@ pub fn current() -> CiEnv {
pub fn is_ci() -> bool { pub fn is_ci() -> bool {
Self::current() != CiEnv::None Self::current() != CiEnv::None
} }
/// Checks if running in rust-lang/rust managed CI job.
pub fn is_rust_lang_managed_ci_job() -> bool {
Self::is_ci()
// If both are present, we can assume it's an upstream CI job
// as they are always set unconditionally.
&& std::env::var_os("CI_JOB_NAME").is_some()
&& std::env::var_os("TOOLSTATE_REPO").is_some()
}
} }
pub mod gha { pub mod gha {