Skip to main content

core/convert/
num.rs

1use crate::num::TryFromIntError;
2
3#[cfg(not(feature = "ferrocene_subset"))]
4mod private {
5    /// This trait being unreachable from outside the crate
6    /// prevents other implementations of the `FloatToInt` trait,
7    /// which allows potentially adding more trait methods after the trait is `#[stable]`.
8    #[unstable(feature = "convert_float_to_int", issue = "67057")]
9    pub trait Sealed {}
10}
11
12/// Supporting trait for inherent methods of `f32` and `f64` such as `to_int_unchecked`.
13/// Typically doesn’t need to be used directly.
14#[cfg(not(feature = "ferrocene_subset"))]
15#[unstable(feature = "convert_float_to_int", issue = "67057")]
16pub trait FloatToInt<Int>: private::Sealed + Sized {
17    #[unstable(feature = "convert_float_to_int", issue = "67057")]
18    #[doc(hidden)]
19    unsafe fn to_int_unchecked(self) -> Int;
20}
21
22#[cfg(not(feature = "ferrocene_subset"))]
23macro_rules! impl_float_to_int {
24    ($Float:ty => $($Int:ty),+) => {
25        #[unstable(feature = "convert_float_to_int", issue = "67057")]
26        impl private::Sealed for $Float {}
27        $(
28            #[unstable(feature = "convert_float_to_int", issue = "67057")]
29            impl FloatToInt<$Int> for $Float {
30                #[inline]
31                unsafe fn to_int_unchecked(self) -> $Int {
32                    // SAFETY: the safety contract must be upheld by the caller.
33                    unsafe { crate::intrinsics::float_to_int_unchecked(self) }
34                }
35            }
36        )+
37    }
38}
39
40#[cfg(not(feature = "ferrocene_subset"))]
41impl_float_to_int!(f16 => u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize);
42#[cfg(not(feature = "ferrocene_subset"))]
43impl_float_to_int!(f32 => u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize);
44#[cfg(not(feature = "ferrocene_subset"))]
45impl_float_to_int!(f64 => u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize);
46#[cfg(not(feature = "ferrocene_subset"))]
47impl_float_to_int!(f128 => u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize);
48
49/// Implement `From<bool>` for integers
50macro_rules! impl_from_bool {
51    ($($int:ty)*) => {$(
52        #[stable(feature = "from_bool", since = "1.28.0")]
53        #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
54        impl const From<bool> for $int {
55            /// Converts from [`bool`] to
56            #[doc = concat!("[`", stringify!($int), "`]")]
57            /// , by turning `false` into `0` and `true` into `1`.
58            ///
59            /// # Examples
60            ///
61            /// ```
62            #[doc = concat!("assert_eq!(", stringify!($int), "::from(false), 0);")]
63            ///
64            #[doc = concat!("assert_eq!(", stringify!($int), "::from(true), 1);")]
65            /// ```
66            #[inline(always)]
67            fn from(b: bool) -> Self {
68                b as Self
69            }
70        }
71    )*}
72}
73
74// boolean -> integer
75impl_from_bool!(u8 u16 u32 u64 u128 usize);
76impl_from_bool!(i8 i16 i32 i64 i128 isize);
77
78/// Implement `From<$small>` for `$large`
79macro_rules! impl_from {
80    ($small:ty => $large:ty, #[$attr:meta]) => {
81        #[$attr]
82        #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
83        impl const From<$small> for $large {
84            #[doc = concat!("Converts from [`", stringify!($small), "`] to [`", stringify!($large), "`] losslessly.")]
85            #[inline(always)]
86            fn from(small: $small) -> Self {
87                debug_assert!(<$large>::MIN as i128 <= <$small>::MIN as i128);
88                debug_assert!(<$small>::MAX as u128 <= <$large>::MAX as u128);
89                small as Self
90            }
91        }
92    }
93}
94
95// unsigned integer -> unsigned integer
96impl_from!(u8 => u16, #[stable(feature = "lossless_int_conv", since = "1.5.0")]);
97impl_from!(u8 => u32, #[stable(feature = "lossless_int_conv", since = "1.5.0")]);
98impl_from!(u8 => u64, #[stable(feature = "lossless_int_conv", since = "1.5.0")]);
99impl_from!(u8 => u128, #[stable(feature = "i128", since = "1.26.0")]);
100impl_from!(u8 => usize, #[stable(feature = "lossless_int_conv", since = "1.5.0")]);
101impl_from!(u16 => u32, #[stable(feature = "lossless_int_conv", since = "1.5.0")]);
102impl_from!(u16 => u64, #[stable(feature = "lossless_int_conv", since = "1.5.0")]);
103impl_from!(u16 => u128, #[stable(feature = "i128", since = "1.26.0")]);
104impl_from!(u32 => u64, #[stable(feature = "lossless_int_conv", since = "1.5.0")]);
105impl_from!(u32 => u128, #[stable(feature = "i128", since = "1.26.0")]);
106impl_from!(u64 => u128, #[stable(feature = "i128", since = "1.26.0")]);
107
108// signed integer -> signed integer
109impl_from!(i8 => i16, #[stable(feature = "lossless_int_conv", since = "1.5.0")]);
110impl_from!(i8 => i32, #[stable(feature = "lossless_int_conv", since = "1.5.0")]);
111impl_from!(i8 => i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")]);
112impl_from!(i8 => i128, #[stable(feature = "i128", since = "1.26.0")]);
113impl_from!(i8 => isize, #[stable(feature = "lossless_int_conv", since = "1.5.0")]);
114impl_from!(i16 => i32, #[stable(feature = "lossless_int_conv", since = "1.5.0")]);
115impl_from!(i16 => i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")]);
116impl_from!(i16 => i128, #[stable(feature = "i128", since = "1.26.0")]);
117impl_from!(i32 => i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")]);
118impl_from!(i32 => i128, #[stable(feature = "i128", since = "1.26.0")]);
119impl_from!(i64 => i128, #[stable(feature = "i128", since = "1.26.0")]);
120
121// unsigned integer -> signed integer
122#[cfg(not(feature = "ferrocene_subset"))]
123impl_from!(u8 => i16, #[stable(feature = "lossless_int_conv", since = "1.5.0")]);
124#[cfg(not(feature = "ferrocene_subset"))]
125impl_from!(u8 => i32, #[stable(feature = "lossless_int_conv", since = "1.5.0")]);
126#[cfg(not(feature = "ferrocene_subset"))]
127impl_from!(u8 => i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")]);
128#[cfg(not(feature = "ferrocene_subset"))]
129impl_from!(u8 => i128, #[stable(feature = "i128", since = "1.26.0")]);
130#[cfg(not(feature = "ferrocene_subset"))]
131impl_from!(u16 => i32, #[stable(feature = "lossless_int_conv", since = "1.5.0")]);
132#[cfg(not(feature = "ferrocene_subset"))]
133impl_from!(u16 => i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")]);
134#[cfg(not(feature = "ferrocene_subset"))]
135impl_from!(u16 => i128, #[stable(feature = "i128", since = "1.26.0")]);
136#[cfg(not(feature = "ferrocene_subset"))]
137impl_from!(u32 => i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")]);
138#[cfg(not(feature = "ferrocene_subset"))]
139impl_from!(u32 => i128, #[stable(feature = "i128", since = "1.26.0")]);
140#[cfg(not(feature = "ferrocene_subset"))]
141impl_from!(u64 => i128, #[stable(feature = "i128", since = "1.26.0")]);
142
143// The C99 standard defines bounds on INTPTR_MIN, INTPTR_MAX, and UINTPTR_MAX
144// which imply that pointer-sized integers must be at least 16 bits:
145// https://port70.net/~nsz/c/c99/n1256.html#7.18.2.4
146impl_from!(u16 => usize, #[stable(feature = "lossless_iusize_conv", since = "1.26.0")]);
147impl_from!(u8 => isize, #[stable(feature = "lossless_iusize_conv", since = "1.26.0")]);
148impl_from!(i16 => isize, #[stable(feature = "lossless_iusize_conv", since = "1.26.0")]);
149
150// RISC-V defines the possibility of a 128-bit address space (RV128).
151
152// CHERI proposes 128-bit “capabilities”. Unclear if this would be relevant to usize/isize.
153// https://www.cl.cam.ac.uk/research/security/ctsrd/pdfs/20171017a-cheri-poster.pdf
154// https://www.cl.cam.ac.uk/techreports/UCAM-CL-TR-951.pdf
155
156// Note: integers can only be represented with full precision in a float if
157// they fit in the significand, which is:
158// * 11 bits in f16
159// * 24 bits in f32
160// * 53 bits in f64
161// * 113 bits in f128
162// Lossy float conversions are not implemented at this time.
163// FIXME(f16,f128): The `f16`/`f128` impls `#[stable]` attributes should be changed to reference
164// `f16`/`f128` when they are stabilised (trait impls have to have a `#[stable]` attribute, but none
165// of the `f16`/`f128` impls can be used on stable as the `f16` and `f128` types are unstable).
166
167// signed integer -> float
168#[cfg(not(feature = "ferrocene_subset"))]
169impl_from!(i8 => f16, #[stable(feature = "lossless_float_conv", since = "1.6.0")]);
170#[cfg(not(feature = "ferrocene_subset"))]
171impl_from!(i8 => f32, #[stable(feature = "lossless_float_conv", since = "1.6.0")]);
172#[cfg(not(feature = "ferrocene_subset"))]
173impl_from!(i8 => f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")]);
174#[cfg(not(feature = "ferrocene_subset"))]
175impl_from!(i8 => f128, #[stable(feature = "lossless_float_conv", since = "1.6.0")]);
176#[cfg(not(feature = "ferrocene_subset"))]
177impl_from!(i16 => f32, #[stable(feature = "lossless_float_conv", since = "1.6.0")]);
178#[cfg(not(feature = "ferrocene_subset"))]
179impl_from!(i16 => f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")]);
180#[cfg(not(feature = "ferrocene_subset"))]
181impl_from!(i16 => f128, #[stable(feature = "lossless_float_conv", since = "1.6.0")]);
182#[cfg(not(feature = "ferrocene_subset"))]
183impl_from!(i32 => f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")]);
184#[cfg(not(feature = "ferrocene_subset"))]
185impl_from!(i32 => f128, #[stable(feature = "lossless_float_conv", since = "1.6.0")]);
186// FIXME(f128): This impl would allow using `f128` on stable before it is stabilised.
187// impl_from!(i64 => f128, #[stable(feature = "lossless_float_conv", since = "1.6.0")]);
188
189// unsigned integer -> float
190#[cfg(not(feature = "ferrocene_subset"))]
191impl_from!(u8 => f16, #[stable(feature = "lossless_float_conv", since = "1.6.0")]);
192#[cfg(not(feature = "ferrocene_subset"))]
193impl_from!(u8 => f32, #[stable(feature = "lossless_float_conv", since = "1.6.0")]);
194#[cfg(not(feature = "ferrocene_subset"))]
195impl_from!(u8 => f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")]);
196#[cfg(not(feature = "ferrocene_subset"))]
197impl_from!(u8 => f128, #[stable(feature = "lossless_float_conv", since = "1.6.0")]);
198#[cfg(not(feature = "ferrocene_subset"))]
199impl_from!(u16 => f32, #[stable(feature = "lossless_float_conv", since = "1.6.0")]);
200#[cfg(not(feature = "ferrocene_subset"))]
201impl_from!(u16 => f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")]);
202#[cfg(not(feature = "ferrocene_subset"))]
203impl_from!(u16 => f128, #[stable(feature = "lossless_float_conv", since = "1.6.0")]);
204#[cfg(not(feature = "ferrocene_subset"))]
205impl_from!(u32 => f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")]);
206#[cfg(not(feature = "ferrocene_subset"))]
207impl_from!(u32 => f128, #[stable(feature = "lossless_float_conv", since = "1.6.0")]);
208// FIXME(f128): This impl would allow using `f128` on stable before it is stabilised.
209// impl_from!(u64 => f128, #[stable(feature = "lossless_float_conv", since = "1.6.0")]);
210
211// float -> float
212// FIXME(f16,f128): adding additional `From<{float}>` impls to `f32` breaks inference. See
213// <https://github.com/rust-lang/rust/issues/123831>
214#[cfg(not(feature = "ferrocene_subset"))]
215impl_from!(f16 => f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")]);
216#[cfg(not(feature = "ferrocene_subset"))]
217impl_from!(f16 => f128, #[stable(feature = "lossless_float_conv", since = "1.6.0")]);
218#[cfg(not(feature = "ferrocene_subset"))]
219impl_from!(f32 => f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")]);
220#[cfg(not(feature = "ferrocene_subset"))]
221impl_from!(f32 => f128, #[stable(feature = "lossless_float_conv", since = "1.6.0")]);
222#[cfg(not(feature = "ferrocene_subset"))]
223impl_from!(f64 => f128, #[stable(feature = "lossless_float_conv", since = "1.6.0")]);
224
225#[cfg(not(feature = "ferrocene_subset"))]
226macro_rules! impl_float_from_bool {
227    (
228        $float:ty $(;
229            doctest_prefix: $(#[doc = $doctest_prefix:literal])*
230            doctest_suffix: $(#[doc = $doctest_suffix:literal])*
231        )?
232    ) => {
233        #[stable(feature = "float_from_bool", since = "1.68.0")]
234        #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
235            impl const From<bool> for $float {
236            #[doc = concat!("Converts a [`bool`] to [`", stringify!($float),"`] losslessly.")]
237            /// The resulting value is positive `0.0` for `false` and `1.0` for `true` values.
238            ///
239            /// # Examples
240            /// ```
241            $($(#[doc = $doctest_prefix])*)?
242            #[doc = concat!("let x: ", stringify!($float)," = false.into();")]
243            /// assert_eq!(x, 0.0);
244            /// assert!(x.is_sign_positive());
245            ///
246            #[doc = concat!("let y: ", stringify!($float)," = true.into();")]
247            /// assert_eq!(y, 1.0);
248            $($(#[doc = $doctest_suffix])*)?
249            /// ```
250            #[inline]
251            fn from(small: bool) -> Self {
252                small as u8 as Self
253            }
254        }
255    };
256}
257
258// boolean -> float
259#[cfg(not(feature = "ferrocene_subset"))]
260impl_float_from_bool!(
261    f16;
262    doctest_prefix:
263    // rustdoc doesn't remove the conventional space after the `///`
264    ///# #![allow(unused_features)]
265    ///#![feature(f16)]
266    ///# #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
267    ///
268    doctest_suffix:
269    ///# }
270);
271#[cfg(not(feature = "ferrocene_subset"))]
272impl_float_from_bool!(f32);
273#[cfg(not(feature = "ferrocene_subset"))]
274impl_float_from_bool!(f64);
275#[cfg(not(feature = "ferrocene_subset"))]
276impl_float_from_bool!(
277    f128;
278    doctest_prefix:
279    ///# #![allow(unused_features)]
280    ///#![feature(f128)]
281    ///# #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
282    ///
283    doctest_suffix:
284    ///# }
285);
286
287// no possible bounds violation
288macro_rules! impl_try_from_unbounded {
289    ($source:ty => $($target:ty),+) => {$(
290        #[stable(feature = "try_from", since = "1.34.0")]
291        #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
292        impl const TryFrom<$source> for $target {
293            type Error = TryFromIntError;
294
295            /// Tries to create the target number type from a source
296            /// number type. This returns an error if the source value
297            /// is outside of the range of the target type.
298            #[inline]
299            fn try_from(value: $source) -> Result<Self, Self::Error> {
300                Ok(value as Self)
301            }
302        }
303    )*}
304}
305
306// only negative bounds
307macro_rules! impl_try_from_lower_bounded {
308    ($source:ty => $($target:ty),+) => {$(
309        #[stable(feature = "try_from", since = "1.34.0")]
310        #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
311        impl const TryFrom<$source> for $target {
312            type Error = TryFromIntError;
313
314            /// Tries to create the target number type from a source
315            /// number type. This returns an error if the source value
316            /// is outside of the range of the target type.
317            #[inline]
318            fn try_from(u: $source) -> Result<Self, Self::Error> {
319                if u >= 0 {
320                    Ok(u as Self)
321                } else {
322                    Err(TryFromIntError(()))
323                }
324            }
325        }
326    )*}
327}
328
329// unsigned to signed (only positive bound)
330macro_rules! impl_try_from_upper_bounded {
331    ($source:ty => $($target:ty),+) => {$(
332        #[stable(feature = "try_from", since = "1.34.0")]
333        #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
334        impl const TryFrom<$source> for $target {
335            type Error = TryFromIntError;
336
337            /// Tries to create the target number type from a source
338            /// number type. This returns an error if the source value
339            /// is outside of the range of the target type.
340            #[inline]
341            fn try_from(u: $source) -> Result<Self, Self::Error> {
342                if u > (Self::MAX as $source) {
343                    Err(TryFromIntError(()))
344                } else {
345                    Ok(u as Self)
346                }
347            }
348        }
349    )*}
350}
351
352// all other cases
353macro_rules! impl_try_from_both_bounded {
354    ($source:ty => $($target:ty),+) => {$(
355        #[stable(feature = "try_from", since = "1.34.0")]
356        #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
357        impl const TryFrom<$source> for $target {
358            type Error = TryFromIntError;
359
360            /// Tries to create the target number type from a source
361            /// number type. This returns an error if the source value
362            /// is outside of the range of the target type.
363            #[inline]
364            fn try_from(u: $source) -> Result<Self, Self::Error> {
365                let min = Self::MIN as $source;
366                let max = Self::MAX as $source;
367                if u < min || u > max {
368                    Err(TryFromIntError(()))
369                } else {
370                    Ok(u as Self)
371                }
372            }
373        }
374    )*}
375}
376
377/// Implement `TryFrom<integer>` for `bool`
378macro_rules! impl_try_from_integer_for_bool {
379    ($($int:ty)+) => {$(
380        #[stable(feature = "try_from", since = "1.34.0")]
381        #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
382        impl const TryFrom<$int> for bool {
383            type Error = TryFromIntError;
384
385            /// Tries to create a bool from an integer type.
386            /// Returns an error if the integer is not 0 or 1.
387            ///
388            /// # Examples
389            ///
390            /// ```
391            #[doc = concat!("assert_eq!(0_", stringify!($int), ".try_into(), Ok(false));")]
392            ///
393            #[doc = concat!("assert_eq!(1_", stringify!($int), ".try_into(), Ok(true));")]
394            ///
395            #[doc = concat!("assert!(<", stringify!($int), " as TryInto<bool>>::try_into(2).is_err());")]
396            /// ```
397            #[inline]
398            fn try_from(i: $int) -> Result<Self, Self::Error> {
399                match i {
400                    0 => Ok(false),
401                    1 => Ok(true),
402                    _ => Err(TryFromIntError(())),
403                }
404            }
405        }
406    )*}
407}
408
409macro_rules! rev {
410    ($mac:ident, $source:ty => $($target:ty),+) => {$(
411        $mac!($target => $source);
412    )*}
413}
414
415// integer -> bool
416impl_try_from_integer_for_bool!(u128 u64 u32 u16 u8);
417impl_try_from_integer_for_bool!(i128 i64 i32 i16 i8);
418
419// unsigned integer -> unsigned integer
420impl_try_from_upper_bounded!(u16 => u8);
421impl_try_from_upper_bounded!(u32 => u8, u16);
422impl_try_from_upper_bounded!(u64 => u8, u16, u32);
423impl_try_from_upper_bounded!(u128 => u8, u16, u32, u64);
424
425// signed integer -> signed integer
426#[cfg(not(feature = "ferrocene_subset"))]
427impl_try_from_both_bounded!(i16 => i8);
428#[cfg(not(feature = "ferrocene_subset"))]
429impl_try_from_both_bounded!(i32 => i8, i16);
430#[cfg(not(feature = "ferrocene_subset"))]
431impl_try_from_both_bounded!(i64 => i8, i16, i32);
432#[cfg(not(feature = "ferrocene_subset"))]
433impl_try_from_both_bounded!(i128 => i8, i16, i32, i64);
434
435// unsigned integer -> signed integer
436#[cfg(not(feature = "ferrocene_subset"))]
437impl_try_from_upper_bounded!(u8 => i8);
438#[cfg(not(feature = "ferrocene_subset"))]
439impl_try_from_upper_bounded!(u16 => i8, i16);
440#[cfg(not(feature = "ferrocene_subset"))]
441impl_try_from_upper_bounded!(u32 => i8, i16, i32);
442#[cfg(not(feature = "ferrocene_subset"))]
443impl_try_from_upper_bounded!(u64 => i8, i16, i32, i64);
444#[cfg(not(feature = "ferrocene_subset"))]
445impl_try_from_upper_bounded!(u128 => i8, i16, i32, i64, i128);
446
447// signed integer -> unsigned integer
448#[cfg(not(feature = "ferrocene_subset"))]
449impl_try_from_lower_bounded!(i8 => u8, u16, u32, u64, u128);
450#[cfg(not(feature = "ferrocene_subset"))]
451impl_try_from_both_bounded!(i16 => u8);
452#[cfg(not(feature = "ferrocene_subset"))]
453impl_try_from_lower_bounded!(i16 => u16, u32, u64, u128);
454impl_try_from_both_bounded!(i32 => u8, u16);
455impl_try_from_lower_bounded!(i32 => u32, u64, u128);
456#[cfg(not(feature = "ferrocene_subset"))]
457impl_try_from_both_bounded!(i64 => u8, u16, u32);
458#[cfg(not(feature = "ferrocene_subset"))]
459impl_try_from_lower_bounded!(i64 => u64, u128);
460#[cfg(not(feature = "ferrocene_subset"))]
461impl_try_from_both_bounded!(i128 => u8, u16, u32, u64);
462#[cfg(not(feature = "ferrocene_subset"))]
463impl_try_from_lower_bounded!(i128 => u128);
464
465// usize/isize
466#[cfg(not(feature = "ferrocene_subset"))]
467impl_try_from_upper_bounded!(usize => isize);
468#[cfg(not(feature = "ferrocene_subset"))]
469impl_try_from_lower_bounded!(isize => usize);
470
471#[cfg(target_pointer_width = "16")]
472mod ptr_try_from_impls {
473    use super::TryFromIntError;
474
475    impl_try_from_upper_bounded!(usize => u8);
476    impl_try_from_unbounded!(usize => u16, u32, u64, u128);
477    #[cfg(not(feature = "ferrocene_subset"))]
478    impl_try_from_upper_bounded!(usize => i8, i16);
479    #[cfg(not(feature = "ferrocene_subset"))]
480    impl_try_from_unbounded!(usize => i32, i64, i128);
481
482    #[cfg(not(feature = "ferrocene_subset"))]
483    impl_try_from_both_bounded!(isize => u8);
484    #[cfg(not(feature = "ferrocene_subset"))]
485    impl_try_from_lower_bounded!(isize => u16, u32, u64, u128);
486    #[cfg(not(feature = "ferrocene_subset"))]
487    impl_try_from_both_bounded!(isize => i8);
488    #[cfg(not(feature = "ferrocene_subset"))]
489    impl_try_from_unbounded!(isize => i16, i32, i64, i128);
490
491    rev!(impl_try_from_upper_bounded, usize => u32, u64, u128);
492    rev!(impl_try_from_lower_bounded, usize => i8, i16);
493    rev!(impl_try_from_both_bounded, usize => i32, i64, i128);
494
495    #[cfg(not(feature = "ferrocene_subset"))]
496    rev!(impl_try_from_upper_bounded, isize => u16, u32, u64, u128);
497    #[cfg(not(feature = "ferrocene_subset"))]
498    rev!(impl_try_from_both_bounded, isize => i32, i64, i128);
499}
500
501#[cfg(target_pointer_width = "32")]
502mod ptr_try_from_impls {
503    use super::TryFromIntError;
504
505    impl_try_from_upper_bounded!(usize => u8, u16);
506    impl_try_from_unbounded!(usize => u32, u64, u128);
507    #[cfg(not(feature = "ferrocene_subset"))]
508    impl_try_from_upper_bounded!(usize => i8, i16, i32);
509    #[cfg(not(feature = "ferrocene_subset"))]
510    impl_try_from_unbounded!(usize => i64, i128);
511
512    #[cfg(not(feature = "ferrocene_subset"))]
513    impl_try_from_both_bounded!(isize => u8, u16);
514    #[cfg(not(feature = "ferrocene_subset"))]
515    impl_try_from_lower_bounded!(isize => u32, u64, u128);
516    #[cfg(not(feature = "ferrocene_subset"))]
517    impl_try_from_both_bounded!(isize => i8, i16);
518    #[cfg(not(feature = "ferrocene_subset"))]
519    impl_try_from_unbounded!(isize => i32, i64, i128);
520
521    rev!(impl_try_from_unbounded, usize => u32);
522    rev!(impl_try_from_upper_bounded, usize => u64, u128);
523    rev!(impl_try_from_lower_bounded, usize => i8, i16, i32);
524    rev!(impl_try_from_both_bounded, usize => i64, i128);
525
526    #[cfg(not(feature = "ferrocene_subset"))]
527    rev!(impl_try_from_unbounded, isize => u16);
528    #[cfg(not(feature = "ferrocene_subset"))]
529    rev!(impl_try_from_upper_bounded, isize => u32, u64, u128);
530    #[cfg(not(feature = "ferrocene_subset"))]
531    rev!(impl_try_from_unbounded, isize => i32);
532    #[cfg(not(feature = "ferrocene_subset"))]
533    rev!(impl_try_from_both_bounded, isize => i64, i128);
534}
535
536#[cfg(target_pointer_width = "64")]
537mod ptr_try_from_impls {
538    use super::TryFromIntError;
539
540    impl_try_from_upper_bounded!(usize => u8, u16, u32);
541    impl_try_from_unbounded!(usize => u64, u128);
542    #[cfg(not(feature = "ferrocene_subset"))]
543    impl_try_from_upper_bounded!(usize => i8, i16, i32, i64);
544    #[cfg(not(feature = "ferrocene_subset"))]
545    impl_try_from_unbounded!(usize => i128);
546
547    #[cfg(not(feature = "ferrocene_subset"))]
548    impl_try_from_both_bounded!(isize => u8, u16, u32);
549    #[cfg(not(feature = "ferrocene_subset"))]
550    impl_try_from_lower_bounded!(isize => u64, u128);
551    #[cfg(not(feature = "ferrocene_subset"))]
552    impl_try_from_both_bounded!(isize => i8, i16, i32);
553    #[cfg(not(feature = "ferrocene_subset"))]
554    impl_try_from_unbounded!(isize => i64, i128);
555
556    rev!(impl_try_from_unbounded, usize => u32, u64);
557    rev!(impl_try_from_upper_bounded, usize => u128);
558    rev!(impl_try_from_lower_bounded, usize => i8, i16, i32, i64);
559    rev!(impl_try_from_both_bounded, usize => i128);
560
561    #[cfg(not(feature = "ferrocene_subset"))]
562    rev!(impl_try_from_unbounded, isize => u16, u32);
563    #[cfg(not(feature = "ferrocene_subset"))]
564    rev!(impl_try_from_upper_bounded, isize => u64, u128);
565    #[cfg(not(feature = "ferrocene_subset"))]
566    rev!(impl_try_from_unbounded, isize => i32, i64);
567    #[cfg(not(feature = "ferrocene_subset"))]
568    rev!(impl_try_from_both_bounded, isize => i128);
569}
570
571// Conversion traits for non-zero integer types
572#[cfg(not(feature = "ferrocene_subset"))]
573use crate::num::NonZero;
574
575#[cfg(not(feature = "ferrocene_subset"))]
576macro_rules! impl_nonzero_int_from_nonzero_int {
577    ($Small:ty => $Large:ty) => {
578        #[stable(feature = "nz_int_conv", since = "1.41.0")]
579        #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
580        impl const From<NonZero<$Small>> for NonZero<$Large> {
581            // Rustdocs on the impl block show a "[+] show undocumented items" toggle.
582            // Rustdocs on functions do not.
583            #[doc = concat!("Converts <code>[NonZero]\\<[", stringify!($Small), "]></code> ")]
584            #[doc = concat!("to <code>[NonZero]\\<[", stringify!($Large), "]></code> losslessly.")]
585            #[inline]
586            fn from(small: NonZero<$Small>) -> Self {
587                // SAFETY: input type guarantees the value is non-zero
588                unsafe { Self::new_unchecked(From::from(small.get())) }
589            }
590        }
591    };
592}
593
594// non-zero unsigned integer -> non-zero unsigned integer
595#[cfg(not(feature = "ferrocene_subset"))]
596impl_nonzero_int_from_nonzero_int!(u8 => u16);
597#[cfg(not(feature = "ferrocene_subset"))]
598impl_nonzero_int_from_nonzero_int!(u8 => u32);
599#[cfg(not(feature = "ferrocene_subset"))]
600impl_nonzero_int_from_nonzero_int!(u8 => u64);
601#[cfg(not(feature = "ferrocene_subset"))]
602impl_nonzero_int_from_nonzero_int!(u8 => u128);
603#[cfg(not(feature = "ferrocene_subset"))]
604impl_nonzero_int_from_nonzero_int!(u8 => usize);
605#[cfg(not(feature = "ferrocene_subset"))]
606impl_nonzero_int_from_nonzero_int!(u16 => u32);
607#[cfg(not(feature = "ferrocene_subset"))]
608impl_nonzero_int_from_nonzero_int!(u16 => u64);
609#[cfg(not(feature = "ferrocene_subset"))]
610impl_nonzero_int_from_nonzero_int!(u16 => u128);
611#[cfg(not(feature = "ferrocene_subset"))]
612impl_nonzero_int_from_nonzero_int!(u16 => usize);
613#[cfg(not(feature = "ferrocene_subset"))]
614impl_nonzero_int_from_nonzero_int!(u32 => u64);
615#[cfg(not(feature = "ferrocene_subset"))]
616impl_nonzero_int_from_nonzero_int!(u32 => u128);
617#[cfg(not(feature = "ferrocene_subset"))]
618impl_nonzero_int_from_nonzero_int!(u64 => u128);
619
620// non-zero signed integer -> non-zero signed integer
621#[cfg(not(feature = "ferrocene_subset"))]
622impl_nonzero_int_from_nonzero_int!(i8 => i16);
623#[cfg(not(feature = "ferrocene_subset"))]
624impl_nonzero_int_from_nonzero_int!(i8 => i32);
625#[cfg(not(feature = "ferrocene_subset"))]
626impl_nonzero_int_from_nonzero_int!(i8 => i64);
627#[cfg(not(feature = "ferrocene_subset"))]
628impl_nonzero_int_from_nonzero_int!(i8 => i128);
629#[cfg(not(feature = "ferrocene_subset"))]
630impl_nonzero_int_from_nonzero_int!(i8 => isize);
631#[cfg(not(feature = "ferrocene_subset"))]
632impl_nonzero_int_from_nonzero_int!(i16 => i32);
633#[cfg(not(feature = "ferrocene_subset"))]
634impl_nonzero_int_from_nonzero_int!(i16 => i64);
635#[cfg(not(feature = "ferrocene_subset"))]
636impl_nonzero_int_from_nonzero_int!(i16 => i128);
637#[cfg(not(feature = "ferrocene_subset"))]
638impl_nonzero_int_from_nonzero_int!(i16 => isize);
639#[cfg(not(feature = "ferrocene_subset"))]
640impl_nonzero_int_from_nonzero_int!(i32 => i64);
641#[cfg(not(feature = "ferrocene_subset"))]
642impl_nonzero_int_from_nonzero_int!(i32 => i128);
643#[cfg(not(feature = "ferrocene_subset"))]
644impl_nonzero_int_from_nonzero_int!(i64 => i128);
645
646// non-zero unsigned -> non-zero signed integer
647#[cfg(not(feature = "ferrocene_subset"))]
648impl_nonzero_int_from_nonzero_int!(u8 => i16);
649#[cfg(not(feature = "ferrocene_subset"))]
650impl_nonzero_int_from_nonzero_int!(u8 => i32);
651#[cfg(not(feature = "ferrocene_subset"))]
652impl_nonzero_int_from_nonzero_int!(u8 => i64);
653#[cfg(not(feature = "ferrocene_subset"))]
654impl_nonzero_int_from_nonzero_int!(u8 => i128);
655#[cfg(not(feature = "ferrocene_subset"))]
656impl_nonzero_int_from_nonzero_int!(u8 => isize);
657#[cfg(not(feature = "ferrocene_subset"))]
658impl_nonzero_int_from_nonzero_int!(u16 => i32);
659#[cfg(not(feature = "ferrocene_subset"))]
660impl_nonzero_int_from_nonzero_int!(u16 => i64);
661#[cfg(not(feature = "ferrocene_subset"))]
662impl_nonzero_int_from_nonzero_int!(u16 => i128);
663#[cfg(not(feature = "ferrocene_subset"))]
664impl_nonzero_int_from_nonzero_int!(u32 => i64);
665#[cfg(not(feature = "ferrocene_subset"))]
666impl_nonzero_int_from_nonzero_int!(u32 => i128);
667#[cfg(not(feature = "ferrocene_subset"))]
668impl_nonzero_int_from_nonzero_int!(u64 => i128);
669
670#[cfg(not(feature = "ferrocene_subset"))]
671macro_rules! impl_nonzero_int_try_from_int {
672    ($Int:ty) => {
673        #[stable(feature = "nzint_try_from_int_conv", since = "1.46.0")]
674        #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
675        impl const TryFrom<$Int> for NonZero<$Int> {
676            type Error = TryFromIntError;
677
678            // Rustdocs on the impl block show a "[+] show undocumented items" toggle.
679            // Rustdocs on functions do not.
680            #[doc = concat!("Attempts to convert [`", stringify!($Int), "`] ")]
681            #[doc = concat!("to <code>[NonZero]\\<[", stringify!($Int), "]></code>.")]
682            #[inline]
683            fn try_from(value: $Int) -> Result<Self, Self::Error> {
684                Self::new(value).ok_or(TryFromIntError(()))
685            }
686        }
687    };
688}
689
690// integer -> non-zero integer
691#[cfg(not(feature = "ferrocene_subset"))]
692impl_nonzero_int_try_from_int!(u8);
693#[cfg(not(feature = "ferrocene_subset"))]
694impl_nonzero_int_try_from_int!(u16);
695#[cfg(not(feature = "ferrocene_subset"))]
696impl_nonzero_int_try_from_int!(u32);
697#[cfg(not(feature = "ferrocene_subset"))]
698impl_nonzero_int_try_from_int!(u64);
699#[cfg(not(feature = "ferrocene_subset"))]
700impl_nonzero_int_try_from_int!(u128);
701#[cfg(not(feature = "ferrocene_subset"))]
702impl_nonzero_int_try_from_int!(usize);
703#[cfg(not(feature = "ferrocene_subset"))]
704impl_nonzero_int_try_from_int!(i8);
705#[cfg(not(feature = "ferrocene_subset"))]
706impl_nonzero_int_try_from_int!(i16);
707#[cfg(not(feature = "ferrocene_subset"))]
708impl_nonzero_int_try_from_int!(i32);
709#[cfg(not(feature = "ferrocene_subset"))]
710impl_nonzero_int_try_from_int!(i64);
711#[cfg(not(feature = "ferrocene_subset"))]
712impl_nonzero_int_try_from_int!(i128);
713#[cfg(not(feature = "ferrocene_subset"))]
714impl_nonzero_int_try_from_int!(isize);
715
716#[cfg(not(feature = "ferrocene_subset"))]
717macro_rules! impl_nonzero_int_try_from_nonzero_int {
718    ($source:ty => $($target:ty),+) => {$(
719        #[stable(feature = "nzint_try_from_nzint_conv", since = "1.49.0")]
720        #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
721        impl const TryFrom<NonZero<$source>> for NonZero<$target> {
722            type Error = TryFromIntError;
723
724            // Rustdocs on the impl block show a "[+] show undocumented items" toggle.
725            // Rustdocs on functions do not.
726            #[doc = concat!("Attempts to convert <code>[NonZero]\\<[", stringify!($source), "]></code> ")]
727            #[doc = concat!("to <code>[NonZero]\\<[", stringify!($target), "]></code>.")]
728            #[inline]
729            fn try_from(value: NonZero<$source>) -> Result<Self, Self::Error> {
730                // SAFETY: Input is guaranteed to be non-zero.
731                Ok(unsafe { Self::new_unchecked(<$target>::try_from(value.get())?) })
732            }
733        }
734    )*};
735}
736
737// unsigned non-zero integer -> unsigned non-zero integer
738#[cfg(not(feature = "ferrocene_subset"))]
739impl_nonzero_int_try_from_nonzero_int!(u16 => u8);
740#[cfg(not(feature = "ferrocene_subset"))]
741impl_nonzero_int_try_from_nonzero_int!(u32 => u8, u16, usize);
742#[cfg(not(feature = "ferrocene_subset"))]
743impl_nonzero_int_try_from_nonzero_int!(u64 => u8, u16, u32, usize);
744#[cfg(not(feature = "ferrocene_subset"))]
745impl_nonzero_int_try_from_nonzero_int!(u128 => u8, u16, u32, u64, usize);
746#[cfg(not(feature = "ferrocene_subset"))]
747impl_nonzero_int_try_from_nonzero_int!(usize => u8, u16, u32, u64, u128);
748
749// signed non-zero integer -> signed non-zero integer
750#[cfg(not(feature = "ferrocene_subset"))]
751impl_nonzero_int_try_from_nonzero_int!(i16 => i8);
752#[cfg(not(feature = "ferrocene_subset"))]
753impl_nonzero_int_try_from_nonzero_int!(i32 => i8, i16, isize);
754#[cfg(not(feature = "ferrocene_subset"))]
755impl_nonzero_int_try_from_nonzero_int!(i64 => i8, i16, i32, isize);
756#[cfg(not(feature = "ferrocene_subset"))]
757impl_nonzero_int_try_from_nonzero_int!(i128 => i8, i16, i32, i64, isize);
758#[cfg(not(feature = "ferrocene_subset"))]
759impl_nonzero_int_try_from_nonzero_int!(isize => i8, i16, i32, i64, i128);
760
761// unsigned non-zero integer -> signed non-zero integer
762#[cfg(not(feature = "ferrocene_subset"))]
763impl_nonzero_int_try_from_nonzero_int!(u8 => i8);
764#[cfg(not(feature = "ferrocene_subset"))]
765impl_nonzero_int_try_from_nonzero_int!(u16 => i8, i16, isize);
766#[cfg(not(feature = "ferrocene_subset"))]
767impl_nonzero_int_try_from_nonzero_int!(u32 => i8, i16, i32, isize);
768#[cfg(not(feature = "ferrocene_subset"))]
769impl_nonzero_int_try_from_nonzero_int!(u64 => i8, i16, i32, i64, isize);
770#[cfg(not(feature = "ferrocene_subset"))]
771impl_nonzero_int_try_from_nonzero_int!(u128 => i8, i16, i32, i64, i128, isize);
772#[cfg(not(feature = "ferrocene_subset"))]
773impl_nonzero_int_try_from_nonzero_int!(usize => i8, i16, i32, i64, i128, isize);
774
775// signed non-zero integer -> unsigned non-zero integer
776#[cfg(not(feature = "ferrocene_subset"))]
777impl_nonzero_int_try_from_nonzero_int!(i8 => u8, u16, u32, u64, u128, usize);
778#[cfg(not(feature = "ferrocene_subset"))]
779impl_nonzero_int_try_from_nonzero_int!(i16 => u8, u16, u32, u64, u128, usize);
780#[cfg(not(feature = "ferrocene_subset"))]
781impl_nonzero_int_try_from_nonzero_int!(i32 => u8, u16, u32, u64, u128, usize);
782#[cfg(not(feature = "ferrocene_subset"))]
783impl_nonzero_int_try_from_nonzero_int!(i64 => u8, u16, u32, u64, u128, usize);
784#[cfg(not(feature = "ferrocene_subset"))]
785impl_nonzero_int_try_from_nonzero_int!(i128 => u8, u16, u32, u64, u128, usize);
786#[cfg(not(feature = "ferrocene_subset"))]
787impl_nonzero_int_try_from_nonzero_int!(isize => u8, u16, u32, u64, u128, usize);