Auto merge of #123545 - matthiaskrgr:rollup-vyx8cfv, r=matthiaskrgr
Rollup of 4 pull requests Successful merges: - #114788 (impl get_mut_or_init and get_mut_or_try_init for OnceCell and OnceLock) - #122291 (Stabilize `const_caller_location` and `const_location_fields`) - #123357 (CI: Redirect stderr to stdout to order GHA logs) - #123504 (bootstrap: split cargo-miri test into separate Step) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
83d0a940c6
6
.github/workflows/ci.yml
vendored
6
.github/workflows/ci.yml
vendored
@ -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)] }}"
|
||||
@ -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)] }}"
|
||||
@ -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)] }}"
|
||||
|
@ -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.
|
||||
@ -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
|
||||
|
@ -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>;
|
||||
|
@ -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)]
|
||||
|
@ -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> {
|
||||
@ -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
|
||||
@ -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
|
||||
@ -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
|
||||
|
@ -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)]
|
||||
@ -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)]
|
||||
|
@ -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.
|
||||
@ -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.
|
||||
///
|
||||
|
@ -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,
|
||||
@ -652,15 +652,46 @@ impl Step for Miri {
|
||||
builder.run(&mut cargo);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// # Run `cargo miri test`.
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct CargoMiri {
|
||||
target: TargetSelection,
|
||||
}
|
||||
|
||||
impl Step for CargoMiri {
|
||||
type Output = ();
|
||||
const ONLY_HOSTS: bool = false;
|
||||
|
||||
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",
|
||||
|
@ -808,6 +808,7 @@ impl<'a> Builder<'a> {
|
||||
test::EditionGuide,
|
||||
test::Rustfmt,
|
||||
test::Miri,
|
||||
test::CargoMiri,
|
||||
test::Clippy,
|
||||
test::RustDemangler,
|
||||
test::CompiletestTest,
|
||||
|
@ -32,9 +32,9 @@ 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.
|
||||
@ -42,8 +42,8 @@ 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
|
||||
|
@ -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)] }}
|
||||
|
@ -6,7 +6,7 @@
|
||||
//@ run-pass
|
||||
//@ compile-flags: -Z unleash-the-miri-inside-of-you
|
||||
|
||||
#![feature(core_intrinsics, const_caller_location)]
|
||||
#![feature(core_intrinsics)]
|
||||
|
||||
type L = &'static std::panic::Location<'static>;
|
||||
|
||||
|
@ -2,15 +2,13 @@
|
||||
//@ revisions: default mir-opt
|
||||
//@[mir-opt] compile-flags: -Zmir-opt-level=4
|
||||
|
||||
#![feature(const_caller_location)]
|
||||
|
||||
use std::panic::Location;
|
||||
|
||||
const LOCATION: &Location = Location::caller();
|
||||
|
||||
const TRACKED: &Location = tracked();
|
||||
#[track_caller]
|
||||
const fn tracked() -> &'static Location <'static> {
|
||||
const fn tracked() -> &'static Location<'static> {
|
||||
Location::caller()
|
||||
}
|
||||
|
||||
@ -26,18 +24,18 @@ const fn contained() -> &'static Location<'static> {
|
||||
|
||||
fn main() {
|
||||
assert_eq!(LOCATION.file(), file!());
|
||||
assert_eq!(LOCATION.line(), 9);
|
||||
assert_eq!(LOCATION.line(), 7);
|
||||
assert_eq!(LOCATION.column(), 29);
|
||||
|
||||
assert_eq!(TRACKED.file(), file!());
|
||||
assert_eq!(TRACKED.line(), 11);
|
||||
assert_eq!(TRACKED.line(), 9);
|
||||
assert_eq!(TRACKED.column(), 28);
|
||||
|
||||
assert_eq!(NESTED.file(), file!());
|
||||
assert_eq!(NESTED.line(), 19);
|
||||
assert_eq!(NESTED.line(), 17);
|
||||
assert_eq!(NESTED.column(), 5);
|
||||
|
||||
assert_eq!(CONTAINED.file(), file!());
|
||||
assert_eq!(CONTAINED.line(), 24);
|
||||
assert_eq!(CONTAINED.line(), 22);
|
||||
assert_eq!(CONTAINED.column(), 5);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user