core/convert/
num.rs

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

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy