core/convert/
num.rs

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