11//! Definitions of integer that is known not to equal zero.
22
3- use super :: { IntErrorKind , ParseIntError } ;
3+ use super :: { IntErrorKind , ParseIntError , TryFromIntError } ;
44use crate :: clone:: { TrivialClone , UseCloned } ;
55use crate :: cmp:: Ordering ;
66use crate :: hash:: { Hash , Hasher } ;
77use crate :: marker:: { Destruct , Freeze , StructuralPartialEq } ;
88use crate :: ops:: { BitOr , BitOrAssign , Div , DivAssign , Neg , Rem , RemAssign } ;
99use crate :: panic:: { RefUnwindSafe , UnwindSafe } ;
1010use 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" ) ]
323414impl <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
503658macro_rules! nonzero_integer {
504659 (
0 commit comments