mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 14:55:26 +00:00
Auto merge of #111933 - matthiaskrgr:rollup-m10k3ts, r=matthiaskrgr
Rollup of 4 pull requests Successful merges: - #95198 (Add slice::{split_,}{first,last}_chunk{,_mut}) - #109899 (Use apple-m1 as target CPU for aarch64-apple-darwin.) - #111624 (Emit diagnostic for privately uninhabited uncovered witnesses.) - #111875 (Don't leak the function that is called on drop) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
0b011b7b7e
@ -102,21 +102,27 @@ pub mod unord;
|
||||
pub use ena::undo_log;
|
||||
pub use ena::unify;
|
||||
|
||||
pub struct OnDrop<F: Fn()>(pub F);
|
||||
/// Returns a structure that calls `f` when dropped.
|
||||
pub fn defer<F: FnOnce()>(f: F) -> OnDrop<F> {
|
||||
OnDrop(Some(f))
|
||||
}
|
||||
|
||||
impl<F: Fn()> OnDrop<F> {
|
||||
/// Forgets the function which prevents it from running.
|
||||
/// Ensure that the function owns no memory, otherwise it will be leaked.
|
||||
pub struct OnDrop<F: FnOnce()>(Option<F>);
|
||||
|
||||
impl<F: FnOnce()> OnDrop<F> {
|
||||
/// Disables on-drop call.
|
||||
#[inline]
|
||||
pub fn disable(self) {
|
||||
std::mem::forget(self);
|
||||
pub fn disable(mut self) {
|
||||
self.0.take();
|
||||
}
|
||||
}
|
||||
|
||||
impl<F: Fn()> Drop for OnDrop<F> {
|
||||
impl<F: FnOnce()> Drop for OnDrop<F> {
|
||||
#[inline]
|
||||
fn drop(&mut self) {
|
||||
(self.0)();
|
||||
if let Some(f) = self.0.take() {
|
||||
f();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -7,8 +7,8 @@ use std::{
|
||||
};
|
||||
|
||||
use crate::{
|
||||
defer,
|
||||
owned_slice::{slice_owned, try_slice_owned, OwnedSlice},
|
||||
OnDrop,
|
||||
};
|
||||
|
||||
#[test]
|
||||
@ -66,7 +66,7 @@ fn boxed() {
|
||||
fn drop_drops() {
|
||||
let flag = Arc::new(AtomicBool::new(false));
|
||||
let flag_prime = Arc::clone(&flag);
|
||||
let d = OnDrop(move || flag_prime.store(true, atomic::Ordering::Relaxed));
|
||||
let d = defer(move || flag_prime.store(true, atomic::Ordering::Relaxed));
|
||||
|
||||
let slice = slice_owned(d, |_| &[]);
|
||||
|
||||
|
@ -3,9 +3,9 @@ use crate::util;
|
||||
use rustc_ast::token;
|
||||
use rustc_ast::{self as ast, LitKind, MetaItemKind};
|
||||
use rustc_codegen_ssa::traits::CodegenBackend;
|
||||
use rustc_data_structures::defer;
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc_data_structures::OnDrop;
|
||||
use rustc_errors::registry::Registry;
|
||||
use rustc_errors::{ErrorGuaranteed, Handler};
|
||||
use rustc_lint::LintStore;
|
||||
@ -325,7 +325,7 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se
|
||||
|
||||
rustc_span::set_source_map(compiler.sess.parse_sess.clone_source_map(), move || {
|
||||
let r = {
|
||||
let _sess_abort_error = OnDrop(|| {
|
||||
let _sess_abort_error = defer(|| {
|
||||
compiler.sess.finish_diagnostics(registry);
|
||||
});
|
||||
|
||||
|
@ -78,7 +78,7 @@ where
|
||||
{
|
||||
TLV.with(|tlv| {
|
||||
let old = tlv.replace(erase(context));
|
||||
let _reset = rustc_data_structures::OnDrop(move || tlv.set(old));
|
||||
let _reset = rustc_data_structures::defer(move || tlv.set(old));
|
||||
f()
|
||||
})
|
||||
}
|
||||
|
@ -340,6 +340,8 @@ mir_build_uncovered = {$count ->
|
||||
*[other] patterns `{$witness_1}`, `{$witness_2}`, `{$witness_3}` and {$remainder} more
|
||||
} not covered
|
||||
|
||||
mir_build_privately_uninhabited = pattern `{$witness_1}` is currently uninhabited, but this variant contains private fields which may become inhabited in the future
|
||||
|
||||
mir_build_pattern_not_covered = refutable pattern in {$origin}
|
||||
.pattern_ty = the matched value is of type `{$pattern_ty}`
|
||||
|
||||
|
@ -781,6 +781,8 @@ pub(crate) struct PatternNotCovered<'s, 'tcx> {
|
||||
pub interpreted_as_const: Option<InterpretedAsConst>,
|
||||
#[subdiagnostic]
|
||||
pub adt_defined_here: Option<AdtDefinedHere<'tcx>>,
|
||||
#[note(mir_build_privately_uninhabited)]
|
||||
pub witness_1_is_privately_uninhabited: Option<()>,
|
||||
#[note(mir_build_pattern_ty)]
|
||||
pub _p: (),
|
||||
pub pattern_ty: Ty<'tcx>,
|
||||
|
@ -479,12 +479,30 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
|
||||
AdtDefinedHere { adt_def_span, ty, variants }
|
||||
};
|
||||
|
||||
// Emit an extra note if the first uncovered witness is
|
||||
// visibly uninhabited anywhere in the current crate.
|
||||
let witness_1_is_privately_uninhabited =
|
||||
if cx.tcx.features().exhaustive_patterns
|
||||
&& let Some(witness_1) = witnesses.get(0)
|
||||
&& let ty::Adt(adt, substs) = witness_1.ty().kind()
|
||||
&& adt.is_enum()
|
||||
&& let Constructor::Variant(variant_index) = witness_1.ctor()
|
||||
{
|
||||
let variant = adt.variant(*variant_index);
|
||||
let inhabited = variant.inhabited_predicate(cx.tcx, *adt).subst(cx.tcx, substs);
|
||||
assert!(inhabited.apply(cx.tcx, cx.param_env, cx.module));
|
||||
!inhabited.apply_ignore_module(cx.tcx, cx.param_env)
|
||||
} else {
|
||||
false
|
||||
};
|
||||
|
||||
self.error = Err(self.tcx.sess.emit_err(PatternNotCovered {
|
||||
span: pat.span,
|
||||
origin,
|
||||
uncovered: Uncovered::new(pat.span, &cx, witnesses),
|
||||
inform,
|
||||
interpreted_as_const,
|
||||
witness_1_is_privately_uninhabited: witness_1_is_privately_uninhabited.then_some(()),
|
||||
_p: (),
|
||||
pattern_ty,
|
||||
let_suggestion,
|
||||
|
@ -22,7 +22,7 @@ use {
|
||||
rustc_data_structures::fx::FxHashSet,
|
||||
rustc_data_structures::sync::Lock,
|
||||
rustc_data_structures::sync::Lrc,
|
||||
rustc_data_structures::{jobserver, OnDrop},
|
||||
rustc_data_structures::{defer, jobserver},
|
||||
rustc_span::DUMMY_SP,
|
||||
std::iter,
|
||||
std::process,
|
||||
@ -530,7 +530,7 @@ fn remove_cycle<D: DepKind>(
|
||||
/// all active queries for cycles before finally resuming all the waiters at once.
|
||||
#[cfg(parallel_compiler)]
|
||||
pub fn deadlock<D: DepKind>(query_map: QueryMap<D>, registry: &rayon_core::Registry) {
|
||||
let on_panic = OnDrop(|| {
|
||||
let on_panic = defer(|| {
|
||||
eprintln!("deadlock handler panicked, aborting process");
|
||||
process::abort();
|
||||
});
|
||||
|
@ -4,7 +4,7 @@ use crate::spec::{FramePointer, SanitizerSet, Target, TargetOptions};
|
||||
pub fn target() -> Target {
|
||||
let arch = Arch::Arm64;
|
||||
let mut base = opts("macos", arch);
|
||||
base.cpu = "apple-a14".into();
|
||||
base.cpu = "apple-m1".into();
|
||||
base.max_atomic_width = Some(128);
|
||||
|
||||
// FIXME: The leak sanitizer currently fails the tests, see #88132.
|
||||
|
@ -319,6 +319,264 @@ impl<T> [T] {
|
||||
if let [.., last] = self { Some(last) } else { None }
|
||||
}
|
||||
|
||||
/// Returns the first `N` elements of the slice, or `None` if it has fewer than `N` elements.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(slice_first_last_chunk)]
|
||||
///
|
||||
/// let u = [10, 40, 30];
|
||||
/// assert_eq!(Some(&[10, 40]), u.first_chunk::<2>());
|
||||
///
|
||||
/// let v: &[i32] = &[10];
|
||||
/// assert_eq!(None, v.first_chunk::<2>());
|
||||
///
|
||||
/// let w: &[i32] = &[];
|
||||
/// assert_eq!(Some(&[]), w.first_chunk::<0>());
|
||||
/// ```
|
||||
#[unstable(feature = "slice_first_last_chunk", issue = "111774")]
|
||||
#[rustc_const_unstable(feature = "slice_first_last_chunk", issue = "111774")]
|
||||
#[inline]
|
||||
pub const fn first_chunk<const N: usize>(&self) -> Option<&[T; N]> {
|
||||
if self.len() < N {
|
||||
None
|
||||
} else {
|
||||
// SAFETY: We explicitly check for the correct number of elements,
|
||||
// and do not let the reference outlive the slice.
|
||||
Some(unsafe { &*(self.as_ptr() as *const [T; N]) })
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a mutable reference to the first `N` elements of the slice,
|
||||
/// or `None` if it has fewer than `N` elements.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(slice_first_last_chunk)]
|
||||
///
|
||||
/// let x = &mut [0, 1, 2];
|
||||
///
|
||||
/// if let Some(first) = x.first_chunk_mut::<2>() {
|
||||
/// first[0] = 5;
|
||||
/// first[1] = 4;
|
||||
/// }
|
||||
/// assert_eq!(x, &[5, 4, 2]);
|
||||
/// ```
|
||||
#[unstable(feature = "slice_first_last_chunk", issue = "111774")]
|
||||
#[rustc_const_unstable(feature = "slice_first_last_chunk", issue = "111774")]
|
||||
#[inline]
|
||||
pub const fn first_chunk_mut<const N: usize>(&mut self) -> Option<&mut [T; N]> {
|
||||
if self.len() < N {
|
||||
None
|
||||
} else {
|
||||
// SAFETY: We explicitly check for the correct number of elements,
|
||||
// do not let the reference outlive the slice,
|
||||
// and require exclusive access to the entire slice to mutate the chunk.
|
||||
Some(unsafe { &mut *(self.as_mut_ptr() as *mut [T; N]) })
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the first `N` elements of the slice and the remainder,
|
||||
/// or `None` if it has fewer than `N` elements.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(slice_first_last_chunk)]
|
||||
///
|
||||
/// let x = &[0, 1, 2];
|
||||
///
|
||||
/// if let Some((first, elements)) = x.split_first_chunk::<2>() {
|
||||
/// assert_eq!(first, &[0, 1]);
|
||||
/// assert_eq!(elements, &[2]);
|
||||
/// }
|
||||
/// ```
|
||||
#[unstable(feature = "slice_first_last_chunk", issue = "111774")]
|
||||
#[rustc_const_unstable(feature = "slice_first_last_chunk", issue = "111774")]
|
||||
#[inline]
|
||||
pub const fn split_first_chunk<const N: usize>(&self) -> Option<(&[T; N], &[T])> {
|
||||
if self.len() < N {
|
||||
None
|
||||
} else {
|
||||
// SAFETY: We manually verified the bounds of the split.
|
||||
let (first, tail) = unsafe { self.split_at_unchecked(N) };
|
||||
|
||||
// SAFETY: We explicitly check for the correct number of elements,
|
||||
// and do not let the references outlive the slice.
|
||||
Some((unsafe { &*(first.as_ptr() as *const [T; N]) }, tail))
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a mutable reference to the first `N` elements of the slice and the remainder,
|
||||
/// or `None` if it has fewer than `N` elements.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(slice_first_last_chunk)]
|
||||
///
|
||||
/// let x = &mut [0, 1, 2];
|
||||
///
|
||||
/// if let Some((first, elements)) = x.split_first_chunk_mut::<2>() {
|
||||
/// first[0] = 3;
|
||||
/// first[1] = 4;
|
||||
/// elements[0] = 5;
|
||||
/// }
|
||||
/// assert_eq!(x, &[3, 4, 5]);
|
||||
/// ```
|
||||
#[unstable(feature = "slice_first_last_chunk", issue = "111774")]
|
||||
#[rustc_const_unstable(feature = "slice_first_last_chunk", issue = "111774")]
|
||||
#[inline]
|
||||
pub const fn split_first_chunk_mut<const N: usize>(
|
||||
&mut self,
|
||||
) -> Option<(&mut [T; N], &mut [T])> {
|
||||
if self.len() < N {
|
||||
None
|
||||
} else {
|
||||
// SAFETY: We manually verified the bounds of the split.
|
||||
let (first, tail) = unsafe { self.split_at_mut_unchecked(N) };
|
||||
|
||||
// SAFETY: We explicitly check for the correct number of elements,
|
||||
// do not let the reference outlive the slice,
|
||||
// and enforce exclusive mutability of the chunk by the split.
|
||||
Some((unsafe { &mut *(first.as_mut_ptr() as *mut [T; N]) }, tail))
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the last `N` elements of the slice and the remainder,
|
||||
/// or `None` if it has fewer than `N` elements.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(slice_first_last_chunk)]
|
||||
///
|
||||
/// let x = &[0, 1, 2];
|
||||
///
|
||||
/// if let Some((last, elements)) = x.split_last_chunk::<2>() {
|
||||
/// assert_eq!(last, &[1, 2]);
|
||||
/// assert_eq!(elements, &[0]);
|
||||
/// }
|
||||
/// ```
|
||||
#[unstable(feature = "slice_first_last_chunk", issue = "111774")]
|
||||
#[rustc_const_unstable(feature = "slice_first_last_chunk", issue = "111774")]
|
||||
#[inline]
|
||||
pub const fn split_last_chunk<const N: usize>(&self) -> Option<(&[T; N], &[T])> {
|
||||
if self.len() < N {
|
||||
None
|
||||
} else {
|
||||
// SAFETY: We manually verified the bounds of the split.
|
||||
let (init, last) = unsafe { self.split_at_unchecked(self.len() - N) };
|
||||
|
||||
// SAFETY: We explicitly check for the correct number of elements,
|
||||
// and do not let the references outlive the slice.
|
||||
Some((unsafe { &*(last.as_ptr() as *const [T; N]) }, init))
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the last and all the rest of the elements of the slice, or `None` if it is empty.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(slice_first_last_chunk)]
|
||||
///
|
||||
/// let x = &mut [0, 1, 2];
|
||||
///
|
||||
/// if let Some((last, elements)) = x.split_last_chunk_mut::<2>() {
|
||||
/// last[0] = 3;
|
||||
/// last[1] = 4;
|
||||
/// elements[0] = 5;
|
||||
/// }
|
||||
/// assert_eq!(x, &[5, 3, 4]);
|
||||
/// ```
|
||||
#[unstable(feature = "slice_first_last_chunk", issue = "111774")]
|
||||
#[rustc_const_unstable(feature = "slice_first_last_chunk", issue = "111774")]
|
||||
#[inline]
|
||||
pub const fn split_last_chunk_mut<const N: usize>(
|
||||
&mut self,
|
||||
) -> Option<(&mut [T; N], &mut [T])> {
|
||||
if self.len() < N {
|
||||
None
|
||||
} else {
|
||||
// SAFETY: We manually verified the bounds of the split.
|
||||
let (init, last) = unsafe { self.split_at_mut_unchecked(self.len() - N) };
|
||||
|
||||
// SAFETY: We explicitly check for the correct number of elements,
|
||||
// do not let the reference outlive the slice,
|
||||
// and enforce exclusive mutability of the chunk by the split.
|
||||
Some((unsafe { &mut *(last.as_mut_ptr() as *mut [T; N]) }, init))
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the last element of the slice, or `None` if it is empty.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(slice_first_last_chunk)]
|
||||
///
|
||||
/// let u = [10, 40, 30];
|
||||
/// assert_eq!(Some(&[40, 30]), u.last_chunk::<2>());
|
||||
///
|
||||
/// let v: &[i32] = &[10];
|
||||
/// assert_eq!(None, v.last_chunk::<2>());
|
||||
///
|
||||
/// let w: &[i32] = &[];
|
||||
/// assert_eq!(Some(&[]), w.last_chunk::<0>());
|
||||
/// ```
|
||||
#[unstable(feature = "slice_first_last_chunk", issue = "111774")]
|
||||
#[rustc_const_unstable(feature = "slice_first_last_chunk", issue = "111774")]
|
||||
#[inline]
|
||||
pub const fn last_chunk<const N: usize>(&self) -> Option<&[T; N]> {
|
||||
if self.len() < N {
|
||||
None
|
||||
} else {
|
||||
// SAFETY: We manually verified the bounds of the slice.
|
||||
// FIXME: Without const traits, we need this instead of `get_unchecked`.
|
||||
let last = unsafe { self.split_at_unchecked(self.len() - N).1 };
|
||||
|
||||
// SAFETY: We explicitly check for the correct number of elements,
|
||||
// and do not let the references outlive the slice.
|
||||
Some(unsafe { &*(last.as_ptr() as *const [T; N]) })
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a mutable pointer to the last item in the slice.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(slice_first_last_chunk)]
|
||||
///
|
||||
/// let x = &mut [0, 1, 2];
|
||||
///
|
||||
/// if let Some(last) = x.last_chunk_mut::<2>() {
|
||||
/// last[0] = 10;
|
||||
/// last[1] = 20;
|
||||
/// }
|
||||
/// assert_eq!(x, &[0, 10, 20]);
|
||||
/// ```
|
||||
#[unstable(feature = "slice_first_last_chunk", issue = "111774")]
|
||||
#[rustc_const_unstable(feature = "slice_first_last_chunk", issue = "111774")]
|
||||
#[inline]
|
||||
pub const fn last_chunk_mut<const N: usize>(&mut self) -> Option<&mut [T; N]> {
|
||||
if self.len() < N {
|
||||
None
|
||||
} else {
|
||||
// SAFETY: We manually verified the bounds of the slice.
|
||||
// FIXME: Without const traits, we need this instead of `get_unchecked`.
|
||||
let last = unsafe { self.split_at_mut_unchecked(self.len() - N).1 };
|
||||
|
||||
// SAFETY: We explicitly check for the correct number of elements,
|
||||
// do not let the reference outlive the slice,
|
||||
// and require exclusive access to the entire slice to mutate the chunk.
|
||||
Some(unsafe { &mut *(last.as_mut_ptr() as *mut [T; N]) })
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a reference to an element or subslice depending on the type of
|
||||
/// index.
|
||||
///
|
||||
|
@ -14,6 +14,7 @@ LL | enum Either<A, B> {
|
||||
LL | A(A),
|
||||
LL | B(inner::Wrapper<B>),
|
||||
| - not covered
|
||||
= note: pattern `Either::B(_)` is currently uninhabited, but this variant contains private fields which may become inhabited in the future
|
||||
= note: the matched value is of type `Either<(), !>`
|
||||
help: you might want to use `if let` to ignore the variant that isn't matched
|
||||
|
|
||||
|
@ -16,7 +16,9 @@ struct NotSoSecretlyEmpty {
|
||||
}
|
||||
|
||||
enum Foo {
|
||||
//~^ NOTE `Foo` defined here
|
||||
A(foo::SecretlyEmpty),
|
||||
//~^ NOTE not covered
|
||||
B(foo::NotSoSecretlyEmpty),
|
||||
C(NotSoSecretlyEmpty),
|
||||
D(u32, u32),
|
||||
@ -27,4 +29,9 @@ fn main() {
|
||||
let Foo::D(_y, _z) = x;
|
||||
//~^ ERROR refutable pattern in local binding
|
||||
//~| `Foo::A(_)` not covered
|
||||
//~| NOTE `let` bindings require an "irrefutable pattern"
|
||||
//~| NOTE for more information
|
||||
//~| NOTE pattern `Foo::A(_)` is currently uninhabited
|
||||
//~| NOTE the matched value is of type `Foo`
|
||||
//~| HELP you might want to use `let else`
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
error[E0005]: refutable pattern in local binding
|
||||
--> $DIR/uninhabited-irrefutable.rs:27:9
|
||||
--> $DIR/uninhabited-irrefutable.rs:29:9
|
||||
|
|
||||
LL | let Foo::D(_y, _z) = x;
|
||||
| ^^^^^^^^^^^^^^ pattern `Foo::A(_)` not covered
|
||||
@ -11,8 +11,10 @@ note: `Foo` defined here
|
||||
|
|
||||
LL | enum Foo {
|
||||
| ^^^
|
||||
LL |
|
||||
LL | A(foo::SecretlyEmpty),
|
||||
| - not covered
|
||||
= note: pattern `Foo::A(_)` is currently uninhabited, but this variant contains private fields which may become inhabited in the future
|
||||
= note: the matched value is of type `Foo`
|
||||
help: you might want to use `let else` to handle the variant that isn't matched
|
||||
|
|
||||
|
Loading…
Reference in New Issue
Block a user