Skip to main content

core/convert/
num.rs

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