Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rollup of 5 pull requests #123544

Closed
wants to merge 10 commits into from
Closed
6 changes: 3 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ jobs:
run: src/ci/scripts/verify-stable-version-number.sh
if: success() && !env.SKIP_JOB
- name: run the build
run: src/ci/scripts/run-build-from-ci.sh
run: src/ci/scripts/run-build-from-ci.sh 2>&1
env:
AWS_ACCESS_KEY_ID: "${{ env.CACHES_AWS_ACCESS_KEY_ID }}"
AWS_SECRET_ACCESS_KEY: "${{ secrets[format('AWS_SECRET_ACCESS_KEY_{0}', env.CACHES_AWS_ACCESS_KEY_ID)] }}"
Expand Down Expand Up @@ -566,7 +566,7 @@ jobs:
run: src/ci/scripts/verify-stable-version-number.sh
if: success() && !env.SKIP_JOB
- name: run the build
run: src/ci/scripts/run-build-from-ci.sh
run: src/ci/scripts/run-build-from-ci.sh 2>&1
env:
AWS_ACCESS_KEY_ID: "${{ env.CACHES_AWS_ACCESS_KEY_ID }}"
AWS_SECRET_ACCESS_KEY: "${{ secrets[format('AWS_SECRET_ACCESS_KEY_{0}', env.CACHES_AWS_ACCESS_KEY_ID)] }}"
Expand Down Expand Up @@ -705,7 +705,7 @@ jobs:
run: src/ci/scripts/verify-stable-version-number.sh
if: success() && !env.SKIP_JOB
- name: run the build
run: src/ci/scripts/run-build-from-ci.sh
run: src/ci/scripts/run-build-from-ci.sh 2>&1
env:
AWS_ACCESS_KEY_ID: "${{ env.CACHES_AWS_ACCESS_KEY_ID }}"
AWS_SECRET_ACCESS_KEY: "${{ secrets[format('AWS_SECRET_ACCESS_KEY_{0}', env.CACHES_AWS_ACCESS_KEY_ID)] }}"
Expand Down
93 changes: 84 additions & 9 deletions library/core/src/cell/once.rs
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,42 @@ impl<T> OnceCell<T> {
}
}

/// Gets the mutable reference of the contents of the cell,
/// initializing it with `f` if the cell was empty.
///
/// # Panics
///
/// If `f` panics, the panic is propagated to the caller, and the cell
/// remains uninitialized.
///
/// # Examples
///
/// ```
/// #![feature(once_cell_get_mut)]
///
/// use std::cell::OnceCell;
///
/// let mut cell = OnceCell::new();
/// let value = cell.get_mut_or_init(|| 92);
/// assert_eq!(*value, 92);
///
/// *value += 2;
/// assert_eq!(*value, 94);
///
/// let value = cell.get_mut_or_init(|| unreachable!());
/// assert_eq!(*value, 94);
/// ```
#[inline]
#[unstable(feature = "once_cell_get_mut", issue = "121641")]
pub fn get_mut_or_init<F>(&mut self, f: F) -> &mut T
where
F: FnOnce() -> T,
{
match self.get_mut_or_try_init(|| Ok::<T, !>(f())) {
Ok(val) => val,
}
}

/// Gets the contents of the cell, initializing it with `f` if
/// the cell was empty. If the cell was empty and `f` failed, an
/// error is returned.
Expand Down Expand Up @@ -200,16 +236,55 @@ impl<T> OnceCell<T> {
if let Some(val) = self.get() {
return Ok(val);
}
/// Avoid inlining the initialization closure into the common path that fetches
/// the already initialized value
#[cold]
fn outlined_call<F, T, E>(f: F) -> Result<T, E>
where
F: FnOnce() -> Result<T, E>,
{
f()
self.try_init(f)
}

/// Gets the mutable reference of the contents of the cell, initializing
/// it with `f` if the cell was empty. If the cell was empty and `f` failed,
/// an error is returned.
///
/// # Panics
///
/// If `f` panics, the panic is propagated to the caller, and the cell
/// remains uninitialized.
///
/// # Examples
///
/// ```
/// #![feature(once_cell_get_mut)]
///
/// use std::cell::OnceCell;
///
/// let mut cell: OnceCell<u32> = OnceCell::new();
///
/// // Failed initializers do not change the value
/// assert!(cell.get_mut_or_try_init(|| "not a number!".parse()).is_err());
/// assert!(cell.get().is_none());
///
/// let value = cell.get_mut_or_try_init(|| "1234".parse());
/// assert_eq!(value, Ok(&mut 1234));
/// *value.unwrap() += 2;
/// assert_eq!(cell.get(), Some(&1236))
/// ```
#[unstable(feature = "once_cell_get_mut", issue = "121641")]
pub fn get_mut_or_try_init<F, E>(&mut self, f: F) -> Result<&mut T, E>
where
F: FnOnce() -> Result<T, E>,
{
if self.get().is_none() {
self.try_init(f)?;
}
let val = outlined_call(f)?;
Ok(self.get_mut().unwrap())
}

// Avoid inlining the initialization closure into the common path that fetches
// the already initialized value
#[cold]
fn try_init<F, E>(&self, f: F) -> Result<&T, E>
where
F: FnOnce() -> Result<T, E>,
{
let val = f()?;
// Note that *some* forms of reentrant initialization might lead to
// UB (see `reentrant_init` test). I believe that just removing this
// `panic`, while keeping `try_insert` would be sound, but it seems
Expand Down
2 changes: 1 addition & 1 deletion library/core/src/intrinsics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1128,7 +1128,7 @@ extern "rust-intrinsic" {
/// any safety invariants.
///
/// Consider using [`core::panic::Location::caller`] instead.
#[rustc_const_unstable(feature = "const_caller_location", issue = "76156")]
#[rustc_const_stable(feature = "const_caller_location", since = "CURRENT_RUSTC_VERSION")]
#[rustc_safe_intrinsic]
#[rustc_nounwind]
pub fn caller_location() -> &'static crate::panic::Location<'static>;
Expand Down
1 change: 0 additions & 1 deletion library/core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,6 @@
#![feature(const_array_into_iter_constructors)]
#![feature(const_bigint_helper_methods)]
#![feature(const_black_box)]
#![feature(const_caller_location)]
#![feature(const_cell_into_inner)]
#![feature(const_char_from_u32_unchecked)]
#![feature(const_eval_select)]
Expand Down
8 changes: 4 additions & 4 deletions library/core/src/panic/location.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ impl<'a> Location<'a> {
/// ```
#[must_use]
#[stable(feature = "track_caller", since = "1.46.0")]
#[rustc_const_unstable(feature = "const_caller_location", issue = "76156")]
#[rustc_const_stable(feature = "const_caller_location", since = "CURRENT_RUSTC_VERSION")]
#[track_caller]
#[inline]
pub const fn caller() -> &'static Location<'static> {
Expand Down Expand Up @@ -123,7 +123,7 @@ impl<'a> Location<'a> {
/// ```
#[must_use]
#[stable(feature = "panic_hooks", since = "1.10.0")]
#[rustc_const_unstable(feature = "const_location_fields", issue = "102911")]
#[rustc_const_stable(feature = "const_location_fields", since = "CURRENT_RUSTC_VERSION")]
#[inline]
pub const fn file(&self) -> &str {
self.file
Expand All @@ -148,7 +148,7 @@ impl<'a> Location<'a> {
/// ```
#[must_use]
#[stable(feature = "panic_hooks", since = "1.10.0")]
#[rustc_const_unstable(feature = "const_location_fields", issue = "102911")]
#[rustc_const_stable(feature = "const_location_fields", since = "CURRENT_RUSTC_VERSION")]
#[inline]
pub const fn line(&self) -> u32 {
self.line
Expand All @@ -173,7 +173,7 @@ impl<'a> Location<'a> {
/// ```
#[must_use]
#[stable(feature = "panic_col", since = "1.25.0")]
#[rustc_const_unstable(feature = "const_location_fields", issue = "102911")]
#[rustc_const_stable(feature = "const_location_fields", since = "CURRENT_RUSTC_VERSION")]
#[inline]
pub const fn column(&self) -> u32 {
self.col
Expand Down
2 changes: 0 additions & 2 deletions library/core/tests/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
#![feature(const_align_offset)]
#![feature(const_align_of_val_raw)]
#![feature(const_black_box)]
#![feature(const_caller_location)]
#![feature(const_cell_into_inner)]
#![feature(const_hash)]
#![feature(const_heap)]
Expand All @@ -25,7 +24,6 @@
#![cfg_attr(not(bootstrap), feature(const_three_way_compare))]
#![feature(const_trait_impl)]
#![feature(const_likely)]
#![feature(const_location_fields)]
#![feature(core_intrinsics)]
#![feature(core_io_borrowed_buf)]
#![feature(core_private_bignum)]
Expand Down
81 changes: 81 additions & 0 deletions library/std/src/sync/once_lock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,46 @@ impl<T> OnceLock<T> {
}
}

/// Gets the mutable reference of the contents of the cell, initializing
/// it with `f` if the cell was empty.
///
/// Many threads may call `get_mut_or_init` concurrently with different
/// initializing functions, but it is guaranteed that only one function
/// will be executed.
///
/// # Panics
///
/// If `f` panics, the panic is propagated to the caller, and the cell
/// remains uninitialized.
///
/// # Examples
///
/// ```
/// #![feature(once_cell_get_mut)]
///
/// use std::sync::OnceLock;
///
/// let mut cell = OnceLock::new();
/// let value = cell.get_mut_or_init(|| 92);
/// assert_eq!(*value, 92);
///
/// *value += 2;
/// assert_eq!(*value, 94);
///
/// let value = cell.get_mut_or_init(|| unreachable!());
/// assert_eq!(*value, 94);
/// ```
#[inline]
#[unstable(feature = "once_cell_get_mut", issue = "121641")]
pub fn get_mut_or_init<F>(&mut self, f: F) -> &mut T
where
F: FnOnce() -> T,
{
match self.get_mut_or_try_init(|| Ok::<T, !>(f())) {
Ok(val) => val,
}
}

/// Gets the contents of the cell, initializing it with `f` if
/// the cell was empty. If the cell was empty and `f` failed, an
/// error is returned.
Expand Down Expand Up @@ -303,6 +343,47 @@ impl<T> OnceLock<T> {
Ok(unsafe { self.get_unchecked() })
}

/// Gets the mutable reference of the contents of the cell, initializing
/// it with `f` if the cell was empty. If the cell was empty and `f` failed,
/// an error is returned.
///
/// # Panics
///
/// If `f` panics, the panic is propagated to the caller, and
/// the cell remains uninitialized.
///
/// # Examples
///
/// ```
/// #![feature(once_cell_get_mut)]
///
/// use std::sync::OnceLock;
///
/// let mut cell: OnceLock<u32> = OnceLock::new();
///
/// // Failed initializers do not change the value
/// assert!(cell.get_mut_or_try_init(|| "not a number!".parse()).is_err());
/// assert!(cell.get().is_none());
///
/// let value = cell.get_mut_or_try_init(|| "1234".parse());
/// assert_eq!(value, Ok(&mut 1234));
/// *value.unwrap() += 2;
/// assert_eq!(cell.get(), Some(&1236))
/// ```
#[inline]
#[unstable(feature = "once_cell_get_mut", issue = "121641")]
pub fn get_mut_or_try_init<F, E>(&mut self, f: F) -> Result<&mut T, E>
where
F: FnOnce() -> Result<T, E>,
{
if self.get().is_none() {
self.initialize(f)?;
}
debug_assert!(self.is_initialized());
// SAFETY: The inner value has been initialized
Ok(unsafe { self.get_unchecked_mut() })
}

/// Consumes the `OnceLock`, returning the wrapped value. Returns
/// `None` if the cell was empty.
///
Expand Down
39 changes: 35 additions & 4 deletions src/bootstrap/src/core/build_steps/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -597,7 +597,7 @@ impl Step for Miri {
builder.ensure(compile::Std::new(target_compiler, host));
let host_sysroot = builder.sysroot(target_compiler);

// # Run `cargo test`.
// Run `cargo test`.
// This is with the Miri crate, so it uses the host compiler.
let mut cargo = tool::prepare_tool_cargo(
builder,
Expand Down Expand Up @@ -652,15 +652,46 @@ impl Step for Miri {
builder.run(&mut cargo);
}
}
}
}

#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct CargoMiri {
target: TargetSelection,
}

impl Step for CargoMiri {
type Output = ();
const ONLY_HOSTS: bool = false;

// # Run `cargo miri test`.
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
run.path("src/tools/miri/cargo-miri")
}

fn make_run(run: RunConfig<'_>) {
run.builder.ensure(CargoMiri { target: run.target });
}

/// Tests `cargo miri test`.
fn run(self, builder: &Builder<'_>) {
let host = builder.build.build;
let target = self.target;
let stage = builder.top_stage;
if stage == 0 {
eprintln!("cargo-miri cannot be tested at stage 0");
std::process::exit(1);
}

// This compiler runs on the host, we'll just use it for the target.
let compiler = builder.compiler(stage, host);

// Run `cargo miri test`.
// This is just a smoke test (Miri's own CI invokes this in a bunch of different ways and ensures
// that we get the desired output), but that is sufficient to make sure that the libtest harness
// itself executes properly under Miri, and that all the logic in `cargo-miri` does not explode.
// This is running the build `cargo-miri` for the given target, so we need the target compiler.
let mut cargo = tool::prepare_tool_cargo(
builder,
target_compiler,
compiler,
Mode::ToolStd, // it's unclear what to use here, we're not building anything just doing a smoke test!
target,
"miri-test",
Expand Down
1 change: 1 addition & 0 deletions src/bootstrap/src/core/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -808,6 +808,7 @@ impl<'a> Builder<'a> {
test::EditionGuide,
test::Rustfmt,
test::Miri,
test::CargoMiri,
test::Clippy,
test::RustDemangler,
test::CompiletestTest,
Expand Down
8 changes: 4 additions & 4 deletions src/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh
Original file line number Diff line number Diff line change
Expand Up @@ -32,18 +32,18 @@ python3 "$X_PY" test --stage 2 src/tools/rustfmt
# that bugs which only surface when the GC runs at a specific time are more likely to cause CI to fail.
# This significantly increases the runtime of our test suite, or we'd do this in PR CI too.
if [ -z "${PR_CI_JOB:-}" ]; then
MIRIFLAGS=-Zmiri-provenance-gc=1 python3 "$X_PY" test --stage 2 src/tools/miri
MIRIFLAGS=-Zmiri-provenance-gc=1 python3 "$X_PY" test --stage 2 src/tools/miri src/tools/miri/cargo-miri
else
python3 "$X_PY" test --stage 2 src/tools/miri
python3 "$X_PY" test --stage 2 src/tools/miri src/tools/miri/cargo-miri
fi
# We natively run this script on x86_64-unknown-linux-gnu and x86_64-pc-windows-msvc.
# Also cover some other targets via cross-testing, in particular all tier 1 targets.
case $HOST_TARGET in
x86_64-unknown-linux-gnu)
# Only this branch runs in PR CI.
# Fully test all main OSes, including a 32bit target.
python3 "$X_PY" test --stage 2 src/tools/miri --target x86_64-apple-darwin
python3 "$X_PY" test --stage 2 src/tools/miri --target i686-pc-windows-msvc
python3 "$X_PY" test --stage 2 src/tools/miri src/tools/miri/cargo-miri --target x86_64-apple-darwin
python3 "$X_PY" test --stage 2 src/tools/miri src/tools/miri/cargo-miri --target i686-pc-windows-msvc
# Only run "pass" tests for the remaining targets, which is quite a bit faster.
python3 "$X_PY" test --stage 2 src/tools/miri --target x86_64-pc-windows-gnu --test-args pass
python3 "$X_PY" test --stage 2 src/tools/miri --target i686-unknown-linux-gnu --test-args pass
Expand Down
3 changes: 2 additions & 1 deletion src/ci/github-actions/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,8 @@ x--expand-yaml-anchors--remove:
<<: *step

- name: run the build
run: src/ci/scripts/run-build-from-ci.sh
# Redirect stderr to stdout to avoid reordering the two streams in the GHA logs.
run: src/ci/scripts/run-build-from-ci.sh 2>&1
env:
AWS_ACCESS_KEY_ID: ${{ env.CACHES_AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets[format('AWS_SECRET_ACCESS_KEY_{0}', env.CACHES_AWS_ACCESS_KEY_ID)] }}
Expand Down
Loading
Loading