Skip to content

Commit 14c0b7b

Browse files
authored
Unrolled build for #147400
Rollup merge of #147400 - hkBst:convert-1, r=Mark-Simulacrum TryFrom<integer> for bool I noticed the manual TryFrom implementation in [this video from RustConf 2025](https://youtu.be/cOP219vkax8?list=PL2b0df3jKKiRFEuVNk76ufXagOgEJ9sBZ&t=1917) and thought I'd add it.
2 parents 92ea9b2 + f12288e commit 14c0b7b

File tree

2 files changed

+74
-49
lines changed

2 files changed

+74
-49
lines changed

‎library/core/src/convert/num.rs‎

Lines changed: 73 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -39,63 +39,52 @@ impl_float_to_int!(f32 => u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i12
3939
impl_float_to_int!(f64 => u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize);
4040
impl_float_to_int!(f128 => u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize);
4141

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
42+
/// Implement `From<bool>` for integers
43+
macro_rules! impl_from_bool {
44+
($($int:ty)*) => {$(
45+
#[stable(feature = "from_bool", since = "1.28.0")]
46+
#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
47+
impl const From<bool> for $int {
48+
/// Converts from [`bool`] to
49+
#[doc = concat!("[`", stringify!($int), "`]")]
50+
/// , by turning `false` into `0` and `true` into `1`.
51+
///
52+
/// # Examples
53+
///
54+
/// ```
55+
#[doc = concat!("assert_eq!(", stringify!($int), "::from(false), 0);")]
56+
///
57+
#[doc = concat!("assert_eq!(", stringify!($int), "::from(true), 1);")]
58+
/// ```
59+
#[inline(always)]
60+
fn from(b: bool) -> Self {
61+
b as Self
62+
}
63+
}
64+
)*}
65+
}
66+
67+
// boolean -> integer
68+
impl_from_bool!(u8 u16 u32 u64 u128 usize);
69+
impl_from_bool!(i8 i16 i32 i64 i128 isize);
70+
71+
/// Implement `From<$small>` for `$large`
4572
macro_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 $(,)?) => {
73+
($small:ty => $large:ty, #[$attr:meta]) => {
7174
#[$attr]
7275
#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
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]
76+
impl const From<$small> for $large {
77+
#[doc = concat!("Converts from [`", stringify!($small), "`] to [`", stringify!($large), "`] losslessly.")]
7778
#[inline(always)]
78-
fn from(small: $Small) -> Self {
79+
fn from(small: $small) -> Self {
80+
debug_assert!(<$large>::MIN as i128 <= <$small>::MIN as i128);
81+
debug_assert!(<$small>::MAX as u128 <= <$large>::MAX as u128);
7982
small as Self
8083
}
8184
}
82-
};
85+
}
8386
}
8487

85-
// boolean -> integer
86-
impl_from!(bool => u8);
87-
impl_from!(bool => u16);
88-
impl_from!(bool => u32);
89-
impl_from!(bool => u64);
90-
impl_from!(bool => u128);
91-
impl_from!(bool => usize);
92-
impl_from!(bool => i8);
93-
impl_from!(bool => i16);
94-
impl_from!(bool => i32);
95-
impl_from!(bool => i64);
96-
impl_from!(bool => i128);
97-
impl_from!(bool => isize);
98-
9988
// unsigned integer -> unsigned integer
10089
impl_from!(u8 => u16, #[stable(feature = "lossless_int_conv", since = "1.5.0")]);
10190
impl_from!(u8 => u32, #[stable(feature = "lossless_int_conv", since = "1.5.0")]);
@@ -338,12 +327,48 @@ macro_rules! impl_try_from_both_bounded {
338327
)*}
339328
}
340329

330+
/// Implement `TryFrom<integer>` for `bool`
331+
macro_rules! impl_try_from_integer_for_bool {
332+
($($int:ty)+) => {$(
333+
#[stable(feature = "try_from", since = "1.34.0")]
334+
#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
335+
impl const TryFrom<$int> for bool {
336+
type Error = TryFromIntError;
337+
338+
/// Tries to create a bool from an integer type.
339+
/// Returns an error if the integer is not 0 or 1.
340+
///
341+
/// # Examples
342+
///
343+
/// ```
344+
#[doc = concat!("assert_eq!(0_", stringify!($int), ".try_into(), Ok(false));")]
345+
///
346+
#[doc = concat!("assert_eq!(1_", stringify!($int), ".try_into(), Ok(true));")]
347+
///
348+
#[doc = concat!("assert!(<", stringify!($int), " as TryInto<bool>>::try_into(2).is_err());")]
349+
/// ```
350+
#[inline]
351+
fn try_from(i: $int) -> Result<Self, Self::Error> {
352+
match i {
353+
0 => Ok(false),
354+
1 => Ok(true),
355+
_ => Err(TryFromIntError(())),
356+
}
357+
}
358+
}
359+
)*}
360+
}
361+
341362
macro_rules! rev {
342363
($mac:ident, $source:ty => $($target:ty),+) => {$(
343364
$mac!($target => $source);
344365
)*}
345366
}
346367

368+
// integer -> bool
369+
impl_try_from_integer_for_bool!(u128 u64 u32 u16 u8);
370+
impl_try_from_integer_for_bool!(i128 i64 i32 i16 i8);
371+
347372
// unsigned integer -> unsigned integer
348373
impl_try_from_upper_bounded!(u16 => u8);
349374
impl_try_from_upper_bounded!(u32 => u8, u16);

‎tests/ui/try-trait/bad-interconversion.stderr‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ help: the following other types implement trait `From<T>`
2222
::: $SRC_DIR/core/src/ascii/ascii_char.rs:LL:COL
2323
|
2424
= note: in this macro invocation
25-
= note: this error originates in the macro `impl_from` which comes from the expansion of the macro `into_int_impl` (in Nightly builds, run with -Z macro-backtrace for more info)
25+
= note: this error originates in the macro `impl_from_bool` which comes from the expansion of the macro `into_int_impl` (in Nightly builds, run with -Z macro-backtrace for more info)
2626

2727
error[E0277]: the `?` operator can only be used on `Result`s, not `Option`s, in a function that returns `Result`
2828
--> $DIR/bad-interconversion.rs:9:12

0 commit comments

Comments
 (0)