Skip to content

Commit a213ff8

Browse files
committed
Move numeric From and TryFrom impls to libcore/convert/num.rs
This makes `libcore/num/mod.rs` slightly smaller. It’s still 4911 lines and not easy to navigate. This doesn’t change any public API.
1 parent cba479f commit a213ff8

File tree

2 files changed

+332
-330
lines changed

2 files changed

+332
-330
lines changed

src/libcore/convert/num.rs

+331
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
use super::{From, TryFrom};
2+
use crate::num::TryFromIntError;
3+
14
mod private {
25
/// This trait being unreachable from outside the crate
36
/// prevents other implementations of the `FloatToInt` trait,
@@ -36,3 +39,331 @@ macro_rules! impl_float_to_int {
3639

3740
impl_float_to_int!(f32 => u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize);
3841
impl_float_to_int!(f64 => u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize);
42+
43+
// Conversion traits for primitive integer and float types
44+
// Conversions T -> T are covered by a blanket impl and therefore excluded
45+
// Some conversions from and to usize/isize are not implemented due to portability concerns
46+
macro_rules! impl_from {
47+
($Small: ty, $Large: ty, #[$attr:meta], $doc: expr) => {
48+
#[$attr]
49+
#[doc = $doc]
50+
impl From<$Small> for $Large {
51+
#[inline]
52+
fn from(small: $Small) -> $Large {
53+
small as $Large
54+
}
55+
}
56+
};
57+
($Small: ty, $Large: ty, #[$attr:meta]) => {
58+
impl_from!($Small,
59+
$Large,
60+
#[$attr],
61+
concat!("Converts `",
62+
stringify!($Small),
63+
"` to `",
64+
stringify!($Large),
65+
"` losslessly."));
66+
}
67+
}
68+
69+
macro_rules! impl_from_bool {
70+
($target: ty, #[$attr:meta]) => {
71+
impl_from!(bool, $target, #[$attr], concat!("Converts a `bool` to a `",
72+
stringify!($target), "`. The resulting value is `0` for `false` and `1` for `true`
73+
values.
74+
75+
# Examples
76+
77+
```
78+
assert_eq!(", stringify!($target), "::from(true), 1);
79+
assert_eq!(", stringify!($target), "::from(false), 0);
80+
```"));
81+
};
82+
}
83+
84+
// Bool -> Any
85+
impl_from_bool! { u8, #[stable(feature = "from_bool", since = "1.28.0")] }
86+
impl_from_bool! { u16, #[stable(feature = "from_bool", since = "1.28.0")] }
87+
impl_from_bool! { u32, #[stable(feature = "from_bool", since = "1.28.0")] }
88+
impl_from_bool! { u64, #[stable(feature = "from_bool", since = "1.28.0")] }
89+
impl_from_bool! { u128, #[stable(feature = "from_bool", since = "1.28.0")] }
90+
impl_from_bool! { usize, #[stable(feature = "from_bool", since = "1.28.0")] }
91+
impl_from_bool! { i8, #[stable(feature = "from_bool", since = "1.28.0")] }
92+
impl_from_bool! { i16, #[stable(feature = "from_bool", since = "1.28.0")] }
93+
impl_from_bool! { i32, #[stable(feature = "from_bool", since = "1.28.0")] }
94+
impl_from_bool! { i64, #[stable(feature = "from_bool", since = "1.28.0")] }
95+
impl_from_bool! { i128, #[stable(feature = "from_bool", since = "1.28.0")] }
96+
impl_from_bool! { isize, #[stable(feature = "from_bool", since = "1.28.0")] }
97+
98+
// Unsigned -> Unsigned
99+
impl_from! { u8, u16, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
100+
impl_from! { u8, u32, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
101+
impl_from! { u8, u64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
102+
impl_from! { u8, u128, #[stable(feature = "i128", since = "1.26.0")] }
103+
impl_from! { u8, usize, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
104+
impl_from! { u16, u32, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
105+
impl_from! { u16, u64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
106+
impl_from! { u16, u128, #[stable(feature = "i128", since = "1.26.0")] }
107+
impl_from! { u32, u64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
108+
impl_from! { u32, u128, #[stable(feature = "i128", since = "1.26.0")] }
109+
impl_from! { u64, u128, #[stable(feature = "i128", since = "1.26.0")] }
110+
111+
// Signed -> Signed
112+
impl_from! { i8, i16, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
113+
impl_from! { i8, i32, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
114+
impl_from! { i8, i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
115+
impl_from! { i8, i128, #[stable(feature = "i128", since = "1.26.0")] }
116+
impl_from! { i8, isize, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
117+
impl_from! { i16, i32, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
118+
impl_from! { i16, i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
119+
impl_from! { i16, i128, #[stable(feature = "i128", since = "1.26.0")] }
120+
impl_from! { i32, i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
121+
impl_from! { i32, i128, #[stable(feature = "i128", since = "1.26.0")] }
122+
impl_from! { i64, i128, #[stable(feature = "i128", since = "1.26.0")] }
123+
124+
// Unsigned -> Signed
125+
impl_from! { u8, i16, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
126+
impl_from! { u8, i32, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
127+
impl_from! { u8, i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
128+
impl_from! { u8, i128, #[stable(feature = "i128", since = "1.26.0")] }
129+
impl_from! { u16, i32, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
130+
impl_from! { u16, i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
131+
impl_from! { u16, i128, #[stable(feature = "i128", since = "1.26.0")] }
132+
impl_from! { u32, i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
133+
impl_from! { u32, i128, #[stable(feature = "i128", since = "1.26.0")] }
134+
impl_from! { u64, i128, #[stable(feature = "i128", since = "1.26.0")] }
135+
136+
// The C99 standard defines bounds on INTPTR_MIN, INTPTR_MAX, and UINTPTR_MAX
137+
// which imply that pointer-sized integers must be at least 16 bits:
138+
// https://port70.net/~nsz/c/c99/n1256.html#7.18.2.4
139+
impl_from! { u16, usize, #[stable(feature = "lossless_iusize_conv", since = "1.26.0")] }
140+
impl_from! { u8, isize, #[stable(feature = "lossless_iusize_conv", since = "1.26.0")] }
141+
impl_from! { i16, isize, #[stable(feature = "lossless_iusize_conv", since = "1.26.0")] }
142+
143+
// RISC-V defines the possibility of a 128-bit address space (RV128).
144+
145+
// CHERI proposes 256-bit “capabilities”. Unclear if this would be relevant to usize/isize.
146+
// https://www.cl.cam.ac.uk/research/security/ctsrd/pdfs/20171017a-cheri-poster.pdf
147+
// http://www.csl.sri.com/users/neumann/2012resolve-cheri.pdf
148+
149+
150+
// Note: integers can only be represented with full precision in a float if
151+
// they fit in the significand, which is 24 bits in f32 and 53 bits in f64.
152+
// Lossy float conversions are not implemented at this time.
153+
154+
// Signed -> Float
155+
impl_from! { i8, f32, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
156+
impl_from! { i8, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
157+
impl_from! { i16, f32, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
158+
impl_from! { i16, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
159+
impl_from! { i32, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
160+
161+
// Unsigned -> Float
162+
impl_from! { u8, f32, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
163+
impl_from! { u8, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
164+
impl_from! { u16, f32, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
165+
impl_from! { u16, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
166+
impl_from! { u32, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
167+
168+
// Float -> Float
169+
impl_from! { f32, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
170+
171+
// no possible bounds violation
172+
macro_rules! try_from_unbounded {
173+
($source:ty, $($target:ty),*) => {$(
174+
#[stable(feature = "try_from", since = "1.34.0")]
175+
impl TryFrom<$source> for $target {
176+
type Error = TryFromIntError;
177+
178+
/// Try to create the target number type from a source
179+
/// number type. This returns an error if the source value
180+
/// is outside of the range of the target type.
181+
#[inline]
182+
fn try_from(value: $source) -> Result<Self, Self::Error> {
183+
Ok(value as $target)
184+
}
185+
}
186+
)*}
187+
}
188+
189+
// only negative bounds
190+
macro_rules! try_from_lower_bounded {
191+
($source:ty, $($target:ty),*) => {$(
192+
#[stable(feature = "try_from", since = "1.34.0")]
193+
impl TryFrom<$source> for $target {
194+
type Error = TryFromIntError;
195+
196+
/// Try to create the target number type from a source
197+
/// number type. This returns an error if the source value
198+
/// is outside of the range of the target type.
199+
#[inline]
200+
fn try_from(u: $source) -> Result<$target, TryFromIntError> {
201+
if u >= 0 {
202+
Ok(u as $target)
203+
} else {
204+
Err(TryFromIntError(()))
205+
}
206+
}
207+
}
208+
)*}
209+
}
210+
211+
// unsigned to signed (only positive bound)
212+
macro_rules! try_from_upper_bounded {
213+
($source:ty, $($target:ty),*) => {$(
214+
#[stable(feature = "try_from", since = "1.34.0")]
215+
impl TryFrom<$source> for $target {
216+
type Error = TryFromIntError;
217+
218+
/// Try to create the target number type from a source
219+
/// number type. This returns an error if the source value
220+
/// is outside of the range of the target type.
221+
#[inline]
222+
fn try_from(u: $source) -> Result<$target, TryFromIntError> {
223+
if u > (<$target>::max_value() as $source) {
224+
Err(TryFromIntError(()))
225+
} else {
226+
Ok(u as $target)
227+
}
228+
}
229+
}
230+
)*}
231+
}
232+
233+
// all other cases
234+
macro_rules! try_from_both_bounded {
235+
($source:ty, $($target:ty),*) => {$(
236+
#[stable(feature = "try_from", since = "1.34.0")]
237+
impl TryFrom<$source> for $target {
238+
type Error = TryFromIntError;
239+
240+
/// Try to create the target number type from a source
241+
/// number type. This returns an error if the source value
242+
/// is outside of the range of the target type.
243+
#[inline]
244+
fn try_from(u: $source) -> Result<$target, TryFromIntError> {
245+
let min = <$target>::min_value() as $source;
246+
let max = <$target>::max_value() as $source;
247+
if u < min || u > max {
248+
Err(TryFromIntError(()))
249+
} else {
250+
Ok(u as $target)
251+
}
252+
}
253+
}
254+
)*}
255+
}
256+
257+
macro_rules! rev {
258+
($mac:ident, $source:ty, $($target:ty),*) => {$(
259+
$mac!($target, $source);
260+
)*}
261+
}
262+
263+
// intra-sign conversions
264+
try_from_upper_bounded!(u16, u8);
265+
try_from_upper_bounded!(u32, u16, u8);
266+
try_from_upper_bounded!(u64, u32, u16, u8);
267+
try_from_upper_bounded!(u128, u64, u32, u16, u8);
268+
269+
try_from_both_bounded!(i16, i8);
270+
try_from_both_bounded!(i32, i16, i8);
271+
try_from_both_bounded!(i64, i32, i16, i8);
272+
try_from_both_bounded!(i128, i64, i32, i16, i8);
273+
274+
// unsigned-to-signed
275+
try_from_upper_bounded!(u8, i8);
276+
try_from_upper_bounded!(u16, i8, i16);
277+
try_from_upper_bounded!(u32, i8, i16, i32);
278+
try_from_upper_bounded!(u64, i8, i16, i32, i64);
279+
try_from_upper_bounded!(u128, i8, i16, i32, i64, i128);
280+
281+
// signed-to-unsigned
282+
try_from_lower_bounded!(i8, u8, u16, u32, u64, u128);
283+
try_from_lower_bounded!(i16, u16, u32, u64, u128);
284+
try_from_lower_bounded!(i32, u32, u64, u128);
285+
try_from_lower_bounded!(i64, u64, u128);
286+
try_from_lower_bounded!(i128, u128);
287+
try_from_both_bounded!(i16, u8);
288+
try_from_both_bounded!(i32, u16, u8);
289+
try_from_both_bounded!(i64, u32, u16, u8);
290+
try_from_both_bounded!(i128, u64, u32, u16, u8);
291+
292+
// usize/isize
293+
try_from_upper_bounded!(usize, isize);
294+
try_from_lower_bounded!(isize, usize);
295+
296+
#[cfg(target_pointer_width = "16")]
297+
mod ptr_try_from_impls {
298+
use super::TryFromIntError;
299+
use crate::convert::TryFrom;
300+
301+
try_from_upper_bounded!(usize, u8);
302+
try_from_unbounded!(usize, u16, u32, u64, u128);
303+
try_from_upper_bounded!(usize, i8, i16);
304+
try_from_unbounded!(usize, i32, i64, i128);
305+
306+
try_from_both_bounded!(isize, u8);
307+
try_from_lower_bounded!(isize, u16, u32, u64, u128);
308+
try_from_both_bounded!(isize, i8);
309+
try_from_unbounded!(isize, i16, i32, i64, i128);
310+
311+
rev!(try_from_upper_bounded, usize, u32, u64, u128);
312+
rev!(try_from_lower_bounded, usize, i8, i16);
313+
rev!(try_from_both_bounded, usize, i32, i64, i128);
314+
315+
rev!(try_from_upper_bounded, isize, u16, u32, u64, u128);
316+
rev!(try_from_both_bounded, isize, i32, i64, i128);
317+
}
318+
319+
#[cfg(target_pointer_width = "32")]
320+
mod ptr_try_from_impls {
321+
use super::TryFromIntError;
322+
use crate::convert::TryFrom;
323+
324+
try_from_upper_bounded!(usize, u8, u16);
325+
try_from_unbounded!(usize, u32, u64, u128);
326+
try_from_upper_bounded!(usize, i8, i16, i32);
327+
try_from_unbounded!(usize, i64, i128);
328+
329+
try_from_both_bounded!(isize, u8, u16);
330+
try_from_lower_bounded!(isize, u32, u64, u128);
331+
try_from_both_bounded!(isize, i8, i16);
332+
try_from_unbounded!(isize, i32, i64, i128);
333+
334+
rev!(try_from_unbounded, usize, u32);
335+
rev!(try_from_upper_bounded, usize, u64, u128);
336+
rev!(try_from_lower_bounded, usize, i8, i16, i32);
337+
rev!(try_from_both_bounded, usize, i64, i128);
338+
339+
rev!(try_from_unbounded, isize, u16);
340+
rev!(try_from_upper_bounded, isize, u32, u64, u128);
341+
rev!(try_from_unbounded, isize, i32);
342+
rev!(try_from_both_bounded, isize, i64, i128);
343+
}
344+
345+
#[cfg(target_pointer_width = "64")]
346+
mod ptr_try_from_impls {
347+
use super::TryFromIntError;
348+
use crate::convert::TryFrom;
349+
350+
try_from_upper_bounded!(usize, u8, u16, u32);
351+
try_from_unbounded!(usize, u64, u128);
352+
try_from_upper_bounded!(usize, i8, i16, i32, i64);
353+
try_from_unbounded!(usize, i128);
354+
355+
try_from_both_bounded!(isize, u8, u16, u32);
356+
try_from_lower_bounded!(isize, u64, u128);
357+
try_from_both_bounded!(isize, i8, i16, i32);
358+
try_from_unbounded!(isize, i64, i128);
359+
360+
rev!(try_from_unbounded, usize, u32, u64);
361+
rev!(try_from_upper_bounded, usize, u128);
362+
rev!(try_from_lower_bounded, usize, i8, i16, i32, i64);
363+
rev!(try_from_both_bounded, usize, i128);
364+
365+
rev!(try_from_unbounded, isize, u16, u32);
366+
rev!(try_from_upper_bounded, isize, u64, u128);
367+
rev!(try_from_unbounded, isize, i32, i64);
368+
rev!(try_from_both_bounded, isize, i128);
369+
}

0 commit comments

Comments
 (0)