mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-25 16:24:46 +00:00
Rollup merge of #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: #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>
This commit is contained in:
commit
9f2ad0a061
@ -125,7 +125,8 @@ impl TryFromSliceError {
|
||||
}
|
||||
|
||||
#[stable(feature = "try_from_slice_error", since = "1.36.0")]
|
||||
impl From<Infallible> for TryFromSliceError {
|
||||
#[rustc_const_unstable(feature = "const_convert", issue = "88674")]
|
||||
impl const From<Infallible> for TryFromSliceError {
|
||||
fn from(x: Infallible) -> TryFromSliceError {
|
||||
match x {}
|
||||
}
|
||||
|
@ -308,7 +308,8 @@ impl<T: Ord + Copy> Ord for Cell<T> {
|
||||
}
|
||||
|
||||
#[stable(feature = "cell_from", since = "1.12.0")]
|
||||
impl<T> From<T> for Cell<T> {
|
||||
#[rustc_const_unstable(feature = "const_convert", issue = "88674")]
|
||||
impl<T> const From<T> for Cell<T> {
|
||||
fn from(t: T) -> Cell<T> {
|
||||
Cell::new(t)
|
||||
}
|
||||
@ -1236,7 +1237,8 @@ impl<T: ?Sized + Ord> Ord for RefCell<T> {
|
||||
}
|
||||
|
||||
#[stable(feature = "cell_from", since = "1.12.0")]
|
||||
impl<T> From<T> for RefCell<T> {
|
||||
#[rustc_const_unstable(feature = "const_convert", issue = "88674")]
|
||||
impl<T> const From<T> for RefCell<T> {
|
||||
fn from(t: T) -> RefCell<T> {
|
||||
RefCell::new(t)
|
||||
}
|
||||
@ -1976,7 +1978,8 @@ impl<T: Default> Default for UnsafeCell<T> {
|
||||
}
|
||||
|
||||
#[stable(feature = "cell_from", since = "1.12.0")]
|
||||
impl<T> From<T> for UnsafeCell<T> {
|
||||
#[rustc_const_unstable(feature = "const_convert", issue = "88674")]
|
||||
impl<T> const From<T> for UnsafeCell<T> {
|
||||
fn from(t: T) -> UnsafeCell<T> {
|
||||
UnsafeCell::new(t)
|
||||
}
|
||||
|
@ -97,7 +97,8 @@ pub unsafe fn from_u32_unchecked(i: u32) -> char {
|
||||
}
|
||||
|
||||
#[stable(feature = "char_convert", since = "1.13.0")]
|
||||
impl From<char> for u32 {
|
||||
#[rustc_const_unstable(feature = "const_convert", issue = "88674")]
|
||||
impl const From<char> for u32 {
|
||||
/// Converts a [`char`] into a [`u32`].
|
||||
///
|
||||
/// # Examples
|
||||
@ -116,7 +117,8 @@ impl From<char> for u32 {
|
||||
}
|
||||
|
||||
#[stable(feature = "more_char_conversions", since = "1.51.0")]
|
||||
impl From<char> for u64 {
|
||||
#[rustc_const_unstable(feature = "const_convert", issue = "88674")]
|
||||
impl const From<char> for u64 {
|
||||
/// Converts a [`char`] into a [`u64`].
|
||||
///
|
||||
/// # Examples
|
||||
@ -137,7 +139,8 @@ impl From<char> for u64 {
|
||||
}
|
||||
|
||||
#[stable(feature = "more_char_conversions", since = "1.51.0")]
|
||||
impl From<char> for u128 {
|
||||
#[rustc_const_unstable(feature = "const_convert", issue = "88674")]
|
||||
impl const From<char> for u128 {
|
||||
/// Converts a [`char`] into a [`u128`].
|
||||
///
|
||||
/// # Examples
|
||||
@ -176,7 +179,8 @@ impl From<char> for u128 {
|
||||
/// for a superset of Windows-1252 that fills the remaining blanks with corresponding
|
||||
/// C0 and C1 control codes.
|
||||
#[stable(feature = "char_convert", since = "1.13.0")]
|
||||
impl From<u8> for char {
|
||||
#[rustc_const_unstable(feature = "const_convert", issue = "88674")]
|
||||
impl const From<u8> for char {
|
||||
/// Converts a [`u8`] into a [`char`].
|
||||
///
|
||||
/// # Examples
|
||||
|
@ -545,7 +545,8 @@ where
|
||||
|
||||
// From (and thus Into) is reflexive
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T> From<T> for T {
|
||||
#[rustc_const_unstable(feature = "const_convert", issue = "88674")]
|
||||
impl<T> const From<T> for T {
|
||||
fn from(t: T) -> T {
|
||||
t
|
||||
}
|
||||
@ -560,7 +561,8 @@ impl<T> From<T> for T {
|
||||
#[allow(unused_attributes)] // FIXME(#58633): do a principled fix instead.
|
||||
#[rustc_reservation_impl = "permitting this impl would forbid us from adding \
|
||||
`impl<T> From<!> for T` later; see rust-lang/rust#64715 for details"]
|
||||
impl<T> From<!> for T {
|
||||
#[rustc_const_unstable(feature = "const_convert", issue = "88674")]
|
||||
impl<T> const From<!> for T {
|
||||
fn from(t: !) -> T {
|
||||
t
|
||||
}
|
||||
@ -726,7 +728,8 @@ impl Ord for Infallible {
|
||||
}
|
||||
|
||||
#[stable(feature = "convert_infallible", since = "1.34.0")]
|
||||
impl From<!> for Infallible {
|
||||
#[rustc_const_unstable(feature = "const_convert", issue = "88674")]
|
||||
impl const From<!> for Infallible {
|
||||
fn from(x: !) -> Self {
|
||||
x
|
||||
}
|
||||
|
@ -74,7 +74,7 @@ impl<T: PartialEq> PartialEq for OnceCell<T> {
|
||||
impl<T: Eq> Eq for OnceCell<T> {}
|
||||
|
||||
#[unstable(feature = "once_cell", issue = "74465")]
|
||||
impl<T> From<T> for OnceCell<T> {
|
||||
impl<T> const From<T> for OnceCell<T> {
|
||||
fn from(value: T) -> Self {
|
||||
OnceCell { inner: UnsafeCell::new(Some(value)) }
|
||||
}
|
||||
|
@ -29,14 +29,15 @@ impl fmt::Display for TryFromIntError {
|
||||
}
|
||||
|
||||
#[stable(feature = "try_from", since = "1.34.0")]
|
||||
impl From<Infallible> for TryFromIntError {
|
||||
#[rustc_const_unstable(feature = "const_convert", issue = "88674")]
|
||||
impl const From<Infallible> for TryFromIntError {
|
||||
fn from(x: Infallible) -> TryFromIntError {
|
||||
match x {}
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "never_type", issue = "35121")]
|
||||
impl From<!> for TryFromIntError {
|
||||
impl const From<!> for TryFromIntError {
|
||||
fn from(never: !) -> TryFromIntError {
|
||||
// Match rather than coerce to make sure that code like
|
||||
// `From<Infallible> for TryFromIntError` above will keep working
|
||||
|
@ -82,7 +82,8 @@ macro_rules! nonzero_integers {
|
||||
}
|
||||
|
||||
#[stable(feature = "from_nonzero", since = "1.31.0")]
|
||||
impl From<$Ty> for $Int {
|
||||
#[rustc_const_unstable(feature = "const_convert", issue = "88674")]
|
||||
impl const From<$Ty> for $Int {
|
||||
#[doc = concat!("Converts a `", stringify!($Ty), "` into an `", stringify!($Int), "`")]
|
||||
#[inline]
|
||||
fn from(nonzero: $Ty) -> Self {
|
||||
|
@ -1723,7 +1723,8 @@ impl<'a, T> IntoIterator for &'a mut Option<T> {
|
||||
}
|
||||
|
||||
#[stable(since = "1.12.0", feature = "option_from")]
|
||||
impl<T> From<T> for Option<T> {
|
||||
#[rustc_const_unstable(feature = "const_convert", issue = "88674")]
|
||||
impl<T> const From<T> for Option<T> {
|
||||
/// Moves `val` into a new [`Some`].
|
||||
///
|
||||
/// # Examples
|
||||
@ -1739,7 +1740,8 @@ impl<T> From<T> for Option<T> {
|
||||
}
|
||||
|
||||
#[stable(feature = "option_ref_from_ref_option", since = "1.30.0")]
|
||||
impl<'a, T> From<&'a Option<T>> for Option<&'a T> {
|
||||
#[rustc_const_unstable(feature = "const_convert", issue = "88674")]
|
||||
impl<'a, T> const From<&'a Option<T>> for Option<&'a T> {
|
||||
/// Converts from `&Option<T>` to `Option<&T>`.
|
||||
///
|
||||
/// # Examples
|
||||
@ -1766,7 +1768,8 @@ impl<'a, T> From<&'a Option<T>> for Option<&'a T> {
|
||||
}
|
||||
|
||||
#[stable(feature = "option_ref_from_ref_option", since = "1.30.0")]
|
||||
impl<'a, T> From<&'a mut Option<T>> for Option<&'a mut T> {
|
||||
#[rustc_const_unstable(feature = "const_convert", issue = "88674")]
|
||||
impl<'a, T> const From<&'a mut Option<T>> for Option<&'a mut T> {
|
||||
/// Converts from `&mut Option<T>` to `Option<&mut T>`
|
||||
///
|
||||
/// # Examples
|
||||
@ -2052,7 +2055,7 @@ impl<T> ops::Try for Option<T> {
|
||||
}
|
||||
|
||||
#[unstable(feature = "try_trait_v2", issue = "84277")]
|
||||
impl<T> ops::FromResidual for Option<T> {
|
||||
impl<T> const ops::FromResidual for Option<T> {
|
||||
#[inline]
|
||||
fn from_residual(residual: Option<convert::Infallible>) -> Self {
|
||||
match residual {
|
||||
|
@ -698,7 +698,8 @@ impl<T: ?Sized> hash::Hash for NonNull<T> {
|
||||
}
|
||||
|
||||
#[unstable(feature = "ptr_internals", issue = "none")]
|
||||
impl<T: ?Sized> From<Unique<T>> for NonNull<T> {
|
||||
#[rustc_const_unstable(feature = "const_convert", issue = "88674")]
|
||||
impl<T: ?Sized> const From<Unique<T>> for NonNull<T> {
|
||||
#[inline]
|
||||
fn from(unique: Unique<T>) -> Self {
|
||||
// SAFETY: A Unique pointer cannot be null, so the conditions for
|
||||
@ -708,7 +709,8 @@ impl<T: ?Sized> From<Unique<T>> for NonNull<T> {
|
||||
}
|
||||
|
||||
#[stable(feature = "nonnull", since = "1.25.0")]
|
||||
impl<T: ?Sized> From<&mut T> for NonNull<T> {
|
||||
#[rustc_const_unstable(feature = "const_convert", issue = "88674")]
|
||||
impl<T: ?Sized> const From<&mut T> for NonNull<T> {
|
||||
#[inline]
|
||||
fn from(reference: &mut T) -> Self {
|
||||
// SAFETY: A mutable reference cannot be null.
|
||||
@ -717,7 +719,8 @@ impl<T: ?Sized> From<&mut T> for NonNull<T> {
|
||||
}
|
||||
|
||||
#[stable(feature = "nonnull", since = "1.25.0")]
|
||||
impl<T: ?Sized> From<&T> for NonNull<T> {
|
||||
#[rustc_const_unstable(feature = "const_convert", issue = "88674")]
|
||||
impl<T: ?Sized> const From<&T> for NonNull<T> {
|
||||
#[inline]
|
||||
fn from(reference: &T) -> Self {
|
||||
// SAFETY: A reference cannot be null, so the conditions for
|
||||
|
@ -176,7 +176,7 @@ impl<T: ?Sized> fmt::Pointer for Unique<T> {
|
||||
}
|
||||
|
||||
#[unstable(feature = "ptr_internals", issue = "none")]
|
||||
impl<T: ?Sized> From<&mut T> for Unique<T> {
|
||||
impl<T: ?Sized> const From<&mut T> for Unique<T> {
|
||||
#[inline]
|
||||
fn from(reference: &mut T) -> Self {
|
||||
// SAFETY: A mutable reference cannot be null
|
||||
|
@ -1273,7 +1273,8 @@ impl<T> AtomicPtr<T> {
|
||||
|
||||
#[cfg(target_has_atomic_load_store = "8")]
|
||||
#[stable(feature = "atomic_bool_from", since = "1.24.0")]
|
||||
impl From<bool> for AtomicBool {
|
||||
#[rustc_const_unstable(feature = "const_convert", issue = "88674")]
|
||||
impl const From<bool> for AtomicBool {
|
||||
/// Converts a `bool` into an `AtomicBool`.
|
||||
///
|
||||
/// # Examples
|
||||
@ -1291,7 +1292,8 @@ impl From<bool> for AtomicBool {
|
||||
|
||||
#[cfg(target_has_atomic_load_store = "ptr")]
|
||||
#[stable(feature = "atomic_from", since = "1.23.0")]
|
||||
impl<T> From<*mut T> for AtomicPtr<T> {
|
||||
#[rustc_const_unstable(feature = "const_convert", issue = "88674")]
|
||||
impl<T> const From<*mut T> for AtomicPtr<T> {
|
||||
#[inline]
|
||||
fn from(p: *mut T) -> Self {
|
||||
Self::new(p)
|
||||
@ -1363,7 +1365,8 @@ macro_rules! atomic_int {
|
||||
}
|
||||
|
||||
#[$stable_from]
|
||||
impl From<$int_type> for $atomic_type {
|
||||
#[rustc_const_unstable(feature = "const_convert", issue = "88674")]
|
||||
impl const From<$int_type> for $atomic_type {
|
||||
#[doc = concat!("Converts an `", stringify!($int_type), "` into an `", stringify!($atomic_type), "`.")]
|
||||
#[inline]
|
||||
fn from(v: $int_type) -> Self { Self::new(v) }
|
||||
|
@ -241,7 +241,8 @@ impl<T, E> Poll<Option<Result<T, E>>> {
|
||||
}
|
||||
|
||||
#[stable(feature = "futures_api", since = "1.36.0")]
|
||||
impl<T> From<T> for Poll<T> {
|
||||
#[rustc_const_unstable(feature = "const_convert", issue = "88674")]
|
||||
impl<T> const From<T> for Poll<T> {
|
||||
/// Convert to a `Ready` variant.
|
||||
///
|
||||
/// # Example
|
||||
|
@ -220,3 +220,10 @@ fn atomic_compare_exchange() {
|
||||
ATOMIC.compare_exchange_weak(0, 1, SeqCst, Acquire).ok();
|
||||
ATOMIC.compare_exchange_weak(0, 1, SeqCst, SeqCst).ok();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn atomic_const_from() {
|
||||
const _ATOMIC_U8: AtomicU8 = AtomicU8::from(1);
|
||||
const _ATOMIC_BOOL: AtomicBool = AtomicBool::from(true);
|
||||
const _ATOMIC_PTR: AtomicPtr<u32> = AtomicPtr::from(core::ptr::null_mut());
|
||||
}
|
||||
|
@ -465,4 +465,13 @@ fn const_cells() {
|
||||
|
||||
const CELL: Cell<i32> = Cell::new(3);
|
||||
const _: i32 = CELL.into_inner();
|
||||
|
||||
const UNSAFE_CELL_FROM: UnsafeCell<i32> = UnsafeCell::from(3);
|
||||
const _: i32 = UNSAFE_CELL.into_inner();
|
||||
|
||||
const REF_CELL_FROM: RefCell<i32> = RefCell::from(3);
|
||||
const _: i32 = REF_CELL.into_inner();
|
||||
|
||||
const CELL_FROM: Cell<i32> = Cell::from(3);
|
||||
const _: i32 = CELL.into_inner();
|
||||
}
|
||||
|
@ -5,6 +5,8 @@ use std::{char, str};
|
||||
#[test]
|
||||
fn test_convert() {
|
||||
assert_eq!(u32::from('a'), 0x61);
|
||||
assert_eq!(u64::from('b'), 0x62);
|
||||
assert_eq!(u128::from('c'), 0x63);
|
||||
assert_eq!(char::from(b'\0'), '\0');
|
||||
assert_eq!(char::from(b'a'), 'a');
|
||||
assert_eq!(char::from(b'\xFF'), '\u{FF}');
|
||||
@ -19,6 +21,16 @@ fn test_convert() {
|
||||
assert!(char::try_from(0xFFFF_FFFF_u32).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
const fn test_convert_const() {
|
||||
assert!(u32::from('a') == 0x61);
|
||||
assert!(u64::from('b') == 0x62);
|
||||
assert!(u128::from('c') == 0x63);
|
||||
assert!(char::from(b'\0') == '\0');
|
||||
assert!(char::from(b'a') == 'a');
|
||||
assert!(char::from(b'\xFF') == '\u{FF}');
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_from_str() {
|
||||
assert_eq!(char::from_str("a").unwrap(), 'a');
|
||||
|
@ -47,6 +47,12 @@ fn unsync_once_cell_drop_empty() {
|
||||
drop(x);
|
||||
}
|
||||
|
||||
#[test]
|
||||
const fn once_cell_const() {
|
||||
let _once_cell: OnceCell<u32> = OnceCell::new();
|
||||
let _once_cell: OnceCell<u32> = OnceCell::from(32);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn clone() {
|
||||
let s = OnceCell::new();
|
||||
|
@ -9,6 +9,7 @@
|
||||
#![feature(cfg_target_has_atomic)]
|
||||
#![feature(const_assume)]
|
||||
#![feature(const_cell_into_inner)]
|
||||
#![feature(const_convert)]
|
||||
#![feature(const_maybe_uninit_assume_init)]
|
||||
#![cfg_attr(bootstrap, feature(const_panic))]
|
||||
#![feature(const_ptr_read)]
|
||||
|
@ -214,6 +214,9 @@ fn nonzero_const() {
|
||||
|
||||
const ONE: Option<NonZeroU8> = NonZeroU8::new(1);
|
||||
assert!(ONE.is_some());
|
||||
|
||||
const FROM_NONZERO: u8 = u8::from(NONZERO);
|
||||
assert_eq!(FROM_NONZERO, 5);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -358,10 +358,17 @@ fn option_const() {
|
||||
// test that the methods of `Option` are usable in a const context
|
||||
|
||||
const OPTION: Option<usize> = Some(32);
|
||||
assert_eq!(OPTION, Some(32));
|
||||
|
||||
const OPTION_FROM: Option<usize> = Option::from(32);
|
||||
assert_eq!(OPTION_FROM, Some(32));
|
||||
|
||||
const REF: Option<&usize> = OPTION.as_ref();
|
||||
assert_eq!(REF, Some(&32));
|
||||
|
||||
const REF_FROM: Option<&usize> = Option::from(&OPTION);
|
||||
assert_eq!(REF_FROM, Some(&32));
|
||||
|
||||
const IS_SOME: bool = OPTION.is_some();
|
||||
assert!(IS_SOME);
|
||||
|
||||
@ -388,6 +395,14 @@ const fn option_const_mut() {
|
||||
None => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
let as_mut: Option<&mut usize> = Option::from(&mut option);
|
||||
match as_mut {
|
||||
Some(v) => *v = 42,
|
||||
None => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
Loading…
Reference in New Issue
Block a user