Skip to content

Commit 795df65

Browse files
committed
Additional NonZero conversions
1 parent db5704f commit 795df65

File tree

1 file changed

+137
-2
lines changed

1 file changed

+137
-2
lines changed

library/core/src/num/nonzero.rs

+137-2
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
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::cmp::Ordering;
55
use crate::hash::{Hash, Hasher};
66
use crate::marker::{Freeze, StructuralPartialEq};
77
use crate::ops::{BitOr, BitOrAssign, Div, DivAssign, Neg, Rem, RemAssign};
88
use crate::panic::{RefUnwindSafe, UnwindSafe};
99
use crate::str::FromStr;
10-
use crate::{fmt, hint, intrinsics, ptr, ub_checks};
10+
use crate::{fmt, hint, intrinsics, ptr, slice, ub_checks};
1111

1212
/// A marker trait for primitive types which can be zero.
1313
///
@@ -273,6 +273,77 @@ where
273273
}
274274
}
275275

276+
#[stable(feature = "more_from_nonzero", since = "CURRENT_RUSTC_VERSION")]
277+
impl<'a, T> From<&'a NonZero<T>> for &'a T
278+
where
279+
T: ZeroablePrimitive,
280+
{
281+
#[inline]
282+
fn from(nonzero: &'a NonZero<T>) -> &'a T {
283+
nonzero.as_ref()
284+
}
285+
}
286+
287+
#[stable(feature = "more_from_nonzero", since = "CURRENT_RUSTC_VERSION")]
288+
impl<'a, T> From<&'a [NonZero<T>]> for &'a [T]
289+
where
290+
T: ZeroablePrimitive,
291+
{
292+
#[inline]
293+
fn from(nonzero: &'a [NonZero<T>]) -> &'a [T] {
294+
nonzero.as_zeroable()
295+
}
296+
}
297+
298+
#[stable(feature = "more_from_nonzero", since = "CURRENT_RUSTC_VERSION")]
299+
impl<T, const N: usize> From<[NonZero<T>; N]> for [T; N]
300+
where
301+
T: ZeroablePrimitive,
302+
{
303+
#[inline]
304+
fn from(nonzero: [NonZero<T>; N]) -> [T; N] {
305+
nonzero.into_zeroable()
306+
}
307+
}
308+
309+
#[stable(feature = "more_from_nonzero", since = "CURRENT_RUSTC_VERSION")]
310+
impl<'a, T> TryFrom<&'a T> for &'a NonZero<T>
311+
where
312+
T: ZeroablePrimitive,
313+
{
314+
type Error = TryFromIntError;
315+
316+
#[inline]
317+
fn try_from(zeroable: &'a T) -> Result<&'a NonZero<T>, TryFromIntError> {
318+
NonZero::from_ref(zeroable).ok_or(TryFromIntError(()))
319+
}
320+
}
321+
322+
#[stable(feature = "more_from_nonzero", since = "CURRENT_RUSTC_VERSION")]
323+
impl<'a, T> TryFrom<&'a [T]> for &'a [NonZero<T>]
324+
where
325+
T: ZeroablePrimitive,
326+
{
327+
type Error = TryFromIntError;
328+
329+
#[inline]
330+
fn try_from(zeroable: &'a [T]) -> Result<&'a [NonZero<T>], TryFromIntError> {
331+
NonZero::from_slice(zeroable).ok_or(TryFromIntError(()))
332+
}
333+
}
334+
335+
#[stable(feature = "more_from_nonzero", since = "CURRENT_RUSTC_VERSION")]
336+
impl<T, const N: usize> TryFrom<[T; N]> for [NonZero<T>; N]
337+
where
338+
T: ZeroablePrimitive,
339+
{
340+
type Error = TryFromIntError;
341+
342+
#[inline]
343+
fn try_from(zeroable: [T; N]) -> Result<[NonZero<T>; N], TryFromIntError> {
344+
NonZero::from_array(zeroable).ok_or(TryFromIntError(()))
345+
}
346+
}
276347
#[stable(feature = "nonzero_bitor", since = "1.45.0")]
277348
impl<T> BitOr for NonZero<T>
278349
where
@@ -421,6 +492,45 @@ where
421492
}
422493
}
423494

495+
/// Implementation of `From<&NonZero<T>> for &T`.
496+
#[must_use]
497+
#[inline]
498+
fn as_ref(&self) -> &T {
499+
// SAFETY: `repr(transparent)` ensures that `NonZero<T>` has same layout as `T`
500+
unsafe { &*(ptr::from_ref(self).cast::<T>()) }
501+
}
502+
503+
/// Implementation of `TryFrom<&T> for &NonZero<T>`.
504+
#[must_use]
505+
#[inline]
506+
fn from_ref(n: &T) -> Option<&Self> {
507+
// SAFETY: Memory layout optimization guarantees that `Option<NonZero<T>>` has
508+
// the same layout and size as `T`, with `0` representing `None`.
509+
let opt_n = unsafe { &*(ptr::from_ref(n).cast::<Option<Self>>()) };
510+
511+
opt_n.as_ref()
512+
}
513+
514+
/// Implementation of `TryFrom<&[T]> for &[NonZero<T>]`.
515+
#[must_use]
516+
#[inline]
517+
fn from_slice(n: &[T]) -> Option<&[Self]> {
518+
if n.iter().all(|x| NonZero::new(*x).is_some()) {
519+
// SAFETY: We explicitly checked that all elements are nonzero, and because of `repr(transparent)`
520+
// the layout remains unchanged
521+
Some(unsafe { &*(slice::from_raw_parts(n.as_ptr().cast::<NonZero<T>>(), n.len())) })
522+
} else {
523+
None
524+
}
525+
}
526+
527+
/// Implementation of `TryFrom<[T; N]> for [NonZero<T>; N]`.
528+
#[must_use]
529+
#[inline]
530+
fn from_array<const N: usize>(n: [T; N]) -> Option<[Self; N]> {
531+
n.try_map(NonZero::new)
532+
}
533+
424534
/// Returns the contained value as a primitive type.
425535
#[stable(feature = "nonzero", since = "1.28.0")]
426536
#[rustc_const_stable(feature = "const_nonzero_get", since = "1.34.0")]
@@ -441,6 +551,31 @@ where
441551
unsafe { intrinsics::transmute_unchecked(self) }
442552
}
443553
}
554+
impl<T> [NonZero<T>]
555+
where
556+
T: ZeroablePrimitive,
557+
{
558+
/// Implementation of `From<&[NonZero<T>]> for &[T]`.
559+
#[must_use]
560+
#[inline]
561+
fn as_zeroable(&self) -> &[T] {
562+
// SAFETY: `repr(transparent)` ensures that `NonZero<T>` has same layout as `T`, and thus
563+
// `[NonZero<T>]` has same layout as `[T]`
564+
unsafe { &*(slice::from_raw_parts(self.as_ptr().cast::<T>(), self.len())) }
565+
}
566+
}
567+
568+
impl<T, const N: usize> [NonZero<T>; N]
569+
where
570+
T: ZeroablePrimitive,
571+
{
572+
/// Implementation of `From<[NonZero<T>; N]> for [T; N]`.
573+
#[must_use]
574+
#[inline]
575+
fn into_zeroable(self) -> [T; N] {
576+
self.map(NonZero::get)
577+
}
578+
}
444579

445580
macro_rules! nonzero_integer {
446581
(

0 commit comments

Comments
 (0)