Skip to content

Commit 8c4d96e

Browse files
committed
Additional NonZero conversions
1 parent dfbfbf7 commit 8c4d96e

1 file changed

Lines changed: 157 additions & 2 deletions

File tree

library/core/src/num/nonzero.rs

Lines changed: 157 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
//! Definitions of integer that is known not to equal zero.
22
3-
use super::{IntErrorKind, ParseIntError};
3+
use super::{IntErrorKind, ParseIntError, TryFromIntError};
44
use crate::clone::{TrivialClone, UseCloned};
55
use crate::cmp::Ordering;
66
use crate::hash::{Hash, Hasher};
77
use crate::marker::{Destruct, Freeze, StructuralPartialEq};
88
use crate::ops::{BitOr, BitOrAssign, Div, DivAssign, Neg, Rem, RemAssign};
99
use crate::panic::{RefUnwindSafe, UnwindSafe};
1010
use crate::str::FromStr;
11-
use crate::{fmt, intrinsics, ptr, ub_checks};
11+
use crate::{fmt, intrinsics, ptr, slice, ub_checks};
1212

1313
/// A marker trait for primitive types which can be zero.
1414
///
@@ -318,6 +318,97 @@ where
318318
}
319319
}
320320

321+
#[stable(feature = "more_from_nonzero", since = "CURRENT_RUSTC_VERSION")]
322+
impl<'a, T> From<&'a NonZero<T>> for &'a T
323+
where
324+
T: ZeroablePrimitive,
325+
{
326+
#[inline]
327+
fn from(nonzero: &'a NonZero<T>) -> &'a T {
328+
nonzero.as_ref()
329+
}
330+
}
331+
332+
#[stable(feature = "more_from_nonzero", since = "CURRENT_RUSTC_VERSION")]
333+
impl<'a, T> From<&'a [NonZero<T>]> for &'a [T]
334+
where
335+
T: ZeroablePrimitive,
336+
{
337+
#[inline]
338+
fn from(nonzero: &'a [NonZero<T>]) -> &'a [T] {
339+
nonzero.as_zeroable()
340+
}
341+
}
342+
343+
#[stable(feature = "more_from_nonzero", since = "CURRENT_RUSTC_VERSION")]
344+
impl<T, const N: usize> From<[NonZero<T>; N]> for [T; N]
345+
where
346+
T: ZeroablePrimitive,
347+
{
348+
#[inline]
349+
fn from(nonzero: [NonZero<T>; N]) -> [T; N] {
350+
nonzero.into_zeroable()
351+
}
352+
}
353+
354+
// FIXME: can't detect that ZeroablePrimitive is a sealed trait
355+
macro_rules! impl_ref_try_from {
356+
($($t:ty),* $(,)?) => {
357+
$(
358+
#[stable(feature = "more_from_nonzero", since = "CURRENT_RUSTC_VERSION")]
359+
impl<'a> TryFrom<&'a $t> for &'a NonZero<$t> {
360+
type Error = TryFromIntError;
361+
362+
#[inline]
363+
fn try_from(zeroable: &'a $t) -> Result<&'a NonZero<$t>, TryFromIntError> {
364+
NonZero::from_ref(zeroable).ok_or(TryFromIntError(()))
365+
}
366+
}
367+
)*
368+
}
369+
}
370+
371+
impl_ref_try_from! {
372+
u8,
373+
u16,
374+
u32,
375+
u64,
376+
u128,
377+
usize,
378+
i8,
379+
i16,
380+
i32,
381+
i64,
382+
i128,
383+
isize,
384+
char,
385+
}
386+
387+
#[stable(feature = "more_from_nonzero", since = "CURRENT_RUSTC_VERSION")]
388+
impl<'a, T> TryFrom<&'a [T]> for &'a [NonZero<T>]
389+
where
390+
T: ZeroablePrimitive,
391+
{
392+
type Error = TryFromIntError;
393+
394+
#[inline]
395+
fn try_from(zeroable: &'a [T]) -> Result<&'a [NonZero<T>], TryFromIntError> {
396+
NonZero::from_slice(zeroable).ok_or(TryFromIntError(()))
397+
}
398+
}
399+
400+
#[stable(feature = "more_from_nonzero", since = "CURRENT_RUSTC_VERSION")]
401+
impl<T, const N: usize> TryFrom<[T; N]> for [NonZero<T>; N]
402+
where
403+
T: ZeroablePrimitive,
404+
{
405+
type Error = TryFromIntError;
406+
407+
#[inline]
408+
fn try_from(zeroable: [T; N]) -> Result<[NonZero<T>; N], TryFromIntError> {
409+
NonZero::from_array(zeroable).ok_or(TryFromIntError(()))
410+
}
411+
}
321412
#[stable(feature = "nonzero_bitor", since = "1.45.0")]
322413
#[rustc_const_unstable(feature = "const_ops", issue = "143802")]
323414
impl<T> const BitOr for NonZero<T>
@@ -473,6 +564,45 @@ where
473564
}
474565
}
475566

567+
/// Implementation of `From<&NonZero<T>> for &T`.
568+
#[must_use]
569+
#[inline]
570+
fn as_ref(&self) -> &T {
571+
// SAFETY: `repr(transparent)` ensures that `NonZero<T>` has same layout as `T`
572+
unsafe { &*(ptr::from_ref(self).cast::<T>()) }
573+
}
574+
575+
/// Implementation of `TryFrom<&T> for &NonZero<T>`.
576+
#[must_use]
577+
#[inline]
578+
fn from_ref(n: &T) -> Option<&Self> {
579+
// SAFETY: Memory layout optimization guarantees that `Option<NonZero<T>>` has
580+
// the same layout and size as `T`, with `0` representing `None`.
581+
let opt_n = unsafe { &*(ptr::from_ref(n).cast::<Option<Self>>()) };
582+
583+
opt_n.as_ref()
584+
}
585+
586+
/// Implementation of `TryFrom<&[T]> for &[NonZero<T>]`.
587+
#[must_use]
588+
#[inline]
589+
fn from_slice(n: &[T]) -> Option<&[Self]> {
590+
if n.iter().all(|x| NonZero::new(*x).is_some()) {
591+
// SAFETY: We explicitly checked that all elements are nonzero, and because of `repr(transparent)`
592+
// the layout remains unchanged
593+
Some(unsafe { &*(slice::from_raw_parts(n.as_ptr().cast::<NonZero<T>>(), n.len())) })
594+
} else {
595+
None
596+
}
597+
}
598+
599+
/// Implementation of `TryFrom<[T; N]> for [NonZero<T>; N]`.
600+
#[must_use]
601+
#[inline]
602+
fn from_array<const N: usize>(n: [T; N]) -> Option<[Self; N]> {
603+
n.try_map(NonZero::new)
604+
}
605+
476606
/// Returns the contained value as a primitive type.
477607
#[stable(feature = "nonzero", since = "1.28.0")]
478608
#[rustc_const_stable(feature = "const_nonzero_get", since = "1.34.0")]
@@ -499,6 +629,31 @@ where
499629
unsafe { intrinsics::transmute_unchecked(self) }
500630
}
501631
}
632+
impl<T> [NonZero<T>]
633+
where
634+
T: ZeroablePrimitive,
635+
{
636+
/// Implementation of `From<&[NonZero<T>]> for &[T]`.
637+
#[must_use]
638+
#[inline]
639+
fn as_zeroable(&self) -> &[T] {
640+
// SAFETY: `repr(transparent)` ensures that `NonZero<T>` has same layout as `T`, and thus
641+
// `[NonZero<T>]` has same layout as `[T]`
642+
unsafe { &*(slice::from_raw_parts(self.as_ptr().cast::<T>(), self.len())) }
643+
}
644+
}
645+
646+
impl<T, const N: usize> [NonZero<T>; N]
647+
where
648+
T: ZeroablePrimitive,
649+
{
650+
/// Implementation of `From<[NonZero<T>; N]> for [T; N]`.
651+
#[must_use]
652+
#[inline]
653+
fn into_zeroable(self) -> [T; N] {
654+
self.map(NonZero::get)
655+
}
656+
}
502657

503658
macro_rules! nonzero_integer {
504659
(

0 commit comments

Comments
 (0)