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