Skip to content

Commit 998914f

Browse files
committed
Add lossless integer conversion by reference
1 parent 800a156 commit 998914f

File tree

7 files changed

+322
-1
lines changed

7 files changed

+322
-1
lines changed

library/core/src/convert/num.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ macro_rules! impl_from {
5555
small as Self
5656
}
5757
}
58+
59+
impl_from_ref! { $Small, $Large }
5860
};
5961
($Small: ty, $Large: ty, #[$attr:meta]) => {
6062
impl_from!($Small,
@@ -68,6 +70,21 @@ macro_rules! impl_from {
6870
}
6971
}
7072

73+
macro_rules! impl_from_ref {
74+
($Small: ty, $Large: ty) => {
75+
#[stable(feature = "num_from_num_ref", since = "1.60.0")]
76+
#[rustc_const_unstable(feature = "const_num_from_num", issue = "87852")]
77+
#[doc = concat!("Converts `&", stringify!($Small), "` to `", stringify!($Large), "` losslessly.")]
78+
#[doc = concat!("See the documentation of the `", stringify!($Small), "` to `", stringify!($Large), "` conversion.")]
79+
impl const From<&$Small> for $Large {
80+
#[inline]
81+
fn from(small: &$Small) -> Self {
82+
From::from(*small)
83+
}
84+
}
85+
}
86+
}
87+
7188
macro_rules! impl_from_bool {
7289
($target: ty, #[$attr:meta]) => {
7390
impl_from!(bool, $target, #[$attr], concat!("Converts a `bool` to a `",
@@ -98,30 +115,40 @@ impl_from_bool! { i128, #[stable(feature = "from_bool", since = "1.28.0")] }
98115
impl_from_bool! { isize, #[stable(feature = "from_bool", since = "1.28.0")] }
99116

100117
// Unsigned -> Unsigned
118+
impl_from_ref! { u8, u8 }
101119
impl_from! { u8, u16, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
102120
impl_from! { u8, u32, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
103121
impl_from! { u8, u64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
104122
impl_from! { u8, u128, #[stable(feature = "i128", since = "1.26.0")] }
105123
impl_from! { u8, usize, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
124+
impl_from_ref! { u16, u16 }
106125
impl_from! { u16, u32, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
107126
impl_from! { u16, u64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
108127
impl_from! { u16, u128, #[stable(feature = "i128", since = "1.26.0")] }
128+
impl_from_ref! { u32, u32 }
109129
impl_from! { u32, u64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
110130
impl_from! { u32, u128, #[stable(feature = "i128", since = "1.26.0")] }
131+
impl_from_ref! { u64, u64 }
111132
impl_from! { u64, u128, #[stable(feature = "i128", since = "1.26.0")] }
133+
impl_from_ref! { u128, u128 }
112134

113135
// Signed -> Signed
136+
impl_from_ref! { i8, i8 }
114137
impl_from! { i8, i16, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
115138
impl_from! { i8, i32, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
116139
impl_from! { i8, i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
117140
impl_from! { i8, i128, #[stable(feature = "i128", since = "1.26.0")] }
118141
impl_from! { i8, isize, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
142+
impl_from_ref! { i16, i16 }
119143
impl_from! { i16, i32, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
120144
impl_from! { i16, i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
121145
impl_from! { i16, i128, #[stable(feature = "i128", since = "1.26.0")] }
146+
impl_from_ref! { i32, i32 }
122147
impl_from! { i32, i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
123148
impl_from! { i32, i128, #[stable(feature = "i128", since = "1.26.0")] }
149+
impl_from_ref! { i64, i64 }
124150
impl_from! { i64, i128, #[stable(feature = "i128", since = "1.26.0")] }
151+
impl_from_ref! { i128, i128 }
125152

126153
// Unsigned -> Signed
127154
impl_from! { u8, i16, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }

library/core/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@
104104
#![feature(const_bigint_helper_methods)]
105105
#![feature(const_caller_location)]
106106
#![feature(const_cell_into_inner)]
107+
#![feature(const_convert)]
107108
#![feature(const_discriminant)]
108109
#![cfg_attr(not(bootstrap), feature(const_eval_select))]
109110
#![feature(const_float_bits_conv)]
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// check-pass
2+
3+
fn main () {
4+
// same size, signed
5+
let _: i8 = From::from(&1_i8);
6+
let _: i16 = From::from(&1_i16);
7+
let _: i32 = From::from(&1_i32);
8+
let _: i64 = From::from(&1_i64);
9+
let _: i128 = From::from(&1_i128);
10+
11+
// same size, unsigned
12+
let _: u8 = From::from(&1_u8);
13+
let _: u16 = From::from(&1_u16);
14+
let _: u32 = From::from(&1_u32);
15+
let _: u64 = From::from(&1_u64);
16+
let _: u128 = From::from(&1_u128);
17+
18+
// smaller, signed
19+
let _: i16 = From::from(&1_i8);
20+
let _: i32 = From::from(&1_i16);
21+
let _: i64 = From::from(&1_i32);
22+
let _: i128 = From::from(&1_i64);
23+
24+
// smaller, unsigned
25+
let _: u16 = From::from(&1_u8);
26+
let _: u32 = From::from(&1_u16);
27+
let _: u64 = From::from(&1_u32);
28+
let _: u128 = From::from(&1_u64);
29+
30+
// mixed signs
31+
let _: i16 = From::from(&1_u8);
32+
let _: i32 = From::from(&1_u16);
33+
let _: i64 = From::from(&1_u32);
34+
let _: i128 = From::from(&1_u64);
35+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// Check that conversions by reference which are not lossless are not implemented.
2+
3+
fn main () {
4+
// larger, signed
5+
let _: i8 = From::from(&1_i16); //~ ERROR
6+
let _: i16 = From::from(&1_i32); //~ ERROR
7+
let _: i32 = From::from(&1_i64); //~ ERROR
8+
let _: i64 = From::from(&1_i128); //~ ERROR
9+
10+
// larger, unsigned
11+
let _: u8 = From::from(&1_u16); //~ ERROR
12+
let _: u16 = From::from(&1_u32); //~ ERROR
13+
let _: u32 = From::from(&1_u64); //~ ERROR
14+
let _: u64 = From::from(&1_u128); //~ ERROR
15+
16+
// mixed signs
17+
let _: i8 = From::from(&1_u8); //~ ERROR
18+
let _: u16 = From::from(&1_i8); //~ ERROR
19+
let _: i32 = From::from(&1_u32); //~ ERROR
20+
let _: u64 = From::from(&1_i32); //~ ERROR
21+
let _: i128 = From::from(&1_u128); //~ ERROR
22+
}
Lines changed: 234 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,234 @@
1+
error[E0277]: the trait bound `i8: From<&i16>` is not satisfied
2+
--> $DIR/illegal.rs:5:17
3+
|
4+
LL | let _: i8 = From::from(&1_i16);
5+
| ^^^^^^^^^^ the trait `From<&i16>` is not implemented for `i8`
6+
|
7+
= help: the following implementations were found:
8+
<i8 as From<&bool>>
9+
<i8 as From<&i8>>
10+
<i8 as From<NonZeroI8>>
11+
<i8 as From<bool>>
12+
note: required by `from`
13+
--> $SRC_DIR/core/src/convert/mod.rs:LL:COL
14+
|
15+
LL | fn from(_: T) -> Self;
16+
| ^^^^^^^^^^^^^^^^^^^^^^
17+
18+
error[E0277]: the trait bound `i16: From<&i32>` is not satisfied
19+
--> $DIR/illegal.rs:6:18
20+
|
21+
LL | let _: i16 = From::from(&1_i32);
22+
| ^^^^^^^^^^ the trait `From<&i32>` is not implemented for `i16`
23+
|
24+
= help: the following implementations were found:
25+
<i16 as From<&bool>>
26+
<i16 as From<&i16>>
27+
<i16 as From<&i8>>
28+
<i16 as From<&u8>>
29+
and 4 others
30+
note: required by `from`
31+
--> $SRC_DIR/core/src/convert/mod.rs:LL:COL
32+
|
33+
LL | fn from(_: T) -> Self;
34+
| ^^^^^^^^^^^^^^^^^^^^^^
35+
36+
error[E0277]: the trait bound `i32: From<&i64>` is not satisfied
37+
--> $DIR/illegal.rs:7:18
38+
|
39+
LL | let _: i32 = From::from(&1_i64);
40+
| ^^^^^^^^^^ the trait `From<&i64>` is not implemented for `i32`
41+
|
42+
= help: the following implementations were found:
43+
<i32 as From<&bool>>
44+
<i32 as From<&i16>>
45+
<i32 as From<&i32>>
46+
<i32 as From<&i8>>
47+
and 8 others
48+
note: required by `from`
49+
--> $SRC_DIR/core/src/convert/mod.rs:LL:COL
50+
|
51+
LL | fn from(_: T) -> Self;
52+
| ^^^^^^^^^^^^^^^^^^^^^^
53+
54+
error[E0277]: the trait bound `i64: From<&i128>` is not satisfied
55+
--> $DIR/illegal.rs:8:18
56+
|
57+
LL | let _: i64 = From::from(&1_i128);
58+
| ^^^^^^^^^^ the trait `From<&i128>` is not implemented for `i64`
59+
|
60+
= help: the following implementations were found:
61+
<i64 as From<&bool>>
62+
<i64 as From<&i16>>
63+
<i64 as From<&i32>>
64+
<i64 as From<&i64>>
65+
and 12 others
66+
note: required by `from`
67+
--> $SRC_DIR/core/src/convert/mod.rs:LL:COL
68+
|
69+
LL | fn from(_: T) -> Self;
70+
| ^^^^^^^^^^^^^^^^^^^^^^
71+
72+
error[E0277]: the trait bound `u8: From<&u16>` is not satisfied
73+
--> $DIR/illegal.rs:11:17
74+
|
75+
LL | let _: u8 = From::from(&1_u16);
76+
| ^^^^^^^^^^ the trait `From<&u16>` is not implemented for `u8`
77+
|
78+
= help: the following implementations were found:
79+
<u8 as From<&bool>>
80+
<u8 as From<&u8>>
81+
<u8 as From<NonZeroU8>>
82+
<u8 as From<bool>>
83+
note: required by `from`
84+
--> $SRC_DIR/core/src/convert/mod.rs:LL:COL
85+
|
86+
LL | fn from(_: T) -> Self;
87+
| ^^^^^^^^^^^^^^^^^^^^^^
88+
89+
error[E0277]: the trait bound `u16: From<&u32>` is not satisfied
90+
--> $DIR/illegal.rs:12:18
91+
|
92+
LL | let _: u16 = From::from(&1_u32);
93+
| ^^^^^^^^^^ the trait `From<&u32>` is not implemented for `u16`
94+
|
95+
= help: the following implementations were found:
96+
<u16 as From<&bool>>
97+
<u16 as From<&u16>>
98+
<u16 as From<&u8>>
99+
<u16 as From<NonZeroU16>>
100+
and 2 others
101+
note: required by `from`
102+
--> $SRC_DIR/core/src/convert/mod.rs:LL:COL
103+
|
104+
LL | fn from(_: T) -> Self;
105+
| ^^^^^^^^^^^^^^^^^^^^^^
106+
107+
error[E0277]: the trait bound `u32: From<&u64>` is not satisfied
108+
--> $DIR/illegal.rs:13:18
109+
|
110+
LL | let _: u32 = From::from(&1_u64);
111+
| ^^^^^^^^^^ the trait `From<&u64>` is not implemented for `u32`
112+
|
113+
= help: the following implementations were found:
114+
<u32 as From<&bool>>
115+
<u32 as From<&u16>>
116+
<u32 as From<&u32>>
117+
<u32 as From<&u8>>
118+
and 6 others
119+
note: required by `from`
120+
--> $SRC_DIR/core/src/convert/mod.rs:LL:COL
121+
|
122+
LL | fn from(_: T) -> Self;
123+
| ^^^^^^^^^^^^^^^^^^^^^^
124+
125+
error[E0277]: the trait bound `u64: From<&u128>` is not satisfied
126+
--> $DIR/illegal.rs:14:18
127+
|
128+
LL | let _: u64 = From::from(&1_u128);
129+
| ^^^^^^^^^^ the trait `From<&u128>` is not implemented for `u64`
130+
|
131+
= help: the following implementations were found:
132+
<u64 as From<&bool>>
133+
<u64 as From<&u16>>
134+
<u64 as From<&u32>>
135+
<u64 as From<&u64>>
136+
and 7 others
137+
note: required by `from`
138+
--> $SRC_DIR/core/src/convert/mod.rs:LL:COL
139+
|
140+
LL | fn from(_: T) -> Self;
141+
| ^^^^^^^^^^^^^^^^^^^^^^
142+
143+
error[E0277]: the trait bound `i8: From<&u8>` is not satisfied
144+
--> $DIR/illegal.rs:17:17
145+
|
146+
LL | let _: i8 = From::from(&1_u8);
147+
| ^^^^^^^^^^ the trait `From<&u8>` is not implemented for `i8`
148+
|
149+
= help: the following implementations were found:
150+
<i8 as From<&bool>>
151+
<i8 as From<&i8>>
152+
<i8 as From<NonZeroI8>>
153+
<i8 as From<bool>>
154+
note: required by `from`
155+
--> $SRC_DIR/core/src/convert/mod.rs:LL:COL
156+
|
157+
LL | fn from(_: T) -> Self;
158+
| ^^^^^^^^^^^^^^^^^^^^^^
159+
160+
error[E0277]: the trait bound `u16: From<&i8>` is not satisfied
161+
--> $DIR/illegal.rs:18:18
162+
|
163+
LL | let _: u16 = From::from(&1_i8);
164+
| ^^^^^^^^^^ the trait `From<&i8>` is not implemented for `u16`
165+
|
166+
= help: the following implementations were found:
167+
<u16 as From<&bool>>
168+
<u16 as From<&u16>>
169+
<u16 as From<&u8>>
170+
<u16 as From<NonZeroU16>>
171+
and 2 others
172+
note: required by `from`
173+
--> $SRC_DIR/core/src/convert/mod.rs:LL:COL
174+
|
175+
LL | fn from(_: T) -> Self;
176+
| ^^^^^^^^^^^^^^^^^^^^^^
177+
178+
error[E0277]: the trait bound `i32: From<&u32>` is not satisfied
179+
--> $DIR/illegal.rs:19:18
180+
|
181+
LL | let _: i32 = From::from(&1_u32);
182+
| ^^^^^^^^^^ the trait `From<&u32>` is not implemented for `i32`
183+
|
184+
= help: the following implementations were found:
185+
<i32 as From<&bool>>
186+
<i32 as From<&i16>>
187+
<i32 as From<&i32>>
188+
<i32 as From<&i8>>
189+
and 8 others
190+
note: required by `from`
191+
--> $SRC_DIR/core/src/convert/mod.rs:LL:COL
192+
|
193+
LL | fn from(_: T) -> Self;
194+
| ^^^^^^^^^^^^^^^^^^^^^^
195+
196+
error[E0277]: the trait bound `u64: From<&i32>` is not satisfied
197+
--> $DIR/illegal.rs:20:18
198+
|
199+
LL | let _: u64 = From::from(&1_i32);
200+
| ^^^^^^^^^^ the trait `From<&i32>` is not implemented for `u64`
201+
|
202+
= help: the following implementations were found:
203+
<u64 as From<&bool>>
204+
<u64 as From<&u16>>
205+
<u64 as From<&u32>>
206+
<u64 as From<&u64>>
207+
and 7 others
208+
note: required by `from`
209+
--> $SRC_DIR/core/src/convert/mod.rs:LL:COL
210+
|
211+
LL | fn from(_: T) -> Self;
212+
| ^^^^^^^^^^^^^^^^^^^^^^
213+
214+
error[E0277]: the trait bound `i128: From<&u128>` is not satisfied
215+
--> $DIR/illegal.rs:21:19
216+
|
217+
LL | let _: i128 = From::from(&1_u128);
218+
| ^^^^^^^^^^ the trait `From<&u128>` is not implemented for `i128`
219+
|
220+
= help: the following implementations were found:
221+
<i128 as From<&bool>>
222+
<i128 as From<&i128>>
223+
<i128 as From<&i16>>
224+
<i128 as From<&i32>>
225+
and 16 others
226+
note: required by `from`
227+
--> $SRC_DIR/core/src/convert/mod.rs:LL:COL
228+
|
229+
LL | fn from(_: T) -> Self;
230+
| ^^^^^^^^^^^^^^^^^^^^^^
231+
232+
error: aborting due to 13 previous errors
233+
234+
For more information about this error, try `rustc --explain E0277`.

src/test/ui/traits/issue-77982.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ LL | let ips: Vec<_> = (0..100_000).map(|_| u32::from(0u32.into())).collect(
4949
- impl From<NonZeroU32> for u32;
5050
- impl From<bool> for u32;
5151
- impl From<char> for u32;
52-
and 3 more
52+
and 7 more
5353
note: required by `from`
5454
--> $SRC_DIR/core/src/convert/mod.rs:LL:COL
5555
|

src/test/ui/try-trait/bad-interconversion.stderr

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ LL | Ok(Err(123_i32)?)
88
|
99
= note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait
1010
= help: the following implementations were found:
11+
<u8 as From<&bool>>
12+
<u8 as From<&u8>>
1113
<u8 as From<NonZeroU8>>
1214
<u8 as From<bool>>
1315
= note: required because of the requirements on the impl of `FromResidual<Result<Infallible, i32>>` for `Result<u64, u8>`

0 commit comments

Comments
 (0)