Rollup merge of #126328 - RalfJung:is_none_or, r=workingjubilee
Add Option::is_none_or ACP: https://github.com/rust-lang/libs-team/issues/212
This commit is contained in:
commit
f5af7eea1a
14 changed files with 41 additions and 11 deletions
|
@ -1057,7 +1057,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
||||||
|
|
||||||
ty::Str | ty::Slice(_) | ty::Dynamic(_, _, ty::Dyn) | ty::Foreign(..) => false,
|
ty::Str | ty::Slice(_) | ty::Dynamic(_, _, ty::Dyn) | ty::Foreign(..) => false,
|
||||||
|
|
||||||
ty::Tuple(tys) => tys.last().iter().all(|ty| is_very_trivially_sized(**ty)),
|
ty::Tuple(tys) => tys.last().is_none_or(|ty| is_very_trivially_sized(*ty)),
|
||||||
|
|
||||||
ty::Pat(ty, ..) => is_very_trivially_sized(*ty),
|
ty::Pat(ty, ..) => is_very_trivially_sized(*ty),
|
||||||
|
|
||||||
|
|
|
@ -446,7 +446,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
||||||
let (alloc_size, _alloc_align, ret_val) = alloc_size(alloc_id, offset, prov)?;
|
let (alloc_size, _alloc_align, ret_val) = alloc_size(alloc_id, offset, prov)?;
|
||||||
// Test bounds.
|
// Test bounds.
|
||||||
// It is sufficient to check this for the end pointer. Also check for overflow!
|
// It is sufficient to check this for the end pointer. Also check for overflow!
|
||||||
if offset.checked_add(size, &self.tcx).map_or(true, |end| end > alloc_size) {
|
if offset.checked_add(size, &self.tcx).is_none_or(|end| end > alloc_size) {
|
||||||
throw_ub!(PointerOutOfBounds {
|
throw_ub!(PointerOutOfBounds {
|
||||||
alloc_id,
|
alloc_id,
|
||||||
alloc_size,
|
alloc_size,
|
||||||
|
|
|
@ -300,7 +300,7 @@ where
|
||||||
) -> InterpResult<'tcx, P> {
|
) -> InterpResult<'tcx, P> {
|
||||||
let len = base.len(self)?; // also asserts that we have a type where this makes sense
|
let len = base.len(self)?; // also asserts that we have a type where this makes sense
|
||||||
let actual_to = if from_end {
|
let actual_to = if from_end {
|
||||||
if from.checked_add(to).map_or(true, |to| to > len) {
|
if from.checked_add(to).is_none_or(|to| to > len) {
|
||||||
// This can only be reached in ConstProp and non-rustc-MIR.
|
// This can only be reached in ConstProp and non-rustc-MIR.
|
||||||
throw_ub!(BoundsCheckFailed { len: len, index: from.saturating_add(to) });
|
throw_ub!(BoundsCheckFailed { len: len, index: from.saturating_add(to) });
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#![feature(box_patterns)]
|
#![feature(box_patterns)]
|
||||||
#![feature(decl_macro)]
|
#![feature(decl_macro)]
|
||||||
#![feature(if_let_guard)]
|
#![feature(if_let_guard)]
|
||||||
|
#![feature(is_none_or)]
|
||||||
#![feature(let_chains)]
|
#![feature(let_chains)]
|
||||||
#![feature(never_type)]
|
#![feature(never_type)]
|
||||||
#![feature(rustdoc_internals)]
|
#![feature(rustdoc_internals)]
|
||||||
|
|
|
@ -234,7 +234,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
let ret_ty = ret_coercion.borrow().expected_ty();
|
let ret_ty = ret_coercion.borrow().expected_ty();
|
||||||
let ret_ty = self.infcx.shallow_resolve(ret_ty);
|
let ret_ty = self.infcx.shallow_resolve(ret_ty);
|
||||||
self.can_coerce(arm_ty, ret_ty)
|
self.can_coerce(arm_ty, ret_ty)
|
||||||
&& prior_arm.map_or(true, |(_, ty, _)| self.can_coerce(ty, ret_ty))
|
&& prior_arm.is_none_or(|(_, ty, _)| self.can_coerce(ty, ret_ty))
|
||||||
// The match arms need to unify for the case of `impl Trait`.
|
// The match arms need to unify for the case of `impl Trait`.
|
||||||
&& !matches!(ret_ty.kind(), ty::Alias(ty::Opaque, ..))
|
&& !matches!(ret_ty.kind(), ty::Alias(ty::Opaque, ..))
|
||||||
}
|
}
|
||||||
|
|
|
@ -913,7 +913,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
|
||||||
if self
|
if self
|
||||||
.tcx
|
.tcx
|
||||||
.upvars_mentioned(closure_def_id_a.expect_local())
|
.upvars_mentioned(closure_def_id_a.expect_local())
|
||||||
.map_or(true, |u| u.is_empty()) =>
|
.is_none_or(|u| u.is_empty()) =>
|
||||||
{
|
{
|
||||||
// We coerce the closure, which has fn type
|
// We coerce the closure, which has fn type
|
||||||
// `extern "rust-call" fn((arg0,arg1,...)) -> _`
|
// `extern "rust-call" fn((arg0,arg1,...)) -> _`
|
||||||
|
|
|
@ -1557,7 +1557,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
|
|
||||||
// If the length is 0, we don't create any elements, so we don't copy any. If the length is 1, we
|
// If the length is 0, we don't create any elements, so we don't copy any. If the length is 1, we
|
||||||
// don't copy that one element, we move it. Only check for Copy if the length is larger.
|
// don't copy that one element, we move it. Only check for Copy if the length is larger.
|
||||||
if count.try_eval_target_usize(tcx, self.param_env).map_or(true, |len| len > 1) {
|
if count.try_eval_target_usize(tcx, self.param_env).is_none_or(|len| len > 1) {
|
||||||
let lang_item = self.tcx.require_lang_item(LangItem::Copy, None);
|
let lang_item = self.tcx.require_lang_item(LangItem::Copy, None);
|
||||||
let code = traits::ObligationCauseCode::RepeatElementCopy {
|
let code = traits::ObligationCauseCode::RepeatElementCopy {
|
||||||
is_constable,
|
is_constable,
|
||||||
|
|
|
@ -2240,7 +2240,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
for (idx, (generic_param, param)) in
|
for (idx, (generic_param, param)) in
|
||||||
params_with_generics.iter().enumerate().filter(|(idx, _)| {
|
params_with_generics.iter().enumerate().filter(|(idx, _)| {
|
||||||
check_for_matched_generics
|
check_for_matched_generics
|
||||||
|| expected_idx.map_or(true, |expected_idx| expected_idx == *idx)
|
|| expected_idx.is_none_or(|expected_idx| expected_idx == *idx)
|
||||||
})
|
})
|
||||||
{
|
{
|
||||||
let Some(generic_param) = generic_param else {
|
let Some(generic_param) = generic_param else {
|
||||||
|
|
|
@ -440,7 +440,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
};
|
};
|
||||||
// Given `Result<_, E>`, check our expected ty is `Result<_, &E>` for
|
// Given `Result<_, E>`, check our expected ty is `Result<_, &E>` for
|
||||||
// `as_ref` and `as_deref` compatibility.
|
// `as_ref` and `as_deref` compatibility.
|
||||||
let error_tys_equate_as_ref = error_tys.map_or(true, |(found, expected)| {
|
let error_tys_equate_as_ref = error_tys.is_none_or(|(found, expected)| {
|
||||||
self.can_eq(
|
self.can_eq(
|
||||||
self.param_env,
|
self.param_env,
|
||||||
Ty::new_imm_ref(self.tcx, self.tcx.lifetimes.re_erased, found),
|
Ty::new_imm_ref(self.tcx, self.tcx.lifetimes.re_erased, found),
|
||||||
|
@ -492,7 +492,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
&& Some(adt.did()) == self.tcx.lang_items().string()
|
&& Some(adt.did()) == self.tcx.lang_items().string()
|
||||||
&& peeled.is_str()
|
&& peeled.is_str()
|
||||||
// `Result::map`, conversely, does not take ref of the error type.
|
// `Result::map`, conversely, does not take ref of the error type.
|
||||||
&& error_tys.map_or(true, |(found, expected)| {
|
&& error_tys.is_none_or(|(found, expected)| {
|
||||||
self.can_eq(self.param_env, found, expected)
|
self.can_eq(self.param_env, found, expected)
|
||||||
})
|
})
|
||||||
{
|
{
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#![feature(box_patterns)]
|
#![feature(box_patterns)]
|
||||||
#![feature(control_flow_enum)]
|
#![feature(control_flow_enum)]
|
||||||
#![feature(if_let_guard)]
|
#![feature(if_let_guard)]
|
||||||
|
#![feature(is_none_or)]
|
||||||
#![feature(let_chains)]
|
#![feature(let_chains)]
|
||||||
#![feature(never_type)]
|
#![feature(never_type)]
|
||||||
#![feature(try_blocks)]
|
#![feature(try_blocks)]
|
||||||
|
|
|
@ -654,6 +654,32 @@ impl<T> Option<T> {
|
||||||
!self.is_some()
|
!self.is_some()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns `true` if the option is a [`None`] or the value inside of it matches a predicate.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// #![feature(is_none_or)]
|
||||||
|
///
|
||||||
|
/// let x: Option<u32> = Some(2);
|
||||||
|
/// assert_eq!(x.is_none_or(|x| x > 1), true);
|
||||||
|
///
|
||||||
|
/// let x: Option<u32> = Some(0);
|
||||||
|
/// assert_eq!(x.is_none_or(|x| x > 1), false);
|
||||||
|
///
|
||||||
|
/// let x: Option<u32> = None;
|
||||||
|
/// assert_eq!(x.is_none_or(|x| x > 1), true);
|
||||||
|
/// ```
|
||||||
|
#[must_use]
|
||||||
|
#[inline]
|
||||||
|
#[unstable(feature = "is_none_or", issue = "none")]
|
||||||
|
pub fn is_none_or(self, f: impl FnOnce(T) -> bool) -> bool {
|
||||||
|
match self {
|
||||||
|
None => true,
|
||||||
|
Some(x) => f(x),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////
|
||||||
// Adapter for working with references
|
// Adapter for working with references
|
||||||
/////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#![feature(lint_reasons)]
|
#![feature(lint_reasons)]
|
||||||
#![feature(trait_upcasting)]
|
#![feature(trait_upcasting)]
|
||||||
#![feature(strict_overflow_ops)]
|
#![feature(strict_overflow_ops)]
|
||||||
|
#![feature(is_none_or)]
|
||||||
// Configure clippy and other lints
|
// Configure clippy and other lints
|
||||||
#![allow(
|
#![allow(
|
||||||
clippy::collapsible_else_if,
|
clippy::collapsible_else_if,
|
||||||
|
|
|
@ -396,12 +396,12 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
||||||
// If the newly promised alignment is bigger than the native alignment of this
|
// If the newly promised alignment is bigger than the native alignment of this
|
||||||
// allocation, and bigger than the previously promised alignment, then set it.
|
// allocation, and bigger than the previously promised alignment, then set it.
|
||||||
if align > alloc_align
|
if align > alloc_align
|
||||||
&& !this
|
&& this
|
||||||
.machine
|
.machine
|
||||||
.symbolic_alignment
|
.symbolic_alignment
|
||||||
.get_mut()
|
.get_mut()
|
||||||
.get(&alloc_id)
|
.get(&alloc_id)
|
||||||
.is_some_and(|&(_, old_align)| align <= old_align)
|
.is_none_or(|&(_, old_align)| align > old_align)
|
||||||
{
|
{
|
||||||
this.machine.symbolic_alignment.get_mut().insert(alloc_id, (offset, align));
|
this.machine.symbolic_alignment.get_mut().insert(alloc_id, (offset, align));
|
||||||
}
|
}
|
||||||
|
|
|
@ -1387,6 +1387,7 @@ fn generic_args_sans_defaults<'ga>(
|
||||||
}
|
}
|
||||||
// otherwise, if the arg is equal to the param default, hide it (unless the
|
// otherwise, if the arg is equal to the param default, hide it (unless the
|
||||||
// default is an error which can happen for the trait Self type)
|
// default is an error which can happen for the trait Self type)
|
||||||
|
#[allow(unstable_name_collisions)]
|
||||||
default_parameters.get(i).is_none_or(|default_parameter| {
|
default_parameters.get(i).is_none_or(|default_parameter| {
|
||||||
// !is_err(default_parameter.skip_binders())
|
// !is_err(default_parameter.skip_binders())
|
||||||
// &&
|
// &&
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue