diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs index 80f29511ebb8e..85697b1414f05 100644 --- a/compiler/rustc_target/src/target_features.rs +++ b/compiler/rustc_target/src/target_features.rs @@ -1,6 +1,44 @@ //! Declares Rust's target feature names for each target. //! Note that these are similar to but not always identical to LLVM's feature names, //! and Rust adds some features that do not correspond to LLVM features at all. +//! +//! The target features listed here can be used in `#[target_feature]` and `#[cfg(target_feature)]`. +//! They also do not trigger any warnings when used with `-Ctarget-feature`. +//! +//! Note that even unstable (and even entirely unlisted) features can be used with `-Ctarget-feature` +//! on stable. Using a feature not on the list of Rust target features only emits a warning. +//! Only `cfg(target_feature)` and `#[target_feature]` actually do any stability gating. +//! `cfg(target_feature)` for unstable features just works on nightly without any feature gate. +//! `#[target_feature]` requires a feature gate. +//! +//! When adding features to the below lists +//! check whether they're named already elsewhere in rust +//! e.g. in stdarch and whether the given name matches LLVM's +//! if it doesn't, to_llvm_feature in llvm_util in rustc_codegen_llvm needs to be adapted. +//! Additionally, if the feature is not available in older version of LLVM supported by the current +//! rust, the same function must be updated to filter out these features to avoid triggering +//! warnings. +//! +//! Also note that all target features listed here must be purely additive: for target_feature 1.1 to +//! be sound, we can never allow features like `+soft-float` (on x86) to be controlled on a +//! per-function level, since we would then allow safe calls from functions with `+soft-float` to +//! functions without that feature! +//! +//! It is important for soundness to consider the interaction of target features and the function +//! call ABI. For example, disabling the `x87` feature on x86 changes how scalar floats are passed as +//! arguments, so letting people toggle that feature would be unsound. To this end, the +//! [`Target::abi_required_features`] function computes which target features must and must not be +//! enabled for any given target, and individual features can also be marked as [`Forbidden`]. See +//! for some more context. +//! +//! The one exception to features that change the ABI is features that enable larger vector +//! registers. Those are permitted to be listed here. The `*_FOR_CORRECT_VECTOR_ABI` arrays store +//! information about which target feature is ABI-required for which vector size; this is used to +//! ensure that vectors can only be passed via `extern "C"` when the right feature is enabled. (For +//! the "Rust" ABI we generally pass vectors by-ref exactly to avoid these issues.) +//! Also see . +//! +//! Stabilizing a target feature requires t-lang approval. use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_macros::StableHash; use rustc_span::{Symbol, sym}; @@ -32,9 +70,12 @@ pub enum Stability { Symbol, ), /// This feature can not be set via `-Ctarget-feature` or `#[target_feature]`, it can only be - /// set in the target spec. It is never set in `cfg(target_feature)`. Used in - /// particular for features are actually ABI configuration flags (not all targets are as nice as - /// RISC-V and have an explicit way to set the ABI separate from target features). + /// set in the target spec. It is never set in `cfg(target_feature)`. Used in particular for + /// features are actually ABI configuration flags (such as "soft-float" on many targets). + /// However, "forbidden" target features can still sometimes be enabled via `-Ctarget-cpu` or + /// target feature implications (on the Rust/LLVM level). To prevent that, ABI-relevant target + /// features are ideally pinned down (required or forbidden) in + /// [`Target::abi_required_features`]. Forbidden { reason: &'static str, /// True if this is always an error, false if this can be reported as a warning when set via @@ -102,50 +143,11 @@ impl Stability { } } -// Here we list target features that rustc "understands": they can be used in `#[target_feature]` -// and `#[cfg(target_feature)]`. They also do not trigger any warnings when used with -// `-Ctarget-feature`. -// -// Note that even unstable (and even entirely unlisted) features can be used with `-Ctarget-feature` -// on stable. Using a feature not on the list of Rust target features only emits a warning. -// Only `cfg(target_feature)` and `#[target_feature]` actually do any stability gating. -// `cfg(target_feature)` for unstable features just works on nightly without any feature gate. -// `#[target_feature]` requires a feature gate. -// -// When adding features to the below lists -// check whether they're named already elsewhere in rust -// e.g. in stdarch and whether the given name matches LLVM's -// if it doesn't, to_llvm_feature in llvm_util in rustc_codegen_llvm needs to be adapted. -// Additionally, if the feature is not available in older version of LLVM supported by the current -// rust, the same function must be updated to filter out these features to avoid triggering -// warnings. -// -// Also note that all target features listed here must be purely additive: for target_feature 1.1 to -// be sound, we can never allow features like `+soft-float` (on x86) to be controlled on a -// per-function level, since we would then allow safe calls from functions with `+soft-float` to -// functions without that feature! -// -// It is important for soundness to consider the interaction of targets features and the function -// call ABI. For example, disabling the `x87` feature on x86 changes how scalar floats are passed as -// arguments, so letting people toggle that feature would be unsound. To this end, the -// `abi_required_features` function computes which target features must and must not be enabled for -// any given target, and individual features can also be marked as `Forbidden`. -// See https://github.com/rust-lang/rust/issues/116344 for some more context. -// -// The one exception to features that change the ABI is features that enable larger vector -// registers. Those are permitted to be listed here. The `*_FOR_CORRECT_VECTOR_ABI` arrays store -// information about which target feature is ABI-required for which vector size; this is used to -// ensure that vectors can only be passed via `extern "C"` when the right feature is enabled. (For -// the "Rust" ABI we generally pass vectors by-ref exactly to avoid these issues.) -// Also see https://github.com/rust-lang/rust/issues/116558. -// -// Stabilizing a target feature requires t-lang approval. - -// If feature A "implies" feature B, then: -// - when A gets enabled (via `-Ctarget-feature` or `#[target_feature]`), we also enable B -// - when B gets disabled (via `-Ctarget-feature`), we also disable A -// -// Both of these are also applied transitively. +/// If feature A "implies" feature B, then: +/// - when A gets enabled (via `-Ctarget-feature` or `#[target_feature]`), we also enable B +/// - when B gets disabled (via `-Ctarget-feature`), we also disable A +/// +/// Both of these are also applied transitively. type ImpliedFeatures = &'static [&'static str]; static ARM_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index 3f0c0ab3080c5..f66dc648f809b 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -73,6 +73,7 @@ // Lints: #![deny(unsafe_op_in_unsafe_fn)] #![deny(fuzzy_provenance_casts)] +#![deny(lossy_provenance_casts)] #![warn(deprecated_in_future)] #![warn(missing_debug_implementations)] #![warn(missing_docs)] diff --git a/library/alloctests/benches/lib.rs b/library/alloctests/benches/lib.rs index b7e09fc2e162b..2be7a24d2de7b 100644 --- a/library/alloctests/benches/lib.rs +++ b/library/alloctests/benches/lib.rs @@ -7,6 +7,7 @@ #![feature(strict_provenance_lints)] #![feature(test)] #![deny(fuzzy_provenance_casts)] +#![deny(lossy_provenance_casts)] extern crate test; diff --git a/library/alloctests/tests/boxed.rs b/library/alloctests/tests/boxed.rs index a0c3cb55edcc6..c73b7109fb387 100644 --- a/library/alloctests/tests/boxed.rs +++ b/library/alloctests/tests/boxed.rs @@ -47,9 +47,9 @@ fn box_clone_from_ptr_stability() { for size in (0..8).map(|i| 2usize.pow(i)) { let control = vec![Dummy { _data: 42 }; size].into_boxed_slice(); let mut copy = vec![Dummy { _data: 84 }; size].into_boxed_slice(); - let copy_raw = copy.as_ptr() as usize; + let copy_raw = copy.as_ptr(); copy.clone_from(&control); - assert_eq!(copy.as_ptr() as usize, copy_raw); + assert_eq!(copy.as_ptr(), copy_raw); } } diff --git a/library/alloctests/tests/heap.rs b/library/alloctests/tests/heap.rs index 246b341eeb387..8eb562622c0a4 100644 --- a/library/alloctests/tests/heap.rs +++ b/library/alloctests/tests/heap.rs @@ -25,7 +25,7 @@ fn check_overalign_requests(allocator: T) { .collect(); for &ptr in &pointers { assert_eq!( - (ptr.as_non_null_ptr().as_ptr() as usize) % align, + ptr.as_non_null_ptr().as_ptr().addr() % align, 0, "Got a pointer less aligned than requested" ) diff --git a/library/alloctests/tests/lib.rs b/library/alloctests/tests/lib.rs index 1414835058b9a..b7c3e39c992b0 100644 --- a/library/alloctests/tests/lib.rs +++ b/library/alloctests/tests/lib.rs @@ -44,6 +44,7 @@ #![feature(ptr_cast_slice)] #![allow(internal_features)] #![deny(fuzzy_provenance_casts)] +#![deny(lossy_provenance_casts)] #![deny(unsafe_op_in_unsafe_fn)] extern crate alloc; diff --git a/library/alloctests/tests/sort/tests.rs b/library/alloctests/tests/sort/tests.rs index 09b76773d6b24..ec4c4fa619ddf 100644 --- a/library/alloctests/tests/sort/tests.rs +++ b/library/alloctests/tests/sort/tests.rs @@ -746,7 +746,7 @@ fn self_cmp( pattern_fn(len).into_iter().map(|val| type_into_fn(val)).collect::>(); let comparison_fn = |a: &T, b: &T| { - assert_ne!(a as *const T as usize, b as *const T as usize); + assert_ne!(a as *const T, b as *const T); a.cmp(b) }; diff --git a/library/alloctests/tests/vec.rs b/library/alloctests/tests/vec.rs index 54bdc4c19cfae..ccf9b8095b290 100644 --- a/library/alloctests/tests/vec.rs +++ b/library/alloctests/tests/vec.rs @@ -1110,7 +1110,7 @@ fn test_into_iter_zst() { struct AlignedZstWithDrop([u64; 0]); impl Drop for AlignedZstWithDrop { fn drop(&mut self) { - let addr = self as *mut _ as usize; + let addr = (self as *mut Self).addr(); assert!(hint::black_box(addr) % align_of::() == 0); } } @@ -1356,10 +1356,10 @@ fn overaligned_allocations() { for i in 0..0x1000 { v.reserve_exact(i); assert!(v[0].0 == 273); - assert!(v.as_ptr() as usize & 0xff == 0); + assert!(v.as_ptr().addr() & 0xff == 0); v.shrink_to_fit(); assert!(v[0].0 == 273); - assert!(v.as_ptr() as usize & 0xff == 0); + assert!(v.as_ptr().addr() & 0xff == 0); } } @@ -2574,7 +2574,7 @@ fn test_box_zero_allocator() { unsafe fn deallocate(&self, ptr: NonNull, layout: Layout) { if layout.size() == 0 { - let addr = ptr.as_ptr() as usize; + let addr = ptr.as_ptr().addr(); let mut state = self.state.borrow_mut(); std::println!("freeing {addr}"); assert!(state.0.remove(&addr), "ZST free that wasn't allocated"); diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index b16996acb1c44..1cdf52de8cad8 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -80,6 +80,7 @@ #![deny(rust_2021_incompatible_or_patterns)] #![deny(unsafe_op_in_unsafe_fn)] #![deny(fuzzy_provenance_casts)] +#![deny(lossy_provenance_casts)] #![warn(deprecated_in_future)] #![warn(missing_debug_implementations)] #![warn(missing_docs)] diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index 5cbbebf9f4788..0a7f9b920364a 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -183,6 +183,7 @@ impl *const T { /// [`with_exposed_provenance`]: with_exposed_provenance #[inline(always)] #[stable(feature = "exposed_provenance", since = "1.84.0")] + #[expect(lossy_provenance_casts, reason = "this *is* the replacement")] pub fn expose_provenance(self) -> usize { self.cast::<()>() as usize } diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index ff2c18d685b65..593011edecf27 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -2618,21 +2618,21 @@ impl Ord for F { #[stable(feature = "fnptr_impls", since = "1.4.0")] impl hash::Hash for F { fn hash(&self, state: &mut HH) { - state.write_usize(self.addr() as _) + state.write_usize(self.addr().addr()) } } #[stable(feature = "fnptr_impls", since = "1.4.0")] impl fmt::Pointer for F { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::pointer_fmt_inner(self.addr() as _, f) + fmt::pointer_fmt_inner(self.addr().addr(), f) } } #[stable(feature = "fnptr_impls", since = "1.4.0")] impl fmt::Debug for F { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::pointer_fmt_inner(self.addr() as _, f) + fmt::pointer_fmt_inner(self.addr().addr(), f) } } diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index 53ef7f754d201..4b68d96aeae68 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -174,6 +174,7 @@ impl *mut T { /// [`with_exposed_provenance_mut`]: with_exposed_provenance_mut #[inline(always)] #[stable(feature = "exposed_provenance", since = "1.84.0")] + #[expect(lossy_provenance_casts, reason = "this *is* the replacement")] pub fn expose_provenance(self) -> usize { self.cast::<()>() as usize } diff --git a/library/coretests/tests/char.rs b/library/coretests/tests/char.rs index 877017f682c97..43372005ad5f3 100644 --- a/library/coretests/tests/char.rs +++ b/library/coretests/tests/char.rs @@ -318,7 +318,7 @@ fn test_encode_utf8() { let mut buf = [0; char::MAX_LEN_UTF8]; let ptr = buf.as_ptr(); let s = input.encode_utf8(&mut buf); - assert_eq!(s.as_ptr() as usize, ptr as usize); + assert_eq!(s.as_ptr(), ptr); assert!(str::from_utf8(s.as_bytes()).is_ok()); assert_eq!(s.as_bytes(), expect); } @@ -335,7 +335,7 @@ fn test_encode_utf16() { let mut buf = [0; 2]; let ptr = buf.as_mut_ptr(); let b = input.encode_utf16(&mut buf); - assert_eq!(b.as_mut_ptr() as usize, ptr as usize); + assert_eq!(b.as_mut_ptr(), ptr); assert_eq!(b, expect); } diff --git a/library/coretests/tests/lib.rs b/library/coretests/tests/lib.rs index 89e8d5d8185ee..aa6aa1478bd70 100644 --- a/library/coretests/tests/lib.rs +++ b/library/coretests/tests/lib.rs @@ -129,6 +129,7 @@ // tidy-alphabetical-end #![allow(internal_features)] #![deny(fuzzy_provenance_casts)] +#![deny(lossy_provenance_casts)] #![deny(unsafe_op_in_unsafe_fn)] /// Version of `assert_matches` that ignores fancy runtime printing in const context and uses structural equality. diff --git a/library/coretests/tests/ptr.rs b/library/coretests/tests/ptr.rs index 93f9454d71378..9dbaf6690c81c 100644 --- a/library/coretests/tests/ptr.rs +++ b/library/coretests/tests/ptr.rs @@ -384,7 +384,7 @@ fn align_offset_stride_one() { #[test] fn align_offset_various_strides() { unsafe fn test_stride(ptr: *const T, align: usize) -> bool { - let numptr = ptr as usize; + let numptr = ptr.addr(); let mut expected = usize::MAX; // Naive but definitely correct way to find the *first* aligned element of stride::. for el in 0..align { diff --git a/library/coretests/tests/slice.rs b/library/coretests/tests/slice.rs index 2bb62f36bb0e6..a4db7304fff90 100644 --- a/library/coretests/tests/slice.rs +++ b/library/coretests/tests/slice.rs @@ -1886,7 +1886,7 @@ fn test_align_to_empty_mid() { type Chunk = u32; for offset in 0..4 { let (_, mid, _) = unsafe { bytes[offset..offset + 1].align_to::() }; - assert_eq!(mid.as_ptr() as usize % align_of::(), 0); + assert_eq!(mid.as_ptr().addr() % align_of::(), 0); } } diff --git a/library/coretests/tests/waker.rs b/library/coretests/tests/waker.rs index 4889b8959ece4..be8b07b8ad009 100644 --- a/library/coretests/tests/waker.rs +++ b/library/coretests/tests/waker.rs @@ -5,16 +5,16 @@ use std::task::{RawWaker, RawWakerVTable, Waker}; fn test_waker_getters() { let raw_waker = RawWaker::new(ptr::without_provenance_mut(42usize), &WAKER_VTABLE); let waker = unsafe { Waker::from_raw(raw_waker) }; - assert_eq!(waker.data() as usize, 42); + assert_eq!(waker.data().addr(), 42); assert!(ptr::eq(waker.vtable(), &WAKER_VTABLE)); let waker2 = waker.clone(); - assert_eq!(waker2.data() as usize, 43); + assert_eq!(waker2.data().addr(), 43); assert!(ptr::eq(waker2.vtable(), &WAKER_VTABLE)); } static WAKER_VTABLE: RawWakerVTable = RawWakerVTable::new( - |data| RawWaker::new(ptr::without_provenance_mut(data as usize + 1), &WAKER_VTABLE), + |data| RawWaker::new(ptr::without_provenance_mut(data.addr() + 1), &WAKER_VTABLE), |_| {}, |_| {}, |_| {}, diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 8086cab34cf44..addbb407083c7 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -246,6 +246,7 @@ #![allow(unused_lifetimes)] #![allow(internal_features)] #![deny(fuzzy_provenance_casts)] +#![deny(lossy_provenance_casts)] #![deny(unsafe_op_in_unsafe_fn)] #![allow(rustdoc::redundant_explicit_links)] #![warn(rustdoc::unescaped_backticks)] @@ -723,7 +724,13 @@ pub mod alloc; mod panicking; #[path = "../../backtrace/src/lib.rs"] -#[allow(dead_code, unused_attributes, fuzzy_provenance_casts, unsafe_op_in_unsafe_fn)] +#[allow( + dead_code, + unused_attributes, + fuzzy_provenance_casts, + lossy_provenance_casts, + unsafe_op_in_unsafe_fn +)] mod backtrace_rs; #[stable(feature = "cfg_select", since = "1.95.0")] diff --git a/library/std/src/os/unix/thread.rs b/library/std/src/os/unix/thread.rs index 32085e525942e..efb349b18d6b5 100644 --- a/library/std/src/os/unix/thread.rs +++ b/library/std/src/os/unix/thread.rs @@ -31,10 +31,15 @@ pub trait JoinHandleExt { #[stable(feature = "thread_extensions", since = "1.9.0")] impl JoinHandleExt for JoinHandle { + // This is an int2ptr cast on some platforms (e.g., *-musl) where RawPthread + // is an integer but libc::pthread_t is a pointer. Exposed provenance is the + // safe choice here, but `as` also works when it's int2int or ptr2ptr. + #[allow(lossy_provenance_casts)] fn as_pthread_t(&self) -> RawPthread { self.as_inner().id() as RawPthread } + #[allow(lossy_provenance_casts)] // see above for why fn into_pthread_t(self) -> RawPthread { self.into_inner().into_id() as RawPthread } diff --git a/library/std/src/random.rs b/library/std/src/random.rs index a18dcf98ec7fc..8274060e5cedf 100644 --- a/library/std/src/random.rs +++ b/library/std/src/random.rs @@ -16,6 +16,8 @@ use crate::sys::random as sys; /// security is not a concern, consider using an alternative random number /// generator (potentially seeded from this one). /// +/// If you need to fill a buffer with random bytes, use `DefaultRandomSource.fill_bytes(&mut buf)`. +/// /// # Underlying sources /// /// Platform | Source @@ -54,6 +56,7 @@ use crate::sys::random as sys; /// /// [`getrandom`]: https://www.man7.org/linux/man-pages/man2/getrandom.2.html /// [`/dev/urandom`]: https://www.man7.org/linux/man-pages/man4/random.4.html +#[doc(alias = "getrandom", alias = "getentropy", alias = "arc4random")] #[derive(Default, Debug, Clone, Copy)] #[unstable(feature = "random", issue = "130703")] pub struct DefaultRandomSource; diff --git a/library/std/src/sync/mpmc/select.rs b/library/std/src/sync/mpmc/select.rs index 56a83fee2e119..ff537aa686157 100644 --- a/library/std/src/sync/mpmc/select.rs +++ b/library/std/src/sync/mpmc/select.rs @@ -22,7 +22,7 @@ impl Operation { /// and is alive for the entire duration of a blocking operation. #[inline] pub fn hook(r: &mut T) -> Operation { - let val = r as *mut T as usize; + let val = (r as *mut T).addr(); // Make sure that the pointer address doesn't equal the numerical representation of // `Selected::{Waiting, Aborted, Disconnected}`. assert!(val > 2); diff --git a/library/std/src/sync/mpmc/zero.rs b/library/std/src/sync/mpmc/zero.rs index c743462501922..4f645e16fbb6f 100644 --- a/library/std/src/sync/mpmc/zero.rs +++ b/library/std/src/sync/mpmc/zero.rs @@ -25,7 +25,7 @@ impl Default for ZeroToken { impl fmt::Debug for ZeroToken { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Debug::fmt(&(self.0 as usize), f) + fmt::Debug::fmt(&self.0.addr(), f) } } diff --git a/library/std/src/sys/args/sgx.rs b/library/std/src/sys/args/sgx.rs index 6ff94f5681b6f..9403059e7c607 100644 --- a/library/std/src/sys/args/sgx.rs +++ b/library/std/src/sys/args/sgx.rs @@ -1,4 +1,5 @@ -#![allow(fuzzy_provenance_casts)] // FIXME: this module systematically confuses pointers and integers +// FIXME: this module systematically confuses pointers and integers +#![allow(fuzzy_provenance_casts, lossy_provenance_casts)] use crate::ffi::OsString; use crate::num::NonZero; diff --git a/library/std/src/sys/env/sgx.rs b/library/std/src/sys/env/sgx.rs index 09090ec7cf0dd..0c19fcc848f4d 100644 --- a/library/std/src/sys/env/sgx.rs +++ b/library/std/src/sys/env/sgx.rs @@ -1,4 +1,5 @@ -#![allow(fuzzy_provenance_casts)] // FIXME: this module systematically confuses pointers and integers +// FIXME: this module systematically confuses pointers and integers +#![allow(fuzzy_provenance_casts, lossy_provenance_casts)] pub use super::common::Env; use crate::collections::HashMap; diff --git a/library/std/src/sys/pal/sgx/mod.rs b/library/std/src/sys/pal/sgx/mod.rs index 2b284cc40b94b..7b2c8e5a8024a 100644 --- a/library/std/src/sys/pal/sgx/mod.rs +++ b/library/std/src/sys/pal/sgx/mod.rs @@ -3,7 +3,8 @@ //! This module contains the facade (aka platform-specific) implementations of //! OS level functionality for Fortanix SGX. #![deny(unsafe_op_in_unsafe_fn)] -#![allow(fuzzy_provenance_casts)] // FIXME: this entire module systematically confuses pointers and integers +// FIXME: this entire module systematically confuses pointers and integers +#![allow(fuzzy_provenance_casts, lossy_provenance_casts)] use crate::io; use crate::sync::atomic::{Atomic, AtomicBool, Ordering}; diff --git a/library/std/src/sys/thread_local/key/tests.rs b/library/std/src/sys/thread_local/key/tests.rs index c7d2c8e6301ef..5e5243d9835ed 100644 --- a/library/std/src/sys/thread_local/key/tests.rs +++ b/library/std/src/sys/thread_local/key/tests.rs @@ -18,8 +18,8 @@ fn smoke() { assert!(get(k2).is_null()); set(k1, ptr::without_provenance_mut(1)); set(k2, ptr::without_provenance_mut(2)); - assert_eq!(get(k1) as usize, 1); - assert_eq!(get(k2) as usize, 2); + assert_eq!(get(k1).addr(), 1); + assert_eq!(get(k2).addr(), 2); } } diff --git a/library/std/src/thread/tests.rs b/library/std/src/thread/tests.rs index 4b934c039a36f..78b6f7c35e8db 100644 --- a/library/std/src/thread/tests.rs +++ b/library/std/src/thread/tests.rs @@ -152,11 +152,11 @@ where { let (tx, rx) = channel(); - let x: Box<_> = Box::new(1); - let x_in_parent = (&*x) as *const i32 as usize; + let x: Box = Box::new(1); + let x_in_parent = (&raw const *x).addr(); spawnfn(Box::new(move || { - let x_in_child = (&*x) as *const i32 as usize; + let x_in_child = (&raw const *x).addr(); tx.send(x_in_child).unwrap(); })); diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs index 68a4f928464f1..3b497e1db923c 100644 --- a/src/bootstrap/src/core/build_steps/compile.rs +++ b/src/bootstrap/src/core/build_steps/compile.rs @@ -1999,12 +1999,16 @@ impl Step for Sysroot { } // Copy the compiler into the correct sysroot. - // NOTE(#108767): We intentionally don't copy `rustc-dev` artifacts until they're requested with `builder.ensure(Rustc)`. - // This fixes an issue where we'd have multiple copies of libc in the sysroot with no way to tell which to load. - // There are a few quirks of bootstrap that interact to make this reliable: + // + // FIXME(#156525): investigate if this is still needed. + // + // NOTE(#108767): We intentionally don't copy `rustc-dev` artifacts until they're + // requested with `builder.ensure(Rustc)`. This fixes an issue where we'd have multiple + // copies of libc in the sysroot with no way to tell which to load. There are a few + // quirks of bootstrap that interact to make this reliable: // 1. The order `Step`s are run is hard-coded in `builder.rs` and not configurable. This - // avoids e.g. reordering `test::UiFulldeps` before `test::Ui` and causing the latter to - // fail because of duplicate metadata. + // avoids e.g. reordering `test::UiFulldeps` before `test::Ui` and causing the latter + // to fail because of duplicate metadata. // 2. The sysroot is deleted and recreated between each invocation, so running `x test // ui-fulldeps && x test ui` can't cause failures. let mut filtered_files = Vec::new(); diff --git a/src/bootstrap/src/core/build_steps/run.rs b/src/bootstrap/src/core/build_steps/run.rs index 2329bb93b4d3d..935844daa9d7c 100644 --- a/src/bootstrap/src/core/build_steps/run.rs +++ b/src/bootstrap/src/core/build_steps/run.rs @@ -510,7 +510,7 @@ impl Step for Rustfmt { let compilers = RustcPrivateCompilers::new(builder, stage, host); let rustfmt_build = builder.ensure(tool::Rustfmt::from_compilers(compilers)); - let mut rustfmt = tool::prepare_tool_cargo( + let mut cargo = tool::prepare_tool_cargo( builder, rustfmt_build.build_compiler, Mode::ToolRustcPrivate, @@ -521,10 +521,10 @@ impl Step for Rustfmt { &[], ); - rustfmt.args(["--bin", "rustfmt", "--"]); - rustfmt.args(builder.config.args()); + cargo.args(["--bin", "rustfmt", "--"]); + cargo.args(builder.config.args()); - rustfmt.into_cmd().run(builder); + cargo.into_cmd().run(builder); } } diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index c28fe4ad832d3..fb45fcf5dcc42 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -579,6 +579,11 @@ impl Step for Rustfmt { let build_compiler = self.compilers.build_compiler(); let target = self.compilers.target(); + // FIXME(#156525): `compile::Sysroot::run` intentionally do not copy `rustc-dev` artifacts + // until they're requested with `builder.ensure(Rustc)`, relevant for `download-rustc` + // flows. + builder.ensure(compile::Rustc::new(build_compiler, target)); + let mut cargo = tool::prepare_tool_cargo( builder, build_compiler, @@ -941,6 +946,11 @@ impl Step for Clippy { let target_compiler = self.compilers.target_compiler(); let build_compiler = self.compilers.build_compiler(); + // FIXME(#156525): `compile::Sysroot::run` intentionally do not copy `rustc-dev` artifacts + // until they're requested with `builder.ensure(Rustc)`, relevant for `download-rustc` + // flows. + builder.ensure(compile::Rustc::new(build_compiler, target)); + let mut cargo = tool::prepare_tool_cargo( builder, build_compiler, diff --git a/src/bootstrap/src/core/build_steps/tool.rs b/src/bootstrap/src/core/build_steps/tool.rs index ed5c2586a5ed6..a75d5e4db8998 100644 --- a/src/bootstrap/src/core/build_steps/tool.rs +++ b/src/bootstrap/src/core/build_steps/tool.rs @@ -224,6 +224,12 @@ pub fn prepare_tool_cargo( // avoid rebuilding when running tests. cargo.env("SYSROOT", builder.sysroot(compiler)); + // Make sure we explicitly add rustc_private libs to path centrally here so that + // RustcPrivate tools can pick them up. + if mode == Mode::ToolRustcPrivate { + cargo.add_rustc_lib_path(builder); + } + // if tools are using lzma we want to force the build script to build its // own copy cargo.env("LZMA_API_STATIC", "1"); diff --git a/src/ci/scripts/free-disk-space-linux.sh b/src/ci/scripts/free-disk-space-linux.sh index 590e594e6aef4..167abf01ac880 100755 --- a/src/ci/scripts/free-disk-space-linux.sh +++ b/src/ci/scripts/free-disk-space-linux.sh @@ -277,6 +277,10 @@ cleanPackages() { fi WAIT_DPKG_LOCK="-o DPkg::Lock::Timeout=60" + # This update is intended to fix any broken state of the index and make + # sure it is fresh. Otherwise we've had problems with missing mirror + # entries. + sudo apt-get update -qq sudo apt-get ${WAIT_DPKG_LOCK} -qq remove -y --fix-missing "${packages[@]}" sudo apt-get ${WAIT_DPKG_LOCK} autoremove -y \ diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 901a7fd340afe..42845124eda50 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1089,7 +1089,13 @@ fn clean_fn_or_proc_macro<'tcx>( match macro_kind { Some(kind) => clean_proc_macro(item, name, kind, cx.tcx), None => { - let mut func = clean_function(cx, sig, generics, ParamsSrc::Body(body_id)); + let mut func = clean_function( + cx, + sig, + generics, + ParamsSrc::Body(body_id), + item.owner_id.to_def_id(), + ); clean_fn_decl_legacy_const_generics(&mut func, attrs); FunctionItem(func) } @@ -1127,18 +1133,30 @@ fn clean_function<'tcx>( sig: &hir::FnSig<'tcx>, generics: &hir::Generics<'tcx>, params: ParamsSrc<'tcx>, + def_id: DefId, ) -> Box { let (generics, decl) = enter_impl_trait(cx, |cx| { // NOTE: Generics must be cleaned before params. let generics = clean_generics(generics, cx); - let params = match params { - ParamsSrc::Body(body_id) => clean_params_via_body(cx, sig.decl.inputs, body_id), - // Let's not perpetuate anon params from Rust 2015; use `_` for them. - ParamsSrc::Idents(idents) => clean_params(cx, sig.decl.inputs, idents, |ident| { - Some(ident.map_or(kw::Underscore, |ident| ident.name)) - }), + let decl = if sig.decl.opt_delegation_sig_id().is_some() { + // A delegation item (`reuse path::method`) has no resolved signature in the + // HIR: its inputs and return type are `InferDelegation` nodes that clean to + // `_`, and an `async` header over that inferred return type would panic in + // `sugared_async_return_type`. The resolved signature only exists on the ty + // side, so clean that instead, exactly like an inlined item. This both fixes + // the rendered `-> _` / `self: _` and makes the async sugaring well-defined. + let sig = cx.tcx.fn_sig(def_id).instantiate_identity().skip_norm_wip(); + clean_poly_fn_sig(cx, Some(def_id), sig) + } else { + let params = match params { + ParamsSrc::Body(body_id) => clean_params_via_body(cx, sig.decl.inputs, body_id), + // Let's not perpetuate anon params from Rust 2015; use `_` for them. + ParamsSrc::Idents(idents) => clean_params(cx, sig.decl.inputs, idents, |ident| { + Some(ident.map_or(kw::Underscore, |ident| ident.name)) + }), + }; + clean_fn_decl_with_params(cx, sig.decl, Some(&sig.header), params) }; - let decl = clean_fn_decl_with_params(cx, sig.decl, Some(&sig.header), params); (generics, decl) }); Box::new(Function { decl, generics }) @@ -1270,11 +1288,18 @@ fn clean_trait_item<'tcx>(trait_item: &hir::TraitItem<'tcx>, cx: &mut DocContext RequiredAssocConstItem(generics, Box::new(clean_ty(ty, cx))) } hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Provided(body)) => { - let m = clean_function(cx, sig, trait_item.generics, ParamsSrc::Body(body)); + let m = + clean_function(cx, sig, trait_item.generics, ParamsSrc::Body(body), local_did); MethodItem(m, Defaultness::from_trait_item(trait_item.defaultness)) } hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Required(idents)) => { - let m = clean_function(cx, sig, trait_item.generics, ParamsSrc::Idents(idents)); + let m = clean_function( + cx, + sig, + trait_item.generics, + ParamsSrc::Idents(idents), + local_did, + ); RequiredMethodItem(m, Defaultness::from_trait_item(trait_item.defaultness)) } hir::TraitItemKind::Type(bounds, Some(default)) => { @@ -1315,7 +1340,7 @@ pub(crate) fn clean_impl_item<'tcx>( type_: clean_ty(ty, cx), })), hir::ImplItemKind::Fn(ref sig, body) => { - let m = clean_function(cx, sig, impl_.generics, ParamsSrc::Body(body)); + let m = clean_function(cx, sig, impl_.generics, ParamsSrc::Body(body), local_did); let defaultness = match impl_.impl_kind { hir::ImplItemImplKind::Inherent { .. } => hir::Defaultness::Final, hir::ImplItemImplKind::Trait { defaultness, .. } => defaultness, @@ -3254,7 +3279,7 @@ fn clean_maybe_renamed_foreign_item<'tcx>( cx.with_param_env(def_id, |cx| { let kind = match item.kind { hir::ForeignItemKind::Fn(sig, idents, generics) => ForeignFunctionItem( - clean_function(cx, &sig, generics, ParamsSrc::Idents(idents)), + clean_function(cx, &sig, generics, ParamsSrc::Idents(idents), def_id), sig.header.safety(), ), hir::ForeignItemKind::Static(ty, mutability, safety) => ForeignStaticItem( diff --git a/tests/rustdoc-html/async/async-fn-delegation.rs b/tests/rustdoc-html/async/async-fn-delegation.rs new file mode 100644 index 0000000000000..7d891ac8be637 --- /dev/null +++ b/tests/rustdoc-html/async/async-fn-delegation.rs @@ -0,0 +1,42 @@ +//@ edition: 2021 + +// Regression test for . +// +// rustdoc used to ICE with "unexpected async fn return type" when cleaning a +// delegated (`reuse`) async fn: the delegation's HIR signature is unresolved +// (`InferDelegation`), so its return type cleaned to `_` even though the header +// is `async`, and unconditionally sugaring that inferred type panicked. +// +// We now clean the resolved (ty-side) signature for delegation items, like we +// already do for inlined items. That both avoids the ICE and renders the real +// return type and `self` parameter instead of `-> _` / `self: _`. +// +// Note: the `` generic on the free-function variants is a pre-existing +// quirk of how delegation generics are rendered (plain sync delegation prints it +// too); it is tracked separately and is not what this test is about. + +#![feature(fn_delegation)] +#![allow(incomplete_features)] +#![crate_name = "async_delegation"] + +pub trait Trait { + async fn unit(&self) {} + async fn nonunit(&self) -> i32 { + 0 + } +} + +//@ has async_delegation/fn.unit.html '//pre[@class="rust item-decl"]' 'pub async fn unit(&self)' +pub reuse Trait::unit; +//@ has async_delegation/fn.nonunit.html '//pre[@class="rust item-decl"]' 'pub async fn nonunit(&self) -> i32' +pub reuse Trait::nonunit; + +pub struct S; +impl Trait for S {} + +//@ has async_delegation/struct.S.html '//*[@class="code-header"]' 'pub async fn unit(self: &S)' +//@ has async_delegation/struct.S.html '//*[@class="code-header"]' 'pub async fn nonunit(self: &S) -> i32' +impl S { + pub reuse Trait::unit { self } + pub reuse Trait::nonunit { self } +}