From 82b4d0d8aa9e1da2c9df3701bc970cb46b00778e Mon Sep 17 00:00:00 2001 From: David Carlier Date: Sun, 11 Aug 2024 12:53:48 +0100 Subject: std::fs::get_path freebsd update. what matters is we re doing the right things as doing sizeof, rather than KINFO_FILE_SIZE (only defined on intel architectures), the kernel making sure it matches the expectation in its side. --- library/std/src/sys/pal/unix/fs.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'library/std/src') diff --git a/library/std/src/sys/pal/unix/fs.rs b/library/std/src/sys/pal/unix/fs.rs index 39aabf0b2d6..1d962fbc0c2 100644 --- a/library/std/src/sys/pal/unix/fs.rs +++ b/library/std/src/sys/pal/unix/fs.rs @@ -1538,7 +1538,7 @@ impl fmt::Debug for File { Some(PathBuf::from(OsString::from_vec(buf))) } - #[cfg(all(target_os = "freebsd", target_arch = "x86_64"))] + #[cfg(target_os = "freebsd")] fn get_path(fd: c_int) -> Option { let info = Box::::new_zeroed(); let mut info = unsafe { info.assume_init() }; @@ -1566,7 +1566,7 @@ impl fmt::Debug for File { #[cfg(not(any( target_os = "linux", target_os = "vxworks", - all(target_os = "freebsd", target_arch = "x86_64"), + target_os = "freebsd", target_os = "netbsd", target_os = "illumos", target_os = "solaris", -- cgit 1.4.1-3-g733a5 From f2d1edfea5689ac638904080ddb972c40e7acc8c Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Sat, 28 Sep 2024 01:46:03 -0400 Subject: Change a few `&Option` into `Option<&T>` --- library/std/src/sys/pal/sgx/net.rs | 14 +++++++------- library/std/src/sys/pal/unix/process/process_common.rs | 4 ++-- library/std/src/sys/pal/unix/process/process_unix.rs | 2 +- library/test/src/lib.rs | 11 ++++++----- library/test/src/test_result.rs | 8 ++++---- 5 files changed, 20 insertions(+), 19 deletions(-) (limited to 'library/std/src') diff --git a/library/std/src/sys/pal/sgx/net.rs b/library/std/src/sys/pal/sgx/net.rs index 44913ffe3a9..c966886d163 100644 --- a/library/std/src/sys/pal/sgx/net.rs +++ b/library/std/src/sys/pal/sgx/net.rs @@ -78,9 +78,8 @@ fn io_err_to_addr(result: io::Result<&SocketAddr>) -> io::Result { } } -fn addr_to_sockaddr(addr: &Option) -> io::Result { - addr.as_ref() - .ok_or(io::ErrorKind::AddrNotAvailable)? +fn addr_to_sockaddr(addr: Option<&str>) -> io::Result { + addr.ok_or(io::ErrorKind::AddrNotAvailable)? .to_socket_addrs() // unwrap OK: if an iterator is returned, we're guaranteed to get exactly one entry .map(|mut it| it.next().unwrap()) @@ -161,11 +160,11 @@ impl TcpStream { } pub fn peer_addr(&self) -> io::Result { - addr_to_sockaddr(&self.peer_addr) + addr_to_sockaddr(self.peer_addr.as_deref()) } pub fn socket_addr(&self) -> io::Result { - addr_to_sockaddr(&self.inner.local_addr) + addr_to_sockaddr(self.inner.local_addr.as_deref()) } pub fn shutdown(&self, _: Shutdown) -> io::Result<()> { @@ -255,13 +254,14 @@ impl TcpListener { } pub fn socket_addr(&self) -> io::Result { - addr_to_sockaddr(&self.inner.local_addr) + addr_to_sockaddr(self.inner.local_addr.as_deref()) } pub fn accept(&self) -> io::Result<(TcpStream, SocketAddr)> { let (fd, local_addr, peer_addr) = usercalls::accept_stream(self.inner.inner.raw())?; let peer_addr = Some(peer_addr); - let ret_peer = addr_to_sockaddr(&peer_addr).unwrap_or_else(|_| ([0; 4], 0).into()); + let ret_peer = + addr_to_sockaddr(peer_addr.as_deref()).unwrap_or_else(|_| ([0; 4], 0).into()); Ok((TcpStream { inner: Socket::new(fd, local_addr), peer_addr }, ret_peer)) } diff --git a/library/std/src/sys/pal/unix/process/process_common.rs b/library/std/src/sys/pal/unix/process/process_common.rs index d9c41d43487..13290fed762 100644 --- a/library/std/src/sys/pal/unix/process/process_common.rs +++ b/library/std/src/sys/pal/unix/process/process_common.rs @@ -312,8 +312,8 @@ impl Command { } #[allow(dead_code)] - pub fn get_cwd(&self) -> &Option { - &self.cwd + pub fn get_cwd(&self) -> Option<&CStr> { + self.cwd.as_deref() } #[allow(dead_code)] pub fn get_uid(&self) -> Option { diff --git a/library/std/src/sys/pal/unix/process/process_unix.rs b/library/std/src/sys/pal/unix/process/process_unix.rs index 5d30f388da1..0fa6551772f 100644 --- a/library/std/src/sys/pal/unix/process/process_unix.rs +++ b/library/std/src/sys/pal/unix/process/process_unix.rs @@ -335,7 +335,7 @@ impl Command { cvt(libc::setuid(u as uid_t))?; } } - if let Some(ref cwd) = *self.get_cwd() { + if let Some(ref cwd) = self.get_cwd() { cvt(libc::chdir(cwd.as_ptr()))?; } diff --git a/library/test/src/lib.rs b/library/test/src/lib.rs index 4b2c65cfdf5..30ccfe2af8d 100644 --- a/library/test/src/lib.rs +++ b/library/test/src/lib.rs @@ -650,8 +650,8 @@ fn run_test_in_process( io::set_output_capture(None); let test_result = match result { - Ok(()) => calc_result(&desc, Ok(()), &time_opts, &exec_time), - Err(e) => calc_result(&desc, Err(e.as_ref()), &time_opts, &exec_time), + Ok(()) => calc_result(&desc, Ok(()), time_opts.as_ref(), exec_time.as_ref()), + Err(e) => calc_result(&desc, Err(e.as_ref()), time_opts.as_ref(), exec_time.as_ref()), }; let stdout = data.lock().unwrap_or_else(|e| e.into_inner()).to_vec(); let message = CompletedTest::new(id, desc, test_result, exec_time, stdout); @@ -712,7 +712,8 @@ fn spawn_test_subprocess( formatters::write_stderr_delimiter(&mut test_output, &desc.name); test_output.extend_from_slice(&stderr); - let result = get_result_from_exit_code(&desc, status, &time_opts, &exec_time); + let result = + get_result_from_exit_code(&desc, status, time_opts.as_ref(), exec_time.as_ref()); (result, test_output, exec_time) })(); @@ -724,8 +725,8 @@ fn run_test_in_spawned_subprocess(desc: TestDesc, runnable_test: RunnableTest) - let builtin_panic_hook = panic::take_hook(); let record_result = Arc::new(move |panic_info: Option<&'_ PanicHookInfo<'_>>| { let test_result = match panic_info { - Some(info) => calc_result(&desc, Err(info.payload()), &None, &None), - None => calc_result(&desc, Ok(()), &None, &None), + Some(info) => calc_result(&desc, Err(info.payload()), None, None), + None => calc_result(&desc, Ok(()), None, None), }; // We don't support serializing TrFailedMsg, so just diff --git a/library/test/src/test_result.rs b/library/test/src/test_result.rs index c5f4b03bfc9..79fe07bc1ac 100644 --- a/library/test/src/test_result.rs +++ b/library/test/src/test_result.rs @@ -42,8 +42,8 @@ pub enum TestResult { pub fn calc_result<'a>( desc: &TestDesc, task_result: Result<(), &'a (dyn Any + 'static + Send)>, - time_opts: &Option, - exec_time: &Option, + time_opts: Option<&time::TestTimeOptions>, + exec_time: Option<&time::TestExecTime>, ) -> TestResult { let result = match (&desc.should_panic, task_result) { (&ShouldPanic::No, Ok(())) | (&ShouldPanic::Yes, Err(_)) => TestResult::TrOk, @@ -96,8 +96,8 @@ pub fn calc_result<'a>( pub fn get_result_from_exit_code( desc: &TestDesc, status: ExitStatus, - time_opts: &Option, - exec_time: &Option, + time_opts: Option<&time::TestTimeOptions>, + exec_time: Option<&time::TestExecTime>, ) -> TestResult { let result = match status.code() { Some(TR_OK) => TestResult::TrOk, -- cgit 1.4.1-3-g733a5 From d2f93c97079a5c7e2b3fff6d3a63f862ce88bb3f Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Wed, 2 Oct 2024 14:25:14 -0400 Subject: Update library/std/src/sys/pal/unix/process/process_unix.rs Co-authored-by: Josh Stone --- library/std/src/sys/pal/unix/process/process_unix.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'library/std/src') diff --git a/library/std/src/sys/pal/unix/process/process_unix.rs b/library/std/src/sys/pal/unix/process/process_unix.rs index 0fa6551772f..4551d49e841 100644 --- a/library/std/src/sys/pal/unix/process/process_unix.rs +++ b/library/std/src/sys/pal/unix/process/process_unix.rs @@ -335,7 +335,7 @@ impl Command { cvt(libc::setuid(u as uid_t))?; } } - if let Some(ref cwd) = self.get_cwd() { + if let Some(cwd) = self.get_cwd() { cvt(libc::chdir(cwd.as_ptr()))?; } -- cgit 1.4.1-3-g733a5 From 442d766cc12014a4a2c5b207ad41019b97fce03b Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Tue, 8 Oct 2024 20:21:27 -0400 Subject: fix ref in process_vxworks.rs --- library/std/src/sys/pal/unix/process/process_vxworks.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'library/std/src') diff --git a/library/std/src/sys/pal/unix/process/process_vxworks.rs b/library/std/src/sys/pal/unix/process/process_vxworks.rs index 2d9a304c495..6add0850a70 100644 --- a/library/std/src/sys/pal/unix/process/process_vxworks.rs +++ b/library/std/src/sys/pal/unix/process/process_vxworks.rs @@ -57,7 +57,7 @@ impl Command { t!(cvt_r(|| libc::dup2(fd, libc::STDERR_FILENO))); } - if let Some(ref cwd) = *self.get_cwd() { + if let Some(cwd) = *self.get_cwd() { t!(cvt(libc::chdir(cwd.as_ptr()))); } -- cgit 1.4.1-3-g733a5 From a278f157241e296ced392a81be5be7e8f608bd3c Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Tue, 8 Oct 2024 22:17:16 -0400 Subject: Update library/std/src/sys/pal/unix/process/process_vxworks.rs Co-authored-by: Josh Stone --- library/std/src/sys/pal/unix/process/process_vxworks.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'library/std/src') diff --git a/library/std/src/sys/pal/unix/process/process_vxworks.rs b/library/std/src/sys/pal/unix/process/process_vxworks.rs index 6add0850a70..38daf6af918 100644 --- a/library/std/src/sys/pal/unix/process/process_vxworks.rs +++ b/library/std/src/sys/pal/unix/process/process_vxworks.rs @@ -57,7 +57,7 @@ impl Command { t!(cvt_r(|| libc::dup2(fd, libc::STDERR_FILENO))); } - if let Some(cwd) = *self.get_cwd() { + if let Some(cwd) = self.get_cwd() { t!(cvt(libc::chdir(cwd.as_ptr()))); } -- cgit 1.4.1-3-g733a5 From 01e248ff974e310be5fb88d374cbed64aa5c4a25 Mon Sep 17 00:00:00 2001 From: Nicola Krumschmidt Date: Wed, 9 Oct 2024 14:39:28 +0200 Subject: Decouple WASIp2 sockets from WasiFd --- library/std/src/os/wasi/mod.rs | 2 + library/std/src/sys/pal/wasip2/net.rs | 74 ++++++++++++++++++++++++++--------- 2 files changed, 58 insertions(+), 18 deletions(-) (limited to 'library/std/src') diff --git a/library/std/src/os/wasi/mod.rs b/library/std/src/os/wasi/mod.rs index 33b50c9e53b..2ee6aa46600 100644 --- a/library/std/src/os/wasi/mod.rs +++ b/library/std/src/os/wasi/mod.rs @@ -36,6 +36,8 @@ pub mod ffi; pub mod fs; pub mod io; + +#[cfg(all(target_os = "wasi", target_env = "p1"))] pub mod net; /// A prelude for conveniently writing platform-specific code. diff --git a/library/std/src/sys/pal/wasip2/net.rs b/library/std/src/sys/pal/wasip2/net.rs index c40eb229ba9..06e623df843 100644 --- a/library/std/src/sys/pal/wasip2/net.rs +++ b/library/std/src/sys/pal/wasip2/net.rs @@ -2,13 +2,12 @@ use libc::{c_int, c_void, size_t}; -use super::fd::WasiFd; use crate::ffi::CStr; use crate::io::{self, BorrowedBuf, BorrowedCursor, IoSlice, IoSliceMut}; use crate::net::{Shutdown, SocketAddr}; -use crate::os::wasi::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, RawFd}; +use crate::os::wasi::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd}; use crate::sys::unsupported; -use crate::sys_common::net::{TcpListener, getsockopt, setsockopt, sockaddr_to_addr}; +use crate::sys_common::net::{getsockopt, setsockopt, sockaddr_to_addr}; use crate::sys_common::{AsInner, FromInner, IntoInner}; use crate::time::{Duration, Instant}; use crate::{cmp, mem, str}; @@ -71,7 +70,9 @@ pub fn cvt_gai(err: c_int) -> io::Result<()> { pub fn init() {} -pub struct Socket(WasiFd); +pub struct WasiSocket(OwnedFd); + +pub struct Socket(WasiSocket); impl Socket { pub fn new(addr: &SocketAddr, ty: c_int) -> io::Result { @@ -327,53 +328,90 @@ impl Socket { } } -impl AsInner for Socket { +impl AsInner for WasiSocket { #[inline] - fn as_inner(&self) -> &WasiFd { + fn as_inner(&self) -> &OwnedFd { &self.0 } } -impl IntoInner for Socket { - fn into_inner(self) -> WasiFd { +impl IntoInner for WasiSocket { + fn into_inner(self) -> OwnedFd { self.0 } } -impl FromInner for Socket { - fn from_inner(inner: WasiFd) -> Socket { - Socket(inner) +impl FromInner for WasiSocket { + fn from_inner(owned_fd: OwnedFd) -> Self { + Self(owned_fd) } } -impl AsFd for Socket { +impl AsFd for WasiSocket { fn as_fd(&self) -> BorrowedFd<'_> { self.0.as_fd() } } -impl AsRawFd for Socket { +impl AsRawFd for WasiSocket { #[inline] fn as_raw_fd(&self) -> RawFd { self.0.as_raw_fd() } } -impl IntoRawFd for Socket { +impl IntoRawFd for WasiSocket { fn into_raw_fd(self) -> RawFd { self.0.into_raw_fd() } } -impl FromRawFd for Socket { +impl FromRawFd for WasiSocket { unsafe fn from_raw_fd(raw_fd: RawFd) -> Self { unsafe { Self(FromRawFd::from_raw_fd(raw_fd)) } } } -impl AsInner for TcpListener { +impl AsInner for Socket { + #[inline] + fn as_inner(&self) -> &WasiSocket { + &self.0 + } +} + +impl IntoInner for Socket { + fn into_inner(self) -> WasiSocket { + self.0 + } +} + +impl FromInner for Socket { + fn from_inner(sock: WasiSocket) -> Socket { + Socket(sock) + } +} + +impl AsFd for Socket { + fn as_fd(&self) -> BorrowedFd<'_> { + self.0.as_fd() + } +} + +impl AsRawFd for Socket { #[inline] - fn as_inner(&self) -> &Socket { - &self.socket() + fn as_raw_fd(&self) -> RawFd { + self.0.as_raw_fd() + } +} + +impl IntoRawFd for Socket { + fn into_raw_fd(self) -> RawFd { + self.0.into_raw_fd() + } +} + +impl FromRawFd for Socket { + unsafe fn from_raw_fd(raw_fd: RawFd) -> Self { + unsafe { Self(FromRawFd::from_raw_fd(raw_fd)) } } } -- cgit 1.4.1-3-g733a5 From e08dc0491a9069681b123bbe27eb388a7861a351 Mon Sep 17 00:00:00 2001 From: LeΓ³n Orell Valerian Liehr Date: Wed, 25 Sep 2024 13:17:58 +0200 Subject: Library: Rename "object safe" to "dyn compatible" --- library/core/src/cell.rs | 6 +++--- library/core/src/error.rs | 21 +++++++++++---------- library/core/src/iter/traits/iterator.rs | 2 +- library/core/src/marker.rs | 3 ++- library/core/src/ops/unsize.rs | 8 +++++--- library/core/tests/hash/mod.rs | 2 +- library/std/src/keyword_docs.rs | 4 +++- 7 files changed, 26 insertions(+), 20 deletions(-) (limited to 'library/std/src') diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index a3e91bc0670..df32c83f645 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -661,7 +661,7 @@ impl Cell { impl, U> CoerceUnsized> for Cell {} // Allow types that wrap `Cell` to also implement `DispatchFromDyn` -// and become object safe method receivers. +// and become dyn-compatible method receivers. // Note that currently `Cell` itself cannot be a method receiver // because it does not implement Deref. // In other words: @@ -2236,7 +2236,7 @@ impl From for UnsafeCell { impl, U> CoerceUnsized> for UnsafeCell {} // Allow types that wrap `UnsafeCell` to also implement `DispatchFromDyn` -// and become object safe method receivers. +// and become dyn-compatible method receivers. // Note that currently `UnsafeCell` itself cannot be a method receiver // because it does not implement Deref. // In other words: @@ -2379,7 +2379,7 @@ impl From for SyncUnsafeCell { impl, U> CoerceUnsized> for SyncUnsafeCell {} // Allow types that wrap `SyncUnsafeCell` to also implement `DispatchFromDyn` -// and become object safe method receivers. +// and become dyn-compatible method receivers. // Note that currently `SyncUnsafeCell` itself cannot be a method receiver // because it does not implement Deref. // In other words: diff --git a/library/core/src/error.rs b/library/core/src/error.rs index cac00b37d1f..95a39cc3aed 100644 --- a/library/core/src/error.rs +++ b/library/core/src/error.rs @@ -335,16 +335,17 @@ impl dyn Error { #[unstable(feature = "error_iter", issue = "58520")] #[inline] pub fn sources(&self) -> Source<'_> { - // You may think this method would be better in the Error trait, and you'd be right. - // Unfortunately that doesn't work, not because of the object safety rules but because we - // save a reference to self in Sources below as a trait object. If this method was - // declared in Error, then self would have the type &T where T is some concrete type which - // implements Error. We would need to coerce self to have type &dyn Error, but that requires - // that Self has a known size (i.e., Self: Sized). We can't put that bound on Error - // since that would forbid Error trait objects, and we can't put that bound on the method - // because that means the method can't be called on trait objects (we'd also need the - // 'static bound, but that isn't allowed because methods with bounds on Self other than - // Sized are not object-safe). Requiring an Unsize bound is not backwards compatible. + // You may think this method would be better in the `Error` trait, and you'd be right. + // Unfortunately that doesn't work, not because of the dyn-incompatibility rules but + // because we save a reference to `self` in `Source`s below as a trait object. + // If this method was declared in `Error`, then `self` would have the type `&T` where + // `T` is some concrete type which implements `Error`. We would need to coerce `self` + // to have type `&dyn Error`, but that requires that `Self` has a known size + // (i.e., `Self: Sized`). We can't put that bound on `Error` since that would forbid + // `Error` trait objects, and we can't put that bound on the method because that means + // the method can't be called on trait objects (we'd also need the `'static` bound, + // but that isn't allowed because methods with bounds on `Self` other than `Sized` are + // dyn-incompatible). Requiring an `Unsize` bound is not backwards compatible. Source { current: Some(self) } } diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index 7963459bfb5..302720eddef 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -9,7 +9,7 @@ use crate::cmp::{self, Ordering}; use crate::num::NonZero; use crate::ops::{ChangeOutputType, ControlFlow, FromResidual, Residual, Try}; -fn _assert_is_object_safe(_: &dyn Iterator) {} +fn _assert_is_dyn_compatible(_: &dyn Iterator) {} /// A trait for dealing with iterators. /// diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs index fd41b80cdbd..aed6be4c627 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -158,7 +158,7 @@ pub trait Sized { /// - Arrays `[T; N]` implement `Unsize<[T]>`. /// - A type implements `Unsize` if all of these conditions are met: /// - The type implements `Trait`. -/// - `Trait` is object safe. +/// - `Trait` is dyn-compatible[^1]. /// - The type is sized. /// - The type outlives `'a`. /// - Structs `Foo<..., T1, ..., Tn, ...>` implement `Unsize>` @@ -178,6 +178,7 @@ pub trait Sized { /// [`Rc`]: ../../std/rc/struct.Rc.html /// [RFC982]: https://github.com/rust-lang/rfcs/blob/master/text/0982-dst-coercion.md /// [nomicon-coerce]: ../../nomicon/coercions.html +/// [^1]: Formerly known as *object safe*. #[unstable(feature = "unsize", issue = "18598")] #[lang = "unsize"] #[rustc_deny_explicit_impl(implement_via_object = false)] diff --git a/library/core/src/ops/unsize.rs b/library/core/src/ops/unsize.rs index b51f12580ea..d2a07197f6f 100644 --- a/library/core/src/ops/unsize.rs +++ b/library/core/src/ops/unsize.rs @@ -68,8 +68,8 @@ impl, U: ?Sized> CoerceUnsized<*const U> for *mut T {} #[unstable(feature = "coerce_unsized", issue = "18598")] impl, U: ?Sized> CoerceUnsized<*const U> for *const T {} -/// `DispatchFromDyn` is used in the implementation of object safety checks (specifically allowing -/// arbitrary self types), to guarantee that a method's receiver type can be dispatched on. +/// `DispatchFromDyn` is used in the implementation of dyn-compatibility[^1] checks (specifically +/// allowing arbitrary self types), to guarantee that a method's receiver type can be dispatched on. /// /// Note: `DispatchFromDyn` was briefly named `CoerceSized` (and had a slightly different /// interpretation). @@ -80,7 +80,7 @@ impl, U: ?Sized> CoerceUnsized<*const U> for *const T {} /// type). The compiler must generate an implicit conversion from the trait object/wide pointer to /// the concrete reference/narrow pointer. Implementing `DispatchFromDyn` indicates that that /// conversion is allowed and thus that the type implementing `DispatchFromDyn` is safe to use as -/// the self type in an object-safe method. (in the above example, the compiler will require +/// the self type in an dyn-compatible method. (in the above example, the compiler will require /// `DispatchFromDyn` is implemented for `&'a U`). /// /// `DispatchFromDyn` does not specify the conversion from wide pointer to narrow pointer; the @@ -112,6 +112,8 @@ impl, U: ?Sized> CoerceUnsized<*const U> for *const T {} /// T: Unsize, /// {} /// ``` +/// +/// [^1]: Formerly known as *object safety*. #[unstable(feature = "dispatch_from_dyn", issue = "none")] #[lang = "dispatch_from_dyn"] pub trait DispatchFromDyn { diff --git a/library/core/tests/hash/mod.rs b/library/core/tests/hash/mod.rs index 03826fc4c92..bf91e9e5df0 100644 --- a/library/core/tests/hash/mod.rs +++ b/library/core/tests/hash/mod.rs @@ -164,7 +164,7 @@ fn test_indirect_hasher() { } #[test] -fn test_build_hasher_object_safe() { +fn test_build_hasher_dyn_compatible() { use std::hash::{DefaultHasher, RandomState}; let _: &dyn BuildHasher = &RandomState::new(); diff --git a/library/std/src/keyword_docs.rs b/library/std/src/keyword_docs.rs index 9f4d244b547..453b2708daa 100644 --- a/library/std/src/keyword_docs.rs +++ b/library/std/src/keyword_docs.rs @@ -2349,12 +2349,13 @@ mod async_keyword {} /// [`async`]: ../std/keyword.async.html mod await_keyword {} +// FIXME(dyn_compat_renaming): Update URL and link text. #[doc(keyword = "dyn")] // /// `dyn` is a prefix of a [trait object]'s type. /// /// The `dyn` keyword is used to highlight that calls to methods on the associated `Trait` -/// are [dynamically dispatched]. To use the trait this way, it must be 'object safe'. +/// are [dynamically dispatched]. To use the trait this way, it must be 'dyn-compatible'[^1]. /// /// Unlike generic parameters or `impl Trait`, the compiler does not know the concrete type that /// is being passed. That is, the type has been [erased]. @@ -2382,6 +2383,7 @@ mod await_keyword {} /// [ref-trait-obj]: ../reference/types/trait-object.html /// [ref-obj-safety]: ../reference/items/traits.html#object-safety /// [erased]: https://en.wikipedia.org/wiki/Type_erasure +/// [^1]: Formerly known as 'object safe'. mod dyn_keyword {} #[doc(keyword = "union")] -- cgit 1.4.1-3-g733a5 From 7b52e6bc479bcefc531fde4947c00cc725d8813d Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Wed, 9 Oct 2024 12:43:23 -0700 Subject: Mention allocation errors for `open_buffered` --- library/std/src/fs.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'library/std/src') diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index 124ef121b18..675140ff18f 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -394,7 +394,8 @@ impl File { /// /// # Errors /// - /// This function will return an error if `path` does not already exist. + /// This function will return an error if `path` does not already exist, + /// or if memory allocation fails for the new buffer. /// Other errors may also be returned according to [`OpenOptions::open`]. /// /// # Examples -- cgit 1.4.1-3-g733a5 From 203573701a186490db661f52bbf852906d45a2fb Mon Sep 17 00:00:00 2001 From: "Tim (Theemathas) Chirananthavat" Date: Thu, 10 Oct 2024 23:12:03 +0700 Subject: More clearly document Stdin::read_line These are common pitfalls for beginners, so I think it's worth making the subtleties more visible. --- library/std/src/io/stdio.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'library/std/src') diff --git a/library/std/src/io/stdio.rs b/library/std/src/io/stdio.rs index bf242e715bd..35b38ed783f 100644 --- a/library/std/src/io/stdio.rs +++ b/library/std/src/io/stdio.rs @@ -370,7 +370,12 @@ impl Stdin { /// Locks this handle and reads a line of input, appending it to the specified buffer. /// /// For detailed semantics of this method, see the documentation on - /// [`BufRead::read_line`]. + /// [`BufRead::read_line`]. In particular: + /// * Previous content of the buffer will be preserved. To avoid appending + /// to the buffer, you need to [`clear`] it first. + /// * The trailing newline character, if any, is included in the buffer. + /// + /// [`clear`]: String::clear /// /// # Examples /// -- cgit 1.4.1-3-g733a5 From 624c071b997f3bab0ef086af24f59ebc95f37c59 Mon Sep 17 00:00:00 2001 From: Manuel Drehwald Date: Fri, 11 Oct 2024 19:13:31 +0200 Subject: Single commit implementing the enzyme/autodiff frontend Co-authored-by: Lorenz Schmidt --- compiler/rustc_ast/src/expand/autodiff_attrs.rs | 283 ++++++++ compiler/rustc_ast/src/expand/mod.rs | 2 + compiler/rustc_ast/src/expand/typetree.rs | 90 +++ compiler/rustc_builtin_macros/Cargo.toml | 4 + compiler/rustc_builtin_macros/messages.ftl | 9 + compiler/rustc_builtin_macros/src/autodiff.rs | 820 ++++++++++++++++++++++++ compiler/rustc_builtin_macros/src/errors.rs | 72 +++ compiler/rustc_builtin_macros/src/lib.rs | 3 + compiler/rustc_expand/src/build.rs | 29 + compiler/rustc_feature/src/builtin_attrs.rs | 5 + compiler/rustc_passes/messages.ftl | 4 + compiler/rustc_passes/src/check_attr.rs | 15 + compiler/rustc_passes/src/errors.rs | 8 + compiler/rustc_span/src/symbol.rs | 5 + library/core/src/lib.rs | 9 + library/core/src/macros/mod.rs | 18 + library/std/src/lib.rs | 9 +- 17 files changed, 1384 insertions(+), 1 deletion(-) create mode 100644 compiler/rustc_ast/src/expand/autodiff_attrs.rs create mode 100644 compiler/rustc_ast/src/expand/typetree.rs create mode 100644 compiler/rustc_builtin_macros/src/autodiff.rs (limited to 'library/std/src') diff --git a/compiler/rustc_ast/src/expand/autodiff_attrs.rs b/compiler/rustc_ast/src/expand/autodiff_attrs.rs new file mode 100644 index 00000000000..05714731b9d --- /dev/null +++ b/compiler/rustc_ast/src/expand/autodiff_attrs.rs @@ -0,0 +1,283 @@ +//! This crate handles the user facing autodiff macro. For each `#[autodiff(...)]` attribute, +//! we create an [`AutoDiffItem`] which contains the source and target function names. The source +//! is the function to which the autodiff attribute is applied, and the target is the function +//! getting generated by us (with a name given by the user as the first autodiff arg). + +use std::fmt::{self, Display, Formatter}; +use std::str::FromStr; + +use crate::expand::typetree::TypeTree; +use crate::expand::{Decodable, Encodable, HashStable_Generic}; +use crate::ptr::P; +use crate::{Ty, TyKind}; + +/// Forward and Reverse Mode are well known names for automatic differentiation implementations. +/// Enzyme does support both, but with different semantics, see DiffActivity. The First variants +/// are a hack to support higher order derivatives. We need to compute first order derivatives +/// before we compute second order derivatives, otherwise we would differentiate our placeholder +/// functions. The proper solution is to recognize and resolve this DAG of autodiff invocations, +/// as it's already done in the C++ and Julia frontend of Enzyme. +/// +/// (FIXME) remove *First variants. +/// Documentation for using [reverse](https://enzyme.mit.edu/rust/rev.html) and +/// [forward](https://enzyme.mit.edu/rust/fwd.html) mode is available online. +#[derive(Clone, Copy, Eq, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)] +pub enum DiffMode { + /// No autodiff is applied (used during error handling). + Error, + /// The primal function which we will differentiate. + Source, + /// The target function, to be created using forward mode AD. + Forward, + /// The target function, to be created using reverse mode AD. + Reverse, + /// The target function, to be created using forward mode AD. + /// This target function will also be used as a source for higher order derivatives, + /// so compute it before all Forward/Reverse targets and optimize it through llvm. + ForwardFirst, + /// The target function, to be created using reverse mode AD. + /// This target function will also be used as a source for higher order derivatives, + /// so compute it before all Forward/Reverse targets and optimize it through llvm. + ReverseFirst, +} + +/// Dual and Duplicated (and their Only variants) are getting lowered to the same Enzyme Activity. +/// However, under forward mode we overwrite the previous shadow value, while for reverse mode +/// we add to the previous shadow value. To not surprise users, we picked different names. +/// Dual numbers is also a quite well known name for forward mode AD types. +#[derive(Clone, Copy, Eq, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)] +pub enum DiffActivity { + /// Implicit or Explicit () return type, so a special case of Const. + None, + /// Don't compute derivatives with respect to this input/output. + Const, + /// Reverse Mode, Compute derivatives for this scalar input/output. + Active, + /// Reverse Mode, Compute derivatives for this scalar output, but don't compute + /// the original return value. + ActiveOnly, + /// Forward Mode, Compute derivatives for this input/output and *overwrite* the shadow argument + /// with it. + Dual, + /// Forward Mode, Compute derivatives for this input/output and *overwrite* the shadow argument + /// with it. Drop the code which updates the original input/output for maximum performance. + DualOnly, + /// Reverse Mode, Compute derivatives for this &T or *T input and *add* it to the shadow argument. + Duplicated, + /// Reverse Mode, Compute derivatives for this &T or *T input and *add* it to the shadow argument. + /// Drop the code which updates the original input for maximum performance. + DuplicatedOnly, + /// All Integers must be Const, but these are used to mark the integer which represents the + /// length of a slice/vec. This is used for safety checks on slices. + FakeActivitySize, +} +/// We generate one of these structs for each `#[autodiff(...)]` attribute. +#[derive(Clone, Eq, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)] +pub struct AutoDiffItem { + /// The name of the function getting differentiated + pub source: String, + /// The name of the function being generated + pub target: String, + pub attrs: AutoDiffAttrs, + /// Describe the memory layout of input types + pub inputs: Vec, + /// Describe the memory layout of the output type + pub output: TypeTree, +} +#[derive(Clone, Eq, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)] +pub struct AutoDiffAttrs { + /// Conceptually either forward or reverse mode AD, as described in various autodiff papers and + /// e.g. in the [JAX + /// Documentation](https://jax.readthedocs.io/en/latest/_tutorials/advanced-autodiff.html#how-it-s-made-two-foundational-autodiff-functions). + pub mode: DiffMode, + pub ret_activity: DiffActivity, + pub input_activity: Vec, +} + +impl DiffMode { + pub fn is_rev(&self) -> bool { + matches!(self, DiffMode::Reverse | DiffMode::ReverseFirst) + } + pub fn is_fwd(&self) -> bool { + matches!(self, DiffMode::Forward | DiffMode::ForwardFirst) + } +} + +impl Display for DiffMode { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + match self { + DiffMode::Error => write!(f, "Error"), + DiffMode::Source => write!(f, "Source"), + DiffMode::Forward => write!(f, "Forward"), + DiffMode::Reverse => write!(f, "Reverse"), + DiffMode::ForwardFirst => write!(f, "ForwardFirst"), + DiffMode::ReverseFirst => write!(f, "ReverseFirst"), + } + } +} + +/// Active(Only) is valid in reverse-mode AD for scalar float returns (f16/f32/...). +/// Dual(Only) is valid in forward-mode AD for scalar float returns (f16/f32/...). +/// Const is valid for all cases and means that we don't compute derivatives wrt. this output. +/// That usually means we have a &mut or *mut T output and compute derivatives wrt. that arg, +/// but this is too complex to verify here. Also it's just a logic error if users get this wrong. +pub fn valid_ret_activity(mode: DiffMode, activity: DiffActivity) -> bool { + if activity == DiffActivity::None { + // Only valid if primal returns (), but we can't check that here. + return true; + } + match mode { + DiffMode::Error => false, + DiffMode::Source => false, + DiffMode::Forward | DiffMode::ForwardFirst => { + activity == DiffActivity::Dual + || activity == DiffActivity::DualOnly + || activity == DiffActivity::Const + } + DiffMode::Reverse | DiffMode::ReverseFirst => { + activity == DiffActivity::Const + || activity == DiffActivity::Active + || activity == DiffActivity::ActiveOnly + } + } +} + +/// For indirections (ptr/ref) we can't use Active, since Active allocates a shadow value +/// for the given argument, but we generally can't know the size of such a type. +/// For scalar types (f16/f32/f64/f128) we can use Active and we can't use Duplicated, +/// since Duplicated expects a mutable ref/ptr and we would thus end up with a shadow value +/// who is an indirect type, which doesn't match the primal scalar type. We can't prevent +/// users here from marking scalars as Duplicated, due to type aliases. +pub fn valid_ty_for_activity(ty: &P, activity: DiffActivity) -> bool { + use DiffActivity::*; + // It's always allowed to mark something as Const, since we won't compute derivatives wrt. it. + if matches!(activity, Const) { + return true; + } + if matches!(activity, Dual | DualOnly) { + return true; + } + // FIXME(ZuseZ4) We should make this more robust to also + // handle type aliases. Once that is done, we can be more restrictive here. + if matches!(activity, Active | ActiveOnly) { + return true; + } + matches!(ty.kind, TyKind::Ptr(_) | TyKind::Ref(..)) + && matches!(activity, Duplicated | DuplicatedOnly) +} +pub fn valid_input_activity(mode: DiffMode, activity: DiffActivity) -> bool { + use DiffActivity::*; + return match mode { + DiffMode::Error => false, + DiffMode::Source => false, + DiffMode::Forward | DiffMode::ForwardFirst => { + matches!(activity, Dual | DualOnly | Const) + } + DiffMode::Reverse | DiffMode::ReverseFirst => { + matches!(activity, Active | ActiveOnly | Duplicated | DuplicatedOnly | Const) + } + }; +} + +impl Display for DiffActivity { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + match self { + DiffActivity::None => write!(f, "None"), + DiffActivity::Const => write!(f, "Const"), + DiffActivity::Active => write!(f, "Active"), + DiffActivity::ActiveOnly => write!(f, "ActiveOnly"), + DiffActivity::Dual => write!(f, "Dual"), + DiffActivity::DualOnly => write!(f, "DualOnly"), + DiffActivity::Duplicated => write!(f, "Duplicated"), + DiffActivity::DuplicatedOnly => write!(f, "DuplicatedOnly"), + DiffActivity::FakeActivitySize => write!(f, "FakeActivitySize"), + } + } +} + +impl FromStr for DiffMode { + type Err = (); + + fn from_str(s: &str) -> Result { + match s { + "Error" => Ok(DiffMode::Error), + "Source" => Ok(DiffMode::Source), + "Forward" => Ok(DiffMode::Forward), + "Reverse" => Ok(DiffMode::Reverse), + "ForwardFirst" => Ok(DiffMode::ForwardFirst), + "ReverseFirst" => Ok(DiffMode::ReverseFirst), + _ => Err(()), + } + } +} +impl FromStr for DiffActivity { + type Err = (); + + fn from_str(s: &str) -> Result { + match s { + "None" => Ok(DiffActivity::None), + "Active" => Ok(DiffActivity::Active), + "ActiveOnly" => Ok(DiffActivity::ActiveOnly), + "Const" => Ok(DiffActivity::Const), + "Dual" => Ok(DiffActivity::Dual), + "DualOnly" => Ok(DiffActivity::DualOnly), + "Duplicated" => Ok(DiffActivity::Duplicated), + "DuplicatedOnly" => Ok(DiffActivity::DuplicatedOnly), + _ => Err(()), + } + } +} + +impl AutoDiffAttrs { + pub fn has_ret_activity(&self) -> bool { + self.ret_activity != DiffActivity::None + } + pub fn has_active_only_ret(&self) -> bool { + self.ret_activity == DiffActivity::ActiveOnly + } + + pub fn error() -> Self { + AutoDiffAttrs { + mode: DiffMode::Error, + ret_activity: DiffActivity::None, + input_activity: Vec::new(), + } + } + pub fn source() -> Self { + AutoDiffAttrs { + mode: DiffMode::Source, + ret_activity: DiffActivity::None, + input_activity: Vec::new(), + } + } + + pub fn is_active(&self) -> bool { + self.mode != DiffMode::Error + } + + pub fn is_source(&self) -> bool { + self.mode == DiffMode::Source + } + pub fn apply_autodiff(&self) -> bool { + !matches!(self.mode, DiffMode::Error | DiffMode::Source) + } + + pub fn into_item( + self, + source: String, + target: String, + inputs: Vec, + output: TypeTree, + ) -> AutoDiffItem { + AutoDiffItem { source, target, inputs, output, attrs: self } + } +} + +impl fmt::Display for AutoDiffItem { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "Differentiating {} -> {}", self.source, self.target)?; + write!(f, " with attributes: {:?}", self.attrs)?; + write!(f, " with inputs: {:?}", self.inputs)?; + write!(f, " with output: {:?}", self.output) + } +} diff --git a/compiler/rustc_ast/src/expand/mod.rs b/compiler/rustc_ast/src/expand/mod.rs index 13413281bc7..d259677e98e 100644 --- a/compiler/rustc_ast/src/expand/mod.rs +++ b/compiler/rustc_ast/src/expand/mod.rs @@ -7,6 +7,8 @@ use rustc_span::symbol::Ident; use crate::MetaItem; pub mod allocator; +pub mod autodiff_attrs; +pub mod typetree; #[derive(Debug, Clone, Encodable, Decodable, HashStable_Generic)] pub struct StrippedCfgItem { diff --git a/compiler/rustc_ast/src/expand/typetree.rs b/compiler/rustc_ast/src/expand/typetree.rs new file mode 100644 index 00000000000..9a2dd2e85e0 --- /dev/null +++ b/compiler/rustc_ast/src/expand/typetree.rs @@ -0,0 +1,90 @@ +//! This module contains the definition of the `TypeTree` and `Type` structs. +//! They are thin Rust wrappers around the TypeTrees used by Enzyme as the LLVM based autodiff +//! backend. The Enzyme TypeTrees currently have various limitations and should be rewritten, so the +//! Rust frontend obviously has the same limitations. The main motivation of TypeTrees is to +//! represent how a type looks like "in memory". Enzyme can deduce this based on usage patterns in +//! the user code, but this is extremely slow and not even always sufficient. As such we lower some +//! information from rustc to help Enzyme. For a full explanation of their design it is necessary to +//! analyze the implementation in Enzyme core itself. As a rough summary, `-1` in Enzyme speech means +//! everywhere. That is `{0:-1: Float}` means at index 0 you have a ptr, if you dereference it it +//! will be floats everywhere. Thus `* f32`. If you have `{-1:int}` it means int's everywhere, +//! e.g. [i32; N]. `{0:-1:-1 float}` then means one pointer at offset 0, if you dereference it there +//! will be only pointers, if you dereference these new pointers they will point to array of floats. +//! Generally, it allows byte-specific descriptions. +//! FIXME: This description might be partly inaccurate and should be extended, along with +//! adding documentation to the corresponding Enzyme core code. +//! FIXME: Rewrite the TypeTree logic in Enzyme core to reduce the need for the rustc frontend to +//! provide typetree information. +//! FIXME: We should also re-evaluate where we create TypeTrees from Rust types, since MIR +//! representations of some types might not be accurate. For example a vector of floats might be +//! represented as a vector of u8s in MIR in some cases. + +use std::fmt; + +use crate::expand::{Decodable, Encodable, HashStable_Generic}; + +#[derive(Clone, Copy, Eq, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)] +pub enum Kind { + Anything, + Integer, + Pointer, + Half, + Float, + Double, + Unknown, +} + +#[derive(Clone, Eq, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)] +pub struct TypeTree(pub Vec); + +impl TypeTree { + pub fn new() -> Self { + Self(Vec::new()) + } + pub fn all_ints() -> Self { + Self(vec![Type { offset: -1, size: 1, kind: Kind::Integer, child: TypeTree::new() }]) + } + pub fn int(size: usize) -> Self { + let mut ints = Vec::with_capacity(size); + for i in 0..size { + ints.push(Type { + offset: i as isize, + size: 1, + kind: Kind::Integer, + child: TypeTree::new(), + }); + } + Self(ints) + } +} + +#[derive(Clone, Eq, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)] +pub struct FncTree { + pub args: Vec, + pub ret: TypeTree, +} + +#[derive(Clone, Eq, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)] +pub struct Type { + pub offset: isize, + pub size: usize, + pub kind: Kind, + pub child: TypeTree, +} + +impl Type { + pub fn add_offset(self, add: isize) -> Self { + let offset = match self.offset { + -1 => add, + x => add + x, + }; + + Self { size: self.size, kind: self.kind, child: self.child, offset } + } +} + +impl fmt::Display for Type { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + ::fmt(self, f) + } +} diff --git a/compiler/rustc_builtin_macros/Cargo.toml b/compiler/rustc_builtin_macros/Cargo.toml index 21b87be4b81..ef48486f6f1 100644 --- a/compiler/rustc_builtin_macros/Cargo.toml +++ b/compiler/rustc_builtin_macros/Cargo.toml @@ -3,6 +3,10 @@ name = "rustc_builtin_macros" version = "0.0.0" edition = "2021" + +[lints.rust] +unexpected_cfgs = { level = "warn", check-cfg = ['cfg(llvm_enzyme)'] } + [lib] doctest = false diff --git a/compiler/rustc_builtin_macros/messages.ftl b/compiler/rustc_builtin_macros/messages.ftl index 77cb8dc63c4..6ebc2fd870c 100644 --- a/compiler/rustc_builtin_macros/messages.ftl +++ b/compiler/rustc_builtin_macros/messages.ftl @@ -69,6 +69,15 @@ builtin_macros_assert_requires_boolean = macro requires a boolean expression as builtin_macros_assert_requires_expression = macro requires an expression as an argument .suggestion = try removing semicolon +builtin_macros_autodiff = autodiff must be applied to function +builtin_macros_autodiff_missing_config = autodiff requires at least a name and mode +builtin_macros_autodiff_mode = unknown Mode: `{$mode}`. Use `Forward` or `Reverse` +builtin_macros_autodiff_mode_activity = {$act} can not be used in {$mode} Mode +builtin_macros_autodiff_not_build = this rustc version does not support autodiff +builtin_macros_autodiff_number_activities = expected {$expected} activities, but found {$found} +builtin_macros_autodiff_ty_activity = {$act} can not be used for this type + +builtin_macros_autodiff_unknown_activity = did not recognize Activity: `{$act}` builtin_macros_bad_derive_target = `derive` may only be applied to `struct`s, `enum`s and `union`s .label = not applicable here .label2 = not a `struct`, `enum` or `union` diff --git a/compiler/rustc_builtin_macros/src/autodiff.rs b/compiler/rustc_builtin_macros/src/autodiff.rs new file mode 100644 index 00000000000..66bb11ca522 --- /dev/null +++ b/compiler/rustc_builtin_macros/src/autodiff.rs @@ -0,0 +1,820 @@ +//! This module contains the implementation of the `#[autodiff]` attribute. +//! Currently our linter isn't smart enough to see that each import is used in one of the two +//! configs (autodiff enabled or disabled), so we have to add cfg's to each import. +//! FIXME(ZuseZ4): Remove this once we have a smarter linter. + +#[cfg(llvm_enzyme)] +mod llvm_enzyme { + use std::str::FromStr; + use std::string::String; + + use rustc_ast::expand::autodiff_attrs::{ + AutoDiffAttrs, DiffActivity, DiffMode, valid_input_activity, valid_ty_for_activity, + }; + use rustc_ast::ptr::P; + use rustc_ast::token::{Token, TokenKind}; + use rustc_ast::tokenstream::*; + use rustc_ast::visit::AssocCtxt::*; + use rustc_ast::{ + self as ast, AssocItemKind, BindingMode, FnRetTy, FnSig, Generics, ItemKind, MetaItemInner, + PatKind, TyKind, + }; + use rustc_expand::base::{Annotatable, ExtCtxt}; + use rustc_span::symbol::{Ident, kw, sym}; + use rustc_span::{Span, Symbol}; + use thin_vec::{ThinVec, thin_vec}; + use tracing::{debug, trace}; + + use crate::errors; + + // If we have a default `()` return type or explicitley `()` return type, + // then we often can skip doing some work. + fn has_ret(ty: &FnRetTy) -> bool { + match ty { + FnRetTy::Ty(ty) => !ty.kind.is_unit(), + FnRetTy::Default(_) => false, + } + } + fn first_ident(x: &MetaItemInner) -> rustc_span::symbol::Ident { + let segments = &x.meta_item().unwrap().path.segments; + assert!(segments.len() == 1); + segments[0].ident + } + + fn name(x: &MetaItemInner) -> String { + first_ident(x).name.to_string() + } + + pub(crate) fn from_ast( + ecx: &mut ExtCtxt<'_>, + meta_item: &ThinVec, + has_ret: bool, + ) -> AutoDiffAttrs { + let dcx = ecx.sess.dcx(); + let mode = name(&meta_item[1]); + let Ok(mode) = DiffMode::from_str(&mode) else { + dcx.emit_err(errors::AutoDiffInvalidMode { span: meta_item[1].span(), mode }); + return AutoDiffAttrs::error(); + }; + let mut activities: Vec = vec![]; + let mut errors = false; + for x in &meta_item[2..] { + let activity_str = name(&x); + let res = DiffActivity::from_str(&activity_str); + match res { + Ok(x) => activities.push(x), + Err(_) => { + dcx.emit_err(errors::AutoDiffUnknownActivity { + span: x.span(), + act: activity_str, + }); + errors = true; + } + }; + } + if errors { + return AutoDiffAttrs::error(); + } + + // If a return type exist, we need to split the last activity, + // otherwise we return None as placeholder. + let (ret_activity, input_activity) = if has_ret { + let Some((last, rest)) = activities.split_last() else { + unreachable!( + "should not be reachable because we counted the number of activities previously" + ); + }; + (last, rest) + } else { + (&DiffActivity::None, activities.as_slice()) + }; + + AutoDiffAttrs { mode, ret_activity: *ret_activity, input_activity: input_activity.to_vec() } + } + + /// We expand the autodiff macro to generate a new placeholder function which passes + /// type-checking and can be called by users. The function body of the placeholder function will + /// later be replaced on LLVM-IR level, so the design of the body is less important and for now + /// should just prevent early inlining and optimizations which alter the function signature. + /// The exact signature of the generated function depends on the configuration provided by the + /// user, but here is an example: + /// + /// ``` + /// #[autodiff(cos_box, Reverse, Duplicated, Active)] + /// fn sin(x: &Box) -> f32 { + /// f32::sin(**x) + /// } + /// ``` + /// which becomes expanded to: + /// ``` + /// #[rustc_autodiff] + /// #[inline(never)] + /// fn sin(x: &Box) -> f32 { + /// f32::sin(**x) + /// } + /// #[rustc_autodiff(Reverse, Duplicated, Active)] + /// #[inline(never)] + /// fn cos_box(x: &Box, dx: &mut Box, dret: f32) -> f32 { + /// unsafe { + /// asm!("NOP"); + /// }; + /// ::core::hint::black_box(sin(x)); + /// ::core::hint::black_box((dx, dret)); + /// ::core::hint::black_box(sin(x)) + /// } + /// ``` + /// FIXME(ZuseZ4): Once autodiff is enabled by default, make this a doc comment which is checked + /// in CI. + pub(crate) fn expand( + ecx: &mut ExtCtxt<'_>, + expand_span: Span, + meta_item: &ast::MetaItem, + mut item: Annotatable, + ) -> Vec { + let dcx = ecx.sess.dcx(); + // first get the annotable item: + let (sig, is_impl): (FnSig, bool) = match &item { + Annotatable::Item(ref iitem) => { + let sig = match &iitem.kind { + ItemKind::Fn(box ast::Fn { sig, .. }) => sig, + _ => { + dcx.emit_err(errors::AutoDiffInvalidApplication { span: item.span() }); + return vec![item]; + } + }; + (sig.clone(), false) + } + Annotatable::AssocItem(ref assoc_item, _) => { + let sig = match &assoc_item.kind { + ast::AssocItemKind::Fn(box ast::Fn { sig, .. }) => sig, + _ => { + dcx.emit_err(errors::AutoDiffInvalidApplication { span: item.span() }); + return vec![item]; + } + }; + (sig.clone(), true) + } + _ => { + dcx.emit_err(errors::AutoDiffInvalidApplication { span: item.span() }); + return vec![item]; + } + }; + + let meta_item_vec: ThinVec = match meta_item.kind { + ast::MetaItemKind::List(ref vec) => vec.clone(), + _ => { + dcx.emit_err(errors::AutoDiffInvalidApplication { span: item.span() }); + return vec![item]; + } + }; + + let has_ret = has_ret(&sig.decl.output); + let sig_span = ecx.with_call_site_ctxt(sig.span); + + let (vis, primal) = match &item { + Annotatable::Item(ref iitem) => (iitem.vis.clone(), iitem.ident.clone()), + Annotatable::AssocItem(ref assoc_item, _) => { + (assoc_item.vis.clone(), assoc_item.ident.clone()) + } + _ => { + dcx.emit_err(errors::AutoDiffInvalidApplication { span: item.span() }); + return vec![item]; + } + }; + + // create TokenStream from vec elemtents: + // meta_item doesn't have a .tokens field + let comma: Token = Token::new(TokenKind::Comma, Span::default()); + let mut ts: Vec = vec![]; + if meta_item_vec.len() < 2 { + // At the bare minimum, we need a fnc name and a mode, even for a dummy function with no + // input and output args. + dcx.emit_err(errors::AutoDiffMissingConfig { span: item.span() }); + return vec![item]; + } else { + for t in meta_item_vec.clone()[1..].iter() { + let val = first_ident(t); + let t = Token::from_ast_ident(val); + ts.push(TokenTree::Token(t, Spacing::Joint)); + ts.push(TokenTree::Token(comma.clone(), Spacing::Alone)); + } + } + if !has_ret { + // We don't want users to provide a return activity if the function doesn't return anything. + // For simplicity, we just add a dummy token to the end of the list. + let t = Token::new(TokenKind::Ident(sym::None, false.into()), Span::default()); + ts.push(TokenTree::Token(t, Spacing::Joint)); + } + let ts: TokenStream = TokenStream::from_iter(ts); + + let x: AutoDiffAttrs = from_ast(ecx, &meta_item_vec, has_ret); + if !x.is_active() { + // We encountered an error, so we return the original item. + // This allows us to potentially parse other attributes. + return vec![item]; + } + let span = ecx.with_def_site_ctxt(expand_span); + + let n_active: u32 = x + .input_activity + .iter() + .filter(|a| **a == DiffActivity::Active || **a == DiffActivity::ActiveOnly) + .count() as u32; + let (d_sig, new_args, idents, errored) = gen_enzyme_decl(ecx, &sig, &x, span); + let new_decl_span = d_sig.span; + let d_body = gen_enzyme_body( + ecx, + &x, + n_active, + &sig, + &d_sig, + primal, + &new_args, + span, + sig_span, + new_decl_span, + idents, + errored, + ); + let d_ident = first_ident(&meta_item_vec[0]); + + // The first element of it is the name of the function to be generated + let asdf = Box::new(ast::Fn { + defaultness: ast::Defaultness::Final, + sig: d_sig, + generics: Generics::default(), + body: Some(d_body), + }); + let mut rustc_ad_attr = + P(ast::NormalAttr::from_ident(Ident::with_dummy_span(sym::rustc_autodiff))); + + let ts2: Vec = vec![TokenTree::Token( + Token::new(TokenKind::Ident(sym::never, false.into()), span), + Spacing::Joint, + )]; + let never_arg = ast::DelimArgs { + dspan: ast::tokenstream::DelimSpan::from_single(span), + delim: ast::token::Delimiter::Parenthesis, + tokens: ast::tokenstream::TokenStream::from_iter(ts2), + }; + let inline_item = ast::AttrItem { + unsafety: ast::Safety::Default, + path: ast::Path::from_ident(Ident::with_dummy_span(sym::inline)), + args: ast::AttrArgs::Delimited(never_arg), + tokens: None, + }; + let inline_never_attr = P(ast::NormalAttr { item: inline_item, tokens: None }); + let new_id = ecx.sess.psess.attr_id_generator.mk_attr_id(); + let attr: ast::Attribute = ast::Attribute { + kind: ast::AttrKind::Normal(rustc_ad_attr.clone()), + id: new_id, + style: ast::AttrStyle::Outer, + span, + }; + let new_id = ecx.sess.psess.attr_id_generator.mk_attr_id(); + let inline_never: ast::Attribute = ast::Attribute { + kind: ast::AttrKind::Normal(inline_never_attr), + id: new_id, + style: ast::AttrStyle::Outer, + span, + }; + + // Don't add it multiple times: + let orig_annotatable: Annotatable = match item { + Annotatable::Item(ref mut iitem) => { + if !iitem.attrs.iter().any(|a| a.id == attr.id) { + iitem.attrs.push(attr.clone()); + } + if !iitem.attrs.iter().any(|a| a.id == inline_never.id) { + iitem.attrs.push(inline_never.clone()); + } + Annotatable::Item(iitem.clone()) + } + Annotatable::AssocItem(ref mut assoc_item, i @ Impl) => { + if !assoc_item.attrs.iter().any(|a| a.id == attr.id) { + assoc_item.attrs.push(attr.clone()); + } + if !assoc_item.attrs.iter().any(|a| a.id == inline_never.id) { + assoc_item.attrs.push(inline_never.clone()); + } + Annotatable::AssocItem(assoc_item.clone(), i) + } + _ => { + unreachable!("annotatable kind checked previously") + } + }; + // Now update for d_fn + rustc_ad_attr.item.args = rustc_ast::AttrArgs::Delimited(rustc_ast::DelimArgs { + dspan: DelimSpan::dummy(), + delim: rustc_ast::token::Delimiter::Parenthesis, + tokens: ts, + }); + let d_attr: ast::Attribute = ast::Attribute { + kind: ast::AttrKind::Normal(rustc_ad_attr.clone()), + id: new_id, + style: ast::AttrStyle::Outer, + span, + }; + + let d_annotatable = if is_impl { + let assoc_item: AssocItemKind = ast::AssocItemKind::Fn(asdf); + let d_fn = P(ast::AssocItem { + attrs: thin_vec![d_attr.clone(), inline_never], + id: ast::DUMMY_NODE_ID, + span, + vis, + ident: d_ident, + kind: assoc_item, + tokens: None, + }); + Annotatable::AssocItem(d_fn, Impl) + } else { + let mut d_fn = ecx.item( + span, + d_ident, + thin_vec![d_attr.clone(), inline_never], + ItemKind::Fn(asdf), + ); + d_fn.vis = vis; + Annotatable::Item(d_fn) + }; + + return vec![orig_annotatable, d_annotatable]; + } + + // shadow arguments (the extra ones which were not in the original (primal) function), in reverse mode must be + // mutable references or ptrs, because Enzyme will write into them. + fn assure_mut_ref(ty: &ast::Ty) -> ast::Ty { + let mut ty = ty.clone(); + match ty.kind { + TyKind::Ptr(ref mut mut_ty) => { + mut_ty.mutbl = ast::Mutability::Mut; + } + TyKind::Ref(_, ref mut mut_ty) => { + mut_ty.mutbl = ast::Mutability::Mut; + } + _ => { + panic!("unsupported type: {:?}", ty); + } + } + ty + } + + /// We only want this function to type-check, since we will replace the body + /// later on llvm level. Using `loop {}` does not cover all return types anymore, + /// so instead we build something that should pass. We also add a inline_asm + /// line, as one more barrier for rustc to prevent inlining of this function. + /// FIXME(ZuseZ4): We still have cases of incorrect inlining across modules, see + /// , so this isn't sufficient. + /// It also triggers an Enzyme crash if we due to a bug ever try to differentiate + /// this function (which should never happen, since it is only a placeholder). + /// Finally, we also add back_box usages of all input arguments, to prevent rustc + /// from optimizing any arguments away. + fn gen_enzyme_body( + ecx: &ExtCtxt<'_>, + x: &AutoDiffAttrs, + n_active: u32, + sig: &ast::FnSig, + d_sig: &ast::FnSig, + primal: Ident, + new_names: &[String], + span: Span, + sig_span: Span, + new_decl_span: Span, + idents: Vec, + errored: bool, + ) -> P { + let blackbox_path = ecx.std_path(&[sym::hint, sym::black_box]); + let noop = ast::InlineAsm { + asm_macro: ast::AsmMacro::Asm, + template: vec![ast::InlineAsmTemplatePiece::String("NOP".into())], + template_strs: Box::new([]), + operands: vec![], + clobber_abis: vec![], + options: ast::InlineAsmOptions::PURE | ast::InlineAsmOptions::NOMEM, + line_spans: vec![], + }; + let noop_expr = ecx.expr_asm(span, P(noop)); + let unsf = ast::BlockCheckMode::Unsafe(ast::UnsafeSource::CompilerGenerated); + let unsf_block = ast::Block { + stmts: thin_vec![ecx.stmt_semi(noop_expr)], + id: ast::DUMMY_NODE_ID, + tokens: None, + rules: unsf, + span, + could_be_bare_literal: false, + }; + let unsf_expr = ecx.expr_block(P(unsf_block)); + let blackbox_call_expr = ecx.expr_path(ecx.path(span, blackbox_path)); + let primal_call = gen_primal_call(ecx, span, primal, idents); + let black_box_primal_call = + ecx.expr_call(new_decl_span, blackbox_call_expr.clone(), thin_vec![ + primal_call.clone() + ]); + let tup_args = new_names + .iter() + .map(|arg| ecx.expr_path(ecx.path_ident(span, Ident::from_str(arg)))) + .collect(); + + let black_box_remaining_args = + ecx.expr_call(sig_span, blackbox_call_expr.clone(), thin_vec![ + ecx.expr_tuple(sig_span, tup_args) + ]); + + let mut body = ecx.block(span, ThinVec::new()); + body.stmts.push(ecx.stmt_semi(unsf_expr)); + + // This uses primal args which won't be available if we errored before + if !errored { + body.stmts.push(ecx.stmt_semi(black_box_primal_call.clone())); + } + body.stmts.push(ecx.stmt_semi(black_box_remaining_args)); + + if !has_ret(&d_sig.decl.output) { + // there is no return type that we have to match, () works fine. + return body; + } + + // having an active-only return means we'll drop the original return type. + // So that can be treated identical to not having one in the first place. + let primal_ret = has_ret(&sig.decl.output) && !x.has_active_only_ret(); + + if primal_ret && n_active == 0 && x.mode.is_rev() { + // We only have the primal ret. + body.stmts.push(ecx.stmt_expr(black_box_primal_call.clone())); + return body; + } + + if !primal_ret && n_active == 1 { + // Again no tuple return, so return default float val. + let ty = match d_sig.decl.output { + FnRetTy::Ty(ref ty) => ty.clone(), + FnRetTy::Default(span) => { + panic!("Did not expect Default ret ty: {:?}", span); + } + }; + let arg = ty.kind.is_simple_path().unwrap(); + let sl: Vec = vec![arg, kw::Default]; + let tmp = ecx.def_site_path(&sl); + let default_call_expr = ecx.expr_path(ecx.path(span, tmp)); + let default_call_expr = ecx.expr_call(new_decl_span, default_call_expr, thin_vec![]); + body.stmts.push(ecx.stmt_expr(default_call_expr)); + return body; + } + + let mut exprs = ThinVec::>::new(); + if primal_ret { + // We have both primal ret and active floats. + // primal ret is first, by construction. + exprs.push(primal_call.clone()); + } + + // Now construct default placeholder for each active float. + // Is there something nicer than f32::default() and f64::default()? + let d_ret_ty = match d_sig.decl.output { + FnRetTy::Ty(ref ty) => ty.clone(), + FnRetTy::Default(span) => { + panic!("Did not expect Default ret ty: {:?}", span); + } + }; + let mut d_ret_ty = match d_ret_ty.kind.clone() { + TyKind::Tup(ref tys) => tys.clone(), + TyKind::Path(_, rustc_ast::Path { segments, .. }) => { + if let [segment] = &segments[..] + && segment.args.is_none() + { + let id = vec![segments[0].ident]; + let kind = TyKind::Path(None, ecx.path(span, id)); + let ty = P(rustc_ast::Ty { kind, id: ast::DUMMY_NODE_ID, span, tokens: None }); + thin_vec![ty] + } else { + panic!("Expected tuple or simple path return type"); + } + } + _ => { + // We messed up construction of d_sig + panic!("Did not expect non-tuple ret ty: {:?}", d_ret_ty); + } + }; + + if x.mode.is_fwd() && x.ret_activity == DiffActivity::Dual { + assert!(d_ret_ty.len() == 2); + // both should be identical, by construction + let arg = d_ret_ty[0].kind.is_simple_path().unwrap(); + let arg2 = d_ret_ty[1].kind.is_simple_path().unwrap(); + assert!(arg == arg2); + let sl: Vec = vec![arg, kw::Default]; + let tmp = ecx.def_site_path(&sl); + let default_call_expr = ecx.expr_path(ecx.path(span, tmp)); + let default_call_expr = ecx.expr_call(new_decl_span, default_call_expr, thin_vec![]); + exprs.push(default_call_expr); + } else if x.mode.is_rev() { + if primal_ret { + // We have extra handling above for the primal ret + d_ret_ty = d_ret_ty[1..].to_vec().into(); + } + + for arg in d_ret_ty.iter() { + let arg = arg.kind.is_simple_path().unwrap(); + let sl: Vec = vec![arg, kw::Default]; + let tmp = ecx.def_site_path(&sl); + let default_call_expr = ecx.expr_path(ecx.path(span, tmp)); + let default_call_expr = + ecx.expr_call(new_decl_span, default_call_expr, thin_vec![]); + exprs.push(default_call_expr); + } + } + + let ret: P; + match &exprs[..] { + [] => { + assert!(!has_ret(&d_sig.decl.output)); + // We don't have to match the return type. + return body; + } + [arg] => { + ret = ecx + .expr_call(new_decl_span, blackbox_call_expr.clone(), thin_vec![arg.clone()]); + } + args => { + let ret_tuple: P = ecx.expr_tuple(span, args.into()); + ret = + ecx.expr_call(new_decl_span, blackbox_call_expr.clone(), thin_vec![ret_tuple]); + } + } + assert!(has_ret(&d_sig.decl.output)); + body.stmts.push(ecx.stmt_expr(ret)); + + body + } + + fn gen_primal_call( + ecx: &ExtCtxt<'_>, + span: Span, + primal: Ident, + idents: Vec, + ) -> P { + let has_self = idents.len() > 0 && idents[0].name == kw::SelfLower; + if has_self { + let args: ThinVec<_> = + idents[1..].iter().map(|arg| ecx.expr_path(ecx.path_ident(span, *arg))).collect(); + let self_expr = ecx.expr_self(span); + ecx.expr_method_call(span, self_expr, primal, args.clone()) + } else { + let args: ThinVec<_> = + idents.iter().map(|arg| ecx.expr_path(ecx.path_ident(span, *arg))).collect(); + let primal_call_expr = ecx.expr_path(ecx.path_ident(span, primal)); + ecx.expr_call(span, primal_call_expr, args) + } + } + + // Generate the new function declaration. Const arguments are kept as is. Duplicated arguments must + // be pointers or references. Those receive a shadow argument, which is a mutable reference/pointer. + // Active arguments must be scalars. Their shadow argument is added to the return type (and will be + // zero-initialized by Enzyme). + // Each argument of the primal function (and the return type if existing) must be annotated with an + // activity. + // + // Error handling: If the user provides an invalid configuration (incorrect numbers, types, or + // both), we emit an error and return the original signature. This allows us to continue parsing. + fn gen_enzyme_decl( + ecx: &ExtCtxt<'_>, + sig: &ast::FnSig, + x: &AutoDiffAttrs, + span: Span, + ) -> (ast::FnSig, Vec, Vec, bool) { + let dcx = ecx.sess.dcx(); + let has_ret = has_ret(&sig.decl.output); + let sig_args = sig.decl.inputs.len() + if has_ret { 1 } else { 0 }; + let num_activities = x.input_activity.len() + if x.has_ret_activity() { 1 } else { 0 }; + if sig_args != num_activities { + dcx.emit_err(errors::AutoDiffInvalidNumberActivities { + span, + expected: sig_args, + found: num_activities, + }); + // This is not the right signature, but we can continue parsing. + return (sig.clone(), vec![], vec![], true); + } + assert!(sig.decl.inputs.len() == x.input_activity.len()); + assert!(has_ret == x.has_ret_activity()); + let mut d_decl = sig.decl.clone(); + let mut d_inputs = Vec::new(); + let mut new_inputs = Vec::new(); + let mut idents = Vec::new(); + let mut act_ret = ThinVec::new(); + + // We have two loops, a first one just to check the activities and types and possibly report + // multiple errors in one compilation session. + let mut errors = false; + for (arg, activity) in sig.decl.inputs.iter().zip(x.input_activity.iter()) { + if !valid_input_activity(x.mode, *activity) { + dcx.emit_err(errors::AutoDiffInvalidApplicationModeAct { + span, + mode: x.mode.to_string(), + act: activity.to_string(), + }); + errors = true; + } + if !valid_ty_for_activity(&arg.ty, *activity) { + dcx.emit_err(errors::AutoDiffInvalidTypeForActivity { + span: arg.ty.span, + act: activity.to_string(), + }); + errors = true; + } + } + if errors { + // This is not the right signature, but we can continue parsing. + return (sig.clone(), new_inputs, idents, true); + } + let unsafe_activities = x + .input_activity + .iter() + .any(|&act| matches!(act, DiffActivity::DuplicatedOnly | DiffActivity::DualOnly)); + for (arg, activity) in sig.decl.inputs.iter().zip(x.input_activity.iter()) { + d_inputs.push(arg.clone()); + match activity { + DiffActivity::Active => { + act_ret.push(arg.ty.clone()); + } + DiffActivity::ActiveOnly => { + // We will add the active scalar to the return type. + // This is handled later. + } + DiffActivity::Duplicated | DiffActivity::DuplicatedOnly => { + let mut shadow_arg = arg.clone(); + // We += into the shadow in reverse mode. + shadow_arg.ty = P(assure_mut_ref(&arg.ty)); + let old_name = if let PatKind::Ident(_, ident, _) = arg.pat.kind { + ident.name + } else { + debug!("{:#?}", &shadow_arg.pat); + panic!("not an ident?"); + }; + let name: String = format!("d{}", old_name); + new_inputs.push(name.clone()); + let ident = Ident::from_str_and_span(&name, shadow_arg.pat.span); + shadow_arg.pat = P(ast::Pat { + id: ast::DUMMY_NODE_ID, + kind: PatKind::Ident(BindingMode::NONE, ident, None), + span: shadow_arg.pat.span, + tokens: shadow_arg.pat.tokens.clone(), + }); + d_inputs.push(shadow_arg); + } + DiffActivity::Dual | DiffActivity::DualOnly => { + let mut shadow_arg = arg.clone(); + let old_name = if let PatKind::Ident(_, ident, _) = arg.pat.kind { + ident.name + } else { + debug!("{:#?}", &shadow_arg.pat); + panic!("not an ident?"); + }; + let name: String = format!("b{}", old_name); + new_inputs.push(name.clone()); + let ident = Ident::from_str_and_span(&name, shadow_arg.pat.span); + shadow_arg.pat = P(ast::Pat { + id: ast::DUMMY_NODE_ID, + kind: PatKind::Ident(BindingMode::NONE, ident, None), + span: shadow_arg.pat.span, + tokens: shadow_arg.pat.tokens.clone(), + }); + d_inputs.push(shadow_arg); + } + DiffActivity::Const => { + // Nothing to do here. + } + DiffActivity::None | DiffActivity::FakeActivitySize => { + panic!("Should not happen"); + } + } + if let PatKind::Ident(_, ident, _) = arg.pat.kind { + idents.push(ident.clone()); + } else { + panic!("not an ident?"); + } + } + + let active_only_ret = x.ret_activity == DiffActivity::ActiveOnly; + if active_only_ret { + assert!(x.mode.is_rev()); + } + + // If we return a scalar in the primal and the scalar is active, + // then add it as last arg to the inputs. + if x.mode.is_rev() { + match x.ret_activity { + DiffActivity::Active | DiffActivity::ActiveOnly => { + let ty = match d_decl.output { + FnRetTy::Ty(ref ty) => ty.clone(), + FnRetTy::Default(span) => { + panic!("Did not expect Default ret ty: {:?}", span); + } + }; + let name = "dret".to_string(); + let ident = Ident::from_str_and_span(&name, ty.span); + let shadow_arg = ast::Param { + attrs: ThinVec::new(), + ty: ty.clone(), + pat: P(ast::Pat { + id: ast::DUMMY_NODE_ID, + kind: PatKind::Ident(BindingMode::NONE, ident, None), + span: ty.span, + tokens: None, + }), + id: ast::DUMMY_NODE_ID, + span: ty.span, + is_placeholder: false, + }; + d_inputs.push(shadow_arg); + new_inputs.push(name); + } + _ => {} + } + } + d_decl.inputs = d_inputs.into(); + + if x.mode.is_fwd() { + if let DiffActivity::Dual = x.ret_activity { + let ty = match d_decl.output { + FnRetTy::Ty(ref ty) => ty.clone(), + FnRetTy::Default(span) => { + panic!("Did not expect Default ret ty: {:?}", span); + } + }; + // Dual can only be used for f32/f64 ret. + // In that case we return now a tuple with two floats. + let kind = TyKind::Tup(thin_vec![ty.clone(), ty.clone()]); + let ty = P(rustc_ast::Ty { kind, id: ty.id, span: ty.span, tokens: None }); + d_decl.output = FnRetTy::Ty(ty); + } + if let DiffActivity::DualOnly = x.ret_activity { + // No need to change the return type, + // we will just return the shadow in place + // of the primal return. + } + } + + // If we use ActiveOnly, drop the original return value. + d_decl.output = + if active_only_ret { FnRetTy::Default(span) } else { d_decl.output.clone() }; + + trace!("act_ret: {:?}", act_ret); + + // If we have an active input scalar, add it's gradient to the + // return type. This might require changing the return type to a + // tuple. + if act_ret.len() > 0 { + let ret_ty = match d_decl.output { + FnRetTy::Ty(ref ty) => { + if !active_only_ret { + act_ret.insert(0, ty.clone()); + } + let kind = TyKind::Tup(act_ret); + P(rustc_ast::Ty { kind, id: ty.id, span: ty.span, tokens: None }) + } + FnRetTy::Default(span) => { + if act_ret.len() == 1 { + act_ret[0].clone() + } else { + let kind = TyKind::Tup(act_ret.iter().map(|arg| arg.clone()).collect()); + P(rustc_ast::Ty { kind, id: ast::DUMMY_NODE_ID, span, tokens: None }) + } + } + }; + d_decl.output = FnRetTy::Ty(ret_ty); + } + + let mut d_header = sig.header.clone(); + if unsafe_activities { + d_header.safety = rustc_ast::Safety::Unsafe(span); + } + let d_sig = FnSig { header: d_header, decl: d_decl, span }; + trace!("Generated signature: {:?}", d_sig); + (d_sig, new_inputs, idents, false) + } +} + +#[cfg(not(llvm_enzyme))] +mod ad_fallback { + use rustc_ast::ast; + use rustc_expand::base::{Annotatable, ExtCtxt}; + use rustc_span::Span; + + use crate::errors; + pub(crate) fn expand( + ecx: &mut ExtCtxt<'_>, + _expand_span: Span, + meta_item: &ast::MetaItem, + item: Annotatable, + ) -> Vec { + ecx.sess.dcx().emit_err(errors::AutoDiffSupportNotBuild { span: meta_item.span }); + return vec![item]; + } +} + +#[cfg(not(llvm_enzyme))] +pub(crate) use ad_fallback::expand; +#[cfg(llvm_enzyme)] +pub(crate) use llvm_enzyme::expand; diff --git a/compiler/rustc_builtin_macros/src/errors.rs b/compiler/rustc_builtin_macros/src/errors.rs index 639c2aa231c..f8e65661e52 100644 --- a/compiler/rustc_builtin_macros/src/errors.rs +++ b/compiler/rustc_builtin_macros/src/errors.rs @@ -145,6 +145,78 @@ pub(crate) struct AllocMustStatics { pub(crate) span: Span, } +#[cfg(llvm_enzyme)] +pub(crate) use autodiff::*; + +#[cfg(llvm_enzyme)] +mod autodiff { + use super::*; + #[derive(Diagnostic)] + #[diag(builtin_macros_autodiff_missing_config)] + pub(crate) struct AutoDiffMissingConfig { + #[primary_span] + pub(crate) span: Span, + } + #[derive(Diagnostic)] + #[diag(builtin_macros_autodiff_unknown_activity)] + pub(crate) struct AutoDiffUnknownActivity { + #[primary_span] + pub(crate) span: Span, + pub(crate) act: String, + } + #[derive(Diagnostic)] + #[diag(builtin_macros_autodiff_ty_activity)] + pub(crate) struct AutoDiffInvalidTypeForActivity { + #[primary_span] + pub(crate) span: Span, + pub(crate) act: String, + } + #[derive(Diagnostic)] + #[diag(builtin_macros_autodiff_number_activities)] + pub(crate) struct AutoDiffInvalidNumberActivities { + #[primary_span] + pub(crate) span: Span, + pub(crate) expected: usize, + pub(crate) found: usize, + } + #[derive(Diagnostic)] + #[diag(builtin_macros_autodiff_mode_activity)] + pub(crate) struct AutoDiffInvalidApplicationModeAct { + #[primary_span] + pub(crate) span: Span, + pub(crate) mode: String, + pub(crate) act: String, + } + + #[derive(Diagnostic)] + #[diag(builtin_macros_autodiff_mode)] + pub(crate) struct AutoDiffInvalidMode { + #[primary_span] + pub(crate) span: Span, + pub(crate) mode: String, + } + + #[derive(Diagnostic)] + #[diag(builtin_macros_autodiff)] + pub(crate) struct AutoDiffInvalidApplication { + #[primary_span] + pub(crate) span: Span, + } +} + +#[cfg(not(llvm_enzyme))] +pub(crate) use ad_fallback::*; +#[cfg(not(llvm_enzyme))] +mod ad_fallback { + use super::*; + #[derive(Diagnostic)] + #[diag(builtin_macros_autodiff_not_build)] + pub(crate) struct AutoDiffSupportNotBuild { + #[primary_span] + pub(crate) span: Span, + } +} + #[derive(Diagnostic)] #[diag(builtin_macros_concat_bytes_invalid)] pub(crate) struct ConcatBytesInvalid { diff --git a/compiler/rustc_builtin_macros/src/lib.rs b/compiler/rustc_builtin_macros/src/lib.rs index ebe5e2b5442..377d7f542cf 100644 --- a/compiler/rustc_builtin_macros/src/lib.rs +++ b/compiler/rustc_builtin_macros/src/lib.rs @@ -5,6 +5,7 @@ #![allow(internal_features)] #![allow(rustc::diagnostic_outside_of_impl)] #![allow(rustc::untranslatable_diagnostic)] +#![cfg_attr(not(bootstrap), feature(autodiff))] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(rust_logo)] #![feature(assert_matches)] @@ -29,6 +30,7 @@ use crate::deriving::*; mod alloc_error_handler; mod assert; +mod autodiff; mod cfg; mod cfg_accessible; mod cfg_eval; @@ -106,6 +108,7 @@ pub fn register_builtin_macros(resolver: &mut dyn ResolverExpand) { register_attr! { alloc_error_handler: alloc_error_handler::expand, + autodiff: autodiff::expand, bench: test::expand_bench, cfg_accessible: cfg_accessible::Expander, cfg_eval: cfg_eval::expand, diff --git a/compiler/rustc_expand/src/build.rs b/compiler/rustc_expand/src/build.rs index b5945759d43..743a9854f79 100644 --- a/compiler/rustc_expand/src/build.rs +++ b/compiler/rustc_expand/src/build.rs @@ -220,6 +220,10 @@ impl<'a> ExtCtxt<'a> { self.stmt_local(local, span) } + pub fn stmt_semi(&self, expr: P) -> ast::Stmt { + ast::Stmt { id: ast::DUMMY_NODE_ID, span: expr.span, kind: ast::StmtKind::Semi(expr) } + } + pub fn stmt_local(&self, local: P, span: Span) -> ast::Stmt { ast::Stmt { id: ast::DUMMY_NODE_ID, kind: ast::StmtKind::Let(local), span } } @@ -287,6 +291,25 @@ impl<'a> ExtCtxt<'a> { self.expr(sp, ast::ExprKind::Paren(e)) } + pub fn expr_method_call( + &self, + span: Span, + expr: P, + ident: Ident, + args: ThinVec>, + ) -> P { + let seg = ast::PathSegment::from_ident(ident); + self.expr( + span, + ast::ExprKind::MethodCall(Box::new(ast::MethodCall { + seg, + receiver: expr, + args, + span, + })), + ) + } + pub fn expr_call( &self, span: Span, @@ -295,6 +318,12 @@ impl<'a> ExtCtxt<'a> { ) -> P { self.expr(span, ast::ExprKind::Call(expr, args)) } + pub fn expr_loop(&self, sp: Span, block: P) -> P { + self.expr(sp, ast::ExprKind::Loop(block, None, sp)) + } + pub fn expr_asm(&self, sp: Span, expr: P) -> P { + self.expr(sp, ast::ExprKind::InlineAsm(expr)) + } pub fn expr_call_ident( &self, span: Span, diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index 17827b4e43b..477760a4597 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -752,6 +752,11 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ template!(NameValueStr: "transparent|semitransparent|opaque"), ErrorFollowing, EncodeCrossCrate::Yes, "used internally for testing macro hygiene", ), + rustc_attr!( + rustc_autodiff, Normal, + template!(Word, List: r#""...""#), DuplicatesOk, + EncodeCrossCrate::No, INTERNAL_UNSTABLE + ), // ========================================================================== // Internal attributes, Diagnostics related: diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl index be76d6cef2b..d60d7e00d4b 100644 --- a/compiler/rustc_passes/messages.ftl +++ b/compiler/rustc_passes/messages.ftl @@ -49,6 +49,10 @@ passes_attr_crate_level = passes_attr_only_in_functions = `{$attr}` attribute can only be used on functions +passes_autodiff_attr = + `#[autodiff]` should be applied to a function + .label = not a function + passes_both_ffi_const_and_pure = `#[ffi_const]` function cannot be `#[ffi_pure]` diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 44a62383e6e..7ce29260e36 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -243,6 +243,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> { self.check_generic_attr(hir_id, attr, target, Target::Fn); self.check_proc_macro(hir_id, target, ProcMacroKind::Derive) } + [sym::autodiff, ..] => { + self.check_autodiff(hir_id, attr, span, target) + } [sym::coroutine, ..] => { self.check_coroutine(attr, target); } @@ -2345,6 +2348,18 @@ impl<'tcx> CheckAttrVisitor<'tcx> { self.dcx().emit_err(errors::RustcPubTransparent { span, attr_span }); } } + + /// Checks if `#[autodiff]` is applied to an item other than a function item. + fn check_autodiff(&self, _hir_id: HirId, _attr: &Attribute, span: Span, target: Target) { + debug!("check_autodiff"); + match target { + Target::Fn => {} + _ => { + self.dcx().emit_err(errors::AutoDiffAttr { attr_span: span }); + self.abort.set(true); + } + } + } } impl<'tcx> Visitor<'tcx> for CheckAttrVisitor<'tcx> { diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index 4f00c90fa3b..70f525ec0e8 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -20,6 +20,14 @@ use crate::lang_items::Duplicate; #[diag(passes_incorrect_do_not_recommend_location)] pub(crate) struct IncorrectDoNotRecommendLocation; +#[derive(Diagnostic)] +#[diag(passes_autodiff_attr)] +pub(crate) struct AutoDiffAttr { + #[primary_span] + #[label] + pub attr_span: Span, +} + #[derive(LintDiagnostic)] #[diag(passes_outer_crate_level_attr)] pub(crate) struct OuterCrateLevelAttr; diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 8e0009695db..92946ef5262 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -481,6 +481,8 @@ symbols! { audit_that, augmented_assignments, auto_traits, + autodiff, + autodiff_fallback, automatically_derived, avx, avx512_target_feature, @@ -544,6 +546,7 @@ symbols! { cfg_accessible, cfg_attr, cfg_attr_multi, + cfg_autodiff_fallback, cfg_boolean_literals, cfg_doctest, cfg_eval, @@ -998,6 +1001,7 @@ symbols! { hashset_iter_ty, hexagon_target_feature, hidden, + hint, homogeneous_aggregate, host, html_favicon_url, @@ -1650,6 +1654,7 @@ symbols! { rustc_allow_incoherent_impl, rustc_allowed_through_unstable_modules, rustc_attrs, + rustc_autodiff, rustc_box, rustc_builtin_macro, rustc_capture_analysis, diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 96ab5755328..f69a33bca84 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -278,6 +278,15 @@ pub mod assert_matches { pub use crate::macros::{assert_matches, debug_assert_matches}; } +// We don't export this through #[macro_export] for now, to avoid breakage. +#[cfg(not(bootstrap))] +#[unstable(feature = "autodiff", issue = "124509")] +/// Unstable module containing the unstable `autodiff` macro. +pub mod autodiff { + #[unstable(feature = "autodiff", issue = "124509")] + pub use crate::macros::builtin::autodiff; +} + #[unstable(feature = "cfg_match", issue = "115585")] pub use crate::macros::cfg_match; diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs index aa0646846e4..b5e5b58f705 100644 --- a/library/core/src/macros/mod.rs +++ b/library/core/src/macros/mod.rs @@ -1539,6 +1539,24 @@ pub(crate) mod builtin { ($file:expr $(,)?) => {{ /* compiler built-in */ }}; } + /// Automatic Differentiation macro which allows generating a new function to compute + /// the derivative of a given function. It may only be applied to a function. + /// The expected usage syntax is + /// `#[autodiff(NAME, MODE, INPUT_ACTIVITIES, OUTPUT_ACTIVITY)]` + /// where: + /// NAME is a string that represents a valid function name. + /// MODE is any of Forward, Reverse, ForwardFirst, ReverseFirst. + /// INPUT_ACTIVITIES consists of one valid activity for each input parameter. + /// OUTPUT_ACTIVITY must not be set if we implicitely return nothing (or explicitely return + /// `-> ()`. Otherwise it must be set to one of the allowed activities. + #[unstable(feature = "autodiff", issue = "124509")] + #[allow_internal_unstable(rustc_attrs)] + #[rustc_builtin_macro] + #[cfg(not(bootstrap))] + pub macro autodiff($item:item) { + /* compiler built-in */ + } + /// Asserts that a boolean expression is `true` at runtime. /// /// This will invoke the [`panic!`] macro if the provided expression cannot be diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 65a9aa66c7c..35ed761759b 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -267,6 +267,7 @@ #![allow(unused_features)] // // Features: +#![cfg_attr(not(bootstrap), feature(autodiff))] #![cfg_attr(test, feature(internal_output_capture, print_internals, update_panic_count, rt))] #![cfg_attr( all(target_vendor = "fortanix", target_env = "sgx"), @@ -627,7 +628,13 @@ pub mod simd { #[doc(inline)] pub use crate::std_float::StdFloat; } - +#[cfg(not(bootstrap))] +#[unstable(feature = "autodiff", issue = "124509")] +/// This module provides support for automatic differentiation. +pub mod autodiff { + /// This macro handles automatic differentiation. + pub use core::autodiff::autodiff; +} #[stable(feature = "futures_api", since = "1.36.0")] pub mod task { //! Types and Traits for working with asynchronous tasks. -- cgit 1.4.1-3-g733a5 From 9f91c5099fb7261cf8c85cc638d2692a317060ec Mon Sep 17 00:00:00 2001 From: joboet Date: Sat, 12 Oct 2024 13:01:36 +0200 Subject: std: fix stdout-before-main Fixes #130210. Since #124881, `ReentrantLock` uses `ThreadId` to identify threads. This has the unfortunate consequence of breaking uses of `Stdout` before main: Locking the `ReentrantLock` that synchronizes the output will initialize the thread ID before the handle for the main thread is set in `rt::init`. But since that would overwrite the current thread ID, `thread::set_current` triggers an abort. This PR fixes the problem by using the already initialized thread ID for constructing the main thread handle and allowing `set_current` calls that do not change the thread's ID. --- library/std/src/rt.rs | 21 ++++++++++++++++++--- library/std/src/thread/current.rs | 20 +++++++++++--------- library/std/src/thread/mod.rs | 24 +++++++++++++----------- tests/ui/runtime/stdout-before-main.rs | 24 ++++++++++++++++++++++++ tests/ui/runtime/stdout-before-main.run.stdout | 1 + 5 files changed, 67 insertions(+), 23 deletions(-) create mode 100644 tests/ui/runtime/stdout-before-main.rs create mode 100644 tests/ui/runtime/stdout-before-main.run.stdout (limited to 'library/std/src') diff --git a/library/std/src/rt.rs b/library/std/src/rt.rs index 0a841f07e3b..80e7c3c026b 100644 --- a/library/std/src/rt.rs +++ b/library/std/src/rt.rs @@ -102,9 +102,24 @@ unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) { sys::init(argc, argv, sigpipe) }; - // Set up the current thread to give it the right name. - let thread = Thread::new_main(); - thread::set_current(thread); + // Set up the current thread handle to give it the right name. + // + // When code running before main uses `ReentrantLock` (for example by + // using `println!`), the thread ID can become initialized before we + // create this handle. Since `set_current` fails when the ID of the + // handle does not match the current ID, we should attempt to use the + // current thread ID here instead of unconditionally creating a new + // one. Also see #130210. + let thread = Thread::new_main(thread::current_id()); + if let Err(_thread) = thread::set_current(thread) { + // `thread::current` will create a new handle if none has been set yet. + // Thus, if someone uses it before main, this call will fail. That's a + // bad idea though, as we then cannot set the main thread name here. + // + // FIXME: detect the main thread in `thread::current` and use the + // correct name there. + rtabort!("code running before main must not use thread::current"); + } } /// Clean up the thread-local runtime state. This *should* be run after all other diff --git a/library/std/src/thread/current.rs b/library/std/src/thread/current.rs index b38149a0da7..e6eb90c4c30 100644 --- a/library/std/src/thread/current.rs +++ b/library/std/src/thread/current.rs @@ -110,22 +110,24 @@ mod id { } } -/// Sets the thread handle for the current thread. -/// -/// Aborts if the handle or the ID has been set already. -pub(crate) fn set_current(thread: Thread) { - if CURRENT.get() != NONE || id::get().is_some() { - // Using `panic` here can add ~3kB to the binary size. We have complete - // control over where this is called, so just abort if there is a bug. - rtabort!("thread::set_current should only be called once per thread"); +/// Tries to set the thread handle for the current thread. Fails if a handle was +/// already set or if the thread ID of `thread` would change an already-set ID. +pub(crate) fn set_current(thread: Thread) -> Result<(), Thread> { + if CURRENT.get() != NONE { + return Err(thread); } - id::set(thread.id()); + match id::get() { + Some(id) if id == thread.id() => {} + None => id::set(thread.id()), + _ => return Err(thread), + } // Make sure that `crate::rt::thread_cleanup` will be run, which will // call `drop_current`. crate::sys::thread_local::guard::enable(); CURRENT.set(thread.into_raw().cast_mut()); + Ok(()) } /// Gets the id of the thread that invokes it. diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs index d1d4eabb9bd..39753888509 100644 --- a/library/std/src/thread/mod.rs +++ b/library/std/src/thread/mod.rs @@ -519,9 +519,14 @@ impl Builder { let f = MaybeDangling::new(f); let main = move || { - // Immediately store the thread handle to avoid setting it or its ID - // twice, which would cause an abort. - set_current(their_thread.clone()); + if let Err(_thread) = set_current(their_thread.clone()) { + // Both the current thread handle and the ID should not be + // initialized yet. Since only the C runtime and some of our + // platform code run before this, this point shouldn't be + // reachable. Use an abort to save binary size (see #123356). + rtabort!("something here is badly broken!"); + } + if let Some(name) = their_thread.cname() { imp::Thread::set_name(name); } @@ -1159,9 +1164,6 @@ pub fn park_timeout(dur: Duration) { pub struct ThreadId(NonZero); impl ThreadId { - // DO NOT rely on this value. - const MAIN_THREAD: ThreadId = ThreadId(unsafe { NonZero::new_unchecked(1) }); - // Generate a new unique thread ID. pub(crate) fn new() -> ThreadId { #[cold] @@ -1173,7 +1175,7 @@ impl ThreadId { if #[cfg(target_has_atomic = "64")] { use crate::sync::atomic::AtomicU64; - static COUNTER: AtomicU64 = AtomicU64::new(1); + static COUNTER: AtomicU64 = AtomicU64::new(0); let mut last = COUNTER.load(Ordering::Relaxed); loop { @@ -1189,7 +1191,7 @@ impl ThreadId { } else { use crate::sync::{Mutex, PoisonError}; - static COUNTER: Mutex = Mutex::new(1); + static COUNTER: Mutex = Mutex::new(0); let mut counter = COUNTER.lock().unwrap_or_else(PoisonError::into_inner); let Some(id) = counter.checked_add(1) else { @@ -1326,9 +1328,9 @@ impl Thread { Self::new_inner(id, ThreadName::Unnamed) } - // Used in runtime to construct main thread - pub(crate) fn new_main() -> Thread { - Self::new_inner(ThreadId::MAIN_THREAD, ThreadName::Main) + /// Constructs the thread handle for the main thread. + pub(crate) fn new_main(id: ThreadId) -> Thread { + Self::new_inner(id, ThreadName::Main) } fn new_inner(id: ThreadId, name: ThreadName) -> Thread { diff --git a/tests/ui/runtime/stdout-before-main.rs b/tests/ui/runtime/stdout-before-main.rs new file mode 100644 index 00000000000..26c734d3e9e --- /dev/null +++ b/tests/ui/runtime/stdout-before-main.rs @@ -0,0 +1,24 @@ +//@ run-pass +//@ check-run-results +//@ only-gnu +//@ only-linux +// +// Regression test for #130210. +// .init_array doesn't work everywhere, so we limit the test to just GNU/Linux. + +use std::ffi::c_int; +use std::thread; + +#[used] +#[link_section = ".init_array"] +static INIT: extern "C" fn(c_int, *const *const u8, *const *const u8) = { + extern "C" fn init(_argc: c_int, _argv: *const *const u8, _envp: *const *const u8) { + print!("Hello from before "); + } + + init +}; + +fn main() { + println!("{}!", thread::current().name().unwrap()); +} diff --git a/tests/ui/runtime/stdout-before-main.run.stdout b/tests/ui/runtime/stdout-before-main.run.stdout new file mode 100644 index 00000000000..d7a3a4389ec --- /dev/null +++ b/tests/ui/runtime/stdout-before-main.run.stdout @@ -0,0 +1 @@ +Hello from before main! -- cgit 1.4.1-3-g733a5 From 1ebfd9705165cf6902dae1eacc49cb4c0a0e142e Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 12 Oct 2024 19:08:34 +0200 Subject: merge const_ipv4 / const_ipv6 feature gate into 'ip' feature gate --- library/core/src/lib.rs | 2 -- library/core/src/net/ip_addr.rs | 14 -------------- library/core/tests/lib.rs | 3 --- library/std/src/lib.rs | 3 --- 4 files changed, 22 deletions(-) (limited to 'library/std/src') diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 726aa209fdf..6851664a89e 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -124,8 +124,6 @@ #![feature(const_hash)] #![feature(const_heap)] #![feature(const_index_range_slice_index)] -#![feature(const_ipv4)] -#![feature(const_ipv6)] #![feature(const_likely)] #![feature(const_make_ascii)] #![feature(const_maybe_uninit_assume_init)] diff --git a/library/core/src/net/ip_addr.rs b/library/core/src/net/ip_addr.rs index 919f681f911..fbf61cf614b 100644 --- a/library/core/src/net/ip_addr.rs +++ b/library/core/src/net/ip_addr.rs @@ -295,7 +295,6 @@ impl IpAddr { /// assert_eq!(IpAddr::V4(Ipv4Addr::new(80, 9, 12, 3)).is_global(), true); /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0, 0, 0x1c9, 0, 0, 0xafc8, 0, 0x1)).is_global(), true); /// ``` - #[rustc_const_unstable(feature = "const_ip", issue = "76205")] #[unstable(feature = "ip", issue = "27709")] #[must_use] #[inline] @@ -348,7 +347,6 @@ impl IpAddr { /// true /// ); /// ``` - #[rustc_const_unstable(feature = "const_ip", issue = "76205")] #[unstable(feature = "ip", issue = "27709")] #[must_use] #[inline] @@ -776,7 +774,6 @@ impl Ipv4Addr { /// /// // For a complete overview see the IANA IPv4 Special-Purpose Address Registry. /// ``` - #[rustc_const_unstable(feature = "const_ipv4", issue = "76205")] #[unstable(feature = "ip", issue = "27709")] #[must_use] #[inline] @@ -813,7 +810,6 @@ impl Ipv4Addr { /// assert_eq!(Ipv4Addr::new(100, 127, 255, 255).is_shared(), true); /// assert_eq!(Ipv4Addr::new(100, 128, 0, 0).is_shared(), false); /// ``` - #[rustc_const_unstable(feature = "const_ipv4", issue = "76205")] #[unstable(feature = "ip", issue = "27709")] #[must_use] #[inline] @@ -841,7 +837,6 @@ impl Ipv4Addr { /// assert_eq!(Ipv4Addr::new(198, 19, 255, 255).is_benchmarking(), true); /// assert_eq!(Ipv4Addr::new(198, 20, 0, 0).is_benchmarking(), false); /// ``` - #[rustc_const_unstable(feature = "const_ipv4", issue = "76205")] #[unstable(feature = "ip", issue = "27709")] #[must_use] #[inline] @@ -878,7 +873,6 @@ impl Ipv4Addr { /// // The broadcast address is not considered as reserved for future use by this implementation /// assert_eq!(Ipv4Addr::new(255, 255, 255, 255).is_reserved(), false); /// ``` - #[rustc_const_unstable(feature = "const_ipv4", issue = "76205")] #[unstable(feature = "ip", issue = "27709")] #[must_use] #[inline] @@ -1510,7 +1504,6 @@ impl Ipv6Addr { /// /// // For a complete overview see the IANA IPv6 Special-Purpose Address Registry. /// ``` - #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")] #[unstable(feature = "ip", issue = "27709")] #[must_use] #[inline] @@ -1562,7 +1555,6 @@ impl Ipv6Addr { /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unique_local(), false); /// assert_eq!(Ipv6Addr::new(0xfc02, 0, 0, 0, 0, 0, 0, 0).is_unique_local(), true); /// ``` - #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")] #[unstable(feature = "ip", issue = "27709")] #[must_use] #[inline] @@ -1591,7 +1583,6 @@ impl Ipv6Addr { /// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0).is_unicast(), true); /// assert_eq!(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0).is_unicast(), false); /// ``` - #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")] #[unstable(feature = "ip", issue = "27709")] #[must_use] #[inline] @@ -1643,7 +1634,6 @@ impl Ipv6Addr { /// assert_eq!(Ipv6Addr::new(0xfe80, 0, 0, 1, 0, 0, 0, 0).is_unicast_link_local(), true); /// assert_eq!(Ipv6Addr::new(0xfe81, 0, 0, 0, 0, 0, 0, 0).is_unicast_link_local(), true); /// ``` - #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")] #[unstable(feature = "ip", issue = "27709")] #[must_use] #[inline] @@ -1668,7 +1658,6 @@ impl Ipv6Addr { /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_documentation(), false); /// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0).is_documentation(), true); /// ``` - #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")] #[unstable(feature = "ip", issue = "27709")] #[must_use] #[inline] @@ -1729,7 +1718,6 @@ impl Ipv6Addr { /// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0).is_unicast_global(), false); /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unicast_global(), true); /// ``` - #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")] #[unstable(feature = "ip", issue = "27709")] #[must_use] #[inline] @@ -1758,7 +1746,6 @@ impl Ipv6Addr { /// ); /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).multicast_scope(), None); /// ``` - #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")] #[unstable(feature = "ip", issue = "27709")] #[must_use] #[inline] @@ -1818,7 +1805,6 @@ impl Ipv6Addr { /// /// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0).is_ipv4_mapped(), false); /// ``` - #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")] #[unstable(feature = "ip", issue = "27709")] #[must_use] #[inline] diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index 9e15bb1dd8f..7616c38cbc2 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -19,9 +19,6 @@ #![feature(const_black_box)] #![feature(const_hash)] #![feature(const_heap)] -#![feature(const_ip)] -#![feature(const_ipv4)] -#![feature(const_ipv6)] #![feature(const_likely)] #![feature(const_nonnull_new)] #![feature(const_option_ext)] diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 65a9aa66c7c..057a57f7997 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -414,9 +414,6 @@ // tidy-alphabetical-start #![feature(const_collections_with_hasher)] #![feature(const_hash)] -#![feature(const_ip)] -#![feature(const_ipv4)] -#![feature(const_ipv6)] #![feature(thread_local_internals)] // tidy-alphabetical-end // -- cgit 1.4.1-3-g733a5 From 2ae3b1b09a09ec9c034c4cc4ba822b11c2ccbd26 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 13 Oct 2024 12:24:54 +0200 Subject: sys/windows: remove miri hack that is only needed for win7 --- library/std/src/sys/pal/windows/c.rs | 2 +- library/std/src/sys/pal/windows/compat.rs | 8 ++------ 2 files changed, 3 insertions(+), 7 deletions(-) (limited to 'library/std/src') diff --git a/library/std/src/sys/pal/windows/c.rs b/library/std/src/sys/pal/windows/c.rs index b65ad7dbe8c..9ce3e912caf 100644 --- a/library/std/src/sys/pal/windows/c.rs +++ b/library/std/src/sys/pal/windows/c.rs @@ -175,9 +175,9 @@ extern "system" { pub fn WakeByAddressAll(address: *const c_void); } +// These are loaded by `load_synch_functions`. #[cfg(target_vendor = "win7")] compat_fn_optional! { - crate::sys::compat::load_synch_functions(); pub fn WaitOnAddress( address: *const c_void, compareaddress: *const c_void, diff --git a/library/std/src/sys/pal/windows/compat.rs b/library/std/src/sys/pal/windows/compat.rs index c8e25dd0c94..42999da1664 100644 --- a/library/std/src/sys/pal/windows/compat.rs +++ b/library/std/src/sys/pal/windows/compat.rs @@ -198,11 +198,10 @@ macro_rules! compat_fn_with_fallback { /// Optionally loaded functions. /// -/// Actual loading of the function defers to $load_functions. +/// Relies on the functions being pre-loaded elsewhere. #[cfg(target_vendor = "win7")] macro_rules! compat_fn_optional { - ($load_functions:expr; - $( + ($( $(#[$meta:meta])* $vis:vis fn $symbol:ident($($argname:ident: $argtype:ty),*) $(-> $rettype:ty)?; )+) => ( @@ -221,9 +220,6 @@ macro_rules! compat_fn_optional { #[inline(always)] pub fn option() -> Option { - // Miri does not understand the way we do preloading - // therefore load the function here instead. - #[cfg(miri)] $load_functions; NonNull::new(PTR.load(Ordering::Relaxed)).map(|f| unsafe { mem::transmute(f) }) } } -- cgit 1.4.1-3-g733a5 From 8d0a0b000c385ca43cc8c46e63b492c7edbf8cf2 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 13 Oct 2024 12:27:09 +0200 Subject: remove outdated comment now that Miri is on CI --- library/std/src/sys/pal/windows/mod.rs | 1 - 1 file changed, 1 deletion(-) (limited to 'library/std/src') diff --git a/library/std/src/sys/pal/windows/mod.rs b/library/std/src/sys/pal/windows/mod.rs index 1ea253e5e52..a9886012e8e 100644 --- a/library/std/src/sys/pal/windows/mod.rs +++ b/library/std/src/sys/pal/windows/mod.rs @@ -346,7 +346,6 @@ pub fn abort_internal() -> ! { } } -// miri is sensitive to changes here so check that miri is happy if touching this #[cfg(miri)] pub fn abort_internal() -> ! { crate::intrinsics::abort(); -- cgit 1.4.1-3-g733a5 From a87f5ca917b5c3c10163601da74df2045ee8e6ea Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 13 Oct 2024 12:34:28 +0200 Subject: sys/unix: add comments for some Miri fallbacks --- library/std/src/sys/pal/unix/fs.rs | 2 +- library/std/src/sys/sync/thread_parking/mod.rs | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'library/std/src') diff --git a/library/std/src/sys/pal/unix/fs.rs b/library/std/src/sys/pal/unix/fs.rs index 39aabf0b2d6..e80299f1868 100644 --- a/library/std/src/sys/pal/unix/fs.rs +++ b/library/std/src/sys/pal/unix/fs.rs @@ -899,7 +899,7 @@ impl DirEntry { target_os = "android", target_os = "hurd" ), - not(miri) + not(miri) // no dirfd on Miri ))] pub fn metadata(&self) -> io::Result { let fd = cvt(unsafe { dirfd(self.dir.dirp.0) })?; diff --git a/library/std/src/sys/sync/thread_parking/mod.rs b/library/std/src/sys/sync/thread_parking/mod.rs index 0ebc5e093ee..f4d8fa0a58c 100644 --- a/library/std/src/sys/sync/thread_parking/mod.rs +++ b/library/std/src/sys/sync/thread_parking/mod.rs @@ -23,6 +23,7 @@ cfg_if::cfg_if! { mod windows7; pub use windows7::Parker; } else if #[cfg(all(target_vendor = "apple", not(miri)))] { + // Doesn't work in Miri, see . mod darwin; pub use darwin::Parker; } else if #[cfg(target_os = "xous")] { -- cgit 1.4.1-3-g733a5 From f8ac1c44dba23d425cb630a9e8b334a5781462fb Mon Sep 17 00:00:00 2001 From: Ayush Singh Date: Sat, 31 Aug 2024 03:02:30 +0530 Subject: uefi: Implement getcwd and chdir - Using EFI Shell Protocol. These functions do not make much sense unless a shell is present. - Return the exe dir in case shell protocol is missing. Signed-off-by: Ayush Singh --- library/std/src/sys/pal/uefi/helpers.rs | 24 +++++++------ library/std/src/sys/pal/uefi/os.rs | 63 ++++++++++++++++++++++++++++++--- 2 files changed, 73 insertions(+), 14 deletions(-) (limited to 'library/std/src') diff --git a/library/std/src/sys/pal/uefi/helpers.rs b/library/std/src/sys/pal/uefi/helpers.rs index bd8a6684b64..4ced7065c82 100644 --- a/library/std/src/sys/pal/uefi/helpers.rs +++ b/library/std/src/sys/pal/uefi/helpers.rs @@ -177,16 +177,8 @@ pub(crate) fn device_path_to_text(path: NonNull) -> io::R ) }; - // SAFETY: `convert_device_path_to_text` returns a pointer to a null-terminated UTF-16 - // string, and that string cannot be deallocated prior to dropping the `WStrUnits`, so - // it's safe for `WStrUnits` to use. - let path_len = unsafe { - WStrUnits::new(path_ptr) - .ok_or(io::const_io_error!(io::ErrorKind::InvalidData, "Invalid path"))? - .count() - }; - - let path = OsString::from_wide(unsafe { slice::from_raw_parts(path_ptr.cast(), path_len) }); + let path = os_string_from_raw(path_ptr) + .ok_or(io::const_io_error!(io::ErrorKind::InvalidData, "Invalid path"))?; if let Some(boot_services) = crate::os::uefi::env::boot_services() { let boot_services: NonNull = boot_services.cast(); @@ -420,3 +412,15 @@ impl Drop for OwnedTable { unsafe { crate::alloc::dealloc(self.ptr as *mut u8, self.layout) }; } } + +/// Create OsString from a pointer to NULL terminated UTF-16 string +pub(crate) fn os_string_from_raw(ptr: *mut r_efi::efi::Char16) -> Option { + let path_len = unsafe { WStrUnits::new(ptr)?.count() }; + Some(OsString::from_wide(unsafe { slice::from_raw_parts(ptr.cast(), path_len) })) +} + +/// Create NULL terminated UTF-16 string +pub(crate) fn os_string_to_raw(s: &OsStr) -> Option> { + let temp = s.encode_wide().chain(Some(0)).collect::>(); + if temp[..temp.len() - 1].contains(&0) { None } else { Some(temp) } +} diff --git a/library/std/src/sys/pal/uefi/os.rs b/library/std/src/sys/pal/uefi/os.rs index 9aee67d622f..4eb7698b43a 100644 --- a/library/std/src/sys/pal/uefi/os.rs +++ b/library/std/src/sys/pal/uefi/os.rs @@ -1,7 +1,7 @@ use r_efi::efi::Status; use r_efi::efi::protocols::{device_path, loaded_image_device_path}; -use super::{RawOsError, helpers, unsupported}; +use super::{RawOsError, helpers, unsupported_err}; use crate::error::Error as StdError; use crate::ffi::{OsStr, OsString}; use crate::marker::PhantomData; @@ -125,11 +125,32 @@ pub fn error_string(errno: RawOsError) -> String { } pub fn getcwd() -> io::Result { - unsupported() + match uefi_shell::open_shell() { + Some(shell) => { + // SAFETY: path_ptr is managed by UEFI shell and should not be deallocated + let path_ptr = unsafe { ((*shell.as_ptr()).get_cur_dir)(crate::ptr::null_mut()) }; + helpers::os_string_from_raw(path_ptr) + .map(PathBuf::from) + .ok_or(io::const_io_error!(io::ErrorKind::InvalidData, "Invalid path")) + } + None => { + let mut t = current_exe()?; + // SAFETY: This should never fail since the disk prefix will be present even for root + // executables + assert!(t.pop()); + Ok(t) + } + } } -pub fn chdir(_: &path::Path) -> io::Result<()> { - unsupported() +pub fn chdir(p: &path::Path) -> io::Result<()> { + let shell = uefi_shell::open_shell().ok_or(unsupported_err())?; + + let mut p = helpers::os_string_to_raw(p.as_os_str()) + .ok_or(io::const_io_error!(io::ErrorKind::InvalidData, "Invalid path"))?; + + let r = unsafe { ((*shell.as_ptr()).set_cur_dir)(crate::ptr::null_mut(), p.as_mut_ptr()) }; + if r.is_error() { Err(io::Error::from_raw_os_error(r.as_usize())) } else { Ok(()) } } pub struct SplitPaths<'a>(!, PhantomData<&'a ()>); @@ -239,3 +260,37 @@ pub fn exit(code: i32) -> ! { pub fn getpid() -> u32 { panic!("no pids on this platform") } + +mod uefi_shell { + use r_efi::protocols::shell; + + use super::super::helpers; + use crate::ptr::NonNull; + use crate::sync::atomic::{AtomicPtr, Ordering}; + + pub fn open_shell() -> Option> { + static LAST_VALID_HANDLE: AtomicPtr = + AtomicPtr::new(crate::ptr::null_mut()); + + if let Some(handle) = NonNull::new(LAST_VALID_HANDLE.load(Ordering::Acquire)) { + if let Ok(protocol) = helpers::open_protocol::( + handle, + r_efi::protocols::shell::PROTOCOL_GUID, + ) { + return Some(protocol); + } + } + + let handles = helpers::locate_handles(shell::PROTOCOL_GUID).ok()?; + for handle in handles { + if let Ok(protocol) = + helpers::open_protocol::(handle, shell::PROTOCOL_GUID) + { + LAST_VALID_HANDLE.store(handle.as_ptr(), Ordering::Release); + return Some(protocol); + } + } + + None + } +} -- cgit 1.4.1-3-g733a5 From 4e438f7d6b7f6fbf2bb0c1ffe6ffe0b6bfc7fa38 Mon Sep 17 00:00:00 2001 From: George Bateman Date: Mon, 14 Oct 2024 20:47:24 +0100 Subject: Fix two const-hacks --- library/core/src/time.rs | 8 +++----- library/std/src/sys/pal/windows/args.rs | 19 ++++--------------- 2 files changed, 7 insertions(+), 20 deletions(-) (limited to 'library/std/src') diff --git a/library/core/src/time.rs b/library/core/src/time.rs index f7ea7e06e9c..51005ff795c 100644 --- a/library/core/src/time.rs +++ b/library/core/src/time.rs @@ -213,11 +213,9 @@ impl Duration { // SAFETY: nanos < NANOS_PER_SEC, therefore nanos is within the valid range Duration { secs, nanos: unsafe { Nanoseconds(nanos) } } } else { - // FIXME(const-hack): use `.expect` once that is possible. - let secs = match secs.checked_add((nanos / NANOS_PER_SEC) as u64) { - Some(secs) => secs, - None => panic!("overflow in Duration::new"), - }; + let secs = secs + .checked_add((nanos / NANOS_PER_SEC) as u64) + .expect("overflow in Duration::new"); let nanos = nanos % NANOS_PER_SEC; // SAFETY: nanos % NANOS_PER_SEC < NANOS_PER_SEC, therefore nanos is within the valid range Duration { secs, nanos: unsafe { Nanoseconds(nanos) } } diff --git a/library/std/src/sys/pal/windows/args.rs b/library/std/src/sys/pal/windows/args.rs index 848632ec2a7..e9fc19bcb99 100644 --- a/library/std/src/sys/pal/windows/args.rs +++ b/library/std/src/sys/pal/windows/args.rs @@ -18,17 +18,6 @@ use crate::sys_common::AsInner; use crate::sys_common::wstr::WStrUnits; use crate::{fmt, io, iter, vec}; -/// This is the const equivalent to `NonZero::new(n).unwrap()` -/// -/// FIXME(const-hack): This can be removed once `Option::unwrap` is stably const. -/// See the `const_option` feature (#67441). -const fn non_zero_u16(n: u16) -> NonZero { - match NonZero::new(n) { - Some(n) => n, - None => panic!("called `unwrap` on a `None` value"), - } -} - pub fn args() -> Args { // SAFETY: `GetCommandLineW` returns a pointer to a null terminated UTF-16 // string so it's safe for `WStrUnits` to use. @@ -66,10 +55,10 @@ fn parse_lp_cmd_line<'a, F: Fn() -> OsString>( lp_cmd_line: Option>, exe_name: F, ) -> Vec { - const BACKSLASH: NonZero = non_zero_u16(b'\\' as u16); - const QUOTE: NonZero = non_zero_u16(b'"' as u16); - const TAB: NonZero = non_zero_u16(b'\t' as u16); - const SPACE: NonZero = non_zero_u16(b' ' as u16); + const BACKSLASH: NonZero = NonZero::new(b'\\' as u16).unwrap(); + const QUOTE: NonZero = NonZero::new(b'"' as u16).unwrap(); + const TAB: NonZero = NonZero::new(b'\t' as u16).unwrap(); + const SPACE: NonZero = NonZero::new(b' ' as u16).unwrap(); let mut ret_val = Vec::new(); // If the cmd line pointer is null or it points to an empty string then -- cgit 1.4.1-3-g733a5 From c09ed3e767a73d83673790f74c357432fa44d320 Mon Sep 17 00:00:00 2001 From: Eduardo SΓ‘nchez MuΓ±oz Date: Mon, 14 Oct 2024 21:02:13 +0200 Subject: Make some float methods unstable `const fn` Some float methods are now `const fn` under the `const_float_methods` feature gate. In order to support `min`, `max`, `abs` and `copysign`, the implementation of some intrinsics had to be moved from Miri to rustc_const_eval. --- .../rustc_const_eval/src/interpret/intrinsics.rs | 80 +++++ library/core/src/intrinsics.rs | 387 +++++++++++++-------- library/core/src/lib.rs | 1 + library/core/src/num/f128.rs | 42 ++- library/core/src/num/f16.rs | 42 ++- library/core/src/num/f32.rs | 33 +- library/core/src/num/f64.rs | 33 +- library/std/src/f128.rs | 9 +- library/std/src/f16.rs | 9 +- library/std/src/f32.rs | 9 +- library/std/src/f64.rs | 9 +- library/std/src/lib.rs | 1 + src/tools/miri/src/intrinsics/mod.rs | 39 --- tests/ui/consts/const-eval/float_methods.rs | 47 +++ 14 files changed, 498 insertions(+), 243 deletions(-) create mode 100644 tests/ui/consts/const-eval/float_methods.rs (limited to 'library/std/src') diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs index 52780cc6a3a..540898ec645 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs @@ -4,6 +4,7 @@ use std::assert_matches::assert_matches; +use rustc_apfloat::ieee::{Double, Half, Quad, Single}; use rustc_hir::def_id::DefId; use rustc_middle::mir::{self, BinOp, ConstValue, NonDivergingIntrinsic}; use rustc_middle::ty::layout::{LayoutOf as _, TyAndLayout, ValidityRequirement}; @@ -438,6 +439,26 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { self.write_scalar(Scalar::from_target_usize(align.bytes(), self), dest)?; } + sym::minnumf16 => self.float_min_intrinsic::(args, dest)?, + sym::minnumf32 => self.float_min_intrinsic::(args, dest)?, + sym::minnumf64 => self.float_min_intrinsic::(args, dest)?, + sym::minnumf128 => self.float_min_intrinsic::(args, dest)?, + + sym::maxnumf16 => self.float_max_intrinsic::(args, dest)?, + sym::maxnumf32 => self.float_max_intrinsic::(args, dest)?, + sym::maxnumf64 => self.float_max_intrinsic::(args, dest)?, + sym::maxnumf128 => self.float_max_intrinsic::(args, dest)?, + + sym::copysignf16 => self.float_copysign_intrinsic::(args, dest)?, + sym::copysignf32 => self.float_copysign_intrinsic::(args, dest)?, + sym::copysignf64 => self.float_copysign_intrinsic::(args, dest)?, + sym::copysignf128 => self.float_copysign_intrinsic::(args, dest)?, + + sym::fabsf16 => self.float_abs_intrinsic::(args, dest)?, + sym::fabsf32 => self.float_abs_intrinsic::(args, dest)?, + sym::fabsf64 => self.float_abs_intrinsic::(args, dest)?, + sym::fabsf128 => self.float_abs_intrinsic::(args, dest)?, + // Unsupported intrinsic: skip the return_to_block below. _ => return interp_ok(false), } @@ -697,4 +718,63 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { let rhs_bytes = get_bytes(self, rhs)?; interp_ok(Scalar::from_bool(lhs_bytes == rhs_bytes)) } + + fn float_min_intrinsic( + &mut self, + args: &[OpTy<'tcx, M::Provenance>], + dest: &MPlaceTy<'tcx, M::Provenance>, + ) -> InterpResult<'tcx, ()> + where + F: rustc_apfloat::Float + rustc_apfloat::FloatConvert + Into>, + { + let a: F = self.read_scalar(&args[0])?.to_float()?; + let b: F = self.read_scalar(&args[1])?.to_float()?; + let res = self.adjust_nan(a.min(b), &[a, b]); + self.write_scalar(res, dest)?; + interp_ok(()) + } + + fn float_max_intrinsic( + &mut self, + args: &[OpTy<'tcx, M::Provenance>], + dest: &MPlaceTy<'tcx, M::Provenance>, + ) -> InterpResult<'tcx, ()> + where + F: rustc_apfloat::Float + rustc_apfloat::FloatConvert + Into>, + { + let a: F = self.read_scalar(&args[0])?.to_float()?; + let b: F = self.read_scalar(&args[1])?.to_float()?; + let res = self.adjust_nan(a.max(b), &[a, b]); + self.write_scalar(res, dest)?; + interp_ok(()) + } + + fn float_copysign_intrinsic( + &mut self, + args: &[OpTy<'tcx, M::Provenance>], + dest: &MPlaceTy<'tcx, M::Provenance>, + ) -> InterpResult<'tcx, ()> + where + F: rustc_apfloat::Float + rustc_apfloat::FloatConvert + Into>, + { + let a: F = self.read_scalar(&args[0])?.to_float()?; + let b: F = self.read_scalar(&args[1])?.to_float()?; + // bitwise, no NaN adjustments + self.write_scalar(a.copy_sign(b), dest)?; + interp_ok(()) + } + + fn float_abs_intrinsic( + &mut self, + args: &[OpTy<'tcx, M::Provenance>], + dest: &MPlaceTy<'tcx, M::Provenance>, + ) -> InterpResult<'tcx, ()> + where + F: rustc_apfloat::Float + rustc_apfloat::FloatConvert + Into>, + { + let x: F = self.read_scalar(&args[0])?.to_float()?; + // bitwise, no NaN adjustments + self.write_scalar(x.abs(), dest)?; + interp_ok(()) + } } diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index 061fba9a1f7..3ae729e76e1 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -1848,154 +1848,6 @@ extern "rust-intrinsic" { #[cfg(not(bootstrap))] pub fn fmuladdf128(a: f128, b: f128, c: f128) -> f128; - /// Returns the absolute value of an `f16`. - /// - /// The stabilized version of this intrinsic is - /// [`f16::abs`](../../std/primitive.f16.html#method.abs) - #[rustc_nounwind] - pub fn fabsf16(x: f16) -> f16; - /// Returns the absolute value of an `f32`. - /// - /// The stabilized version of this intrinsic is - /// [`f32::abs`](../../std/primitive.f32.html#method.abs) - #[rustc_nounwind] - pub fn fabsf32(x: f32) -> f32; - /// Returns the absolute value of an `f64`. - /// - /// The stabilized version of this intrinsic is - /// [`f64::abs`](../../std/primitive.f64.html#method.abs) - #[rustc_nounwind] - pub fn fabsf64(x: f64) -> f64; - /// Returns the absolute value of an `f128`. - /// - /// The stabilized version of this intrinsic is - /// [`f128::abs`](../../std/primitive.f128.html#method.abs) - #[rustc_nounwind] - pub fn fabsf128(x: f128) -> f128; - - /// Returns the minimum of two `f16` values. - /// - /// Note that, unlike most intrinsics, this is safe to call; - /// it does not require an `unsafe` block. - /// Therefore, implementations must not require the user to uphold - /// any safety invariants. - /// - /// The stabilized version of this intrinsic is - /// [`f16::min`] - #[rustc_safe_intrinsic] - #[rustc_nounwind] - pub fn minnumf16(x: f16, y: f16) -> f16; - /// Returns the minimum of two `f32` values. - /// - /// Note that, unlike most intrinsics, this is safe to call; - /// it does not require an `unsafe` block. - /// Therefore, implementations must not require the user to uphold - /// any safety invariants. - /// - /// The stabilized version of this intrinsic is - /// [`f32::min`] - #[rustc_safe_intrinsic] - #[rustc_nounwind] - pub fn minnumf32(x: f32, y: f32) -> f32; - /// Returns the minimum of two `f64` values. - /// - /// Note that, unlike most intrinsics, this is safe to call; - /// it does not require an `unsafe` block. - /// Therefore, implementations must not require the user to uphold - /// any safety invariants. - /// - /// The stabilized version of this intrinsic is - /// [`f64::min`] - #[rustc_safe_intrinsic] - #[rustc_nounwind] - pub fn minnumf64(x: f64, y: f64) -> f64; - /// Returns the minimum of two `f128` values. - /// - /// Note that, unlike most intrinsics, this is safe to call; - /// it does not require an `unsafe` block. - /// Therefore, implementations must not require the user to uphold - /// any safety invariants. - /// - /// The stabilized version of this intrinsic is - /// [`f128::min`] - #[rustc_safe_intrinsic] - #[rustc_nounwind] - pub fn minnumf128(x: f128, y: f128) -> f128; - - /// Returns the maximum of two `f16` values. - /// - /// Note that, unlike most intrinsics, this is safe to call; - /// it does not require an `unsafe` block. - /// Therefore, implementations must not require the user to uphold - /// any safety invariants. - /// - /// The stabilized version of this intrinsic is - /// [`f16::max`] - #[rustc_safe_intrinsic] - #[rustc_nounwind] - pub fn maxnumf16(x: f16, y: f16) -> f16; - /// Returns the maximum of two `f32` values. - /// - /// Note that, unlike most intrinsics, this is safe to call; - /// it does not require an `unsafe` block. - /// Therefore, implementations must not require the user to uphold - /// any safety invariants. - /// - /// The stabilized version of this intrinsic is - /// [`f32::max`] - #[rustc_safe_intrinsic] - #[rustc_nounwind] - pub fn maxnumf32(x: f32, y: f32) -> f32; - /// Returns the maximum of two `f64` values. - /// - /// Note that, unlike most intrinsics, this is safe to call; - /// it does not require an `unsafe` block. - /// Therefore, implementations must not require the user to uphold - /// any safety invariants. - /// - /// The stabilized version of this intrinsic is - /// [`f64::max`] - #[rustc_safe_intrinsic] - #[rustc_nounwind] - pub fn maxnumf64(x: f64, y: f64) -> f64; - /// Returns the maximum of two `f128` values. - /// - /// Note that, unlike most intrinsics, this is safe to call; - /// it does not require an `unsafe` block. - /// Therefore, implementations must not require the user to uphold - /// any safety invariants. - /// - /// The stabilized version of this intrinsic is - /// [`f128::max`] - #[rustc_safe_intrinsic] - #[rustc_nounwind] - pub fn maxnumf128(x: f128, y: f128) -> f128; - - /// Copies the sign from `y` to `x` for `f16` values. - /// - /// The stabilized version of this intrinsic is - /// [`f16::copysign`](../../std/primitive.f16.html#method.copysign) - #[rustc_nounwind] - pub fn copysignf16(x: f16, y: f16) -> f16; - /// Copies the sign from `y` to `x` for `f32` values. - /// - /// The stabilized version of this intrinsic is - /// [`f32::copysign`](../../std/primitive.f32.html#method.copysign) - #[rustc_nounwind] - pub fn copysignf32(x: f32, y: f32) -> f32; - /// Copies the sign from `y` to `x` for `f64` values. - /// - /// The stabilized version of this intrinsic is - /// [`f64::copysign`](../../std/primitive.f64.html#method.copysign) - #[rustc_nounwind] - pub fn copysignf64(x: f64, y: f64) -> f64; - /// Copies the sign from `y` to `x` for `f128` values. - /// - /// The stabilized version of this intrinsic is - /// [`f128::copysign`](../../std/primitive.f128.html#method.copysign) - #[rustc_nounwind] - pub fn copysignf128(x: f128, y: f128) -> f128; - /// Returns the largest integer less than or equal to an `f16`. /// /// The stabilized version of this intrinsic is @@ -3550,6 +3402,245 @@ pub const unsafe fn write_bytes(dst: *mut T, val: u8, count: usize) { } } +/// Returns the minimum of two `f16` values. +/// +/// Note that, unlike most intrinsics, this is safe to call; +/// it does not require an `unsafe` block. +/// Therefore, implementations must not require the user to uphold +/// any safety invariants. +/// +/// The stabilized version of this intrinsic is +/// [`f16::min`] +#[rustc_nounwind] +// #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] +#[rustc_const_unstable(feature = "f16", issue = "116909")] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const fn minnumf16(_x: f16, _y: f16) -> f16 { + unimplemented!(); +} + +/// Returns the minimum of two `f32` values. +/// +/// Note that, unlike most intrinsics, this is safe to call; +/// it does not require an `unsafe` block. +/// Therefore, implementations must not require the user to uphold +/// any safety invariants. +/// +/// The stabilized version of this intrinsic is +/// [`f32::min`] +#[rustc_nounwind] +#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const fn minnumf32(_x: f32, _y: f32) -> f32 { + unimplemented!(); +} + +/// Returns the minimum of two `f64` values. +/// +/// Note that, unlike most intrinsics, this is safe to call; +/// it does not require an `unsafe` block. +/// Therefore, implementations must not require the user to uphold +/// any safety invariants. +/// +/// The stabilized version of this intrinsic is +/// [`f64::min`] +#[rustc_nounwind] +#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const fn minnumf64(_x: f64, _y: f64) -> f64 { + unimplemented!(); +} + +/// Returns the minimum of two `f128` values. +/// +/// Note that, unlike most intrinsics, this is safe to call; +/// it does not require an `unsafe` block. +/// Therefore, implementations must not require the user to uphold +/// any safety invariants. +/// +/// The stabilized version of this intrinsic is +/// [`f128::min`] +#[rustc_nounwind] +// #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] +#[rustc_const_unstable(feature = "f128", issue = "116909")] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const fn minnumf128(_x: f128, _y: f128) -> f128 { + unimplemented!(); +} + +/// Returns the maximum of two `f16` values. +/// +/// Note that, unlike most intrinsics, this is safe to call; +/// it does not require an `unsafe` block. +/// Therefore, implementations must not require the user to uphold +/// any safety invariants. +/// +/// The stabilized version of this intrinsic is +/// [`f16::max`] +#[rustc_nounwind] +// #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] +#[rustc_const_unstable(feature = "f16", issue = "116909")] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const fn maxnumf16(_x: f16, _y: f16) -> f16 { + unimplemented!(); +} + +/// Returns the maximum of two `f32` values. +/// +/// Note that, unlike most intrinsics, this is safe to call; +/// it does not require an `unsafe` block. +/// Therefore, implementations must not require the user to uphold +/// any safety invariants. +/// +/// The stabilized version of this intrinsic is +/// [`f32::max`] +#[rustc_nounwind] +#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const fn maxnumf32(_x: f32, _y: f32) -> f32 { + unimplemented!(); +} + +/// Returns the maximum of two `f64` values. +/// +/// Note that, unlike most intrinsics, this is safe to call; +/// it does not require an `unsafe` block. +/// Therefore, implementations must not require the user to uphold +/// any safety invariants. +/// +/// The stabilized version of this intrinsic is +/// [`f64::max`] +#[rustc_nounwind] +#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const fn maxnumf64(_x: f64, _y: f64) -> f64 { + unimplemented!(); +} + +/// Returns the maximum of two `f128` values. +/// +/// Note that, unlike most intrinsics, this is safe to call; +/// it does not require an `unsafe` block. +/// Therefore, implementations must not require the user to uphold +/// any safety invariants. +/// +/// The stabilized version of this intrinsic is +/// [`f128::max`] +#[rustc_nounwind] +// #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] +#[rustc_const_unstable(feature = "f128", issue = "116909")] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const fn maxnumf128(_x: f128, _y: f128) -> f128 { + unimplemented!(); +} + +/// Returns the absolute value of an `f16`. +/// +/// The stabilized version of this intrinsic is +/// [`f16::abs`](../../std/primitive.f16.html#method.abs) +#[rustc_nounwind] +// #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] +#[rustc_const_unstable(feature = "f16", issue = "116909")] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const unsafe fn fabsf16(_x: f16) -> f16 { + unimplemented!(); +} + +/// Returns the absolute value of an `f32`. +/// +/// The stabilized version of this intrinsic is +/// [`f32::abs`](../../std/primitive.f32.html#method.abs) +#[rustc_nounwind] +#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const unsafe fn fabsf32(_x: f32) -> f32 { + unimplemented!(); +} + +/// Returns the absolute value of an `f64`. +/// +/// The stabilized version of this intrinsic is +/// [`f64::abs`](../../std/primitive.f64.html#method.abs) +#[rustc_nounwind] +#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const unsafe fn fabsf64(_x: f64) -> f64 { + unimplemented!(); +} + +/// Returns the absolute value of an `f128`. +/// +/// The stabilized version of this intrinsic is +/// [`f128::abs`](../../std/primitive.f128.html#method.abs) +#[rustc_nounwind] +// #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] +#[rustc_const_unstable(feature = "f128", issue = "116909")] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const unsafe fn fabsf128(_x: f128) -> f128 { + unimplemented!(); +} + +/// Copies the sign from `y` to `x` for `f16` values. +/// +/// The stabilized version of this intrinsic is +/// [`f16::copysign`](../../std/primitive.f16.html#method.copysign) +#[rustc_nounwind] +// #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] +#[rustc_const_unstable(feature = "f16", issue = "116909")] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const unsafe fn copysignf16(_x: f16, _y: f16) -> f16 { + unimplemented!(); +} + +/// Copies the sign from `y` to `x` for `f32` values. +/// +/// The stabilized version of this intrinsic is +/// [`f32::copysign`](../../std/primitive.f32.html#method.copysign) +#[rustc_nounwind] +#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const unsafe fn copysignf32(_x: f32, _y: f32) -> f32 { + unimplemented!(); +} +/// Copies the sign from `y` to `x` for `f64` values. +/// +/// The stabilized version of this intrinsic is +/// [`f64::copysign`](../../std/primitive.f64.html#method.copysign) +#[rustc_nounwind] +#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const unsafe fn copysignf64(_x: f64, _y: f64) -> f64 { + unimplemented!(); +} + +/// Copies the sign from `y` to `x` for `f128` values. +/// +/// The stabilized version of this intrinsic is +/// [`f128::copysign`](../../std/primitive.f128.html#method.copysign) +#[rustc_nounwind] +// #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] +#[rustc_const_unstable(feature = "f128", issue = "116909")] +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const unsafe fn copysignf128(_x: f128, _y: f128) -> f128 { + unimplemented!(); +} + /// Inform Miri that a given pointer definitely has a certain alignment. #[cfg(miri)] pub(crate) const fn miri_promise_symbolic_alignment(ptr: *const (), align: usize) { diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 7f9a2152426..482e1f30b7e 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -120,6 +120,7 @@ #![feature(const_char_encode_utf16)] #![feature(const_eval_select)] #![feature(const_exact_div)] +#![feature(const_float_methods)] #![feature(const_fmt_arguments_new)] #![feature(const_hash)] #![feature(const_heap)] diff --git a/library/core/src/num/f128.rs b/library/core/src/num/f128.rs index 764df4fe4b0..5ab2ab50d7c 100644 --- a/library/core/src/num/f128.rs +++ b/library/core/src/num/f128.rs @@ -471,7 +471,7 @@ impl f128 { #[inline] #[must_use] #[unstable(feature = "f128", issue = "116909")] - pub fn is_sign_positive(self) -> bool { + pub const fn is_sign_positive(self) -> bool { !self.is_sign_negative() } @@ -497,7 +497,7 @@ impl f128 { #[inline] #[must_use] #[unstable(feature = "f128", issue = "116909")] - pub fn is_sign_negative(self) -> bool { + pub const fn is_sign_negative(self) -> bool { // IEEE754 says: isSignMinus(x) is true if and only if x has negative sign. isSignMinus // applies to zeros and NaNs as well. // SAFETY: This is just transmuting to get the sign bit, it's fine. @@ -538,7 +538,7 @@ impl f128 { #[inline] #[unstable(feature = "f128", issue = "116909")] // #[unstable(feature = "float_next_up_down", issue = "91399")] - pub fn next_up(self) -> Self { + pub const fn next_up(self) -> Self { // Some targets violate Rust's assumption of IEEE semantics, e.g. by flushing // denormals to zero. This is in general unsound and unsupported, but here // we do our best to still produce the correct result on such targets. @@ -592,7 +592,7 @@ impl f128 { #[inline] #[unstable(feature = "f128", issue = "116909")] // #[unstable(feature = "float_next_up_down", issue = "91399")] - pub fn next_down(self) -> Self { + pub const fn next_down(self) -> Self { // Some targets violate Rust's assumption of IEEE semantics, e.g. by flushing // denormals to zero. This is in general unsound and unsupported, but here // we do our best to still produce the correct result on such targets. @@ -627,8 +627,9 @@ impl f128 { /// ``` #[inline] #[unstable(feature = "f128", issue = "116909")] + #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] #[must_use = "this returns the result of the operation, without modifying the original"] - pub fn recip(self) -> Self { + pub const fn recip(self) -> Self { 1.0 / self } @@ -647,8 +648,9 @@ impl f128 { /// ``` #[inline] #[unstable(feature = "f128", issue = "116909")] + #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] #[must_use = "this returns the result of the operation, without modifying the original"] - pub fn to_degrees(self) -> Self { + pub const fn to_degrees(self) -> Self { // Use a literal for better precision. const PIS_IN_180: f128 = 57.2957795130823208767981548141051703324054724665643215491602_f128; self * PIS_IN_180 @@ -670,8 +672,9 @@ impl f128 { /// ``` #[inline] #[unstable(feature = "f128", issue = "116909")] + #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] #[must_use = "this returns the result of the operation, without modifying the original"] - pub fn to_radians(self) -> f128 { + pub const fn to_radians(self) -> f128 { // Use a literal for better precision. const RADS_PER_DEG: f128 = 0.0174532925199432957692369076848861271344287188854172545609719_f128; @@ -698,8 +701,9 @@ impl f128 { /// ``` #[inline] #[unstable(feature = "f128", issue = "116909")] + #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] #[must_use = "this returns the result of the comparison, without modifying either input"] - pub fn max(self, other: f128) -> f128 { + pub const fn max(self, other: f128) -> f128 { intrinsics::maxnumf128(self, other) } @@ -723,8 +727,9 @@ impl f128 { /// ``` #[inline] #[unstable(feature = "f128", issue = "116909")] + #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] #[must_use = "this returns the result of the comparison, without modifying either input"] - pub fn min(self, other: f128) -> f128 { + pub const fn min(self, other: f128) -> f128 { intrinsics::minnumf128(self, other) } @@ -757,7 +762,7 @@ impl f128 { #[unstable(feature = "f128", issue = "116909")] // #[unstable(feature = "float_minimum_maximum", issue = "91079")] #[must_use = "this returns the result of the comparison, without modifying either input"] - pub fn maximum(self, other: f128) -> f128 { + pub const fn maximum(self, other: f128) -> f128 { if self > other { self } else if other > self { @@ -798,7 +803,7 @@ impl f128 { #[unstable(feature = "f128", issue = "116909")] // #[unstable(feature = "float_minimum_maximum", issue = "91079")] #[must_use = "this returns the result of the comparison, without modifying either input"] - pub fn minimum(self, other: f128) -> f128 { + pub const fn minimum(self, other: f128) -> f128 { if self < other { self } else if other < self { @@ -1269,9 +1274,20 @@ impl f128 { /// ``` #[inline] #[unstable(feature = "f128", issue = "116909")] + #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] #[must_use = "method returns a new number and does not mutate the original value"] - pub fn clamp(mut self, min: f128, max: f128) -> f128 { - assert!(min <= max, "min > max, or either was NaN. min = {min:?}, max = {max:?}"); + pub const fn clamp(mut self, min: f128, max: f128) -> f128 { + #[inline] // inline to avoid LLVM crash + const fn assert_at_const(min: f128, max: f128) { + // Note that we cannot format in constant expressions. + assert!(min <= max, "min > max, or either was NaN"); + } + #[inline] // inline to avoid codegen regression + fn assert_at_rt(min: f128, max: f128) { + assert!(min <= max, "min > max, or either was NaN. min = {min:?}, max = {max:?}"); + } + // FIXME(const-hack): We would prefer to have streamlined panics when formatters become const-friendly. + intrinsics::const_eval_select((min, max), assert_at_const, assert_at_rt); if self < min { self = min; } diff --git a/library/core/src/num/f16.rs b/library/core/src/num/f16.rs index 897fc8c105d..60a88496696 100644 --- a/library/core/src/num/f16.rs +++ b/library/core/src/num/f16.rs @@ -459,7 +459,7 @@ impl f16 { #[inline] #[must_use] #[unstable(feature = "f16", issue = "116909")] - pub fn is_sign_positive(self) -> bool { + pub const fn is_sign_positive(self) -> bool { !self.is_sign_negative() } @@ -488,7 +488,7 @@ impl f16 { #[inline] #[must_use] #[unstable(feature = "f16", issue = "116909")] - pub fn is_sign_negative(self) -> bool { + pub const fn is_sign_negative(self) -> bool { // IEEE754 says: isSignMinus(x) is true if and only if x has negative sign. isSignMinus // applies to zeros and NaNs as well. // SAFETY: This is just transmuting to get the sign bit, it's fine. @@ -529,7 +529,7 @@ impl f16 { #[inline] #[unstable(feature = "f16", issue = "116909")] // #[unstable(feature = "float_next_up_down", issue = "91399")] - pub fn next_up(self) -> Self { + pub const fn next_up(self) -> Self { // Some targets violate Rust's assumption of IEEE semantics, e.g. by flushing // denormals to zero. This is in general unsound and unsupported, but here // we do our best to still produce the correct result on such targets. @@ -583,7 +583,7 @@ impl f16 { #[inline] #[unstable(feature = "f16", issue = "116909")] // #[unstable(feature = "float_next_up_down", issue = "91399")] - pub fn next_down(self) -> Self { + pub const fn next_down(self) -> Self { // Some targets violate Rust's assumption of IEEE semantics, e.g. by flushing // denormals to zero. This is in general unsound and unsupported, but here // we do our best to still produce the correct result on such targets. @@ -618,8 +618,9 @@ impl f16 { /// ``` #[inline] #[unstable(feature = "f16", issue = "116909")] + #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] #[must_use = "this returns the result of the operation, without modifying the original"] - pub fn recip(self) -> Self { + pub const fn recip(self) -> Self { 1.0 / self } @@ -638,8 +639,9 @@ impl f16 { /// ``` #[inline] #[unstable(feature = "f16", issue = "116909")] + #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] #[must_use = "this returns the result of the operation, without modifying the original"] - pub fn to_degrees(self) -> Self { + pub const fn to_degrees(self) -> Self { // Use a literal for better precision. const PIS_IN_180: f16 = 57.2957795130823208767981548141051703_f16; self * PIS_IN_180 @@ -661,8 +663,9 @@ impl f16 { /// ``` #[inline] #[unstable(feature = "f16", issue = "116909")] + #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] #[must_use = "this returns the result of the operation, without modifying the original"] - pub fn to_radians(self) -> f16 { + pub const fn to_radians(self) -> f16 { // Use a literal for better precision. const RADS_PER_DEG: f16 = 0.017453292519943295769236907684886_f16; self * RADS_PER_DEG @@ -687,8 +690,9 @@ impl f16 { /// ``` #[inline] #[unstable(feature = "f16", issue = "116909")] + #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] #[must_use = "this returns the result of the comparison, without modifying either input"] - pub fn max(self, other: f16) -> f16 { + pub const fn max(self, other: f16) -> f16 { intrinsics::maxnumf16(self, other) } @@ -711,8 +715,9 @@ impl f16 { /// ``` #[inline] #[unstable(feature = "f16", issue = "116909")] + #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] #[must_use = "this returns the result of the comparison, without modifying either input"] - pub fn min(self, other: f16) -> f16 { + pub const fn min(self, other: f16) -> f16 { intrinsics::minnumf16(self, other) } @@ -744,7 +749,7 @@ impl f16 { #[unstable(feature = "f16", issue = "116909")] // #[unstable(feature = "float_minimum_maximum", issue = "91079")] #[must_use = "this returns the result of the comparison, without modifying either input"] - pub fn maximum(self, other: f16) -> f16 { + pub const fn maximum(self, other: f16) -> f16 { if self > other { self } else if other > self { @@ -784,7 +789,7 @@ impl f16 { #[unstable(feature = "f16", issue = "116909")] // #[unstable(feature = "float_minimum_maximum", issue = "91079")] #[must_use = "this returns the result of the comparison, without modifying either input"] - pub fn minimum(self, other: f16) -> f16 { + pub const fn minimum(self, other: f16) -> f16 { if self < other { self } else if other < self { @@ -1244,9 +1249,20 @@ impl f16 { /// ``` #[inline] #[unstable(feature = "f16", issue = "116909")] + #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] #[must_use = "method returns a new number and does not mutate the original value"] - pub fn clamp(mut self, min: f16, max: f16) -> f16 { - assert!(min <= max, "min > max, or either was NaN. min = {min:?}, max = {max:?}"); + pub const fn clamp(mut self, min: f16, max: f16) -> f16 { + #[inline] // inline to avoid LLVM crash + const fn assert_at_const(min: f16, max: f16) { + // Note that we cannot format in constant expressions. + assert!(min <= max, "min > max, or either was NaN"); + } + #[inline] // inline to avoid codegen regression + fn assert_at_rt(min: f16, max: f16) { + assert!(min <= max, "min > max, or either was NaN. min = {min:?}, max = {max:?}"); + } + // FIXME(const-hack): We would prefer to have streamlined panics when formatters become const-friendly. + intrinsics::const_eval_select((min, max), assert_at_const, assert_at_rt); if self < min { self = min; } diff --git a/library/core/src/num/f32.rs b/library/core/src/num/f32.rs index a9a2595c25c..05f5a08ad0a 100644 --- a/library/core/src/num/f32.rs +++ b/library/core/src/num/f32.rs @@ -828,8 +828,9 @@ impl f32 { /// ``` #[must_use = "this returns the result of the operation, without modifying the original"] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] #[inline] - pub fn recip(self) -> f32 { + pub const fn recip(self) -> f32 { 1.0 / self } @@ -845,8 +846,9 @@ impl f32 { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[stable(feature = "f32_deg_rad_conversions", since = "1.7.0")] + #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] #[inline] - pub fn to_degrees(self) -> f32 { + pub const fn to_degrees(self) -> f32 { // Use a constant for better precision. const PIS_IN_180: f32 = 57.2957795130823208767981548141051703_f32; self * PIS_IN_180 @@ -864,8 +866,9 @@ impl f32 { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[stable(feature = "f32_deg_rad_conversions", since = "1.7.0")] + #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] #[inline] - pub fn to_radians(self) -> f32 { + pub const fn to_radians(self) -> f32 { const RADS_PER_DEG: f32 = consts::PI / 180.0; self * RADS_PER_DEG } @@ -885,8 +888,9 @@ impl f32 { /// ``` #[must_use = "this returns the result of the comparison, without modifying either input"] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] #[inline] - pub fn max(self, other: f32) -> f32 { + pub const fn max(self, other: f32) -> f32 { intrinsics::maxnumf32(self, other) } @@ -905,8 +909,9 @@ impl f32 { /// ``` #[must_use = "this returns the result of the comparison, without modifying either input"] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] #[inline] - pub fn min(self, other: f32) -> f32 { + pub const fn min(self, other: f32) -> f32 { intrinsics::minnumf32(self, other) } @@ -933,7 +938,7 @@ impl f32 { #[must_use = "this returns the result of the comparison, without modifying either input"] #[unstable(feature = "float_minimum_maximum", issue = "91079")] #[inline] - pub fn maximum(self, other: f32) -> f32 { + pub const fn maximum(self, other: f32) -> f32 { if self > other { self } else if other > self { @@ -968,7 +973,7 @@ impl f32 { #[must_use = "this returns the result of the comparison, without modifying either input"] #[unstable(feature = "float_minimum_maximum", issue = "91079")] #[inline] - pub fn minimum(self, other: f32) -> f32 { + pub const fn minimum(self, other: f32) -> f32 { if self < other { self } else if other < self { @@ -1401,9 +1406,19 @@ impl f32 { /// ``` #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "clamp", since = "1.50.0")] + #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] #[inline] - pub fn clamp(mut self, min: f32, max: f32) -> f32 { - assert!(min <= max, "min > max, or either was NaN. min = {min:?}, max = {max:?}"); + pub const fn clamp(mut self, min: f32, max: f32) -> f32 { + const fn assert_at_const(min: f32, max: f32) { + // Note that we cannot format in constant expressions. + assert!(min <= max, "min > max, or either was NaN"); + } + #[inline] // inline to avoid codegen regression + fn assert_at_rt(min: f32, max: f32) { + assert!(min <= max, "min > max, or either was NaN. min = {min:?}, max = {max:?}"); + } + // FIXME(const-hack): We would prefer to have streamlined panics when formatters become const-friendly. + intrinsics::const_eval_select((min, max), assert_at_const, assert_at_rt); if self < min { self = min; } diff --git a/library/core/src/num/f64.rs b/library/core/src/num/f64.rs index aa7a54ca650..89c6726d985 100644 --- a/library/core/src/num/f64.rs +++ b/library/core/src/num/f64.rs @@ -845,8 +845,9 @@ impl f64 { /// ``` #[must_use = "this returns the result of the operation, without modifying the original"] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] #[inline] - pub fn recip(self) -> f64 { + pub const fn recip(self) -> f64 { 1.0 / self } @@ -862,8 +863,9 @@ impl f64 { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] #[inline] - pub fn to_degrees(self) -> f64 { + pub const fn to_degrees(self) -> f64 { // The division here is correctly rounded with respect to the true // value of 180/Ο€. (This differs from f32, where a constant must be // used to ensure a correctly rounded result.) @@ -882,8 +884,9 @@ impl f64 { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] #[inline] - pub fn to_radians(self) -> f64 { + pub const fn to_radians(self) -> f64 { const RADS_PER_DEG: f64 = consts::PI / 180.0; self * RADS_PER_DEG } @@ -903,8 +906,9 @@ impl f64 { /// ``` #[must_use = "this returns the result of the comparison, without modifying either input"] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] #[inline] - pub fn max(self, other: f64) -> f64 { + pub const fn max(self, other: f64) -> f64 { intrinsics::maxnumf64(self, other) } @@ -923,8 +927,9 @@ impl f64 { /// ``` #[must_use = "this returns the result of the comparison, without modifying either input"] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] #[inline] - pub fn min(self, other: f64) -> f64 { + pub const fn min(self, other: f64) -> f64 { intrinsics::minnumf64(self, other) } @@ -951,7 +956,7 @@ impl f64 { #[must_use = "this returns the result of the comparison, without modifying either input"] #[unstable(feature = "float_minimum_maximum", issue = "91079")] #[inline] - pub fn maximum(self, other: f64) -> f64 { + pub const fn maximum(self, other: f64) -> f64 { if self > other { self } else if other > self { @@ -986,7 +991,7 @@ impl f64 { #[must_use = "this returns the result of the comparison, without modifying either input"] #[unstable(feature = "float_minimum_maximum", issue = "91079")] #[inline] - pub fn minimum(self, other: f64) -> f64 { + pub const fn minimum(self, other: f64) -> f64 { if self < other { self } else if other < self { @@ -1401,9 +1406,19 @@ impl f64 { /// ``` #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "clamp", since = "1.50.0")] + #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] #[inline] - pub fn clamp(mut self, min: f64, max: f64) -> f64 { - assert!(min <= max, "min > max, or either was NaN. min = {min:?}, max = {max:?}"); + pub const fn clamp(mut self, min: f64, max: f64) -> f64 { + const fn assert_at_const(min: f64, max: f64) { + // Note that we cannot format in constant expressions. + assert!(min <= max, "min > max, or either was NaN"); + } + #[inline] // inline to avoid codegen regression + fn assert_at_rt(min: f64, max: f64) { + assert!(min <= max, "min > max, or either was NaN. min = {min:?}, max = {max:?}"); + } + // FIXME(const-hack): We would prefer to have streamlined panics when formatters become const-friendly. + intrinsics::const_eval_select((min, max), assert_at_const, assert_at_rt); if self < min { self = min; } diff --git a/library/std/src/f128.rs b/library/std/src/f128.rs index b436fe9929c..229f979b5b1 100644 --- a/library/std/src/f128.rs +++ b/library/std/src/f128.rs @@ -210,8 +210,9 @@ impl f128 { #[inline] #[rustc_allow_incoherent_impl] #[unstable(feature = "f128", issue = "116909")] + #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] #[must_use = "method returns a new number and does not mutate the original value"] - pub fn abs(self) -> Self { + pub const fn abs(self) -> Self { // FIXME(f16_f128): replace with `intrinsics::fabsf128` when available // We don't do this now because LLVM has lowering bugs for f128 math. Self::from_bits(self.to_bits() & !(1 << 127)) @@ -240,8 +241,9 @@ impl f128 { #[inline] #[rustc_allow_incoherent_impl] #[unstable(feature = "f128", issue = "116909")] + #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] #[must_use = "method returns a new number and does not mutate the original value"] - pub fn signum(self) -> f128 { + pub const fn signum(self) -> f128 { if self.is_nan() { Self::NAN } else { 1.0_f128.copysign(self) } } @@ -278,8 +280,9 @@ impl f128 { #[inline] #[rustc_allow_incoherent_impl] #[unstable(feature = "f128", issue = "116909")] + #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] #[must_use = "method returns a new number and does not mutate the original value"] - pub fn copysign(self, sign: f128) -> f128 { + pub const fn copysign(self, sign: f128) -> f128 { unsafe { intrinsics::copysignf128(self, sign) } } diff --git a/library/std/src/f16.rs b/library/std/src/f16.rs index b2cd5fae9d0..bed21cda1cd 100644 --- a/library/std/src/f16.rs +++ b/library/std/src/f16.rs @@ -210,8 +210,9 @@ impl f16 { #[inline] #[rustc_allow_incoherent_impl] #[unstable(feature = "f16", issue = "116909")] + #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] #[must_use = "method returns a new number and does not mutate the original value"] - pub fn abs(self) -> Self { + pub const fn abs(self) -> Self { // FIXME(f16_f128): replace with `intrinsics::fabsf16` when available Self::from_bits(self.to_bits() & !(1 << 15)) } @@ -239,8 +240,9 @@ impl f16 { #[inline] #[rustc_allow_incoherent_impl] #[unstable(feature = "f16", issue = "116909")] + #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] #[must_use = "method returns a new number and does not mutate the original value"] - pub fn signum(self) -> f16 { + pub const fn signum(self) -> f16 { if self.is_nan() { Self::NAN } else { 1.0_f16.copysign(self) } } @@ -277,8 +279,9 @@ impl f16 { #[inline] #[rustc_allow_incoherent_impl] #[unstable(feature = "f16", issue = "116909")] + #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] #[must_use = "method returns a new number and does not mutate the original value"] - pub fn copysign(self, sign: f16) -> f16 { + pub const fn copysign(self, sign: f16) -> f16 { unsafe { intrinsics::copysignf16(self, sign) } } diff --git a/library/std/src/f32.rs b/library/std/src/f32.rs index fa0b3ef6484..30cf4e1f756 100644 --- a/library/std/src/f32.rs +++ b/library/std/src/f32.rs @@ -194,8 +194,9 @@ impl f32 { #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] #[inline] - pub fn abs(self) -> f32 { + pub const fn abs(self) -> f32 { unsafe { intrinsics::fabsf32(self) } } @@ -218,8 +219,9 @@ impl f32 { #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] #[inline] - pub fn signum(self) -> f32 { + pub const fn signum(self) -> f32 { if self.is_nan() { Self::NAN } else { 1.0_f32.copysign(self) } } @@ -253,7 +255,8 @@ impl f32 { #[must_use = "method returns a new number and does not mutate the original value"] #[inline] #[stable(feature = "copysign", since = "1.35.0")] - pub fn copysign(self, sign: f32) -> f32 { + #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] + pub const fn copysign(self, sign: f32) -> f32 { unsafe { intrinsics::copysignf32(self, sign) } } diff --git a/library/std/src/f64.rs b/library/std/src/f64.rs index 9fa43a6742e..51d5476b372 100644 --- a/library/std/src/f64.rs +++ b/library/std/src/f64.rs @@ -194,8 +194,9 @@ impl f64 { #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] #[inline] - pub fn abs(self) -> f64 { + pub const fn abs(self) -> f64 { unsafe { intrinsics::fabsf64(self) } } @@ -218,8 +219,9 @@ impl f64 { #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] #[inline] - pub fn signum(self) -> f64 { + pub const fn signum(self) -> f64 { if self.is_nan() { Self::NAN } else { 1.0_f64.copysign(self) } } @@ -252,8 +254,9 @@ impl f64 { #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "copysign", since = "1.35.0")] + #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")] #[inline] - pub fn copysign(self, sign: f64) -> f64 { + pub const fn copysign(self, sign: f64) -> f64 { unsafe { intrinsics::copysignf64(self, sign) } } diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 65a9aa66c7c..990d83513cf 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -288,6 +288,7 @@ #![feature(cfg_target_thread_local)] #![feature(cfi_encoding)] #![feature(concat_idents)] +#![feature(const_float_methods)] #![feature(decl_macro)] #![feature(deprecated_suggestion)] #![feature(doc_cfg)] diff --git a/src/tools/miri/src/intrinsics/mod.rs b/src/tools/miri/src/intrinsics/mod.rs index 9f772cfa982..e0d27f21dae 100644 --- a/src/tools/miri/src/intrinsics/mod.rs +++ b/src/tools/miri/src/intrinsics/mod.rs @@ -145,20 +145,6 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.write_scalar(Scalar::from_bool(branch), dest)?; } - // Floating-point operations - "fabsf32" => { - let [f] = check_arg_count(args)?; - let f = this.read_scalar(f)?.to_f32()?; - // This is a "bitwise" operation, so there's no NaN non-determinism. - this.write_scalar(Scalar::from_f32(f.abs()), dest)?; - } - "fabsf64" => { - let [f] = check_arg_count(args)?; - let f = this.read_scalar(f)?.to_f64()?; - // This is a "bitwise" operation, so there's no NaN non-determinism. - this.write_scalar(Scalar::from_f64(f.abs()), dest)?; - } - "floorf32" | "ceilf32" | "truncf32" | "roundf32" | "rintf32" => { let [f] = check_arg_count(args)?; let f = this.read_scalar(f)?.to_f32()?; @@ -249,31 +235,6 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.write_scalar(res, dest)?; } - "minnumf32" | "maxnumf32" | "copysignf32" => { - let [a, b] = check_arg_count(args)?; - let a = this.read_scalar(a)?.to_f32()?; - let b = this.read_scalar(b)?.to_f32()?; - let res = match intrinsic_name { - "minnumf32" => this.adjust_nan(a.min(b), &[a, b]), - "maxnumf32" => this.adjust_nan(a.max(b), &[a, b]), - "copysignf32" => a.copy_sign(b), // bitwise, no NaN adjustments - _ => bug!(), - }; - this.write_scalar(Scalar::from_f32(res), dest)?; - } - "minnumf64" | "maxnumf64" | "copysignf64" => { - let [a, b] = check_arg_count(args)?; - let a = this.read_scalar(a)?.to_f64()?; - let b = this.read_scalar(b)?.to_f64()?; - let res = match intrinsic_name { - "minnumf64" => this.adjust_nan(a.min(b), &[a, b]), - "maxnumf64" => this.adjust_nan(a.max(b), &[a, b]), - "copysignf64" => a.copy_sign(b), // bitwise, no NaN adjustments - _ => bug!(), - }; - this.write_scalar(Scalar::from_f64(res), dest)?; - } - "fmaf32" => { let [a, b, c] = check_arg_count(args)?; let a = this.read_scalar(a)?.to_f32()?; diff --git a/tests/ui/consts/const-eval/float_methods.rs b/tests/ui/consts/const-eval/float_methods.rs new file mode 100644 index 00000000000..49c31f68c5f --- /dev/null +++ b/tests/ui/consts/const-eval/float_methods.rs @@ -0,0 +1,47 @@ +//@ run-pass +//! Tests the float intrinsics: min, max, abs, copysign + +#![feature(const_float_methods)] +#![feature(f16, f128)] + +const F16_MIN: f16 = 1.0_f16.min(0.5_f16); +const F16_MAX: f16 = 1.0_f16.max(0.5_f16); +const F16_ABS: f16 = (-1.0_f16).abs(); +const F16_COPYSIGN: f16 = 1.0_f16.copysign(-2.0_f16); + +const F32_MIN: f32 = 1.0_f32.min(0.5_f32); +const F32_MAX: f32 = 1.0_f32.max(0.5_f32); +const F32_ABS: f32 = (-1.0_f32).abs(); +const F32_COPYSIGN: f32 = 1.0_f32.copysign(-2.0_f32); + +const F64_MIN: f64 = 1.0_f64.min(0.5_f64); +const F64_MAX: f64 = 1.0_f64.max(0.5_f64); +const F64_ABS: f64 = (-1.0_f64).abs(); +const F64_COPYSIGN: f64 = 1.0_f64.copysign(-2.0_f64); + +const F128_MIN: f128 = 1.0_f128.min(0.5_f128); +const F128_MAX: f128 = 1.0_f128.max(0.5_f128); +const F128_ABS: f128 = (-1.0_f128).abs(); +const F128_COPYSIGN: f128 = 1.0_f128.copysign(-2.0_f128); + +fn main() { + assert_eq!(F16_MIN, 0.5); + assert_eq!(F16_MAX, 1.0); + assert_eq!(F16_ABS, 1.0); + assert_eq!(F16_COPYSIGN, -1.0); + + assert_eq!(F32_MIN, 0.5); + assert_eq!(F32_MAX, 1.0); + assert_eq!(F32_ABS, 1.0); + assert_eq!(F32_COPYSIGN, -1.0); + + assert_eq!(F64_MIN, 0.5); + assert_eq!(F64_MAX, 1.0); + assert_eq!(F64_ABS, 1.0); + assert_eq!(F64_COPYSIGN, -1.0); + + assert_eq!(F128_MIN, 0.5); + assert_eq!(F128_MAX, 1.0); + assert_eq!(F128_ABS, 1.0); + assert_eq!(F128_COPYSIGN, -1.0); +} -- cgit 1.4.1-3-g733a5 From 937d13b8efc43f3f2e93f81360565d82f243ce15 Mon Sep 17 00:00:00 2001 From: Slanterns Date: Wed, 16 Oct 2024 00:22:05 +0800 Subject: relax a memory order in `once_box` --- library/std/src/sys/sync/once_box.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'library/std/src') diff --git a/library/std/src/sys/sync/once_box.rs b/library/std/src/sys/sync/once_box.rs index 1422b5a1721..9d24db2245a 100644 --- a/library/std/src/sys/sync/once_box.rs +++ b/library/std/src/sys/sync/once_box.rs @@ -8,7 +8,7 @@ use crate::mem::replace; use crate::ptr::null_mut; use crate::sync::atomic::AtomicPtr; -use crate::sync::atomic::Ordering::{AcqRel, Acquire, Relaxed}; +use crate::sync::atomic::Ordering::{Acquire, Relaxed, Release}; pub(crate) struct OnceBox { ptr: AtomicPtr, @@ -60,7 +60,7 @@ impl OnceBox { #[cold] fn initialize(&self, f: impl FnOnce() -> Box) -> &T { let new_ptr = Box::into_raw(f()); - match self.ptr.compare_exchange(null_mut(), new_ptr, AcqRel, Acquire) { + match self.ptr.compare_exchange(null_mut(), new_ptr, Release, Acquire) { Ok(_) => unsafe { &*new_ptr }, Err(ptr) => { // Lost the race to another thread. -- cgit 1.4.1-3-g733a5 From f204e2c23b20f3052acaec7e0e231deb4ee23e50 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Mon, 14 Oct 2024 10:22:50 -0700 Subject: replace placeholder version (cherry picked from commit 567fd9610cbfd220844443487059335d7e1ff021) --- compiler/rustc_feature/src/accepted.rs | 10 +++++----- compiler/rustc_feature/src/removed.rs | 4 ++-- compiler/rustc_feature/src/unstable.rs | 14 +++++++------- library/core/src/array/mod.rs | 2 +- library/core/src/cell.rs | 8 ++++---- library/core/src/cell/once.rs | 2 +- library/core/src/char/methods.rs | 6 +++--- library/core/src/fmt/builders.rs | 8 ++++---- library/core/src/intrinsics.rs | 20 ++++++++++---------- library/core/src/mem/maybe_uninit.rs | 5 +---- library/core/src/mem/mod.rs | 2 +- library/core/src/num/f32.rs | 32 ++++++++++++++++---------------- library/core/src/num/f64.rs | 32 ++++++++++++++++---------------- library/core/src/ops/control_flow.rs | 8 ++++---- library/core/src/option.rs | 22 +++++++++++----------- library/core/src/ptr/const_ptr.rs | 6 +++--- library/core/src/ptr/metadata.rs | 6 +++--- library/core/src/ptr/mod.rs | 8 ++++---- library/core/src/ptr/mut_ptr.rs | 16 ++++++++-------- library/core/src/ptr/non_null.rs | 21 +++++++++------------ library/core/src/result.rs | 8 ++++---- library/core/src/slice/mod.rs | 22 +++++++++++----------- library/core/src/slice/raw.rs | 4 ++-- library/core/src/str/converts.rs | 5 +---- library/core/src/str/mod.rs | 4 ++-- library/core/src/task/wake.rs | 8 ++++---- library/core/src/time.rs | 8 ++++---- library/std/src/collections/hash/map.rs | 20 ++++++++++---------- library/std/src/collections/hash/set.rs | 4 ++-- library/std/src/io/error.rs | 32 ++++++++++++++++---------------- library/std/src/io/mod.rs | 2 +- 31 files changed, 170 insertions(+), 179 deletions(-) (limited to 'library/std/src') diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs index a850eb95620..0c5fe6e8d8b 100644 --- a/compiler/rustc_feature/src/accepted.rs +++ b/compiler/rustc_feature/src/accepted.rs @@ -116,7 +116,7 @@ declare_features! ( /// Allows calling constructor functions in `const fn`. (accepted, const_constructor, "1.40.0", Some(61456)), /// Allows the definition of `const extern fn` and `const unsafe extern fn`. - (accepted, const_extern_fn, "CURRENT_RUSTC_VERSION", Some(64926)), + (accepted, const_extern_fn, "1.83.0", Some(64926)), /// Allows basic arithmetic on floating point types in a `const fn`. (accepted, const_fn_floating_point_arithmetic, "1.82.0", Some(57241)), /// Allows using and casting function pointers in a `const fn`. @@ -144,15 +144,15 @@ declare_features! ( /// Allows the use of `loop` and `while` in constants. (accepted, const_loop, "1.46.0", Some(52000)), /// Allows using `&mut` in constant functions. - (accepted, const_mut_refs, "CURRENT_RUSTC_VERSION", Some(57349)), + (accepted, const_mut_refs, "1.83.0", Some(57349)), /// Allows panicking during const eval (producing compile-time errors). (accepted, const_panic, "1.57.0", Some(51999)), /// Allows dereferencing raw pointers during const eval. (accepted, const_raw_ptr_deref, "1.58.0", Some(51911)), /// Allows references to types with interior mutability within constants - (accepted, const_refs_to_cell, "CURRENT_RUSTC_VERSION", Some(80384)), + (accepted, const_refs_to_cell, "1.83.0", Some(80384)), /// Allows creating pointers and references to `static` items in constants. - (accepted, const_refs_to_static, "CURRENT_RUSTC_VERSION", Some(119618)), + (accepted, const_refs_to_static, "1.83.0", Some(119618)), /// Allows implementing `Copy` for closures where possible (RFC 2132). (accepted, copy_closures, "1.26.0", Some(44490)), /// Allows `crate` in paths. @@ -190,7 +190,7 @@ declare_features! ( /// Allows explicit generic arguments specification with `impl Trait` present. (accepted, explicit_generic_args_with_impl_trait, "1.63.0", Some(83701)), /// Uses 2024 rules for matching `expr` fragments in macros. Also enables `expr_2021` fragment. - (accepted, expr_fragment_specifier_2024, "CURRENT_RUSTC_VERSION", Some(123742)), + (accepted, expr_fragment_specifier_2024, "1.83.0", Some(123742)), /// Allows arbitrary expressions in key-value attributes at parse time. (accepted, extended_key_value_attributes, "1.54.0", Some(78835)), /// Allows resolving absolute paths as paths from other crates. diff --git a/compiler/rustc_feature/src/removed.rs b/compiler/rustc_feature/src/removed.rs index cba4535156b..d797fee000d 100644 --- a/compiler/rustc_feature/src/removed.rs +++ b/compiler/rustc_feature/src/removed.rs @@ -156,7 +156,7 @@ declare_features! ( (removed, no_stack_check, "1.0.0", None, None), /// Allows making `dyn Trait` well-formed even if `Trait` is not dyn-compatible (object safe). /// Renamed to `dyn_compatible_for_dispatch`. - (removed, object_safe_for_dispatch, "CURRENT_RUSTC_VERSION", Some(43561), + (removed, object_safe_for_dispatch, "1.83.0", Some(43561), Some("renamed to `dyn_compatible_for_dispatch`")), /// Allows using `#[on_unimplemented(..)]` on traits. /// (Moved to `rustc_attrs`.) @@ -221,7 +221,7 @@ declare_features! ( /// Allows using items which are missing stability attributes (removed, unmarked_api, "1.0.0", None, None), /// Allows unnamed fields of struct and union type - (removed, unnamed_fields, "CURRENT_RUSTC_VERSION", Some(49804), Some("feature needs redesign")), + (removed, unnamed_fields, "1.83.0", Some(49804), Some("feature needs redesign")), (removed, unsafe_no_drop_flag, "1.0.0", None, None), /// Allows `union` fields that don't implement `Copy` as long as they don't have any drop glue. (removed, untagged_unions, "1.13.0", Some(55149), diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index c0398db9c10..1067156958d 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -228,7 +228,7 @@ declare_features! ( /// Added for testing unstable lints; perma-unstable. (internal, test_unstable_lint, "1.60.0", None), /// Helps with formatting for `group_imports = "StdExternalCrate"`. - (unstable, unqualified_local_imports, "CURRENT_RUSTC_VERSION", None), + (unstable, unqualified_local_imports, "1.83.0", None), /// Use for stable + negative coherence and strict coherence depending on trait's /// rustc_strict_coherence value. (unstable, with_negative_coherence, "1.60.0", None), @@ -266,7 +266,7 @@ declare_features! ( /// Renamed from `object_safe_for_dispatch`. /// /// [^1]: Formerly known as "object safe". - (unstable, dyn_compatible_for_dispatch, "CURRENT_RUSTC_VERSION", Some(43561)), + (unstable, dyn_compatible_for_dispatch, "1.83.0", Some(43561)), /// Allows using the `#[fundamental]` attribute. (unstable, fundamental, "1.0.0", Some(29635)), /// Allows using `#[link_name="llvm.*"]`. @@ -360,7 +360,7 @@ declare_features! ( /// Allows inherent and trait methods with arbitrary self types. (unstable, arbitrary_self_types, "1.23.0", Some(44874)), /// Allows inherent and trait methods with arbitrary self types that are raw pointers. - (unstable, arbitrary_self_types_pointers, "CURRENT_RUSTC_VERSION", Some(44874)), + (unstable, arbitrary_self_types_pointers, "1.83.0", Some(44874)), /// Enables experimental inline assembly support for additional architectures. (unstable, asm_experimental_arch, "1.58.0", Some(93335)), /// Allows using `label` operands in inline assembly. @@ -380,7 +380,7 @@ declare_features! ( /// Allows using C-variadics. (unstable, c_variadic, "1.34.0", Some(44930)), /// Allows the use of `#[cfg()]`. - (unstable, cfg_boolean_literals, "CURRENT_RUSTC_VERSION", Some(131204)), + (unstable, cfg_boolean_literals, "1.83.0", Some(131204)), /// Allows the use of `#[cfg(overflow_checks)` to check if integer overflow behaviour. (unstable, cfg_overflow_checks, "1.71.0", Some(111466)), /// Provides the relocation model information as cfg entry @@ -498,7 +498,7 @@ declare_features! ( /// Allows `if let` guard in match arms. (unstable, if_let_guard, "1.47.0", Some(51114)), /// Rescoping temporaries in `if let` to align with Rust 2024. - (unstable, if_let_rescope, "CURRENT_RUSTC_VERSION", Some(124085)), + (unstable, if_let_rescope, "1.83.0", Some(124085)), /// Allows `impl Trait` to be used inside associated types (RFC 2515). (unstable, impl_trait_in_assoc_type, "1.70.0", Some(63063)), /// Allows `impl Trait` as output type in `Fn` traits in return position of functions. @@ -563,11 +563,11 @@ declare_features! ( /// Allows specifying nop padding on functions for dynamic patching. (unstable, patchable_function_entry, "1.81.0", Some(123115)), /// Experimental features that make `Pin` more ergonomic. - (incomplete, pin_ergonomics, "CURRENT_RUSTC_VERSION", Some(130494)), + (incomplete, pin_ergonomics, "1.83.0", Some(130494)), /// Allows postfix match `expr.match { ... }` (unstable, postfix_match, "1.79.0", Some(121618)), /// Allows `use<..>` precise capturign on impl Trait in traits. - (unstable, precise_capturing_in_traits, "CURRENT_RUSTC_VERSION", Some(130044)), + (unstable, precise_capturing_in_traits, "1.83.0", Some(130044)), /// Allows macro attributes on expressions, statements and non-inline modules. (unstable, proc_macro_hygiene, "1.30.0", Some(54727)), /// Makes `&` and `&mut` patterns eat only one layer of references in Rust 2024. diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs index a95046162d2..72f48878904 100644 --- a/library/core/src/array/mod.rs +++ b/library/core/src/array/mod.rs @@ -146,7 +146,7 @@ pub const fn from_ref(s: &T) -> &[T; 1] { /// Converts a mutable reference to `T` into a mutable reference to an array of length 1 (without copying). #[stable(feature = "array_from_ref", since = "1.53.0")] -#[rustc_const_stable(feature = "const_array_from_ref", since = "CURRENT_RUSTC_VERSION")] +#[rustc_const_stable(feature = "const_array_from_ref", since = "1.83.0")] #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] pub const fn from_mut(s: &mut T) -> &mut [T; 1] { // SAFETY: Converting `&mut T` to `&mut [T; 1]` is sound. diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index 513b9cbcefc..0945845021e 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -515,7 +515,7 @@ impl Cell { /// assert_eq!(five, 5); /// ``` #[stable(feature = "move_cell", since = "1.17.0")] - #[rustc_const_stable(feature = "const_cell_into_inner", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_cell_into_inner", since = "1.83.0")] #[rustc_allow_const_fn_unstable(const_precise_live_drops)] pub const fn into_inner(self) -> T { self.value.into_inner() @@ -864,7 +864,7 @@ impl RefCell { /// let five = c.into_inner(); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_cell_into_inner", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_cell_into_inner", since = "1.83.0")] #[rustc_allow_const_fn_unstable(const_precise_live_drops)] #[inline] pub const fn into_inner(self) -> T { @@ -2108,7 +2108,7 @@ impl UnsafeCell { /// ``` #[inline(always)] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_cell_into_inner", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_cell_into_inner", since = "1.83.0")] #[rustc_allow_const_fn_unstable(const_precise_live_drops)] pub const fn into_inner(self) -> T { self.value @@ -2182,7 +2182,7 @@ impl UnsafeCell { #[inline(always)] #[stable(feature = "unsafe_cell_get_mut", since = "1.50.0")] #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] - #[rustc_const_stable(feature = "const_unsafecell_get_mut", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_unsafecell_get_mut", since = "1.83.0")] pub const fn get_mut(&mut self) -> &mut T { &mut self.value } diff --git a/library/core/src/cell/once.rs b/library/core/src/cell/once.rs index 14c587e0c48..c14afe0f476 100644 --- a/library/core/src/cell/once.rs +++ b/library/core/src/cell/once.rs @@ -309,7 +309,7 @@ impl OnceCell { /// ``` #[inline] #[stable(feature = "once_cell", since = "1.70.0")] - #[rustc_const_stable(feature = "const_cell_into_inner", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_cell_into_inner", since = "1.83.0")] #[rustc_allow_const_fn_unstable(const_precise_live_drops)] pub const fn into_inner(self) -> Option { // Because `into_inner` takes `self` by value, the compiler statically verifies diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs index 04698193bba..1abfaa46ec6 100644 --- a/library/core/src/char/methods.rs +++ b/library/core/src/char/methods.rs @@ -36,7 +36,7 @@ impl char { /// let value_at_min = u32::from(char::MIN); /// assert_eq!(char::from_u32(value_at_min), Some('\0')); /// ``` - #[stable(feature = "char_min", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "char_min", since = "1.83.0")] pub const MIN: char = '\0'; /// The highest valid code point a `char` can have, `'\u{10FFFF}'`. @@ -674,7 +674,7 @@ impl char { /// 'ß'.encode_utf8(&mut b); /// ``` #[stable(feature = "unicode_encode_char", since = "1.15.0")] - #[rustc_const_stable(feature = "const_char_encode_utf8", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_char_encode_utf8", since = "1.83.0")] #[inline] #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] pub const fn encode_utf8(self, dst: &mut [u8]) -> &mut str { @@ -1773,7 +1773,7 @@ const fn len_utf16(code: u32) -> usize { /// Panics if the buffer is not large enough. /// A buffer of length four is large enough to encode any `char`. #[unstable(feature = "char_internals", reason = "exposed only for libstd", issue = "none")] -#[rustc_const_stable(feature = "const_char_encode_utf8", since = "CURRENT_RUSTC_VERSION")] +#[rustc_const_stable(feature = "const_char_encode_utf8", since = "1.83.0")] #[doc(hidden)] #[inline] #[rustc_allow_const_fn_unstable(const_eval_select)] diff --git a/library/core/src/fmt/builders.rs b/library/core/src/fmt/builders.rs index 3d0c9f7c964..1862be0e86c 100644 --- a/library/core/src/fmt/builders.rs +++ b/library/core/src/fmt/builders.rs @@ -383,7 +383,7 @@ impl<'a, 'b: 'a> DebugTuple<'a, 'b> { /// "Foo(10, ..)", /// ); /// ``` - #[stable(feature = "debug_more_non_exhaustive", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "debug_more_non_exhaustive", since = "1.83.0")] pub fn finish_non_exhaustive(&mut self) -> fmt::Result { self.result = self.result.and_then(|_| { if self.fields > 0 { @@ -626,7 +626,7 @@ impl<'a, 'b: 'a> DebugSet<'a, 'b> { /// "{1, 2, ..}", /// ); /// ``` - #[stable(feature = "debug_more_non_exhaustive", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "debug_more_non_exhaustive", since = "1.83.0")] pub fn finish_non_exhaustive(&mut self) -> fmt::Result { self.inner.result = self.inner.result.and_then(|_| { if self.inner.has_fields { @@ -818,7 +818,7 @@ impl<'a, 'b: 'a> DebugList<'a, 'b> { /// "[1, 2, ..]", /// ); /// ``` - #[stable(feature = "debug_more_non_exhaustive", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "debug_more_non_exhaustive", since = "1.83.0")] pub fn finish_non_exhaustive(&mut self) -> fmt::Result { self.inner.result.and_then(|_| { if self.inner.has_fields { @@ -1146,7 +1146,7 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> { /// r#"{"A": 10, "B": 11, ..}"#, /// ); /// ``` - #[stable(feature = "debug_more_non_exhaustive", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "debug_more_non_exhaustive", since = "1.83.0")] pub fn finish_non_exhaustive(&mut self) -> fmt::Result { self.result = self.result.and_then(|_| { assert!(!self.has_key, "attempted to finish a map with a partial entry"); diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index e8f5af863c1..ca5b9fc98b9 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -1085,7 +1085,7 @@ extern "rust-intrinsic" { /// it does not require an `unsafe` block. /// Therefore, implementations must not require the user to uphold /// any safety invariants. - #[rustc_const_stable(feature = "const_intrinsic_forget", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_intrinsic_forget", since = "1.83.0")] #[rustc_safe_intrinsic] #[rustc_nounwind] pub fn forget(_: T); @@ -2541,7 +2541,7 @@ extern "rust-intrinsic" { /// This intrinsic can *only* be called where the pointer is a local without /// projections (`write_via_move(ptr, x)`, not `write_via_move(*ptr, x)`) so /// that it trivially obeys runtime-MIR rules about derefs in operands. - #[rustc_const_stable(feature = "const_ptr_write", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_ptr_write", since = "1.83.0")] #[rustc_nounwind] pub fn write_via_move(ptr: *mut T, value: T); @@ -3070,7 +3070,7 @@ pub const fn type_id() -> u128 { /// change the possible layouts of pointers. #[rustc_nounwind] #[unstable(feature = "core_intrinsics", issue = "none")] -#[rustc_const_stable(feature = "ptr_metadata_const", since = "CURRENT_RUSTC_VERSION")] +#[rustc_const_stable(feature = "ptr_metadata_const", since = "1.83.0")] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const fn aggregate_raw_ptr, D, M>(_data: D, _meta: M) -> P { @@ -3095,7 +3095,7 @@ impl AggregateRawPtr<*mut T> for *mut P { /// This is used to implement functions like `ptr::metadata`. #[rustc_nounwind] #[unstable(feature = "core_intrinsics", issue = "none")] -#[rustc_const_stable(feature = "ptr_metadata_const", since = "CURRENT_RUSTC_VERSION")] +#[rustc_const_stable(feature = "ptr_metadata_const", since = "1.83.0")] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const fn ptr_metadata + ?Sized, M>(_ptr: *const P) -> M { @@ -3196,13 +3196,13 @@ pub const fn ptr_metadata + ?Sized, M>(_ptr: *cons #[doc(alias = "memcpy")] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_allowed_through_unstable_modules] -#[rustc_const_stable(feature = "const_intrinsic_copy", since = "CURRENT_RUSTC_VERSION")] +#[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.83.0")] #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[rustc_diagnostic_item = "ptr_copy_nonoverlapping"] pub const unsafe fn copy_nonoverlapping(src: *const T, dst: *mut T, count: usize) { extern "rust-intrinsic" { - #[rustc_const_stable(feature = "const_intrinsic_copy", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.83.0")] #[rustc_nounwind] pub fn copy_nonoverlapping(src: *const T, dst: *mut T, count: usize); } @@ -3300,13 +3300,13 @@ pub const unsafe fn copy_nonoverlapping(src: *const T, dst: *mut T, count: us #[doc(alias = "memmove")] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_allowed_through_unstable_modules] -#[rustc_const_stable(feature = "const_intrinsic_copy", since = "CURRENT_RUSTC_VERSION")] +#[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.83.0")] #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[rustc_diagnostic_item = "ptr_copy"] pub const unsafe fn copy(src: *const T, dst: *mut T, count: usize) { extern "rust-intrinsic" { - #[rustc_const_stable(feature = "const_intrinsic_copy", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.83.0")] #[rustc_nounwind] fn copy(src: *const T, dst: *mut T, count: usize); } @@ -3381,13 +3381,13 @@ pub const unsafe fn copy(src: *const T, dst: *mut T, count: usize) { #[doc(alias = "memset")] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_allowed_through_unstable_modules] -#[rustc_const_stable(feature = "const_ptr_write", since = "CURRENT_RUSTC_VERSION")] +#[rustc_const_stable(feature = "const_ptr_write", since = "1.83.0")] #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[rustc_diagnostic_item = "ptr_write_bytes"] pub const unsafe fn write_bytes(dst: *mut T, val: u8, count: usize) { extern "rust-intrinsic" { - #[rustc_const_stable(feature = "const_ptr_write", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_ptr_write", since = "1.83.0")] #[rustc_nounwind] fn write_bytes(dst: *mut T, val: u8, count: usize); } diff --git a/library/core/src/mem/maybe_uninit.rs b/library/core/src/mem/maybe_uninit.rs index f992785c43b..bb01d4e642c 100644 --- a/library/core/src/mem/maybe_uninit.rs +++ b/library/core/src/mem/maybe_uninit.rs @@ -569,10 +569,7 @@ impl MaybeUninit { /// (Notice that the rules around references to uninitialized data are not finalized yet, but /// until they are, it is advisable to avoid them.) #[stable(feature = "maybe_uninit", since = "1.36.0")] - #[rustc_const_stable( - feature = "const_maybe_uninit_as_mut_ptr", - since = "CURRENT_RUSTC_VERSION" - )] + #[rustc_const_stable(feature = "const_maybe_uninit_as_mut_ptr", since = "1.83.0")] #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] #[inline(always)] pub const fn as_mut_ptr(&mut self) -> *mut T { diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs index 9bf2aa594c0..ada80463306 100644 --- a/library/core/src/mem/mod.rs +++ b/library/core/src/mem/mod.rs @@ -858,7 +858,7 @@ pub fn take(dest: &mut T) -> T { #[stable(feature = "rust1", since = "1.0.0")] #[must_use = "if you don't need the old value, you can just assign the new value directly"] #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] -#[rustc_const_stable(feature = "const_replace", since = "CURRENT_RUSTC_VERSION")] +#[rustc_const_stable(feature = "const_replace", since = "1.83.0")] #[cfg_attr(not(test), rustc_diagnostic_item = "mem_replace")] pub const fn replace(dest: &mut T, src: T) -> T { // It may be tempting to use `swap` to avoid `unsafe` here. Don't! diff --git a/library/core/src/num/f32.rs b/library/core/src/num/f32.rs index 05f5a08ad0a..a01761ee5d4 100644 --- a/library/core/src/num/f32.rs +++ b/library/core/src/num/f32.rs @@ -517,7 +517,7 @@ impl f32 { /// ``` #[must_use] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_float_classify", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_classify", since = "1.83.0")] #[inline] #[allow(clippy::eq_op)] // > if you intended to check if the operand is NaN, use `.is_nan()` instead :) pub const fn is_nan(self) -> bool { @@ -550,7 +550,7 @@ impl f32 { /// ``` #[must_use] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_float_classify", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_classify", since = "1.83.0")] #[inline] pub const fn is_infinite(self) -> bool { // Getting clever with transmutation can result in incorrect answers on some FPUs @@ -575,7 +575,7 @@ impl f32 { /// ``` #[must_use] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_float_classify", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_classify", since = "1.83.0")] #[inline] pub const fn is_finite(self) -> bool { // There's no need to handle NaN separately: if self is NaN, @@ -603,7 +603,7 @@ impl f32 { /// [subnormal]: https://en.wikipedia.org/wiki/Denormal_number #[must_use] #[stable(feature = "is_subnormal", since = "1.53.0")] - #[rustc_const_stable(feature = "const_float_classify", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_classify", since = "1.83.0")] #[inline] pub const fn is_subnormal(self) -> bool { matches!(self.classify(), FpCategory::Subnormal) @@ -630,7 +630,7 @@ impl f32 { /// [subnormal]: https://en.wikipedia.org/wiki/Denormal_number #[must_use] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_float_classify", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_classify", since = "1.83.0")] #[inline] pub const fn is_normal(self) -> bool { matches!(self.classify(), FpCategory::Normal) @@ -650,7 +650,7 @@ impl f32 { /// assert_eq!(inf.classify(), FpCategory::Infinite); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_float_classify", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_classify", since = "1.83.0")] pub const fn classify(self) -> FpCategory { // We used to have complicated logic here that avoids the simple bit-based tests to work // around buggy codegen for x87 targets (see @@ -686,7 +686,7 @@ impl f32 { /// ``` #[must_use] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_float_classify", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_classify", since = "1.83.0")] #[inline] pub const fn is_sign_positive(self) -> bool { !self.is_sign_negative() @@ -711,7 +711,7 @@ impl f32 { /// ``` #[must_use] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_float_classify", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_classify", since = "1.83.0")] #[inline] pub const fn is_sign_negative(self) -> bool { // IEEE754 says: isSignMinus(x) is true if and only if x has negative sign. isSignMinus @@ -1093,7 +1093,7 @@ impl f32 { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[stable(feature = "float_bits_conv", since = "1.20.0")] - #[rustc_const_stable(feature = "const_float_bits_conv", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_bits_conv", since = "1.83.0")] #[inline] pub const fn to_bits(self) -> u32 { // SAFETY: `u32` is a plain old datatype so we can always transmute to it. @@ -1137,7 +1137,7 @@ impl f32 { /// assert_eq!(v, 12.5); /// ``` #[stable(feature = "float_bits_conv", since = "1.20.0")] - #[rustc_const_stable(feature = "const_float_bits_conv", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_bits_conv", since = "1.83.0")] #[must_use] #[inline] pub const fn from_bits(v: u32) -> Self { @@ -1161,7 +1161,7 @@ impl f32 { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[stable(feature = "float_to_from_bytes", since = "1.40.0")] - #[rustc_const_stable(feature = "const_float_bits_conv", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_bits_conv", since = "1.83.0")] #[inline] pub const fn to_be_bytes(self) -> [u8; 4] { self.to_bits().to_be_bytes() @@ -1182,7 +1182,7 @@ impl f32 { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[stable(feature = "float_to_from_bytes", since = "1.40.0")] - #[rustc_const_stable(feature = "const_float_bits_conv", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_bits_conv", since = "1.83.0")] #[inline] pub const fn to_le_bytes(self) -> [u8; 4] { self.to_bits().to_le_bytes() @@ -1216,7 +1216,7 @@ impl f32 { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[stable(feature = "float_to_from_bytes", since = "1.40.0")] - #[rustc_const_stable(feature = "const_float_bits_conv", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_bits_conv", since = "1.83.0")] #[inline] pub const fn to_ne_bytes(self) -> [u8; 4] { self.to_bits().to_ne_bytes() @@ -1234,7 +1234,7 @@ impl f32 { /// assert_eq!(value, 12.5); /// ``` #[stable(feature = "float_to_from_bytes", since = "1.40.0")] - #[rustc_const_stable(feature = "const_float_bits_conv", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_bits_conv", since = "1.83.0")] #[must_use] #[inline] pub const fn from_be_bytes(bytes: [u8; 4]) -> Self { @@ -1253,7 +1253,7 @@ impl f32 { /// assert_eq!(value, 12.5); /// ``` #[stable(feature = "float_to_from_bytes", since = "1.40.0")] - #[rustc_const_stable(feature = "const_float_bits_conv", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_bits_conv", since = "1.83.0")] #[must_use] #[inline] pub const fn from_le_bytes(bytes: [u8; 4]) -> Self { @@ -1283,7 +1283,7 @@ impl f32 { /// assert_eq!(value, 12.5); /// ``` #[stable(feature = "float_to_from_bytes", since = "1.40.0")] - #[rustc_const_stable(feature = "const_float_bits_conv", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_bits_conv", since = "1.83.0")] #[must_use] #[inline] pub const fn from_ne_bytes(bytes: [u8; 4]) -> Self { diff --git a/library/core/src/num/f64.rs b/library/core/src/num/f64.rs index 89c6726d985..2995e41cd6e 100644 --- a/library/core/src/num/f64.rs +++ b/library/core/src/num/f64.rs @@ -516,7 +516,7 @@ impl f64 { /// ``` #[must_use] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_float_classify", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_classify", since = "1.83.0")] #[inline] #[allow(clippy::eq_op)] // > if you intended to check if the operand is NaN, use `.is_nan()` instead :) pub const fn is_nan(self) -> bool { @@ -549,7 +549,7 @@ impl f64 { /// ``` #[must_use] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_float_classify", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_classify", since = "1.83.0")] #[inline] pub const fn is_infinite(self) -> bool { // Getting clever with transmutation can result in incorrect answers on some FPUs @@ -574,7 +574,7 @@ impl f64 { /// ``` #[must_use] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_float_classify", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_classify", since = "1.83.0")] #[inline] pub const fn is_finite(self) -> bool { // There's no need to handle NaN separately: if self is NaN, @@ -602,7 +602,7 @@ impl f64 { /// [subnormal]: https://en.wikipedia.org/wiki/Denormal_number #[must_use] #[stable(feature = "is_subnormal", since = "1.53.0")] - #[rustc_const_stable(feature = "const_float_classify", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_classify", since = "1.83.0")] #[inline] pub const fn is_subnormal(self) -> bool { matches!(self.classify(), FpCategory::Subnormal) @@ -629,7 +629,7 @@ impl f64 { /// [subnormal]: https://en.wikipedia.org/wiki/Denormal_number #[must_use] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_float_classify", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_classify", since = "1.83.0")] #[inline] pub const fn is_normal(self) -> bool { matches!(self.classify(), FpCategory::Normal) @@ -649,7 +649,7 @@ impl f64 { /// assert_eq!(inf.classify(), FpCategory::Infinite); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_float_classify", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_classify", since = "1.83.0")] pub const fn classify(self) -> FpCategory { // We used to have complicated logic here that avoids the simple bit-based tests to work // around buggy codegen for x87 targets (see @@ -685,7 +685,7 @@ impl f64 { /// ``` #[must_use] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_float_classify", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_classify", since = "1.83.0")] #[inline] pub const fn is_sign_positive(self) -> bool { !self.is_sign_negative() @@ -719,7 +719,7 @@ impl f64 { /// ``` #[must_use] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_float_classify", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_classify", since = "1.83.0")] #[inline] pub const fn is_sign_negative(self) -> bool { // IEEE754 says: isSignMinus(x) is true if and only if x has negative sign. isSignMinus @@ -1093,7 +1093,7 @@ impl f64 { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[stable(feature = "float_bits_conv", since = "1.20.0")] - #[rustc_const_stable(feature = "const_float_bits_conv", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_bits_conv", since = "1.83.0")] #[inline] pub const fn to_bits(self) -> u64 { // SAFETY: `u64` is a plain old datatype so we can always transmute to it. @@ -1137,7 +1137,7 @@ impl f64 { /// assert_eq!(v, 12.5); /// ``` #[stable(feature = "float_bits_conv", since = "1.20.0")] - #[rustc_const_stable(feature = "const_float_bits_conv", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_bits_conv", since = "1.83.0")] #[must_use] #[inline] pub const fn from_bits(v: u64) -> Self { @@ -1161,7 +1161,7 @@ impl f64 { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[stable(feature = "float_to_from_bytes", since = "1.40.0")] - #[rustc_const_stable(feature = "const_float_bits_conv", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_bits_conv", since = "1.83.0")] #[inline] pub const fn to_be_bytes(self) -> [u8; 8] { self.to_bits().to_be_bytes() @@ -1182,7 +1182,7 @@ impl f64 { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[stable(feature = "float_to_from_bytes", since = "1.40.0")] - #[rustc_const_stable(feature = "const_float_bits_conv", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_bits_conv", since = "1.83.0")] #[inline] pub const fn to_le_bytes(self) -> [u8; 8] { self.to_bits().to_le_bytes() @@ -1216,7 +1216,7 @@ impl f64 { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[stable(feature = "float_to_from_bytes", since = "1.40.0")] - #[rustc_const_stable(feature = "const_float_bits_conv", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_bits_conv", since = "1.83.0")] #[inline] pub const fn to_ne_bytes(self) -> [u8; 8] { self.to_bits().to_ne_bytes() @@ -1234,7 +1234,7 @@ impl f64 { /// assert_eq!(value, 12.5); /// ``` #[stable(feature = "float_to_from_bytes", since = "1.40.0")] - #[rustc_const_stable(feature = "const_float_bits_conv", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_bits_conv", since = "1.83.0")] #[must_use] #[inline] pub const fn from_be_bytes(bytes: [u8; 8]) -> Self { @@ -1253,7 +1253,7 @@ impl f64 { /// assert_eq!(value, 12.5); /// ``` #[stable(feature = "float_to_from_bytes", since = "1.40.0")] - #[rustc_const_stable(feature = "const_float_bits_conv", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_bits_conv", since = "1.83.0")] #[must_use] #[inline] pub const fn from_le_bytes(bytes: [u8; 8]) -> Self { @@ -1283,7 +1283,7 @@ impl f64 { /// assert_eq!(value, 12.5); /// ``` #[stable(feature = "float_to_from_bytes", since = "1.40.0")] - #[rustc_const_stable(feature = "const_float_bits_conv", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_bits_conv", since = "1.83.0")] #[must_use] #[inline] pub const fn from_ne_bytes(bytes: [u8; 8]) -> Self { diff --git a/library/core/src/ops/control_flow.rs b/library/core/src/ops/control_flow.rs index 7a8158b8231..55deabbee8f 100644 --- a/library/core/src/ops/control_flow.rs +++ b/library/core/src/ops/control_flow.rs @@ -177,7 +177,7 @@ impl ControlFlow { /// assert_eq!(ControlFlow::::Continue(3).break_value(), None); /// ``` #[inline] - #[stable(feature = "control_flow_enum", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "control_flow_enum", since = "1.83.0")] pub fn break_value(self) -> Option { match self { ControlFlow::Continue(..) => None, @@ -188,7 +188,7 @@ impl ControlFlow { /// Maps `ControlFlow` to `ControlFlow` by applying a function /// to the break value in case it exists. #[inline] - #[stable(feature = "control_flow_enum", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "control_flow_enum", since = "1.83.0")] pub fn map_break(self, f: impl FnOnce(B) -> T) -> ControlFlow { match self { ControlFlow::Continue(x) => ControlFlow::Continue(x), @@ -208,7 +208,7 @@ impl ControlFlow { /// assert_eq!(ControlFlow::::Continue(3).continue_value(), Some(3)); /// ``` #[inline] - #[stable(feature = "control_flow_enum", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "control_flow_enum", since = "1.83.0")] pub fn continue_value(self) -> Option { match self { ControlFlow::Continue(x) => Some(x), @@ -219,7 +219,7 @@ impl ControlFlow { /// Maps `ControlFlow` to `ControlFlow` by applying a function /// to the continue value in case it exists. #[inline] - #[stable(feature = "control_flow_enum", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "control_flow_enum", since = "1.83.0")] pub fn map_continue(self, f: impl FnOnce(C) -> T) -> ControlFlow { match self { ControlFlow::Continue(x) => ControlFlow::Continue(f(x)), diff --git a/library/core/src/option.rs b/library/core/src/option.rs index 84ccb7a1f66..661176ce9fc 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -724,7 +724,7 @@ impl Option { #[inline] #[stable(feature = "rust1", since = "1.0.0")] #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] - #[rustc_const_stable(feature = "const_option", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_option", since = "1.83.0")] pub const fn as_mut(&mut self) -> Option<&mut T> { match *self { Some(ref mut x) => Some(x), @@ -926,7 +926,7 @@ impl Option { #[stable(feature = "rust1", since = "1.0.0")] #[cfg_attr(not(test), rustc_diagnostic_item = "option_expect")] #[rustc_allow_const_fn_unstable(const_precise_live_drops)] - #[rustc_const_stable(feature = "const_option", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_option", since = "1.83.0")] pub const fn expect(self, msg: &str) -> T { match self { Some(val) => val, @@ -965,7 +965,7 @@ impl Option { #[stable(feature = "rust1", since = "1.0.0")] #[cfg_attr(not(test), rustc_diagnostic_item = "option_unwrap")] #[rustc_allow_const_fn_unstable(const_precise_live_drops)] - #[rustc_const_stable(feature = "const_option", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_option", since = "1.83.0")] pub const fn unwrap(self) -> T { match self { Some(val) => val, @@ -1073,7 +1073,7 @@ impl Option { #[track_caller] #[stable(feature = "option_result_unwrap_unchecked", since = "1.58.0")] #[rustc_allow_const_fn_unstable(const_precise_live_drops)] - #[rustc_const_stable(feature = "const_option", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_option", since = "1.83.0")] pub const unsafe fn unwrap_unchecked(self) -> T { match self { Some(val) => val, @@ -1655,7 +1655,7 @@ impl Option { /// assert_eq!(x, Some(7)); /// ``` #[inline] - #[stable(feature = "option_get_or_insert_default", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "option_get_or_insert_default", since = "1.83.0")] pub fn get_or_insert_default(&mut self) -> &mut T where T: Default, @@ -1717,7 +1717,7 @@ impl Option { #[inline] #[stable(feature = "rust1", since = "1.0.0")] #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] - #[rustc_const_stable(feature = "const_option", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_option", since = "1.83.0")] pub const fn take(&mut self) -> Option { // FIXME(const-hack) replace `mem::replace` by `mem::take` when the latter is const ready mem::replace(self, None) @@ -1776,7 +1776,7 @@ impl Option { #[inline] #[stable(feature = "option_replace", since = "1.31.0")] #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] - #[rustc_const_stable(feature = "const_option", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_option", since = "1.83.0")] pub const fn replace(&mut self, value: T) -> Option { mem::replace(self, Some(value)) } @@ -1884,7 +1884,7 @@ impl Option<&T> { /// ``` #[must_use = "`self` will be dropped if the result is not used"] #[stable(feature = "copied", since = "1.35.0")] - #[rustc_const_stable(feature = "const_option", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_option", since = "1.83.0")] pub const fn copied(self) -> Option where T: Copy, @@ -1938,7 +1938,7 @@ impl Option<&mut T> { #[must_use = "`self` will be dropped if the result is not used"] #[stable(feature = "copied", since = "1.35.0")] #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] - #[rustc_const_stable(feature = "const_option", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_option", since = "1.83.0")] pub const fn copied(self) -> Option where T: Copy, @@ -1994,7 +1994,7 @@ impl Option> { #[inline] #[stable(feature = "transpose_result", since = "1.33.0")] #[rustc_allow_const_fn_unstable(const_precise_live_drops)] - #[rustc_const_stable(feature = "const_option", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_option", since = "1.83.0")] pub const fn transpose(self) -> Result, E> { match self { Some(Ok(x)) => Ok(Some(x)), @@ -2542,7 +2542,7 @@ impl Option> { #[inline] #[stable(feature = "option_flattening", since = "1.40.0")] #[rustc_allow_const_fn_unstable(const_precise_live_drops)] - #[rustc_const_stable(feature = "const_option", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_option", since = "1.83.0")] pub const fn flatten(self) -> Option { // FIXME(const-hack): could be written with `and_then` match self { diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index 0b0449d6174..72f4bc2c9da 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -113,7 +113,7 @@ impl *const T { /// println!("{:?}", unsafe { &*bad }); /// ``` #[unstable(feature = "set_ptr_value", issue = "75091")] - #[rustc_const_stable(feature = "ptr_metadata_const", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "ptr_metadata_const", since = "1.83.0")] #[must_use = "returns a new pointer rather than modifying its argument"] #[inline] pub const fn with_metadata_of(self, meta: *const U) -> *const U @@ -1299,7 +1299,7 @@ impl *const T { /// See [`ptr::copy`] for safety concerns and examples. /// /// [`ptr::copy`]: crate::ptr::copy() - #[rustc_const_stable(feature = "const_intrinsic_copy", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.83.0")] #[stable(feature = "pointer_methods", since = "1.26.0")] #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces @@ -1319,7 +1319,7 @@ impl *const T { /// See [`ptr::copy_nonoverlapping`] for safety concerns and examples. /// /// [`ptr::copy_nonoverlapping`]: crate::ptr::copy_nonoverlapping() - #[rustc_const_stable(feature = "const_intrinsic_copy", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.83.0")] #[stable(feature = "pointer_methods", since = "1.26.0")] #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces diff --git a/library/core/src/ptr/metadata.rs b/library/core/src/ptr/metadata.rs index feeaf78d3e7..09c4002dbc7 100644 --- a/library/core/src/ptr/metadata.rs +++ b/library/core/src/ptr/metadata.rs @@ -92,7 +92,7 @@ pub trait Thin = Pointee; /// /// assert_eq!(std::ptr::metadata("foo"), 3_usize); /// ``` -#[rustc_const_stable(feature = "ptr_metadata_const", since = "CURRENT_RUSTC_VERSION")] +#[rustc_const_stable(feature = "ptr_metadata_const", since = "1.83.0")] #[inline] pub const fn metadata(ptr: *const T) -> ::Metadata { ptr_metadata(ptr) @@ -106,7 +106,7 @@ pub const fn metadata(ptr: *const T) -> ::Metadata { /// /// [`slice::from_raw_parts`]: crate::slice::from_raw_parts #[unstable(feature = "ptr_metadata", issue = "81513")] -#[rustc_const_stable(feature = "ptr_metadata_const", since = "CURRENT_RUSTC_VERSION")] +#[rustc_const_stable(feature = "ptr_metadata_const", since = "1.83.0")] #[inline] pub const fn from_raw_parts( data_pointer: *const impl Thin, @@ -120,7 +120,7 @@ pub const fn from_raw_parts( /// /// See the documentation of [`from_raw_parts`] for more details. #[unstable(feature = "ptr_metadata", issue = "81513")] -#[rustc_const_stable(feature = "ptr_metadata_const", since = "CURRENT_RUSTC_VERSION")] +#[rustc_const_stable(feature = "ptr_metadata_const", since = "1.83.0")] #[inline] pub const fn from_raw_parts_mut( data_pointer: *mut impl Thin, diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index dd93f919c92..61b48e312cf 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -992,7 +992,7 @@ pub const fn slice_from_raw_parts(data: *const T, len: usize) -> *const [T] { /// ``` #[inline] #[stable(feature = "slice_from_raw_parts", since = "1.42.0")] -#[rustc_const_stable(feature = "const_slice_from_raw_parts_mut", since = "CURRENT_RUSTC_VERSION")] +#[rustc_const_stable(feature = "const_slice_from_raw_parts_mut", since = "1.83.0")] #[rustc_diagnostic_item = "ptr_slice_from_raw_parts_mut"] pub const fn slice_from_raw_parts_mut(data: *mut T, len: usize) -> *mut [T] { from_raw_parts_mut(data, len) @@ -1266,7 +1266,7 @@ const unsafe fn swap_nonoverlapping_simple_untyped(x: *mut T, y: *mut T, coun #[inline] #[stable(feature = "rust1", since = "1.0.0")] #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] -#[rustc_const_stable(feature = "const_replace", since = "CURRENT_RUSTC_VERSION")] +#[rustc_const_stable(feature = "const_replace", since = "1.83.0")] #[rustc_diagnostic_item = "ptr_replace"] pub const unsafe fn replace(dst: *mut T, src: T) -> T { // SAFETY: the caller must guarantee that `dst` is valid to be @@ -1616,7 +1616,7 @@ pub const unsafe fn read_unaligned(src: *const T) -> T { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_const_stable(feature = "const_ptr_write", since = "CURRENT_RUSTC_VERSION")] +#[rustc_const_stable(feature = "const_ptr_write", since = "1.83.0")] #[rustc_diagnostic_item = "ptr_write"] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn write(dst: *mut T, src: T) { @@ -1726,7 +1726,7 @@ pub const unsafe fn write(dst: *mut T, src: T) { #[inline] #[stable(feature = "ptr_unaligned", since = "1.17.0")] #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_refs_to_cell))] -#[rustc_const_stable(feature = "const_ptr_write", since = "CURRENT_RUSTC_VERSION")] +#[rustc_const_stable(feature = "const_ptr_write", since = "1.83.0")] #[rustc_diagnostic_item = "ptr_write_unaligned"] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn write_unaligned(dst: *mut T, src: T) { diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index 8b61da74d02..d7ce197848b 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -94,7 +94,7 @@ impl *mut T { /// // This dereference is UB. The pointer only has provenance for `x` but points to `y`. /// println!("{:?}", unsafe { &*bad }); #[unstable(feature = "set_ptr_value", issue = "75091")] - #[rustc_const_stable(feature = "ptr_metadata_const", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "ptr_metadata_const", since = "1.83.0")] #[must_use = "returns a new pointer rather than modifying its argument"] #[inline] pub const fn with_metadata_of(self, meta: *const U) -> *mut U @@ -1378,7 +1378,7 @@ impl *mut T { /// See [`ptr::copy`] for safety concerns and examples. /// /// [`ptr::copy`]: crate::ptr::copy() - #[rustc_const_stable(feature = "const_intrinsic_copy", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.83.0")] #[stable(feature = "pointer_methods", since = "1.26.0")] #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces @@ -1398,7 +1398,7 @@ impl *mut T { /// See [`ptr::copy_nonoverlapping`] for safety concerns and examples. /// /// [`ptr::copy_nonoverlapping`]: crate::ptr::copy_nonoverlapping() - #[rustc_const_stable(feature = "const_intrinsic_copy", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.83.0")] #[stable(feature = "pointer_methods", since = "1.26.0")] #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces @@ -1418,7 +1418,7 @@ impl *mut T { /// See [`ptr::copy`] for safety concerns and examples. /// /// [`ptr::copy`]: crate::ptr::copy() - #[rustc_const_stable(feature = "const_intrinsic_copy", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.83.0")] #[stable(feature = "pointer_methods", since = "1.26.0")] #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces @@ -1438,7 +1438,7 @@ impl *mut T { /// See [`ptr::copy_nonoverlapping`] for safety concerns and examples. /// /// [`ptr::copy_nonoverlapping`]: crate::ptr::copy_nonoverlapping() - #[rustc_const_stable(feature = "const_intrinsic_copy", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.83.0")] #[stable(feature = "pointer_methods", since = "1.26.0")] #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces @@ -1469,7 +1469,7 @@ impl *mut T { /// /// [`ptr::write`]: crate::ptr::write() #[stable(feature = "pointer_methods", since = "1.26.0")] - #[rustc_const_stable(feature = "const_ptr_write", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_ptr_write", since = "1.83.0")] #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn write(self, val: T) @@ -1488,7 +1488,7 @@ impl *mut T { /// [`ptr::write_bytes`]: crate::ptr::write_bytes() #[doc(alias = "memset")] #[stable(feature = "pointer_methods", since = "1.26.0")] - #[rustc_const_stable(feature = "const_ptr_write", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_ptr_write", since = "1.83.0")] #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn write_bytes(self, val: u8, count: usize) @@ -1529,7 +1529,7 @@ impl *mut T { /// /// [`ptr::write_unaligned`]: crate::ptr::write_unaligned() #[stable(feature = "pointer_methods", since = "1.26.0")] - #[rustc_const_stable(feature = "const_ptr_write", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_ptr_write", since = "1.83.0")] #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn write_unaligned(self, val: T) diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs index 980d4a3cf6c..c6839136348 100644 --- a/library/core/src/ptr/non_null.rs +++ b/library/core/src/ptr/non_null.rs @@ -395,7 +395,7 @@ impl NonNull { /// [the module documentation]: crate::ptr#safety #[stable(feature = "nonnull", since = "1.25.0")] #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] - #[rustc_const_stable(feature = "const_ptr_as_ref", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_ptr_as_ref", since = "1.83.0")] #[must_use] #[inline(always)] pub const unsafe fn as_mut<'a>(&mut self) -> &'a mut T { @@ -923,7 +923,7 @@ impl NonNull { #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[stable(feature = "non_null_convenience", since = "1.80.0")] - #[rustc_const_stable(feature = "const_intrinsic_copy", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.83.0")] pub const unsafe fn copy_to(self, dest: NonNull, count: usize) where T: Sized, @@ -943,7 +943,7 @@ impl NonNull { #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[stable(feature = "non_null_convenience", since = "1.80.0")] - #[rustc_const_stable(feature = "const_intrinsic_copy", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.83.0")] pub const unsafe fn copy_to_nonoverlapping(self, dest: NonNull, count: usize) where T: Sized, @@ -963,7 +963,7 @@ impl NonNull { #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[stable(feature = "non_null_convenience", since = "1.80.0")] - #[rustc_const_stable(feature = "const_intrinsic_copy", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.83.0")] pub const unsafe fn copy_from(self, src: NonNull, count: usize) where T: Sized, @@ -983,7 +983,7 @@ impl NonNull { #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[stable(feature = "non_null_convenience", since = "1.80.0")] - #[rustc_const_stable(feature = "const_intrinsic_copy", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.83.0")] pub const unsafe fn copy_from_nonoverlapping(self, src: NonNull, count: usize) where T: Sized, @@ -1013,7 +1013,7 @@ impl NonNull { #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[stable(feature = "non_null_convenience", since = "1.80.0")] - #[rustc_const_stable(feature = "const_ptr_write", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_ptr_write", since = "1.83.0")] pub const unsafe fn write(self, val: T) where T: Sized, @@ -1032,7 +1032,7 @@ impl NonNull { #[doc(alias = "memset")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[stable(feature = "non_null_convenience", since = "1.80.0")] - #[rustc_const_stable(feature = "const_ptr_write", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_ptr_write", since = "1.83.0")] pub const unsafe fn write_bytes(self, val: u8, count: usize) where T: Sized, @@ -1073,7 +1073,7 @@ impl NonNull { #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[stable(feature = "non_null_convenience", since = "1.80.0")] - #[rustc_const_stable(feature = "const_ptr_write", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_ptr_write", since = "1.83.0")] pub const unsafe fn write_unaligned(self, val: T) where T: Sized, @@ -1432,10 +1432,7 @@ impl NonNull<[T]> { /// (Note that this example artificially demonstrates a use of this method, /// but `let slice = NonNull::from(&x[..]);` would be a better way to write code like this.) #[stable(feature = "nonnull_slice_from_raw_parts", since = "1.70.0")] - #[rustc_const_stable( - feature = "const_slice_from_raw_parts_mut", - since = "CURRENT_RUSTC_VERSION" - )] + #[rustc_const_stable(feature = "const_slice_from_raw_parts_mut", since = "1.83.0")] #[must_use] #[inline] pub const fn slice_from_raw_parts(data: NonNull, len: usize) -> Self { diff --git a/library/core/src/result.rs b/library/core/src/result.rs index 95faacbf96d..e84c4e3a239 100644 --- a/library/core/src/result.rs +++ b/library/core/src/result.rs @@ -734,7 +734,7 @@ impl Result { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_result", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_result", since = "1.83.0")] #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] pub const fn as_mut(&mut self) -> Result<&mut T, &mut E> { match *self { @@ -1537,7 +1537,7 @@ impl Result<&T, E> { /// ``` #[inline] #[stable(feature = "result_copied", since = "1.59.0")] - #[rustc_const_stable(feature = "const_result", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_result", since = "1.83.0")] #[rustc_allow_const_fn_unstable(const_precise_live_drops)] pub const fn copied(self) -> Result where @@ -1588,7 +1588,7 @@ impl Result<&mut T, E> { /// ``` #[inline] #[stable(feature = "result_copied", since = "1.59.0")] - #[rustc_const_stable(feature = "const_result", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_result", since = "1.83.0")] #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] #[rustc_allow_const_fn_unstable(const_precise_live_drops)] pub const fn copied(self) -> Result @@ -1643,7 +1643,7 @@ impl Result, E> { /// ``` #[inline] #[stable(feature = "transpose_result", since = "1.33.0")] - #[rustc_const_stable(feature = "const_result", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_result", since = "1.83.0")] #[rustc_allow_const_fn_unstable(const_precise_live_drops)] pub const fn transpose(self) -> Option> { match self { diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 90ddc9c1d85..9fdcea1f7b7 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -172,7 +172,7 @@ impl [T] { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] - #[rustc_const_stable(feature = "const_slice_first_last", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_slice_first_last", since = "1.83.0")] #[inline] #[must_use] pub const fn first_mut(&mut self) -> Option<&mut T> { @@ -215,7 +215,7 @@ impl [T] { /// ``` #[stable(feature = "slice_splits", since = "1.5.0")] #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] - #[rustc_const_stable(feature = "const_slice_first_last", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_slice_first_last", since = "1.83.0")] #[inline] #[must_use] pub const fn split_first_mut(&mut self) -> Option<(&mut T, &mut [T])> { @@ -258,7 +258,7 @@ impl [T] { /// ``` #[stable(feature = "slice_splits", since = "1.5.0")] #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] - #[rustc_const_stable(feature = "const_slice_first_last", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_slice_first_last", since = "1.83.0")] #[inline] #[must_use] pub const fn split_last_mut(&mut self) -> Option<(&mut T, &mut [T])> { @@ -301,7 +301,7 @@ impl [T] { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] - #[rustc_const_stable(feature = "const_slice_first_last", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_slice_first_last", since = "1.83.0")] #[inline] #[must_use] pub const fn last_mut(&mut self) -> Option<&mut T> { @@ -356,7 +356,7 @@ impl [T] { /// ``` #[inline] #[stable(feature = "slice_first_last_chunk", since = "1.77.0")] - #[rustc_const_stable(feature = "const_slice_first_last_chunk", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_slice_first_last_chunk", since = "1.83.0")] #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] pub const fn first_chunk_mut(&mut self) -> Option<&mut [T; N]> { if self.len() < N { @@ -422,7 +422,7 @@ impl [T] { /// ``` #[inline] #[stable(feature = "slice_first_last_chunk", since = "1.77.0")] - #[rustc_const_stable(feature = "const_slice_first_last_chunk", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_slice_first_last_chunk", since = "1.83.0")] #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] pub const fn split_first_chunk_mut( &mut self, @@ -493,7 +493,7 @@ impl [T] { /// ``` #[inline] #[stable(feature = "slice_first_last_chunk", since = "1.77.0")] - #[rustc_const_stable(feature = "const_slice_first_last_chunk", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_slice_first_last_chunk", since = "1.83.0")] #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] pub const fn split_last_chunk_mut( &mut self, @@ -563,7 +563,7 @@ impl [T] { /// ``` #[inline] #[stable(feature = "slice_first_last_chunk", since = "1.77.0")] - #[rustc_const_stable(feature = "const_slice_first_last_chunk", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_slice_first_last_chunk", since = "1.83.0")] #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] pub const fn last_chunk_mut(&mut self) -> Option<&mut [T; N]> { if self.len() < N { @@ -1907,7 +1907,7 @@ impl [T] { #[inline] #[track_caller] #[must_use] - #[rustc_const_stable(feature = "const_slice_split_at_mut", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_slice_split_at_mut", since = "1.83.0")] #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] pub const fn split_at_mut(&mut self, mid: usize) -> (&mut [T], &mut [T]) { match self.split_at_mut_checked(mid) { @@ -2010,7 +2010,7 @@ impl [T] { /// assert_eq!(v, [1, 2, 3, 4, 5, 6]); /// ``` #[stable(feature = "slice_split_at_unchecked", since = "1.79.0")] - #[rustc_const_stable(feature = "const_slice_split_at_mut", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_slice_split_at_mut", since = "1.83.0")] #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] #[inline] #[must_use] @@ -2111,7 +2111,7 @@ impl [T] { /// assert_eq!(None, v.split_at_mut_checked(7)); /// ``` #[stable(feature = "split_at_checked", since = "1.80.0")] - #[rustc_const_stable(feature = "const_slice_split_at_mut", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_slice_split_at_mut", since = "1.83.0")] #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] #[inline] #[must_use] diff --git a/library/core/src/slice/raw.rs b/library/core/src/slice/raw.rs index 20c5e026946..976749cc148 100644 --- a/library/core/src/slice/raw.rs +++ b/library/core/src/slice/raw.rs @@ -171,7 +171,7 @@ pub const unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T] /// [`NonNull::dangling()`]: ptr::NonNull::dangling #[inline] #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_const_stable(feature = "const_slice_from_raw_parts_mut", since = "CURRENT_RUSTC_VERSION")] +#[rustc_const_stable(feature = "const_slice_from_raw_parts_mut", since = "1.83.0")] #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] #[must_use] #[rustc_diagnostic_item = "slice_from_raw_parts_mut"] @@ -204,7 +204,7 @@ pub const fn from_ref(s: &T) -> &[T] { /// Converts a reference to T into a slice of length 1 (without copying). #[stable(feature = "from_ref", since = "1.28.0")] -#[rustc_const_stable(feature = "const_slice_from_ref", since = "CURRENT_RUSTC_VERSION")] +#[rustc_const_stable(feature = "const_slice_from_ref", since = "1.83.0")] #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] #[must_use] pub const fn from_mut(s: &mut T) -> &mut [T] { diff --git a/library/core/src/str/converts.rs b/library/core/src/str/converts.rs index 194db56fdaf..b61ed454cd9 100644 --- a/library/core/src/str/converts.rs +++ b/library/core/src/str/converts.rs @@ -196,10 +196,7 @@ pub const unsafe fn from_utf8_unchecked(v: &[u8]) -> &str { #[must_use] #[stable(feature = "str_mut_extras", since = "1.20.0")] #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] -#[rustc_const_stable( - feature = "const_str_from_utf8_unchecked_mut", - since = "CURRENT_RUSTC_VERSION" -)] +#[rustc_const_stable(feature = "const_str_from_utf8_unchecked_mut", since = "1.83.0")] #[rustc_diagnostic_item = "str_from_utf8_unchecked_mut"] pub const unsafe fn from_utf8_unchecked_mut(v: &mut [u8]) -> &mut str { // SAFETY: the caller must guarantee that the bytes `v` diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs index 1d10015d75a..09938dda262 100644 --- a/library/core/src/str/mod.rs +++ b/library/core/src/str/mod.rs @@ -340,7 +340,7 @@ impl str { /// ``` #[stable(feature = "str_mut_extras", since = "1.20.0")] #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] - #[rustc_const_stable(feature = "const_str_as_mut", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_str_as_mut", since = "1.83.0")] #[must_use] #[inline(always)] pub const unsafe fn as_bytes_mut(&mut self) -> &mut [u8] { @@ -387,7 +387,7 @@ impl str { /// modified in a way that it remains valid UTF-8. #[stable(feature = "str_as_mut_ptr", since = "1.36.0")] #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] - #[rustc_const_stable(feature = "const_str_as_mut", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_str_as_mut", since = "1.83.0")] #[rustc_never_returns_null_ptr] #[must_use] #[inline(always)] diff --git a/library/core/src/task/wake.rs b/library/core/src/task/wake.rs index fc549abd433..3e795e7b5e3 100644 --- a/library/core/src/task/wake.rs +++ b/library/core/src/task/wake.rs @@ -519,8 +519,8 @@ impl Waker { /// [`Wake`]: ../../alloc/task/trait.Wake.html #[inline] #[must_use] - #[stable(feature = "waker_getters", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "waker_getters", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "waker_getters", since = "1.83.0")] + #[rustc_const_stable(feature = "waker_getters", since = "1.83.0")] pub const unsafe fn new(data: *const (), vtable: &'static RawWakerVTable) -> Self { Waker { waker: RawWaker { data, vtable } } } @@ -584,7 +584,7 @@ impl Waker { /// Gets the `data` pointer used to create this `Waker`. #[inline] #[must_use] - #[stable(feature = "waker_getters", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "waker_getters", since = "1.83.0")] pub fn data(&self) -> *const () { self.waker.data } @@ -592,7 +592,7 @@ impl Waker { /// Gets the `vtable` pointer used to create this `Waker`. #[inline] #[must_use] - #[stable(feature = "waker_getters", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "waker_getters", since = "1.83.0")] pub fn vtable(&self) -> &'static RawWakerVTable { self.waker.vtable } diff --git a/library/core/src/time.rs b/library/core/src/time.rs index 51005ff795c..5081e777af4 100644 --- a/library/core/src/time.rs +++ b/library/core/src/time.rs @@ -844,7 +844,7 @@ impl Duration { #[stable(feature = "duration_float", since = "1.38.0")] #[must_use] #[inline] - #[rustc_const_stable(feature = "duration_consts_float", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "duration_consts_float", since = "1.83.0")] pub const fn as_secs_f64(&self) -> f64 { (self.secs as f64) + (self.nanos.0 as f64) / (NANOS_PER_SEC as f64) } @@ -863,7 +863,7 @@ impl Duration { #[stable(feature = "duration_float", since = "1.38.0")] #[must_use] #[inline] - #[rustc_const_stable(feature = "duration_consts_float", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "duration_consts_float", since = "1.83.0")] pub const fn as_secs_f32(&self) -> f32 { (self.secs as f32) + (self.nanos.0 as f32) / (NANOS_PER_SEC as f32) } @@ -1084,7 +1084,7 @@ impl Duration { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - #[rustc_const_stable(feature = "duration_consts_float", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "duration_consts_float", since = "1.83.0")] pub const fn div_duration_f64(self, rhs: Duration) -> f64 { let self_nanos = (self.secs as f64) * (NANOS_PER_SEC as f64) + (self.nanos.0 as f64); let rhs_nanos = (rhs.secs as f64) * (NANOS_PER_SEC as f64) + (rhs.nanos.0 as f64); @@ -1105,7 +1105,7 @@ impl Duration { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - #[rustc_const_stable(feature = "duration_consts_float", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "duration_consts_float", since = "1.83.0")] pub const fn div_duration_f32(self, rhs: Duration) -> f32 { let self_nanos = (self.secs as f32) * (NANOS_PER_SEC as f32) + (self.nanos.0 as f32); let rhs_nanos = (rhs.secs as f32) * (NANOS_PER_SEC as f32) + (rhs.nanos.0 as f32); diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs index f2e523dca77..ded4f404d78 100644 --- a/library/std/src/collections/hash/map.rs +++ b/library/std/src/collections/hash/map.rs @@ -1438,7 +1438,7 @@ impl Clone for Iter<'_, K, V> { } } -#[stable(feature = "default_iters_hash", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "default_iters_hash", since = "1.83.0")] impl Default for Iter<'_, K, V> { #[inline] fn default() -> Self { @@ -1484,7 +1484,7 @@ impl<'a, K, V> IterMut<'a, K, V> { } } -#[stable(feature = "default_iters_hash", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "default_iters_hash", since = "1.83.0")] impl Default for IterMut<'_, K, V> { #[inline] fn default() -> Self { @@ -1522,7 +1522,7 @@ impl IntoIter { } } -#[stable(feature = "default_iters_hash", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "default_iters_hash", since = "1.83.0")] impl Default for IntoIter { #[inline] fn default() -> Self { @@ -1562,7 +1562,7 @@ impl Clone for Keys<'_, K, V> { } } -#[stable(feature = "default_iters_hash", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "default_iters_hash", since = "1.83.0")] impl Default for Keys<'_, K, V> { #[inline] fn default() -> Self { @@ -1609,7 +1609,7 @@ impl Clone for Values<'_, K, V> { } } -#[stable(feature = "default_iters_hash", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "default_iters_hash", since = "1.83.0")] impl Default for Values<'_, K, V> { #[inline] fn default() -> Self { @@ -1705,7 +1705,7 @@ pub struct ValuesMut<'a, K: 'a, V: 'a> { inner: IterMut<'a, K, V>, } -#[stable(feature = "default_iters_hash", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "default_iters_hash", since = "1.83.0")] impl Default for ValuesMut<'_, K, V> { #[inline] fn default() -> Self { @@ -1735,7 +1735,7 @@ pub struct IntoKeys { inner: IntoIter, } -#[stable(feature = "default_iters_hash", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "default_iters_hash", since = "1.83.0")] impl Default for IntoKeys { #[inline] fn default() -> Self { @@ -1765,7 +1765,7 @@ pub struct IntoValues { inner: IntoIter, } -#[stable(feature = "default_iters_hash", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "default_iters_hash", since = "1.83.0")] impl Default for IntoValues { #[inline] fn default() -> Self { @@ -2865,7 +2865,7 @@ impl<'a, K, V> Entry<'a, K, V> { /// assert_eq!(entry.key(), &"poneyland"); /// ``` #[inline] - #[stable(feature = "entry_insert", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "entry_insert", since = "1.83.0")] pub fn insert_entry(self, value: V) -> OccupiedEntry<'a, K, V> { match self { Occupied(mut entry) => { @@ -3152,7 +3152,7 @@ impl<'a, K: 'a, V: 'a> VacantEntry<'a, K, V> { /// assert_eq!(map["poneyland"], 37); /// ``` #[inline] - #[stable(feature = "entry_insert", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "entry_insert", since = "1.83.0")] pub fn insert_entry(self, value: V) -> OccupiedEntry<'a, K, V> { let base = self.base.insert_entry(value); OccupiedEntry { base } diff --git a/library/std/src/collections/hash/set.rs b/library/std/src/collections/hash/set.rs index 210f5715225..e1e0eb36d23 100644 --- a/library/std/src/collections/hash/set.rs +++ b/library/std/src/collections/hash/set.rs @@ -1244,7 +1244,7 @@ pub struct Iter<'a, K: 'a> { base: base::Iter<'a, K>, } -#[stable(feature = "default_iters_hash", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "default_iters_hash", since = "1.83.0")] impl Default for Iter<'_, K> { #[inline] fn default() -> Self { @@ -1273,7 +1273,7 @@ pub struct IntoIter { base: base::IntoIter, } -#[stable(feature = "default_iters_hash", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "default_iters_hash", since = "1.83.0")] impl Default for IntoIter { #[inline] fn default() -> Self { diff --git a/library/std/src/io/error.rs b/library/std/src/io/error.rs index f20814dd95c..adf103e9430 100644 --- a/library/std/src/io/error.rs +++ b/library/std/src/io/error.rs @@ -223,10 +223,10 @@ pub enum ErrorKind { #[stable(feature = "rust1", since = "1.0.0")] ConnectionReset, /// The remote host is not reachable. - #[stable(feature = "io_error_a_bit_more", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "io_error_a_bit_more", since = "1.83.0")] HostUnreachable, /// The network containing the remote host is not reachable. - #[stable(feature = "io_error_a_bit_more", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "io_error_a_bit_more", since = "1.83.0")] NetworkUnreachable, /// The connection was aborted (terminated) by the remote server. #[stable(feature = "rust1", since = "1.0.0")] @@ -243,7 +243,7 @@ pub enum ErrorKind { #[stable(feature = "rust1", since = "1.0.0")] AddrNotAvailable, /// The system's networking is down. - #[stable(feature = "io_error_a_bit_more", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "io_error_a_bit_more", since = "1.83.0")] NetworkDown, /// The operation failed because a pipe was closed. #[stable(feature = "rust1", since = "1.0.0")] @@ -259,18 +259,18 @@ pub enum ErrorKind { /// /// For example, a filesystem path was specified where one of the intermediate directory /// components was, in fact, a plain file. - #[stable(feature = "io_error_a_bit_more", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "io_error_a_bit_more", since = "1.83.0")] NotADirectory, /// The filesystem object is, unexpectedly, a directory. /// /// A directory was specified when a non-directory was expected. - #[stable(feature = "io_error_a_bit_more", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "io_error_a_bit_more", since = "1.83.0")] IsADirectory, /// A non-empty directory was specified where an empty directory was expected. - #[stable(feature = "io_error_a_bit_more", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "io_error_a_bit_more", since = "1.83.0")] DirectoryNotEmpty, /// The filesystem or storage medium is read-only, but a write operation was attempted. - #[stable(feature = "io_error_a_bit_more", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "io_error_a_bit_more", since = "1.83.0")] ReadOnlyFilesystem, /// Loop in the filesystem or IO subsystem; often, too many levels of symbolic links. /// @@ -285,7 +285,7 @@ pub enum ErrorKind { /// /// With some network filesystems, notably NFS, an open file (or directory) can be invalidated /// by problems with the network or server. - #[stable(feature = "io_error_a_bit_more", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "io_error_a_bit_more", since = "1.83.0")] StaleNetworkFileHandle, /// A parameter was incorrect. #[stable(feature = "rust1", since = "1.0.0")] @@ -319,13 +319,13 @@ pub enum ErrorKind { /// The underlying storage (typically, a filesystem) is full. /// /// This does not include out of quota errors. - #[stable(feature = "io_error_a_bit_more", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "io_error_a_bit_more", since = "1.83.0")] StorageFull, /// Seek on unseekable file. /// /// Seeking was attempted on an open file handle which is not suitable for seeking - for /// example, on Unix, a named pipe opened with `File::open`. - #[stable(feature = "io_error_a_bit_more", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "io_error_a_bit_more", since = "1.83.0")] NotSeekable, /// Filesystem quota was exceeded. #[unstable(feature = "io_error_more", issue = "86442")] @@ -335,22 +335,22 @@ pub enum ErrorKind { /// This might arise from a hard limit of the underlying filesystem or file access API, or from /// an administratively imposed resource limitation. Simple disk full, and out of quota, have /// their own errors. - #[stable(feature = "io_error_a_bit_more", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "io_error_a_bit_more", since = "1.83.0")] FileTooLarge, /// Resource is busy. - #[stable(feature = "io_error_a_bit_more", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "io_error_a_bit_more", since = "1.83.0")] ResourceBusy, /// Executable file is busy. /// /// An attempt was made to write to a file which is also in use as a running program. (Not all /// operating systems detect this situation.) - #[stable(feature = "io_error_a_bit_more", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "io_error_a_bit_more", since = "1.83.0")] ExecutableFileBusy, /// Deadlock (avoided). /// /// A file locking operation would result in deadlock. This situation is typically detected, if /// at all, on a best-effort basis. - #[stable(feature = "io_error_a_bit_more", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "io_error_a_bit_more", since = "1.83.0")] Deadlock, /// Cross-device or cross-filesystem (hard) link or rename. #[unstable(feature = "io_error_more", issue = "86442")] @@ -358,7 +358,7 @@ pub enum ErrorKind { /// Too many (hard) links to the same filesystem object. /// /// The filesystem does not support making so many hardlinks to the same file. - #[stable(feature = "io_error_a_bit_more", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "io_error_a_bit_more", since = "1.83.0")] TooManyLinks, /// A filename was invalid. /// @@ -369,7 +369,7 @@ pub enum ErrorKind { /// /// When trying to run an external program, a system or process limit on the size of the /// arguments would have been exceeded. - #[stable(feature = "io_error_a_bit_more", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "io_error_a_bit_more", since = "1.83.0")] ArgumentListTooLong, /// This operation was interrupted. /// diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index 8fedcb241d0..71dfd0676c9 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -2405,7 +2405,7 @@ pub trait BufRead: Read { /// assert_eq!(num_bytes, 11); /// assert_eq!(animal, b"Crustacean\0"); /// ``` - #[stable(feature = "bufread_skip_until", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "bufread_skip_until", since = "1.83.0")] fn skip_until(&mut self, byte: u8) -> Result { skip_until(self, byte) } -- cgit 1.4.1-3-g733a5 From acb09bf741ba439356e824dd10a07054c6656fb6 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Mon, 14 Oct 2024 14:46:44 -0700 Subject: update bootstrap configs --- compiler/rustc_const_eval/src/lib.rs | 4 +-- compiler/rustc_data_structures/src/steal.rs | 2 +- compiler/rustc_lint/src/if_let_rescope.rs | 2 +- compiler/rustc_lint_defs/src/builtin.rs | 1 - compiler/rustc_next_trait_solver/src/lib.rs | 2 +- compiler/rustc_type_ir/src/lib.rs | 2 +- library/alloc/src/lib.rs | 2 -- library/alloc/tests/lib.rs | 1 - library/alloc/tests/vec.rs | 2 +- library/core/src/arch.rs | 35 ---------------------- library/core/src/array/mod.rs | 1 - library/core/src/cell.rs | 1 - library/core/src/char/methods.rs | 4 --- library/core/src/intrinsics.rs | 4 --- library/core/src/lib.rs | 3 -- library/core/src/mem/maybe_uninit.rs | 3 -- library/core/src/mem/mod.rs | 1 - library/core/src/num/mod.rs | 2 -- library/core/src/option.rs | 4 --- library/core/src/ptr/mod.rs | 5 +--- library/core/src/ptr/mut_ptr.rs | 2 -- library/core/src/ptr/non_null.rs | 1 - library/core/src/result.rs | 2 -- library/core/src/slice/ascii.rs | 2 -- library/core/src/slice/mod.rs | 12 -------- library/core/src/slice/raw.rs | 2 -- library/core/src/str/converts.rs | 1 - library/core/src/str/mod.rs | 4 --- library/core/tests/atomic.rs | 2 +- library/core/tests/lib.rs | 1 - library/std/src/lib.rs | 1 - src/tools/miri/src/lib.rs | 4 +-- .../internal-lints/import-of-type-ir-inherent.rs | 3 -- .../import-of-type-ir-inherent.stderr | 8 ++--- .../internal-lints/query_completeness.rs | 2 -- .../internal-lints/query_completeness.stderr | 4 +-- 36 files changed, 17 insertions(+), 115 deletions(-) (limited to 'library/std/src') diff --git a/compiler/rustc_const_eval/src/lib.rs b/compiler/rustc_const_eval/src/lib.rs index cbe8a043fba..39e2d3b4ebb 100644 --- a/compiler/rustc_const_eval/src/lib.rs +++ b/compiler/rustc_const_eval/src/lib.rs @@ -1,8 +1,6 @@ // tidy-alphabetical-start #![allow(internal_features)] #![allow(rustc::diagnostic_outside_of_impl)] -#![cfg_attr(not(bootstrap), feature(unqualified_local_imports))] -#![cfg_attr(not(bootstrap), warn(unqualified_local_imports))] #![doc(rust_logo)] #![feature(assert_matches)] #![feature(box_patterns)] @@ -15,7 +13,9 @@ #![feature(strict_provenance)] #![feature(trait_alias)] #![feature(try_blocks)] +#![feature(unqualified_local_imports)] #![feature(yeet_expr)] +#![warn(unqualified_local_imports)] #![warn(unreachable_pub)] // tidy-alphabetical-end diff --git a/compiler/rustc_data_structures/src/steal.rs b/compiler/rustc_data_structures/src/steal.rs index aaa95f6b7f1..0d79d98b5d9 100644 --- a/compiler/rustc_data_structures/src/steal.rs +++ b/compiler/rustc_data_structures/src/steal.rs @@ -57,7 +57,7 @@ impl Steal { /// /// This should not be used within rustc as it leaks information not tracked /// by the query system, breaking incremental compilation. - #[cfg_attr(not(bootstrap), rustc_lint_untracked_query_information)] + #[rustc_lint_untracked_query_information] pub fn is_stolen(&self) -> bool { self.value.borrow().is_none() } diff --git a/compiler/rustc_lint/src/if_let_rescope.rs b/compiler/rustc_lint/src/if_let_rescope.rs index cdd0e80c458..58fd11fcc29 100644 --- a/compiler/rustc_lint/src/if_let_rescope.rs +++ b/compiler/rustc_lint/src/if_let_rescope.rs @@ -24,7 +24,7 @@ declare_lint! { /// ### Example /// /// ```rust,edition2021 - /// #![cfg_attr(not(bootstrap), feature(if_let_rescope))] // Simplify this in bootstrap bump. + /// #![feature(if_let_rescope)] /// #![warn(if_let_rescope)] /// #![allow(unused_variables)] /// diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index da603df9a9a..f532b9b153b 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -1871,7 +1871,6 @@ declare_lint! { /// ### Example /// /// ```rust,compile_fail - /// # #[cfg_attr(bootstrap)] compile_error!(); // Remove this in bootstrap bump. /// #![deny(elided_named_lifetimes)] /// struct Foo; /// impl Foo { diff --git a/compiler/rustc_next_trait_solver/src/lib.rs b/compiler/rustc_next_trait_solver/src/lib.rs index de74ac32804..d67ae2550d9 100644 --- a/compiler/rustc_next_trait_solver/src/lib.rs +++ b/compiler/rustc_next_trait_solver/src/lib.rs @@ -5,7 +5,7 @@ //! So if you got to this crate from the old solver, it's totally normal. // tidy-alphabetical-start -#![cfg_attr(not(bootstrap), allow(rustc::usage_of_type_ir_inherent))] +#![allow(rustc::usage_of_type_ir_inherent)] #![warn(unreachable_pub)] // tidy-alphabetical-end diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs index 51c887fc4da..9e6d1f424ba 100644 --- a/compiler/rustc_type_ir/src/lib.rs +++ b/compiler/rustc_type_ir/src/lib.rs @@ -1,11 +1,11 @@ // tidy-alphabetical-start #![allow(rustc::usage_of_ty_tykind)] +#![allow(rustc::usage_of_type_ir_inherent)] #![cfg_attr( feature = "nightly", feature(associated_type_defaults, never_type, rustc_attrs, negative_impls) )] #![cfg_attr(feature = "nightly", allow(internal_features))] -#![cfg_attr(not(bootstrap), allow(rustc::usage_of_type_ir_inherent))] #![warn(unreachable_pub)] // tidy-alphabetical-end diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index 50bf385d671..12512f0dd8c 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -162,8 +162,6 @@ // // Language features: // tidy-alphabetical-start -#![cfg_attr(bootstrap, feature(const_mut_refs))] -#![cfg_attr(bootstrap, feature(const_refs_to_cell))] #![cfg_attr(not(test), feature(coroutine_trait))] #![cfg_attr(test, feature(panic_update_hook))] #![cfg_attr(test, feature(test))] diff --git a/library/alloc/tests/lib.rs b/library/alloc/tests/lib.rs index 3ec4332c71b..301126b5d4d 100644 --- a/library/alloc/tests/lib.rs +++ b/library/alloc/tests/lib.rs @@ -5,7 +5,6 @@ #![feature(btree_extract_if)] #![feature(cow_is_borrowed)] #![feature(const_heap)] -#![cfg_attr(bootstrap, feature(const_mut_refs))] #![feature(const_try)] #![feature(core_intrinsics)] #![feature(extract_if)] diff --git a/library/alloc/tests/vec.rs b/library/alloc/tests/vec.rs index f508a3e4c22..0f27fdff3e1 100644 --- a/library/alloc/tests/vec.rs +++ b/library/alloc/tests/vec.rs @@ -1288,7 +1288,7 @@ fn test_from_iter_specialization_panic_during_iteration_drops() { #[test] #[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] // FIXME(static_mut_refs): Do not allow `static_mut_refs` lint -#[cfg_attr(not(bootstrap), allow(static_mut_refs))] +#[allow(static_mut_refs)] fn test_from_iter_specialization_panic_during_drop_doesnt_leak() { static mut DROP_COUNTER_OLD: [usize; 5] = [0; 5]; static mut DROP_COUNTER_NEW: [usize; 2] = [0; 2]; diff --git a/library/core/src/arch.rs b/library/core/src/arch.rs index 4945c045bc6..57f456c98b3 100644 --- a/library/core/src/arch.rs +++ b/library/core/src/arch.rs @@ -3,9 +3,6 @@ #[allow(unused_imports)] #[stable(feature = "simd_arch", since = "1.27.0")] pub use crate::core_arch::arch::*; -#[unstable(feature = "naked_functions", issue = "90957")] -#[cfg(bootstrap)] -pub use crate::naked_asm; /// Inline assembly. /// @@ -20,37 +17,6 @@ pub macro asm("assembly template", $(operands,)* $(options($(option),*))?) { /* compiler built-in */ } -/// Inline assembly used in combination with `#[naked]` functions. -/// -/// Refer to [Rust By Example] for a usage guide and the [reference] for -/// detailed information about the syntax and available options. -/// -/// [Rust By Example]: https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html -/// [reference]: https://doc.rust-lang.org/nightly/reference/inline-assembly.html -#[unstable(feature = "naked_functions", issue = "90957")] -#[macro_export] -#[cfg(bootstrap)] -macro_rules! naked_asm { - ([$last:expr], [$($pushed:expr),*]) => { - #[cfg(any(target_arch = "x86_64", target_arch = "x86"))] - { - core::arch::asm!($($pushed),*, options(att_syntax, noreturn)) - } - #[cfg(not(any(target_arch = "x86_64", target_arch = "x86")))] - { - core::arch::asm!($($pushed),* , $last, options(noreturn)) - } - }; - - ([$first:expr $(, $rest:expr)*], [$($pushed:expr),*]) => { - naked_asm!([$($rest),*], [$($pushed,)* $first]); - }; - - ($($expr:expr),* $(,)?) => { - naked_asm!([$($expr),*], []); - }; -} - /// Inline assembly used in combination with `#[naked]` functions. /// /// Refer to [Rust By Example] for a usage guide and the [reference] for @@ -60,7 +26,6 @@ macro_rules! naked_asm { /// [reference]: https://doc.rust-lang.org/nightly/reference/inline-assembly.html #[unstable(feature = "naked_functions", issue = "90957")] #[rustc_builtin_macro] -#[cfg(not(bootstrap))] pub macro naked_asm("assembly template", $(operands,)* $(options($(option),*))?) { /* compiler built-in */ } diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs index 72f48878904..9b28b8b613e 100644 --- a/library/core/src/array/mod.rs +++ b/library/core/src/array/mod.rs @@ -147,7 +147,6 @@ pub const fn from_ref(s: &T) -> &[T; 1] { /// Converts a mutable reference to `T` into a mutable reference to an array of length 1 (without copying). #[stable(feature = "array_from_ref", since = "1.53.0")] #[rustc_const_stable(feature = "const_array_from_ref", since = "1.83.0")] -#[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] pub const fn from_mut(s: &mut T) -> &mut [T; 1] { // SAFETY: Converting `&mut T` to `&mut [T; 1]` is sound. unsafe { &mut *(s as *mut T).cast::<[T; 1]>() } diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index 0945845021e..e1fa43296d0 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -2181,7 +2181,6 @@ impl UnsafeCell { /// ``` #[inline(always)] #[stable(feature = "unsafe_cell_get_mut", since = "1.50.0")] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] #[rustc_const_stable(feature = "const_unsafecell_get_mut", since = "1.83.0")] pub const fn get_mut(&mut self) -> &mut T { &mut self.value diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs index 1abfaa46ec6..30c0fff3104 100644 --- a/library/core/src/char/methods.rs +++ b/library/core/src/char/methods.rs @@ -676,7 +676,6 @@ impl char { #[stable(feature = "unicode_encode_char", since = "1.15.0")] #[rustc_const_stable(feature = "const_char_encode_utf8", since = "1.83.0")] #[inline] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] pub const fn encode_utf8(self, dst: &mut [u8]) -> &mut str { // SAFETY: `char` is not a surrogate, so this is valid UTF-8. unsafe { from_utf8_unchecked_mut(encode_utf8_raw(self as u32, dst)) } @@ -1284,7 +1283,6 @@ impl char { #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] #[rustc_const_stable(feature = "const_make_ascii", since = "CURRENT_RUSTC_VERSION")] #[inline] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] pub const fn make_ascii_uppercase(&mut self) { *self = self.to_ascii_uppercase(); } @@ -1311,7 +1309,6 @@ impl char { #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] #[rustc_const_stable(feature = "const_make_ascii", since = "CURRENT_RUSTC_VERSION")] #[inline] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] pub const fn make_ascii_lowercase(&mut self) { *self = self.to_ascii_lowercase(); } @@ -1777,7 +1774,6 @@ const fn len_utf16(code: u32) -> usize { #[doc(hidden)] #[inline] #[rustc_allow_const_fn_unstable(const_eval_select)] -#[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] pub const fn encode_utf8_raw(code: u32, dst: &mut [u8]) -> &mut [u8] { const fn panic_at_const(_code: u32, _len: usize, _dst_len: usize) { // Note that we cannot format in constant expressions. diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index ca5b9fc98b9..69ad4f41519 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -1807,7 +1807,6 @@ extern "rust-intrinsic" { /// is selected, and that may depend on optimization level and context, for /// example. #[rustc_nounwind] - #[cfg(not(bootstrap))] pub fn fmuladdf16(a: f16, b: f16, c: f16) -> f16; /// Returns `a * b + c` for `f32` values, non-deterministically executing /// either a fused multiply-add or two operations with rounding of the @@ -1820,7 +1819,6 @@ extern "rust-intrinsic" { /// is selected, and that may depend on optimization level and context, for /// example. #[rustc_nounwind] - #[cfg(not(bootstrap))] pub fn fmuladdf32(a: f32, b: f32, c: f32) -> f32; /// Returns `a * b + c` for `f64` values, non-deterministically executing /// either a fused multiply-add or two operations with rounding of the @@ -1833,7 +1831,6 @@ extern "rust-intrinsic" { /// is selected, and that may depend on optimization level and context, for /// example. #[rustc_nounwind] - #[cfg(not(bootstrap))] pub fn fmuladdf64(a: f64, b: f64, c: f64) -> f64; /// Returns `a * b + c` for `f128` values, non-deterministically executing /// either a fused multiply-add or two operations with rounding of the @@ -1846,7 +1843,6 @@ extern "rust-intrinsic" { /// is selected, and that may depend on optimization level and context, for /// example. #[rustc_nounwind] - #[cfg(not(bootstrap))] pub fn fmuladdf128(a: f128, b: f128, c: f128) -> f128; /// Returns the largest integer less than or equal to an `f16`. diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index ccd6534de9b..7060da172f3 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -173,9 +173,6 @@ // // Language features: // tidy-alphabetical-start -#![cfg_attr(bootstrap, feature(const_mut_refs))] -#![cfg_attr(bootstrap, feature(const_refs_to_cell))] -#![cfg_attr(bootstrap, feature(const_refs_to_static))] #![feature(abi_unadjusted)] #![feature(adt_const_params)] #![feature(allow_internal_unsafe)] diff --git a/library/core/src/mem/maybe_uninit.rs b/library/core/src/mem/maybe_uninit.rs index bb01d4e642c..ea73cfc3781 100644 --- a/library/core/src/mem/maybe_uninit.rs +++ b/library/core/src/mem/maybe_uninit.rs @@ -570,7 +570,6 @@ impl MaybeUninit { /// until they are, it is advisable to avoid them.) #[stable(feature = "maybe_uninit", since = "1.36.0")] #[rustc_const_stable(feature = "const_maybe_uninit_as_mut_ptr", since = "1.83.0")] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] #[inline(always)] pub const fn as_mut_ptr(&mut self) -> *mut T { // `MaybeUninit` and `ManuallyDrop` are both `repr(transparent)` so we can cast the pointer. @@ -910,7 +909,6 @@ impl MaybeUninit { /// }; /// ``` #[stable(feature = "maybe_uninit_ref", since = "1.55.0")] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] #[rustc_const_stable( feature = "const_maybe_uninit_assume_init", since = "CURRENT_RUSTC_VERSION" @@ -1000,7 +998,6 @@ impl MaybeUninit { /// /// [`assume_init_mut`]: MaybeUninit::assume_init_mut #[unstable(feature = "maybe_uninit_slice", issue = "63569")] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] #[rustc_const_unstable(feature = "maybe_uninit_slice", issue = "63569")] #[inline(always)] pub const unsafe fn slice_assume_init_mut(slice: &mut [Self]) -> &mut [T] { diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs index ada80463306..74b198c4fdd 100644 --- a/library/core/src/mem/mod.rs +++ b/library/core/src/mem/mod.rs @@ -857,7 +857,6 @@ pub fn take(dest: &mut T) -> T { #[inline] #[stable(feature = "rust1", since = "1.0.0")] #[must_use = "if you don't need the old value, you can just assign the new value directly"] -#[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] #[rustc_const_stable(feature = "const_replace", since = "1.83.0")] #[cfg_attr(not(test), rustc_diagnostic_item = "mem_replace")] pub const fn replace(dest: &mut T, src: T) -> T { diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs index f55d55171f2..5e2f45884dd 100644 --- a/library/core/src/num/mod.rs +++ b/library/core/src/num/mod.rs @@ -626,7 +626,6 @@ impl u8 { #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] #[rustc_const_stable(feature = "const_make_ascii", since = "CURRENT_RUSTC_VERSION")] #[inline] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] pub const fn make_ascii_uppercase(&mut self) { *self = self.to_ascii_uppercase(); } @@ -653,7 +652,6 @@ impl u8 { #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] #[rustc_const_stable(feature = "const_make_ascii", since = "CURRENT_RUSTC_VERSION")] #[inline] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] pub const fn make_ascii_lowercase(&mut self) { *self = self.to_ascii_lowercase(); } diff --git a/library/core/src/option.rs b/library/core/src/option.rs index 661176ce9fc..0b996c40c04 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -723,7 +723,6 @@ impl Option { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] #[rustc_const_stable(feature = "const_option", since = "1.83.0")] pub const fn as_mut(&mut self) -> Option<&mut T> { match *self { @@ -1716,7 +1715,6 @@ impl Option { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] #[rustc_const_stable(feature = "const_option", since = "1.83.0")] pub const fn take(&mut self) -> Option { // FIXME(const-hack) replace `mem::replace` by `mem::take` when the latter is const ready @@ -1775,7 +1773,6 @@ impl Option { /// ``` #[inline] #[stable(feature = "option_replace", since = "1.31.0")] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] #[rustc_const_stable(feature = "const_option", since = "1.83.0")] pub const fn replace(&mut self, value: T) -> Option { mem::replace(self, Some(value)) @@ -1937,7 +1934,6 @@ impl Option<&mut T> { /// ``` #[must_use = "`self` will be dropped if the result is not used"] #[stable(feature = "copied", since = "1.35.0")] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] #[rustc_const_stable(feature = "const_option", since = "1.83.0")] pub const fn copied(self) -> Option where diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index 61b48e312cf..09ff7f8cab1 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -1265,7 +1265,6 @@ const unsafe fn swap_nonoverlapping_simple_untyped(x: *mut T, y: *mut T, coun /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] -#[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] #[rustc_const_stable(feature = "const_replace", since = "1.83.0")] #[rustc_diagnostic_item = "ptr_replace"] pub const unsafe fn replace(dst: *mut T, src: T) -> T { @@ -1518,7 +1517,6 @@ pub const unsafe fn read(src: *const T) -> T { #[inline] #[stable(feature = "ptr_unaligned", since = "1.17.0")] #[rustc_const_stable(feature = "const_ptr_read", since = "1.71.0")] -#[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[rustc_diagnostic_item = "ptr_read_unaligned"] pub const unsafe fn read_unaligned(src: *const T) -> T { @@ -1725,7 +1723,6 @@ pub const unsafe fn write(dst: *mut T, src: T) { /// ``` #[inline] #[stable(feature = "ptr_unaligned", since = "1.17.0")] -#[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_refs_to_cell))] #[rustc_const_stable(feature = "const_ptr_write", since = "1.83.0")] #[rustc_diagnostic_item = "ptr_write_unaligned"] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces @@ -1918,7 +1915,7 @@ pub unsafe fn write_volatile(dst: *mut T, src: T) { /// than trying to adapt this to accommodate that change. /// /// Any questions go to @nagisa. -#[cfg_attr(not(bootstrap), allow(ptr_to_integer_transmute_in_consts))] +#[allow(ptr_to_integer_transmute_in_consts)] #[lang = "align_offset"] pub(crate) const unsafe fn align_offset(p: *const T, a: usize) -> usize { // FIXME(#75598): Direct use of these intrinsics improves codegen significantly at opt-level <= diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index d7ce197848b..613d2c91ac6 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -1678,7 +1678,6 @@ impl *mut T { /// /// ``` /// #![feature(const_pointer_is_aligned)] - /// # #![cfg_attr(bootstrap, feature(const_mut_refs))] /// /// // On some platforms, the alignment of primitives is less than their size. /// #[repr(align(4))] @@ -1804,7 +1803,6 @@ impl *mut T { /// ``` /// #![feature(pointer_is_aligned_to)] /// #![feature(const_pointer_is_aligned)] - /// # #![cfg_attr(bootstrap, feature(const_mut_refs))] /// /// // On some platforms, the alignment of i32 is less than 4. /// #[repr(align(4))] diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs index c6839136348..dfd0bd8fd1e 100644 --- a/library/core/src/ptr/non_null.rs +++ b/library/core/src/ptr/non_null.rs @@ -394,7 +394,6 @@ impl NonNull { /// /// [the module documentation]: crate::ptr#safety #[stable(feature = "nonnull", since = "1.25.0")] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] #[rustc_const_stable(feature = "const_ptr_as_ref", since = "1.83.0")] #[must_use] #[inline(always)] diff --git a/library/core/src/result.rs b/library/core/src/result.rs index e84c4e3a239..330d1eb14ed 100644 --- a/library/core/src/result.rs +++ b/library/core/src/result.rs @@ -735,7 +735,6 @@ impl Result { #[inline] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_result", since = "1.83.0")] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] pub const fn as_mut(&mut self) -> Result<&mut T, &mut E> { match *self { Ok(ref mut x) => Ok(x), @@ -1589,7 +1588,6 @@ impl Result<&mut T, E> { #[inline] #[stable(feature = "result_copied", since = "1.59.0")] #[rustc_const_stable(feature = "const_result", since = "1.83.0")] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] #[rustc_allow_const_fn_unstable(const_precise_live_drops)] pub const fn copied(self) -> Result where diff --git a/library/core/src/slice/ascii.rs b/library/core/src/slice/ascii.rs index 8d8ac6a1d2a..a03e9fbae11 100644 --- a/library/core/src/slice/ascii.rs +++ b/library/core/src/slice/ascii.rs @@ -69,7 +69,6 @@ impl [u8] { #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] #[rustc_const_stable(feature = "const_make_ascii", since = "CURRENT_RUSTC_VERSION")] #[inline] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] pub const fn make_ascii_uppercase(&mut self) { // FIXME(const-hack): We would like to simply iterate using `for` loops but this isn't currently allowed in constant expressions. let mut i = 0; @@ -92,7 +91,6 @@ impl [u8] { #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] #[rustc_const_stable(feature = "const_make_ascii", since = "CURRENT_RUSTC_VERSION")] #[inline] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] pub const fn make_ascii_lowercase(&mut self) { // FIXME(const-hack): We would like to simply iterate using `for` loops but this isn't currently allowed in constant expressions. let mut i = 0; diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 9fdcea1f7b7..dbcfe946440 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -171,7 +171,6 @@ impl [T] { /// assert_eq!(None, y.first_mut()); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] #[rustc_const_stable(feature = "const_slice_first_last", since = "1.83.0")] #[inline] #[must_use] @@ -214,7 +213,6 @@ impl [T] { /// assert_eq!(x, &[3, 4, 5]); /// ``` #[stable(feature = "slice_splits", since = "1.5.0")] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] #[rustc_const_stable(feature = "const_slice_first_last", since = "1.83.0")] #[inline] #[must_use] @@ -257,7 +255,6 @@ impl [T] { /// assert_eq!(x, &[4, 5, 3]); /// ``` #[stable(feature = "slice_splits", since = "1.5.0")] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] #[rustc_const_stable(feature = "const_slice_first_last", since = "1.83.0")] #[inline] #[must_use] @@ -300,7 +297,6 @@ impl [T] { /// assert_eq!(None, y.last_mut()); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] #[rustc_const_stable(feature = "const_slice_first_last", since = "1.83.0")] #[inline] #[must_use] @@ -357,7 +353,6 @@ impl [T] { #[inline] #[stable(feature = "slice_first_last_chunk", since = "1.77.0")] #[rustc_const_stable(feature = "const_slice_first_last_chunk", since = "1.83.0")] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] pub const fn first_chunk_mut(&mut self) -> Option<&mut [T; N]> { if self.len() < N { None @@ -423,7 +418,6 @@ impl [T] { #[inline] #[stable(feature = "slice_first_last_chunk", since = "1.77.0")] #[rustc_const_stable(feature = "const_slice_first_last_chunk", since = "1.83.0")] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] pub const fn split_first_chunk_mut( &mut self, ) -> Option<(&mut [T; N], &mut [T])> { @@ -494,7 +488,6 @@ impl [T] { #[inline] #[stable(feature = "slice_first_last_chunk", since = "1.77.0")] #[rustc_const_stable(feature = "const_slice_first_last_chunk", since = "1.83.0")] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] pub const fn split_last_chunk_mut( &mut self, ) -> Option<(&mut [T], &mut [T; N])> { @@ -564,7 +557,6 @@ impl [T] { #[inline] #[stable(feature = "slice_first_last_chunk", since = "1.77.0")] #[rustc_const_stable(feature = "const_slice_first_last_chunk", since = "1.83.0")] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] pub const fn last_chunk_mut(&mut self) -> Option<&mut [T; N]> { if self.len() < N { None @@ -853,7 +845,6 @@ impl [T] { /// [`as_mut_ptr`]: slice::as_mut_ptr #[stable(feature = "slice_ptr_range", since = "1.48.0")] #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs, const_refs_to_cell))] #[inline] #[must_use] pub const fn as_mut_ptr_range(&mut self) -> Range<*mut T> { @@ -1908,7 +1899,6 @@ impl [T] { #[track_caller] #[must_use] #[rustc_const_stable(feature = "const_slice_split_at_mut", since = "1.83.0")] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] pub const fn split_at_mut(&mut self, mid: usize) -> (&mut [T], &mut [T]) { match self.split_at_mut_checked(mid) { Some(pair) => pair, @@ -2011,7 +2001,6 @@ impl [T] { /// ``` #[stable(feature = "slice_split_at_unchecked", since = "1.79.0")] #[rustc_const_stable(feature = "const_slice_split_at_mut", since = "1.83.0")] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] #[inline] #[must_use] pub const unsafe fn split_at_mut_unchecked(&mut self, mid: usize) -> (&mut [T], &mut [T]) { @@ -2112,7 +2101,6 @@ impl [T] { /// ``` #[stable(feature = "split_at_checked", since = "1.80.0")] #[rustc_const_stable(feature = "const_slice_split_at_mut", since = "1.83.0")] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] #[inline] #[must_use] pub const fn split_at_mut_checked(&mut self, mid: usize) -> Option<(&mut [T], &mut [T])> { diff --git a/library/core/src/slice/raw.rs b/library/core/src/slice/raw.rs index 976749cc148..89840881c4d 100644 --- a/library/core/src/slice/raw.rs +++ b/library/core/src/slice/raw.rs @@ -172,7 +172,6 @@ pub const unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T] #[inline] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_slice_from_raw_parts_mut", since = "1.83.0")] -#[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] #[must_use] #[rustc_diagnostic_item = "slice_from_raw_parts_mut"] pub const unsafe fn from_raw_parts_mut<'a, T>(data: *mut T, len: usize) -> &'a mut [T] { @@ -205,7 +204,6 @@ pub const fn from_ref(s: &T) -> &[T] { /// Converts a reference to T into a slice of length 1 (without copying). #[stable(feature = "from_ref", since = "1.28.0")] #[rustc_const_stable(feature = "const_slice_from_ref", since = "1.83.0")] -#[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] #[must_use] pub const fn from_mut(s: &mut T) -> &mut [T] { array::from_mut(s) diff --git a/library/core/src/str/converts.rs b/library/core/src/str/converts.rs index b61ed454cd9..c997e5e443d 100644 --- a/library/core/src/str/converts.rs +++ b/library/core/src/str/converts.rs @@ -195,7 +195,6 @@ pub const unsafe fn from_utf8_unchecked(v: &[u8]) -> &str { #[inline] #[must_use] #[stable(feature = "str_mut_extras", since = "1.20.0")] -#[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] #[rustc_const_stable(feature = "const_str_from_utf8_unchecked_mut", since = "1.83.0")] #[rustc_diagnostic_item = "str_from_utf8_unchecked_mut"] pub const unsafe fn from_utf8_unchecked_mut(v: &mut [u8]) -> &mut str { diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs index 09938dda262..89addc4cb74 100644 --- a/library/core/src/str/mod.rs +++ b/library/core/src/str/mod.rs @@ -339,7 +339,6 @@ impl str { /// assert_eq!("πŸ”βˆˆπŸŒ", s); /// ``` #[stable(feature = "str_mut_extras", since = "1.20.0")] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] #[rustc_const_stable(feature = "const_str_as_mut", since = "1.83.0")] #[must_use] #[inline(always)] @@ -386,7 +385,6 @@ impl str { /// It is your responsibility to make sure that the string slice only gets /// modified in a way that it remains valid UTF-8. #[stable(feature = "str_as_mut_ptr", since = "1.36.0")] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] #[rustc_const_stable(feature = "const_str_as_mut", since = "1.83.0")] #[rustc_never_returns_null_ptr] #[must_use] @@ -2477,7 +2475,6 @@ impl str { #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] #[rustc_const_stable(feature = "const_make_ascii", since = "CURRENT_RUSTC_VERSION")] #[inline] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] pub const fn make_ascii_uppercase(&mut self) { // SAFETY: changing ASCII letters only does not invalidate UTF-8. let me = unsafe { self.as_bytes_mut() }; @@ -2506,7 +2503,6 @@ impl str { #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] #[rustc_const_stable(feature = "const_make_ascii", since = "CURRENT_RUSTC_VERSION")] #[inline] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] pub const fn make_ascii_lowercase(&mut self) { // SAFETY: changing ASCII letters only does not invalidate UTF-8. let me = unsafe { self.as_bytes_mut() }; diff --git a/library/core/tests/atomic.rs b/library/core/tests/atomic.rs index 2bdaeb3845a..0ffba538b20 100644 --- a/library/core/tests/atomic.rs +++ b/library/core/tests/atomic.rs @@ -229,7 +229,7 @@ fn static_init() { #[test] // FIXME(static_mut_refs): Do not allow `static_mut_refs` lint -#[cfg_attr(not(bootstrap), allow(static_mut_refs))] +#[allow(static_mut_refs)] fn atomic_access_bool() { static mut ATOMIC: AtomicBool = AtomicBool::new(false); diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index 37e7db1157c..bfc0b638b7e 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -1,5 +1,4 @@ // tidy-alphabetical-start -#![cfg_attr(bootstrap, feature(const_mut_refs))] #![cfg_attr(target_has_atomic = "128", feature(integer_atomics))] #![cfg_attr(test, feature(cfg_match))] #![feature(alloc_layout_extra)] diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index ed448e50e60..3ab65238368 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -279,7 +279,6 @@ // // Language features: // tidy-alphabetical-start -#![cfg_attr(bootstrap, feature(const_mut_refs))] #![feature(alloc_error_handler)] #![feature(allocator_internals)] #![feature(allow_internal_unsafe)] diff --git a/src/tools/miri/src/lib.rs b/src/tools/miri/src/lib.rs index f089d1e1bcc..9814858beaa 100644 --- a/src/tools/miri/src/lib.rs +++ b/src/tools/miri/src/lib.rs @@ -14,6 +14,7 @@ #![feature(strict_provenance)] #![feature(exposed_provenance)] #![feature(pointer_is_aligned_to)] +#![feature(unqualified_local_imports)] // Configure clippy and other lints #![allow( clippy::collapsible_else_if, @@ -42,13 +43,12 @@ )] #![warn( rust_2018_idioms, + unqualified_local_imports, clippy::cast_possible_wrap, // unsigned -> signed clippy::cast_sign_loss, // signed -> unsigned clippy::cast_lossless, clippy::cast_possible_truncation, )] -#![cfg_attr(not(bootstrap), feature(unqualified_local_imports))] -#![cfg_attr(not(bootstrap), warn(unqualified_local_imports))] // Needed for rustdoc from bootstrap (with `-Znormalize-docs`). #![recursion_limit = "256"] diff --git a/tests/ui-fulldeps/internal-lints/import-of-type-ir-inherent.rs b/tests/ui-fulldeps/internal-lints/import-of-type-ir-inherent.rs index 08d86606a6b..a26d00b77ac 100644 --- a/tests/ui-fulldeps/internal-lints/import-of-type-ir-inherent.rs +++ b/tests/ui-fulldeps/internal-lints/import-of-type-ir-inherent.rs @@ -1,8 +1,5 @@ //@ compile-flags: -Z unstable-options -// #[cfg(bootstrap)]: We can stop ignoring next beta bump; afterward this ALWAYS should run. -//@ ignore-stage1 - #![feature(rustc_private)] #![deny(rustc::usage_of_type_ir_inherent)] diff --git a/tests/ui-fulldeps/internal-lints/import-of-type-ir-inherent.stderr b/tests/ui-fulldeps/internal-lints/import-of-type-ir-inherent.stderr index cc6cb9170c0..3326b1047ac 100644 --- a/tests/ui-fulldeps/internal-lints/import-of-type-ir-inherent.stderr +++ b/tests/ui-fulldeps/internal-lints/import-of-type-ir-inherent.stderr @@ -1,18 +1,18 @@ error: do not use `rustc_type_ir::inherent` unless you're inside of the trait solver - --> $DIR/import-of-type-ir-inherent.rs:11:20 + --> $DIR/import-of-type-ir-inherent.rs:8:20 | LL | use rustc_type_ir::inherent::*; | ^^^^^^^^ | = note: the method or struct you're looking for is likely defined somewhere else downstream in the compiler note: the lint level is defined here - --> $DIR/import-of-type-ir-inherent.rs:7:9 + --> $DIR/import-of-type-ir-inherent.rs:4:9 | LL | #![deny(rustc::usage_of_type_ir_inherent)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: do not use `rustc_type_ir::inherent` unless you're inside of the trait solver - --> $DIR/import-of-type-ir-inherent.rs:13:20 + --> $DIR/import-of-type-ir-inherent.rs:10:20 | LL | use rustc_type_ir::inherent; | ^^^^^^^^ @@ -20,7 +20,7 @@ LL | use rustc_type_ir::inherent; = note: the method or struct you're looking for is likely defined somewhere else downstream in the compiler error: do not use `rustc_type_ir::inherent` unless you're inside of the trait solver - --> $DIR/import-of-type-ir-inherent.rs:15:20 + --> $DIR/import-of-type-ir-inherent.rs:12:20 | LL | use rustc_type_ir::inherent::Predicate; | ^^^^^^^^ diff --git a/tests/ui-fulldeps/internal-lints/query_completeness.rs b/tests/ui-fulldeps/internal-lints/query_completeness.rs index 50b0fb4c3fc..791f4599273 100644 --- a/tests/ui-fulldeps/internal-lints/query_completeness.rs +++ b/tests/ui-fulldeps/internal-lints/query_completeness.rs @@ -1,6 +1,4 @@ //@ compile-flags: -Z unstable-options -// #[cfg(bootstrap)]: We can stop ignoring next beta bump; afterward this ALWAYS should run. -//@ ignore-stage1 (requires matching sysroot built with in-tree compiler) #![feature(rustc_private)] #![deny(rustc::untracked_query_information)] diff --git a/tests/ui-fulldeps/internal-lints/query_completeness.stderr b/tests/ui-fulldeps/internal-lints/query_completeness.stderr index 35bb867f40e..e17c2a891cf 100644 --- a/tests/ui-fulldeps/internal-lints/query_completeness.stderr +++ b/tests/ui-fulldeps/internal-lints/query_completeness.stderr @@ -1,12 +1,12 @@ error: `is_stolen` accesses information that is not tracked by the query system - --> $DIR/query_completeness.rs:12:15 + --> $DIR/query_completeness.rs:10:15 | LL | let _ = x.is_stolen(); | ^^^^^^^^^ | = note: if you believe this case to be fine, allow this lint and add a comment explaining your rationale note: the lint level is defined here - --> $DIR/query_completeness.rs:5:9 + --> $DIR/query_completeness.rs:3:9 | LL | #![deny(rustc::untracked_query_information)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -- cgit 1.4.1-3-g733a5