Skip to content

Commit 9f2ad0a

Browse files
authored
Rollup merge of rust-lang#90009 - woppopo:const_from_more, r=dtolnay
Make more `From` impls `const` (libcore) Adding `const` to `From` implementations in the core. `rustc_const_unstable` attribute is not added to unstable implementations. Tracking issue: rust-lang#88674 <details> <summary>Done</summary><div> - `T` from `T` - `T` from `!` - `Option<T>` from `T` - `Option<&T>` from `&Option<T>` - `Option<&mut T>` from `&mut Option<T>` - `Cell<T>` from `T` - `RefCell<T>` from `T` - `UnsafeCell<T>` from `T` - `OnceCell<T>` from `T` - `Poll<T>` from `T` - `u32` from `char` - `u64` from `char` - `u128` from `char` - `char` from `u8` - `AtomicBool` from `bool` - `AtomicPtr<T>` from `*mut T` - `AtomicI(bits)` from `i(bits)` - `AtomicU(bits)` from `u(bits)` - `i(bits)` from `NonZeroI(bits)` - `u(bits)` from `NonZeroU(bits)` - `NonNull<T>` from `Unique<T>` - `NonNull<T>` from `&T` - `NonNull<T>` from `&mut T` - `Unique<T>` from `&mut T` - `Infallible` from `!` - `TryIntError` from `!` - `TryIntError` from `Infallible` - `TryFromSliceError` from `Infallible` - `FromResidual for Option<T>` </div></details> <details> <summary>Remaining</summary><dev> - `NonZero` from `NonZero` These can't be made const at this time because these use Into::into. https://github.com/rust-lang/rust/blob/master/library/core/src/convert/num.rs#L393 - `std`, `alloc` There may still be many implementations that can be made `const`. </div></details>
2 parents f702499 + 7936ecf commit 9f2ad0a

File tree

19 files changed

+103
-27
lines changed

19 files changed

+103
-27
lines changed

library/core/src/array/mod.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,8 @@ impl TryFromSliceError {
125125
}
126126

127127
#[stable(feature = "try_from_slice_error", since = "1.36.0")]
128-
impl From<Infallible> for TryFromSliceError {
128+
#[rustc_const_unstable(feature = "const_convert", issue = "88674")]
129+
impl const From<Infallible> for TryFromSliceError {
129130
fn from(x: Infallible) -> TryFromSliceError {
130131
match x {}
131132
}

library/core/src/cell.rs

+6-3
Original file line numberDiff line numberDiff line change
@@ -308,7 +308,8 @@ impl<T: Ord + Copy> Ord for Cell<T> {
308308
}
309309

310310
#[stable(feature = "cell_from", since = "1.12.0")]
311-
impl<T> From<T> for Cell<T> {
311+
#[rustc_const_unstable(feature = "const_convert", issue = "88674")]
312+
impl<T> const From<T> for Cell<T> {
312313
fn from(t: T) -> Cell<T> {
313314
Cell::new(t)
314315
}
@@ -1236,7 +1237,8 @@ impl<T: ?Sized + Ord> Ord for RefCell<T> {
12361237
}
12371238

12381239
#[stable(feature = "cell_from", since = "1.12.0")]
1239-
impl<T> From<T> for RefCell<T> {
1240+
#[rustc_const_unstable(feature = "const_convert", issue = "88674")]
1241+
impl<T> const From<T> for RefCell<T> {
12401242
fn from(t: T) -> RefCell<T> {
12411243
RefCell::new(t)
12421244
}
@@ -1976,7 +1978,8 @@ impl<T: Default> Default for UnsafeCell<T> {
19761978
}
19771979

19781980
#[stable(feature = "cell_from", since = "1.12.0")]
1979-
impl<T> From<T> for UnsafeCell<T> {
1981+
#[rustc_const_unstable(feature = "const_convert", issue = "88674")]
1982+
impl<T> const From<T> for UnsafeCell<T> {
19801983
fn from(t: T) -> UnsafeCell<T> {
19811984
UnsafeCell::new(t)
19821985
}

library/core/src/char/convert.rs

+8-4
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,8 @@ pub unsafe fn from_u32_unchecked(i: u32) -> char {
9797
}
9898

9999
#[stable(feature = "char_convert", since = "1.13.0")]
100-
impl From<char> for u32 {
100+
#[rustc_const_unstable(feature = "const_convert", issue = "88674")]
101+
impl const From<char> for u32 {
101102
/// Converts a [`char`] into a [`u32`].
102103
///
103104
/// # Examples
@@ -116,7 +117,8 @@ impl From<char> for u32 {
116117
}
117118

118119
#[stable(feature = "more_char_conversions", since = "1.51.0")]
119-
impl From<char> for u64 {
120+
#[rustc_const_unstable(feature = "const_convert", issue = "88674")]
121+
impl const From<char> for u64 {
120122
/// Converts a [`char`] into a [`u64`].
121123
///
122124
/// # Examples
@@ -137,7 +139,8 @@ impl From<char> for u64 {
137139
}
138140

139141
#[stable(feature = "more_char_conversions", since = "1.51.0")]
140-
impl From<char> for u128 {
142+
#[rustc_const_unstable(feature = "const_convert", issue = "88674")]
143+
impl const From<char> for u128 {
141144
/// Converts a [`char`] into a [`u128`].
142145
///
143146
/// # Examples
@@ -176,7 +179,8 @@ impl From<char> for u128 {
176179
/// for a superset of Windows-1252 that fills the remaining blanks with corresponding
177180
/// C0 and C1 control codes.
178181
#[stable(feature = "char_convert", since = "1.13.0")]
179-
impl From<u8> for char {
182+
#[rustc_const_unstable(feature = "const_convert", issue = "88674")]
183+
impl const From<u8> for char {
180184
/// Converts a [`u8`] into a [`char`].
181185
///
182186
/// # Examples

library/core/src/convert/mod.rs

+6-3
Original file line numberDiff line numberDiff line change
@@ -545,7 +545,8 @@ where
545545

546546
// From (and thus Into) is reflexive
547547
#[stable(feature = "rust1", since = "1.0.0")]
548-
impl<T> From<T> for T {
548+
#[rustc_const_unstable(feature = "const_convert", issue = "88674")]
549+
impl<T> const From<T> for T {
549550
fn from(t: T) -> T {
550551
t
551552
}
@@ -560,7 +561,8 @@ impl<T> From<T> for T {
560561
#[allow(unused_attributes)] // FIXME(#58633): do a principled fix instead.
561562
#[rustc_reservation_impl = "permitting this impl would forbid us from adding \
562563
`impl<T> From<!> for T` later; see rust-lang/rust#64715 for details"]
563-
impl<T> From<!> for T {
564+
#[rustc_const_unstable(feature = "const_convert", issue = "88674")]
565+
impl<T> const From<!> for T {
564566
fn from(t: !) -> T {
565567
t
566568
}
@@ -726,7 +728,8 @@ impl Ord for Infallible {
726728
}
727729

728730
#[stable(feature = "convert_infallible", since = "1.34.0")]
729-
impl From<!> for Infallible {
731+
#[rustc_const_unstable(feature = "const_convert", issue = "88674")]
732+
impl const From<!> for Infallible {
730733
fn from(x: !) -> Self {
731734
x
732735
}

library/core/src/lazy.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ impl<T: PartialEq> PartialEq for OnceCell<T> {
7474
impl<T: Eq> Eq for OnceCell<T> {}
7575

7676
#[unstable(feature = "once_cell", issue = "74465")]
77-
impl<T> From<T> for OnceCell<T> {
77+
impl<T> const From<T> for OnceCell<T> {
7878
fn from(value: T) -> Self {
7979
OnceCell { inner: UnsafeCell::new(Some(value)) }
8080
}

library/core/src/num/error.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,15 @@ impl fmt::Display for TryFromIntError {
2929
}
3030

3131
#[stable(feature = "try_from", since = "1.34.0")]
32-
impl From<Infallible> for TryFromIntError {
32+
#[rustc_const_unstable(feature = "const_convert", issue = "88674")]
33+
impl const From<Infallible> for TryFromIntError {
3334
fn from(x: Infallible) -> TryFromIntError {
3435
match x {}
3536
}
3637
}
3738

3839
#[unstable(feature = "never_type", issue = "35121")]
39-
impl From<!> for TryFromIntError {
40+
impl const From<!> for TryFromIntError {
4041
fn from(never: !) -> TryFromIntError {
4142
// Match rather than coerce to make sure that code like
4243
// `From<Infallible> for TryFromIntError` above will keep working

library/core/src/num/nonzero.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,8 @@ macro_rules! nonzero_integers {
8282
}
8383

8484
#[stable(feature = "from_nonzero", since = "1.31.0")]
85-
impl From<$Ty> for $Int {
85+
#[rustc_const_unstable(feature = "const_convert", issue = "88674")]
86+
impl const From<$Ty> for $Int {
8687
#[doc = concat!("Converts a `", stringify!($Ty), "` into an `", stringify!($Int), "`")]
8788
#[inline]
8889
fn from(nonzero: $Ty) -> Self {

library/core/src/option.rs

+7-4
Original file line numberDiff line numberDiff line change
@@ -1723,7 +1723,8 @@ impl<'a, T> IntoIterator for &'a mut Option<T> {
17231723
}
17241724

17251725
#[stable(since = "1.12.0", feature = "option_from")]
1726-
impl<T> From<T> for Option<T> {
1726+
#[rustc_const_unstable(feature = "const_convert", issue = "88674")]
1727+
impl<T> const From<T> for Option<T> {
17271728
/// Moves `val` into a new [`Some`].
17281729
///
17291730
/// # Examples
@@ -1739,7 +1740,8 @@ impl<T> From<T> for Option<T> {
17391740
}
17401741

17411742
#[stable(feature = "option_ref_from_ref_option", since = "1.30.0")]
1742-
impl<'a, T> From<&'a Option<T>> for Option<&'a T> {
1743+
#[rustc_const_unstable(feature = "const_convert", issue = "88674")]
1744+
impl<'a, T> const From<&'a Option<T>> for Option<&'a T> {
17431745
/// Converts from `&Option<T>` to `Option<&T>`.
17441746
///
17451747
/// # Examples
@@ -1766,7 +1768,8 @@ impl<'a, T> From<&'a Option<T>> for Option<&'a T> {
17661768
}
17671769

17681770
#[stable(feature = "option_ref_from_ref_option", since = "1.30.0")]
1769-
impl<'a, T> From<&'a mut Option<T>> for Option<&'a mut T> {
1771+
#[rustc_const_unstable(feature = "const_convert", issue = "88674")]
1772+
impl<'a, T> const From<&'a mut Option<T>> for Option<&'a mut T> {
17701773
/// Converts from `&mut Option<T>` to `Option<&mut T>`
17711774
///
17721775
/// # Examples
@@ -2052,7 +2055,7 @@ impl<T> ops::Try for Option<T> {
20522055
}
20532056

20542057
#[unstable(feature = "try_trait_v2", issue = "84277")]
2055-
impl<T> ops::FromResidual for Option<T> {
2058+
impl<T> const ops::FromResidual for Option<T> {
20562059
#[inline]
20572060
fn from_residual(residual: Option<convert::Infallible>) -> Self {
20582061
match residual {

library/core/src/ptr/non_null.rs

+6-3
Original file line numberDiff line numberDiff line change
@@ -698,7 +698,8 @@ impl<T: ?Sized> hash::Hash for NonNull<T> {
698698
}
699699

700700
#[unstable(feature = "ptr_internals", issue = "none")]
701-
impl<T: ?Sized> From<Unique<T>> for NonNull<T> {
701+
#[rustc_const_unstable(feature = "const_convert", issue = "88674")]
702+
impl<T: ?Sized> const From<Unique<T>> for NonNull<T> {
702703
#[inline]
703704
fn from(unique: Unique<T>) -> Self {
704705
// SAFETY: A Unique pointer cannot be null, so the conditions for
@@ -708,7 +709,8 @@ impl<T: ?Sized> From<Unique<T>> for NonNull<T> {
708709
}
709710

710711
#[stable(feature = "nonnull", since = "1.25.0")]
711-
impl<T: ?Sized> From<&mut T> for NonNull<T> {
712+
#[rustc_const_unstable(feature = "const_convert", issue = "88674")]
713+
impl<T: ?Sized> const From<&mut T> for NonNull<T> {
712714
#[inline]
713715
fn from(reference: &mut T) -> Self {
714716
// SAFETY: A mutable reference cannot be null.
@@ -717,7 +719,8 @@ impl<T: ?Sized> From<&mut T> for NonNull<T> {
717719
}
718720

719721
#[stable(feature = "nonnull", since = "1.25.0")]
720-
impl<T: ?Sized> From<&T> for NonNull<T> {
722+
#[rustc_const_unstable(feature = "const_convert", issue = "88674")]
723+
impl<T: ?Sized> const From<&T> for NonNull<T> {
721724
#[inline]
722725
fn from(reference: &T) -> Self {
723726
// SAFETY: A reference cannot be null, so the conditions for

library/core/src/ptr/unique.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ impl<T: ?Sized> fmt::Pointer for Unique<T> {
176176
}
177177

178178
#[unstable(feature = "ptr_internals", issue = "none")]
179-
impl<T: ?Sized> From<&mut T> for Unique<T> {
179+
impl<T: ?Sized> const From<&mut T> for Unique<T> {
180180
#[inline]
181181
fn from(reference: &mut T) -> Self {
182182
// SAFETY: A mutable reference cannot be null

library/core/src/sync/atomic.rs

+6-3
Original file line numberDiff line numberDiff line change
@@ -1273,7 +1273,8 @@ impl<T> AtomicPtr<T> {
12731273

12741274
#[cfg(target_has_atomic_load_store = "8")]
12751275
#[stable(feature = "atomic_bool_from", since = "1.24.0")]
1276-
impl From<bool> for AtomicBool {
1276+
#[rustc_const_unstable(feature = "const_convert", issue = "88674")]
1277+
impl const From<bool> for AtomicBool {
12771278
/// Converts a `bool` into an `AtomicBool`.
12781279
///
12791280
/// # Examples
@@ -1291,7 +1292,8 @@ impl From<bool> for AtomicBool {
12911292

12921293
#[cfg(target_has_atomic_load_store = "ptr")]
12931294
#[stable(feature = "atomic_from", since = "1.23.0")]
1294-
impl<T> From<*mut T> for AtomicPtr<T> {
1295+
#[rustc_const_unstable(feature = "const_convert", issue = "88674")]
1296+
impl<T> const From<*mut T> for AtomicPtr<T> {
12951297
#[inline]
12961298
fn from(p: *mut T) -> Self {
12971299
Self::new(p)
@@ -1363,7 +1365,8 @@ macro_rules! atomic_int {
13631365
}
13641366

13651367
#[$stable_from]
1366-
impl From<$int_type> for $atomic_type {
1368+
#[rustc_const_unstable(feature = "const_convert", issue = "88674")]
1369+
impl const From<$int_type> for $atomic_type {
13671370
#[doc = concat!("Converts an `", stringify!($int_type), "` into an `", stringify!($atomic_type), "`.")]
13681371
#[inline]
13691372
fn from(v: $int_type) -> Self { Self::new(v) }

library/core/src/task/poll.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,8 @@ impl<T, E> Poll<Option<Result<T, E>>> {
241241
}
242242

243243
#[stable(feature = "futures_api", since = "1.36.0")]
244-
impl<T> From<T> for Poll<T> {
244+
#[rustc_const_unstable(feature = "const_convert", issue = "88674")]
245+
impl<T> const From<T> for Poll<T> {
245246
/// Convert to a `Ready` variant.
246247
///
247248
/// # Example

library/core/tests/atomic.rs

+7
Original file line numberDiff line numberDiff line change
@@ -220,3 +220,10 @@ fn atomic_compare_exchange() {
220220
ATOMIC.compare_exchange_weak(0, 1, SeqCst, Acquire).ok();
221221
ATOMIC.compare_exchange_weak(0, 1, SeqCst, SeqCst).ok();
222222
}
223+
224+
#[test]
225+
fn atomic_const_from() {
226+
const _ATOMIC_U8: AtomicU8 = AtomicU8::from(1);
227+
const _ATOMIC_BOOL: AtomicBool = AtomicBool::from(true);
228+
const _ATOMIC_PTR: AtomicPtr<u32> = AtomicPtr::from(core::ptr::null_mut());
229+
}

library/core/tests/cell.rs

+9
Original file line numberDiff line numberDiff line change
@@ -465,4 +465,13 @@ fn const_cells() {
465465

466466
const CELL: Cell<i32> = Cell::new(3);
467467
const _: i32 = CELL.into_inner();
468+
469+
const UNSAFE_CELL_FROM: UnsafeCell<i32> = UnsafeCell::from(3);
470+
const _: i32 = UNSAFE_CELL.into_inner();
471+
472+
const REF_CELL_FROM: RefCell<i32> = RefCell::from(3);
473+
const _: i32 = REF_CELL.into_inner();
474+
475+
const CELL_FROM: Cell<i32> = Cell::from(3);
476+
const _: i32 = CELL.into_inner();
468477
}

library/core/tests/char.rs

+12
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ use std::{char, str};
55
#[test]
66
fn test_convert() {
77
assert_eq!(u32::from('a'), 0x61);
8+
assert_eq!(u64::from('b'), 0x62);
9+
assert_eq!(u128::from('c'), 0x63);
810
assert_eq!(char::from(b'\0'), '\0');
911
assert_eq!(char::from(b'a'), 'a');
1012
assert_eq!(char::from(b'\xFF'), '\u{FF}');
@@ -19,6 +21,16 @@ fn test_convert() {
1921
assert!(char::try_from(0xFFFF_FFFF_u32).is_err());
2022
}
2123

24+
#[test]
25+
const fn test_convert_const() {
26+
assert!(u32::from('a') == 0x61);
27+
assert!(u64::from('b') == 0x62);
28+
assert!(u128::from('c') == 0x63);
29+
assert!(char::from(b'\0') == '\0');
30+
assert!(char::from(b'a') == 'a');
31+
assert!(char::from(b'\xFF') == '\u{FF}');
32+
}
33+
2234
#[test]
2335
fn test_from_str() {
2436
assert_eq!(char::from_str("a").unwrap(), 'a');

library/core/tests/lazy.rs

+6
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,12 @@ fn unsync_once_cell_drop_empty() {
4747
drop(x);
4848
}
4949

50+
#[test]
51+
const fn once_cell_const() {
52+
let _once_cell: OnceCell<u32> = OnceCell::new();
53+
let _once_cell: OnceCell<u32> = OnceCell::from(32);
54+
}
55+
5056
#[test]
5157
fn clone() {
5258
let s = OnceCell::new();

library/core/tests/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#![feature(cfg_target_has_atomic)]
1010
#![feature(const_assume)]
1111
#![feature(const_cell_into_inner)]
12+
#![feature(const_convert)]
1213
#![feature(const_maybe_uninit_assume_init)]
1314
#![cfg_attr(bootstrap, feature(const_panic))]
1415
#![feature(const_ptr_read)]

library/core/tests/nonzero.rs

+3
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,9 @@ fn nonzero_const() {
214214

215215
const ONE: Option<NonZeroU8> = NonZeroU8::new(1);
216216
assert!(ONE.is_some());
217+
218+
const FROM_NONZERO: u8 = u8::from(NONZERO);
219+
assert_eq!(FROM_NONZERO, 5);
217220
}
218221

219222
#[test]

library/core/tests/option.rs

+15
Original file line numberDiff line numberDiff line change
@@ -358,10 +358,17 @@ fn option_const() {
358358
// test that the methods of `Option` are usable in a const context
359359

360360
const OPTION: Option<usize> = Some(32);
361+
assert_eq!(OPTION, Some(32));
362+
363+
const OPTION_FROM: Option<usize> = Option::from(32);
364+
assert_eq!(OPTION_FROM, Some(32));
361365

362366
const REF: Option<&usize> = OPTION.as_ref();
363367
assert_eq!(REF, Some(&32));
364368

369+
const REF_FROM: Option<&usize> = Option::from(&OPTION);
370+
assert_eq!(REF_FROM, Some(&32));
371+
365372
const IS_SOME: bool = OPTION.is_some();
366373
assert!(IS_SOME);
367374

@@ -388,6 +395,14 @@ const fn option_const_mut() {
388395
None => unreachable!(),
389396
}
390397
}
398+
399+
{
400+
let as_mut: Option<&mut usize> = Option::from(&mut option);
401+
match as_mut {
402+
Some(v) => *v = 42,
403+
None => unreachable!(),
404+
}
405+
}
391406
}
392407

393408
#[test]

0 commit comments

Comments
 (0)