summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_data_structures
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_data_structures')
-rw-r--r--compiler/rustc_data_structures/Cargo.toml4
-rw-r--r--compiler/rustc_data_structures/src/fingerprint/tests.rs1
-rw-r--r--compiler/rustc_data_structures/src/graph/dominators/mod.rs1
-rw-r--r--compiler/rustc_data_structures/src/graph/implementation/tests.rs1
-rw-r--r--compiler/rustc_data_structures/src/graph/scc/mod.rs2
-rw-r--r--compiler/rustc_data_structures/src/intern/tests.rs1
-rw-r--r--compiler/rustc_data_structures/src/jobserver.rs96
-rw-r--r--compiler/rustc_data_structures/src/lib.rs4
-rw-r--r--compiler/rustc_data_structures/src/obligation_forest/tests.rs1
-rw-r--r--compiler/rustc_data_structures/src/sharded.rs10
-rw-r--r--compiler/rustc_data_structures/src/sip128/tests.rs2
-rw-r--r--compiler/rustc_data_structures/src/sorted_map.rs2
-rw-r--r--compiler/rustc_data_structures/src/sync/lock.rs4
-rw-r--r--compiler/rustc_data_structures/src/sync/worker_local.rs11
-rw-r--r--compiler/rustc_data_structures/src/tagged_ptr/impl_tag.rs144
15 files changed, 233 insertions, 51 deletions
diff --git a/compiler/rustc_data_structures/Cargo.toml b/compiler/rustc_data_structures/Cargo.toml
index 8d91c4c43..4732783a1 100644
--- a/compiler/rustc_data_structures/Cargo.toml
+++ b/compiler/rustc_data_structures/Cargo.toml
@@ -10,8 +10,8 @@ bitflags = "1.2.1"
elsa = "=1.7.1"
ena = "0.14.2"
indexmap = { version = "2.0.0" }
-itertools = "0.10.1"
-jobserver_crate = { version = "0.1.13", package = "jobserver" }
+itertools = "0.11"
+jobserver_crate = { version = "0.1.27", package = "jobserver" }
libc = "0.2"
measureme = "10.0.0"
rustc-hash = "1.1.0"
diff --git a/compiler/rustc_data_structures/src/fingerprint/tests.rs b/compiler/rustc_data_structures/src/fingerprint/tests.rs
index 09ec2622a..e04af19ab 100644
--- a/compiler/rustc_data_structures/src/fingerprint/tests.rs
+++ b/compiler/rustc_data_structures/src/fingerprint/tests.rs
@@ -1,5 +1,4 @@
use super::*;
-use crate::stable_hasher::Hash64;
// Check that `combine_commutative` is order independent.
#[test]
diff --git a/compiler/rustc_data_structures/src/graph/dominators/mod.rs b/compiler/rustc_data_structures/src/graph/dominators/mod.rs
index 5dd414cfd..4b819e1cb 100644
--- a/compiler/rustc_data_structures/src/graph/dominators/mod.rs
+++ b/compiler/rustc_data_structures/src/graph/dominators/mod.rs
@@ -23,6 +23,7 @@ struct PreOrderFrame<Iter> {
}
rustc_index::newtype_index! {
+ #[orderable]
struct PreorderIndex {}
}
diff --git a/compiler/rustc_data_structures/src/graph/implementation/tests.rs b/compiler/rustc_data_structures/src/graph/implementation/tests.rs
index dc1ce1747..3ae5f5868 100644
--- a/compiler/rustc_data_structures/src/graph/implementation/tests.rs
+++ b/compiler/rustc_data_structures/src/graph/implementation/tests.rs
@@ -1,5 +1,4 @@
use crate::graph::implementation::*;
-use std::fmt::Debug;
type TestGraph = Graph<&'static str, &'static str>;
diff --git a/compiler/rustc_data_structures/src/graph/scc/mod.rs b/compiler/rustc_data_structures/src/graph/scc/mod.rs
index cf9312ea8..b54d75f7e 100644
--- a/compiler/rustc_data_structures/src/graph/scc/mod.rs
+++ b/compiler/rustc_data_structures/src/graph/scc/mod.rs
@@ -492,7 +492,7 @@ where
let returned_walk =
return_value.take().into_iter().map(|walk| (*successor_node, Some(walk)));
- let successor_walk = successors.by_ref().map(|successor_node| {
+ let successor_walk = successors.map(|successor_node| {
debug!(?node, ?successor_node);
(successor_node, self.inspect_node(successor_node))
});
diff --git a/compiler/rustc_data_structures/src/intern/tests.rs b/compiler/rustc_data_structures/src/intern/tests.rs
index 09810a085..a85cd480a 100644
--- a/compiler/rustc_data_structures/src/intern/tests.rs
+++ b/compiler/rustc_data_structures/src/intern/tests.rs
@@ -1,5 +1,4 @@
use super::*;
-use std::cmp::Ordering;
#[derive(Debug)]
struct S(u32);
diff --git a/compiler/rustc_data_structures/src/jobserver.rs b/compiler/rustc_data_structures/src/jobserver.rs
index 09baa3095..412e33aaa 100644
--- a/compiler/rustc_data_structures/src/jobserver.rs
+++ b/compiler/rustc_data_structures/src/jobserver.rs
@@ -1,40 +1,78 @@
pub use jobserver_crate::Client;
-use std::sync::LazyLock;
-
-// We can only call `from_env` once per process
-
-// Note that this is unsafe because it may misinterpret file descriptors
-// on Unix as jobserver file descriptors. We hopefully execute this near
-// the beginning of the process though to ensure we don't get false
-// positives, or in other words we try to execute this before we open
-// any file descriptors ourselves.
-//
-// Pick a "reasonable maximum" if we don't otherwise have
-// a jobserver in our environment, capping out at 32 so we
-// don't take everything down by hogging the process run queue.
-// The fixed number is used to have deterministic compilation
-// across machines.
-//
-// Also note that we stick this in a global because there could be
-// multiple rustc instances in this process, and the jobserver is
-// per-process.
-static GLOBAL_CLIENT: LazyLock<Client> = LazyLock::new(|| unsafe {
- Client::from_env().unwrap_or_else(|| {
- let client = Client::new(32).expect("failed to create jobserver");
- // Acquire a token for the main thread which we can release later
- client.acquire_raw().ok();
- client
- })
+
+use jobserver_crate::{FromEnv, FromEnvErrorKind};
+
+use std::sync::{LazyLock, OnceLock};
+
+// We can only call `from_env_ext` once per process
+
+// We stick this in a global because there could be multiple rustc instances
+// in this process, and the jobserver is per-process.
+static GLOBAL_CLIENT: LazyLock<Result<Client, String>> = LazyLock::new(|| {
+ // Note that this is unsafe because it may misinterpret file descriptors
+ // on Unix as jobserver file descriptors. We hopefully execute this near
+ // the beginning of the process though to ensure we don't get false
+ // positives, or in other words we try to execute this before we open
+ // any file descriptors ourselves.
+ let FromEnv { client, var } = unsafe { Client::from_env_ext(true) };
+
+ let error = match client {
+ Ok(client) => return Ok(client),
+ Err(e) => e,
+ };
+
+ if matches!(
+ error.kind(),
+ FromEnvErrorKind::NoEnvVar | FromEnvErrorKind::NoJobserver | FromEnvErrorKind::Unsupported
+ ) {
+ return Ok(default_client());
+ }
+
+ // Environment specifies jobserver, but it looks incorrect.
+ // Safety: `error.kind()` should be `NoEnvVar` if `var == None`.
+ let (name, value) = var.unwrap();
+ Err(format!(
+ "failed to connect to jobserver from environment variable `{name}={:?}`: {error}",
+ value
+ ))
});
+// Create a new jobserver if there's no inherited one.
+fn default_client() -> Client {
+ // Pick a "reasonable maximum" capping out at 32
+ // so we don't take everything down by hogging the process run queue.
+ // The fixed number is used to have deterministic compilation across machines.
+ let client = Client::new(32).expect("failed to create jobserver");
+
+ // Acquire a token for the main thread which we can release later
+ client.acquire_raw().ok();
+
+ client
+}
+
+static GLOBAL_CLIENT_CHECKED: OnceLock<Client> = OnceLock::new();
+
+pub fn initialize_checked(report_warning: impl FnOnce(&'static str)) {
+ let client_checked = match &*GLOBAL_CLIENT {
+ Ok(client) => client.clone(),
+ Err(e) => {
+ report_warning(e);
+ default_client()
+ }
+ };
+ GLOBAL_CLIENT_CHECKED.set(client_checked).ok();
+}
+
+const ACCESS_ERROR: &str = "jobserver check should have been called earlier";
+
pub fn client() -> Client {
- GLOBAL_CLIENT.clone()
+ GLOBAL_CLIENT_CHECKED.get().expect(ACCESS_ERROR).clone()
}
pub fn acquire_thread() {
- GLOBAL_CLIENT.acquire_raw().ok();
+ GLOBAL_CLIENT_CHECKED.get().expect(ACCESS_ERROR).acquire_raw().ok();
}
pub fn release_thread() {
- GLOBAL_CLIENT.release_raw().ok();
+ GLOBAL_CLIENT_CHECKED.get().expect(ACCESS_ERROR).release_raw().ok();
}
diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs
index d09c026c4..3ef87684f 100644
--- a/compiler/rustc_data_structures/src/lib.rs
+++ b/compiler/rustc_data_structures/src/lib.rs
@@ -10,12 +10,11 @@
#![allow(internal_features)]
#![allow(rustc::default_hash_types)]
#![allow(rustc::potential_query_instability)]
-#![cfg_attr(not(bootstrap), doc(rust_logo))]
-#![cfg_attr(not(bootstrap), feature(rustdoc_internals))]
#![deny(rustc::diagnostic_outside_of_impl)]
#![deny(rustc::untranslatable_diagnostic)]
#![deny(unsafe_op_in_unsafe_fn)]
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
+#![doc(rust_logo)]
#![feature(allocator_api)]
#![feature(array_windows)]
#![feature(auto_traits)]
@@ -34,6 +33,7 @@
#![feature(never_type)]
#![feature(ptr_alignment_type)]
#![feature(rustc_attrs)]
+#![feature(rustdoc_internals)]
#![feature(strict_provenance)]
#![feature(test)]
#![feature(thread_id_value)]
diff --git a/compiler/rustc_data_structures/src/obligation_forest/tests.rs b/compiler/rustc_data_structures/src/obligation_forest/tests.rs
index bc252f772..d09c8e544 100644
--- a/compiler/rustc_data_structures/src/obligation_forest/tests.rs
+++ b/compiler/rustc_data_structures/src/obligation_forest/tests.rs
@@ -1,7 +1,6 @@
use super::*;
use std::fmt;
-use std::marker::PhantomData;
impl<'a> super::ForestObligation for &'a str {
type CacheKey = &'a str;
diff --git a/compiler/rustc_data_structures/src/sharded.rs b/compiler/rustc_data_structures/src/sharded.rs
index 29516fffd..162dbd234 100644
--- a/compiler/rustc_data_structures/src/sharded.rs
+++ b/compiler/rustc_data_structures/src/sharded.rs
@@ -50,7 +50,7 @@ impl<T> Sharded<T> {
#[inline]
pub fn get_shard_by_value<K: Hash + ?Sized>(&self, _val: &K) -> &Lock<T> {
match self {
- Self::Single(single) => &single,
+ Self::Single(single) => single,
#[cfg(parallel_compiler)]
Self::Shards(..) => self.get_shard_by_hash(make_hash(_val)),
}
@@ -64,7 +64,7 @@ impl<T> Sharded<T> {
#[inline]
pub fn get_shard_by_index(&self, _i: usize) -> &Lock<T> {
match self {
- Self::Single(single) => &single,
+ Self::Single(single) => single,
#[cfg(parallel_compiler)]
Self::Shards(shards) => {
// SAFETY: The index gets ANDed with the shard mask, ensuring it is always inbounds.
@@ -79,7 +79,7 @@ impl<T> Sharded<T> {
pub fn lock_shard_by_value<K: Hash + ?Sized>(&self, _val: &K) -> LockGuard<'_, T> {
match self {
Self::Single(single) => {
- // Syncronization is disabled so use the `lock_assume_no_sync` method optimized
+ // Synchronization is disabled so use the `lock_assume_no_sync` method optimized
// for that case.
// SAFETY: We know `is_dyn_thread_safe` was false when creating the lock thus
@@ -102,7 +102,7 @@ impl<T> Sharded<T> {
pub fn lock_shard_by_index(&self, _i: usize) -> LockGuard<'_, T> {
match self {
Self::Single(single) => {
- // Syncronization is disabled so use the `lock_assume_no_sync` method optimized
+ // Synchronization is disabled so use the `lock_assume_no_sync` method optimized
// for that case.
// SAFETY: We know `is_dyn_thread_safe` was false when creating the lock thus
@@ -111,7 +111,7 @@ impl<T> Sharded<T> {
}
#[cfg(parallel_compiler)]
Self::Shards(shards) => {
- // Syncronization is enabled so use the `lock_assume_sync` method optimized
+ // Synchronization is enabled so use the `lock_assume_sync` method optimized
// for that case.
// SAFETY (get_unchecked): The index gets ANDed with the shard mask, ensuring it is
diff --git a/compiler/rustc_data_structures/src/sip128/tests.rs b/compiler/rustc_data_structures/src/sip128/tests.rs
index cc6d3b0f4..e9dd0f117 100644
--- a/compiler/rustc_data_structures/src/sip128/tests.rs
+++ b/compiler/rustc_data_structures/src/sip128/tests.rs
@@ -1,6 +1,6 @@
use super::*;
-use std::hash::{Hash, Hasher};
+use std::hash::Hash;
// Hash just the bytes of the slice, without length prefix
struct Bytes<'a>(&'a [u8]);
diff --git a/compiler/rustc_data_structures/src/sorted_map.rs b/compiler/rustc_data_structures/src/sorted_map.rs
index 60b343afb..ed2e558bf 100644
--- a/compiler/rustc_data_structures/src/sorted_map.rs
+++ b/compiler/rustc_data_structures/src/sorted_map.rs
@@ -198,7 +198,7 @@ impl<K: Ord, V> SortedMap<K, V> {
if index == self.data.len() || elements.last().unwrap().0 < self.data[index].0 {
// We can copy the whole range without having to mix with
// existing elements.
- self.data.splice(index..index, elements.into_iter());
+ self.data.splice(index..index, elements);
return;
}
diff --git a/compiler/rustc_data_structures/src/sync/lock.rs b/compiler/rustc_data_structures/src/sync/lock.rs
index 339aebbf8..040a8aa6b 100644
--- a/compiler/rustc_data_structures/src/sync/lock.rs
+++ b/compiler/rustc_data_structures/src/sync/lock.rs
@@ -38,7 +38,7 @@ mod maybe_sync {
lock: &'a Lock<T>,
marker: PhantomData<&'a mut T>,
- /// The syncronization mode of the lock. This is explicitly passed to let LLVM relate it
+ /// The synchronization mode of the lock. This is explicitly passed to let LLVM relate it
/// to the original lock operation.
mode: Mode,
}
@@ -142,7 +142,7 @@ mod maybe_sync {
.then(|| LockGuard { lock: self, marker: PhantomData, mode })
}
- /// This acquires the lock assuming syncronization is in a specific mode.
+ /// This acquires the lock assuming synchronization is in a specific mode.
///
/// Safety
/// This method must only be called with `Mode::Sync` if `might_be_dyn_thread_safe` was
diff --git a/compiler/rustc_data_structures/src/sync/worker_local.rs b/compiler/rustc_data_structures/src/sync/worker_local.rs
index ffafdba13..b34d3dd90 100644
--- a/compiler/rustc_data_structures/src/sync/worker_local.rs
+++ b/compiler/rustc_data_structures/src/sync/worker_local.rs
@@ -1,6 +1,7 @@
use parking_lot::Mutex;
use std::cell::Cell;
use std::cell::OnceCell;
+use std::num::NonZeroUsize;
use std::ops::Deref;
use std::ptr;
use std::sync::Arc;
@@ -30,7 +31,7 @@ impl RegistryId {
}
struct RegistryData {
- thread_limit: usize,
+ thread_limit: NonZeroUsize,
threads: Mutex<usize>,
}
@@ -60,7 +61,7 @@ thread_local! {
impl Registry {
/// Creates a registry which can hold up to `thread_limit` threads.
- pub fn new(thread_limit: usize) -> Self {
+ pub fn new(thread_limit: NonZeroUsize) -> Self {
Registry(Arc::new(RegistryData { thread_limit, threads: Mutex::new(0) }))
}
@@ -73,7 +74,7 @@ impl Registry {
/// Panics if the thread limit is hit or if the thread already has an associated registry.
pub fn register(&self) {
let mut threads = self.0.threads.lock();
- if *threads < self.0.thread_limit {
+ if *threads < self.0.thread_limit.get() {
REGISTRY.with(|registry| {
if registry.get().is_some() {
drop(threads);
@@ -126,7 +127,9 @@ impl<T> WorkerLocal<T> {
{
let registry = Registry::current();
WorkerLocal {
- locals: (0..registry.0.thread_limit).map(|i| CacheAligned(initial(i))).collect(),
+ locals: (0..registry.0.thread_limit.get())
+ .map(|i| CacheAligned(initial(i)))
+ .collect(),
registry,
}
}
diff --git a/compiler/rustc_data_structures/src/tagged_ptr/impl_tag.rs b/compiler/rustc_data_structures/src/tagged_ptr/impl_tag.rs
index cb7f7d318..cafa91c8b 100644
--- a/compiler/rustc_data_structures/src/tagged_ptr/impl_tag.rs
+++ b/compiler/rustc_data_structures/src/tagged_ptr/impl_tag.rs
@@ -81,6 +81,7 @@
/// E::A,
/// }
/// ```
+#[cfg(bootstrap)]
#[macro_export]
macro_rules! impl_tag {
(
@@ -140,5 +141,148 @@ macro_rules! impl_tag {
};
}
+/// Implements [`Tag`] for a given type.
+///
+/// You can use `impl_tag` on structs and enums.
+/// You need to specify the type and all its possible values,
+/// which can only be paths with optional fields.
+///
+/// [`Tag`]: crate::tagged_ptr::Tag
+///
+/// # Examples
+///
+/// Basic usage:
+///
+/// ```
+/// #![feature(macro_metavar_expr)]
+/// use rustc_data_structures::{impl_tag, tagged_ptr::Tag};
+///
+/// #[derive(Copy, Clone, PartialEq, Debug)]
+/// enum SomeTag {
+/// A,
+/// B,
+/// X { v: bool },
+/// Y(bool, bool),
+/// }
+///
+/// impl_tag! {
+/// // The type for which the `Tag` will be implemented
+/// impl Tag for SomeTag;
+/// // You need to specify all possible tag values:
+/// SomeTag::A, // 0
+/// SomeTag::B, // 1
+/// // For variants with fields, you need to specify the fields:
+/// SomeTag::X { v: true }, // 2
+/// SomeTag::X { v: false }, // 3
+/// // For tuple variants use named syntax:
+/// SomeTag::Y { 0: true, 1: true }, // 4
+/// SomeTag::Y { 0: false, 1: true }, // 5
+/// SomeTag::Y { 0: true, 1: false }, // 6
+/// SomeTag::Y { 0: false, 1: false }, // 7
+/// }
+///
+/// // Tag values are assigned in order:
+/// assert_eq!(SomeTag::A.into_usize(), 0);
+/// assert_eq!(SomeTag::X { v: false }.into_usize(), 3);
+/// assert_eq!(SomeTag::Y(false, true).into_usize(), 5);
+///
+/// assert_eq!(unsafe { SomeTag::from_usize(1) }, SomeTag::B);
+/// assert_eq!(unsafe { SomeTag::from_usize(2) }, SomeTag::X { v: true });
+/// assert_eq!(unsafe { SomeTag::from_usize(7) }, SomeTag::Y(false, false));
+/// ```
+///
+/// Structs are supported:
+///
+/// ```
+/// #![feature(macro_metavar_expr)]
+/// # use rustc_data_structures::impl_tag;
+/// #[derive(Copy, Clone)]
+/// struct Flags { a: bool, b: bool }
+///
+/// impl_tag! {
+/// impl Tag for Flags;
+/// Flags { a: true, b: true },
+/// Flags { a: false, b: true },
+/// Flags { a: true, b: false },
+/// Flags { a: false, b: false },
+/// }
+/// ```
+///
+/// Not specifying all values results in a compile error:
+///
+/// ```compile_fail,E0004
+/// #![feature(macro_metavar_expr)]
+/// # use rustc_data_structures::impl_tag;
+/// #[derive(Copy, Clone)]
+/// enum E {
+/// A,
+/// B,
+/// }
+///
+/// impl_tag! {
+/// impl Tag for E;
+/// E::A,
+/// }
+/// ```
+#[cfg(not(bootstrap))]
+#[macro_export]
+macro_rules! impl_tag {
+ (
+ impl Tag for $Self:ty;
+ $(
+ $($path:ident)::* $( { $( $fields:tt )* })?,
+ )*
+ ) => {
+ // Safety:
+ // `bits_for_tags` is called on the same `${index()}`-es as
+ // `into_usize` returns, thus `BITS` constant is correct.
+ unsafe impl $crate::tagged_ptr::Tag for $Self {
+ const BITS: u32 = $crate::tagged_ptr::bits_for_tags(&[
+ $(
+ ${index()},
+ $( ${ignore($path)} )*
+ )*
+ ]);
+
+ #[inline]
+ fn into_usize(self) -> usize {
+ // This forbids use of repeating patterns (`Enum::V`&`Enum::V`, etc)
+ // (or at least it should, see <https://github.com/rust-lang/rust/issues/110613>)
+ #[forbid(unreachable_patterns)]
+ match self {
+ // `match` is doing heavy lifting here, by requiring exhaustiveness
+ $(
+ $($path)::* $( { $( $fields )* } )? => ${index()},
+ )*
+ }
+ }
+
+ #[inline]
+ unsafe fn from_usize(tag: usize) -> Self {
+ match tag {
+ $(
+ ${index()} => $($path)::* $( { $( $fields )* } )?,
+ )*
+
+ // Safety:
+ // `into_usize` only returns `${index()}` of the same
+ // repetition as we are filtering above, thus if this is
+ // reached, the safety contract of this function was
+ // already breached.
+ _ => unsafe {
+ debug_assert!(
+ false,
+ "invalid tag: {tag}\
+ (this is a bug in the caller of `from_usize`)"
+ );
+ std::hint::unreachable_unchecked()
+ },
+ }
+ }
+
+ }
+ };
+}
+
#[cfg(test)]
mod tests;