diff --git a/compiler/rustc_abi/src/callconv.rs b/compiler/rustc_abi/src/callconv.rs index 2ecac8a9df1c6..872cae59a4e03 100644 --- a/compiler/rustc_abi/src/callconv.rs +++ b/compiler/rustc_abi/src/callconv.rs @@ -3,18 +3,23 @@ mod abi { pub(crate) use crate::Variants; } +#[cfg(feature = "nightly")] use rustc_macros::HashStable_Generic; -use crate::{Abi, Align, FieldsShape, HasDataLayout, Size, TyAbiInterface, TyAndLayout}; +#[cfg(feature = "nightly")] +use crate::{Abi, FieldsShape, TyAbiInterface, TyAndLayout}; +use crate::{Align, HasDataLayout, Size}; -#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)] +#[cfg_attr(feature = "nightly", derive(HashStable_Generic))] +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] pub enum RegKind { Integer, Float, Vector, } -#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)] +#[cfg_attr(feature = "nightly", derive(HashStable_Generic))] +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] pub struct Reg { pub kind: RegKind, pub size: Size, @@ -108,15 +113,8 @@ impl HomogeneousAggregate { } } +#[cfg(feature = "nightly")] impl<'a, Ty> TyAndLayout<'a, Ty> { - /// Returns `true` if this is an aggregate type (including a ScalarPair!) - pub fn is_aggregate(&self) -> bool { - match self.abi { - Abi::Uninhabited | Abi::Scalar(_) | Abi::Vector { .. } => false, - Abi::ScalarPair(..) | Abi::Aggregate { .. } => true, - } - } - /// Returns `Homogeneous` if this layout is an aggregate containing fields of /// only a single type (e.g., `(u32, u32)`). Such aggregates are often /// special-cased in ABIs. diff --git a/compiler/rustc_abi/src/layout.rs b/compiler/rustc_abi/src/layout.rs index 59f42425bb936..0340d1bd6bcd1 100644 --- a/compiler/rustc_abi/src/layout.rs +++ b/compiler/rustc_abi/src/layout.rs @@ -11,8 +11,10 @@ use crate::{ Variants, WrappingRange, }; +#[cfg(feature = "nightly")] mod ty; +#[cfg(feature = "nightly")] pub use ty::{FIRST_VARIANT, FieldIdx, Layout, TyAbiInterface, TyAndLayout, VariantIdx}; // A variant is absent if it's uninhabited and only has ZST fields. diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index 84d756b6d517c..8e90130da4c01 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -29,14 +29,14 @@ mod layout; mod tests; pub use callconv::{Heterogeneous, HomogeneousAggregate, Reg, RegKind}; -pub use layout::{ - FIRST_VARIANT, FieldIdx, Layout, LayoutCalculator, LayoutCalculatorError, TyAbiInterface, - TyAndLayout, VariantIdx, -}; +#[cfg(feature = "nightly")] +pub use layout::{FIRST_VARIANT, FieldIdx, Layout, TyAbiInterface, TyAndLayout, VariantIdx}; +pub use layout::{LayoutCalculator, LayoutCalculatorError}; /// Requirements for a `StableHashingContext` to be used in this crate. /// This is a hack to allow using the `HashStable_Generic` derive macro /// instead of implementing everything in `rustc_middle`. +#[cfg(feature = "nightly")] pub trait HashStableContext {} #[derive(Clone, Copy, PartialEq, Eq, Default)] @@ -1644,6 +1644,14 @@ pub struct LayoutS { } impl LayoutS { + /// Returns `true` if this is an aggregate type (including a ScalarPair!) + pub fn is_aggregate(&self) -> bool { + match self.abi { + Abi::Uninhabited | Abi::Scalar(_) | Abi::Vector { .. } => false, + Abi::ScalarPair(..) | Abi::Aggregate { .. } => true, + } + } + pub fn scalar(cx: &C, scalar: Scalar) -> Self { let largest_niche = Niche::from_scalar(cx, Size::ZERO, scalar); let size = scalar.size(cx); diff --git a/compiler/rustc_arena/src/lib.rs b/compiler/rustc_arena/src/lib.rs index cecf223b96193..4d8525989cc59 100644 --- a/compiler/rustc_arena/src/lib.rs +++ b/compiler/rustc_arena/src/lib.rs @@ -23,7 +23,6 @@ #![feature(maybe_uninit_slice)] #![feature(rustc_attrs)] #![feature(rustdoc_internals)] -#![feature(strict_provenance)] #![warn(unreachable_pub)] // tidy-alphabetical-end diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs index cbd95146294f5..73bfa9dbd10e2 100644 --- a/compiler/rustc_codegen_ssa/src/lib.rs +++ b/compiler/rustc_codegen_ssa/src/lib.rs @@ -11,7 +11,6 @@ #![feature(let_chains)] #![feature(negative_impls)] #![feature(rustdoc_internals)] -#![feature(strict_provenance)] #![feature(trait_alias)] #![feature(try_blocks)] #![warn(unreachable_pub)] diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs index a132ca6954050..82fea4c58e191 100644 --- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs +++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs @@ -361,12 +361,16 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { (Int(..) | Float(_), Int(..) | Float(_)) => bx.bitcast(imm, to_backend_ty), (Pointer(..), Pointer(..)) => bx.pointercast(imm, to_backend_ty), (Int(..), Pointer(..)) => bx.ptradd(bx.const_null(bx.type_ptr()), imm), - (Pointer(..), Int(..)) => bx.ptrtoint(imm, to_backend_ty), + (Pointer(..), Int(..)) => { + // FIXME: this exposes the provenance, which shouldn't be necessary. + bx.ptrtoint(imm, to_backend_ty) + } (Float(_), Pointer(..)) => { let int_imm = bx.bitcast(imm, bx.cx().type_isize()); bx.ptradd(bx.const_null(bx.type_ptr()), int_imm) } (Pointer(..), Float(_)) => { + // FIXME: this exposes the provenance, which shouldn't be necessary. let int_imm = bx.ptrtoint(imm, bx.cx().type_isize()); bx.bitcast(int_imm, to_backend_ty) } diff --git a/compiler/rustc_const_eval/src/lib.rs b/compiler/rustc_const_eval/src/lib.rs index 39e2d3b4ebbb1..0490195caf4f9 100644 --- a/compiler/rustc_const_eval/src/lib.rs +++ b/compiler/rustc_const_eval/src/lib.rs @@ -10,7 +10,6 @@ #![feature(never_type)] #![feature(rustdoc_internals)] #![feature(slice_ptr_get)] -#![feature(strict_provenance)] #![feature(trait_alias)] #![feature(try_blocks)] #![feature(unqualified_local_imports)] diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs index fba2707922bcd..afac08ae6f818 100644 --- a/compiler/rustc_data_structures/src/lib.rs +++ b/compiler/rustc_data_structures/src/lib.rs @@ -33,7 +33,6 @@ #![feature(ptr_alignment_type)] #![feature(rustc_attrs)] #![feature(rustdoc_internals)] -#![feature(strict_provenance)] #![feature(test)] #![feature(thread_id_value)] #![feature(type_alias_impl_trait)] diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index fc3696c402265..f4795c75e4834 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -595,7 +595,7 @@ declare_features! ( /// Allows attributes on expressions and non-item statements. (unstable, stmt_expr_attributes, "1.6.0", Some(15701)), /// Allows lints part of the strict provenance effort. - (unstable, strict_provenance, "1.61.0", Some(95228)), + (unstable, strict_provenance_lints, "1.61.0", Some(130351)), /// Allows string patterns to dereference values to match them. (unstable, string_deref_patterns, "1.67.0", Some(87121)), /// Allows the use of `#[target_feature]` on safe functions. diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index c11571182fe21..ffbe5363897dc 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -2667,7 +2667,6 @@ declare_lint! { /// ### Example /// /// ```rust - /// #![feature(strict_provenance)] /// #![warn(fuzzy_provenance_casts)] /// /// fn main() { @@ -2701,7 +2700,7 @@ declare_lint! { pub FUZZY_PROVENANCE_CASTS, Allow, "a fuzzy integer to pointer cast is used", - @feature_gate = strict_provenance; + @feature_gate = strict_provenance_lints; } declare_lint! { @@ -2711,7 +2710,6 @@ declare_lint! { /// ### Example /// /// ```rust - /// #![feature(strict_provenance)] /// #![warn(lossy_provenance_casts)] /// /// fn main() { @@ -2747,7 +2745,7 @@ declare_lint! { pub LOSSY_PROVENANCE_CASTS, Allow, "a lossy pointer to integer cast is used", - @feature_gate = strict_provenance; + @feature_gate = strict_provenance_lints; } declare_lint! { diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs index e9b73d25ba208..04a06ba7464cb 100644 --- a/compiler/rustc_middle/src/lib.rs +++ b/compiler/rustc_middle/src/lib.rs @@ -56,7 +56,6 @@ #![feature(ptr_alignment_type)] #![feature(rustc_attrs)] #![feature(rustdoc_internals)] -#![feature(strict_provenance)] #![feature(trait_upcasting)] #![feature(trusted_len)] #![feature(try_blocks)] diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs index f49f3a1a3bf04..71ce0cce77224 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs @@ -16,7 +16,7 @@ use rustc_type_ir::fold::TypeFoldable; use rustc_type_ir::inherent::*; use rustc_type_ir::relate::solver_relating::RelateExt; use rustc_type_ir::{self as ty, Canonical, CanonicalVarValues, InferCtxtLike, Interner}; -use tracing::{instrument, trace}; +use tracing::{debug, instrument, trace}; use crate::canonicalizer::{CanonicalizeMode, Canonicalizer}; use crate::delegate::SolverDelegate; @@ -165,12 +165,22 @@ where // HACK: We bail with overflow if the response would have too many non-region // inference variables. This tends to only happen if we encounter a lot of // ambiguous alias types which get replaced with fresh inference variables - // during generalization. This prevents a hang in nalgebra. - let num_non_region_vars = canonical.variables.iter().filter(|c| !c.is_region()).count(); - if num_non_region_vars > self.cx().recursion_limit() { - return Ok(self.make_ambiguous_response_no_constraints(MaybeCause::Overflow { - suggest_increasing_limit: true, - })); + // during generalization. This prevents hangs caused by an exponential blowup, + // see tests/ui/traits/next-solver/coherence-alias-hang.rs. + // + // We don't do so for `NormalizesTo` goals as we erased the expected term and + // bailing with overflow here would prevent us from detecting a type-mismatch, + // causing a coherence error in diesel, see #131969. We still bail with verflow + // when later returning from the parent AliasRelate goal. + if !self.is_normalizes_to_goal { + let num_non_region_vars = + canonical.variables.iter().filter(|c| !c.is_region() && c.is_existential()).count(); + if num_non_region_vars > self.cx().recursion_limit() { + debug!(?num_non_region_vars, "too many inference variables -> overflow"); + return Ok(self.make_ambiguous_response_no_constraints(MaybeCause::Overflow { + suggest_increasing_limit: true, + })); + } } Ok(canonical) diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 6f62b4f82d76e..3ab482072b8f4 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1913,7 +1913,7 @@ symbols! { str_trim, str_trim_end, str_trim_start, - strict_provenance, + strict_provenance_lints, string_as_mut_str, string_as_str, string_deref_patterns, diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index f4a2483cebf87..f8fb297e36c4b 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -298,6 +298,7 @@ fn equate_impl_headers<'tcx>( } /// The result of [fn impl_intersection_has_impossible_obligation]. +#[derive(Debug)] enum IntersectionHasImpossibleObligations<'tcx> { Yes, No { @@ -328,6 +329,7 @@ enum IntersectionHasImpossibleObligations<'tcx> { /// of the two impls above to be empty. /// /// Importantly, this works even if there isn't a `impl !Error for MyLocalType`. +#[instrument(level = "debug", skip(selcx), ret)] fn impl_intersection_has_impossible_obligation<'a, 'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligations: &'a [PredicateObligation<'tcx>], diff --git a/library/alloc/benches/lib.rs b/library/alloc/benches/lib.rs index ae9608ec7bd5c..c1907361f93e1 100644 --- a/library/alloc/benches/lib.rs +++ b/library/alloc/benches/lib.rs @@ -4,7 +4,8 @@ #![feature(iter_next_chunk)] #![feature(repr_simd)] #![feature(slice_partition_dedup)] -#![feature(strict_provenance)] +#![cfg_attr(bootstrap, feature(strict_provenance))] +#![cfg_attr(not(bootstrap), feature(strict_provenance_lints))] #![feature(test)] #![deny(fuzzy_provenance_casts)] diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index ae9b3739858cb..50a5f3c5b1e04 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -147,7 +147,6 @@ #![feature(slice_range)] #![feature(std_internals)] #![feature(str_internals)] -#![feature(strict_provenance)] #![feature(trusted_fused)] #![feature(trusted_len)] #![feature(trusted_random_access)] @@ -162,6 +161,8 @@ // // Language features: // tidy-alphabetical-start +#![cfg_attr(bootstrap, feature(strict_provenance))] +#![cfg_attr(not(bootstrap), feature(strict_provenance_lints))] #![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 301126b5d4d34..699a8e6776e6d 100644 --- a/library/alloc/tests/lib.rs +++ b/library/alloc/tests/lib.rs @@ -32,7 +32,8 @@ #![feature(panic_update_hook)] #![feature(pointer_is_aligned_to)] #![feature(thin_box)] -#![feature(strict_provenance)] +#![cfg_attr(bootstrap, feature(strict_provenance))] +#![cfg_attr(not(bootstrap), feature(strict_provenance_lints))] #![feature(drain_keep_rest)] #![feature(local_waker)] #![feature(vec_pop_if)] diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index 38e858626b94b..97e727633c5fa 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -2794,7 +2794,6 @@ where /// #![feature(is_val_statically_known)] /// #![feature(core_intrinsics)] /// # #![allow(internal_features)] -/// #![feature(strict_provenance)] /// use std::intrinsics::is_val_statically_known; /// /// fn foo(x: &i32) -> bool { diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index ad034d3e576b8..168775667651d 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -163,7 +163,6 @@ #![feature(str_internals)] #![feature(str_split_inclusive_remainder)] #![feature(str_split_remainder)] -#![feature(strict_provenance)] #![feature(ub_checks)] #![feature(unchecked_neg)] #![feature(unchecked_shifts)] @@ -174,6 +173,8 @@ // // Language features: // tidy-alphabetical-start +#![cfg_attr(bootstrap, feature(strict_provenance))] +#![cfg_attr(not(bootstrap), feature(strict_provenance_lints))] #![feature(abi_unadjusted)] #![feature(adt_const_params)] #![feature(allow_internal_unsafe)] diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs index 22fd47b05962b..95fa6c9c9507c 100644 --- a/library/core/src/primitive_docs.rs +++ b/library/core/src/primitive_docs.rs @@ -1784,9 +1784,11 @@ mod prim_ref {} /// unique field that doesn't have size 0 and alignment 1 (if there is such a field). /// - `i32` is ABI-compatible with `NonZero`, and similar for all other integer types. /// - If `T` is guaranteed to be subject to the [null pointer -/// optimization](option/index.html#representation), then `T` and `Option` are ABI-compatible. -/// Furthermore, if `U` satisfies the requirements [outlined here](result/index.html#representation), -/// then `T` and `Result` and `Result` are all ABI-compatible. +/// optimization](option/index.html#representation), and `E` is an enum satisfying the following +/// requirements, then `T` and `E` are ABI-compatible. Such an enum `E` is called "option-like". +/// - The enum `E` has exactly two variants. +/// - One variant has exactly one field, of type `T`. +/// - All fields of the other variant are zero-sized with 1-byte alignment. /// /// Furthermore, ABI compatibility satisfies the following general properties: /// diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index 72f4bc2c9dae8..9ee0fb5948e16 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -137,10 +137,11 @@ impl *const T { /// Gets the "address" portion of the pointer. /// - /// This is similar to `self as usize`, which semantically discards *provenance* and - /// *address-space* information. However, unlike `self as usize`, casting the returned address - /// back to a pointer yields a [pointer without provenance][without_provenance], which is undefined behavior to dereference. To - /// properly restore the lost information and obtain a dereferenceable pointer, use + /// This is similar to `self as usize`, except that the [provenance][crate::ptr#provenance] of + /// the pointer is discarded and not [exposed][crate::ptr#exposed-provenance]. This means that + /// casting the returned address back to a pointer yields a [pointer without + /// provenance][without_provenance], which is undefined behavior to dereference. To properly + /// restore the lost information and obtain a dereferenceable pointer, use /// [`with_addr`][pointer::with_addr] or [`map_addr`][pointer::map_addr]. /// /// If using those APIs is not possible because there is no way to preserve a pointer with the @@ -155,90 +156,81 @@ impl *const T { /// perform a change of representation to produce a value containing only the address /// portion of the pointer. What that means is up to the platform to define. /// - /// This API and its claimed semantics are part of the Strict Provenance experiment, and as such - /// might change in the future (including possibly weakening this so it becomes wholly - /// equivalent to `self as usize`). See the [module documentation][crate::ptr] for details. + /// This is a [Strict Provenance][crate::ptr#strict-provenance] API. #[must_use] #[inline(always)] - #[unstable(feature = "strict_provenance", issue = "95228")] + #[stable(feature = "strict_provenance", since = "CURRENT_RUSTC_VERSION")] pub fn addr(self) -> usize { - // FIXME(strict_provenance_magic): I am magic and should be a compiler intrinsic. + // A pointer-to-integer transmute currently has exactly the right semantics: it returns the + // address without exposing the provenance. Note that this is *not* a stable guarantee about + // transmute semantics, it relies on sysroot crates having special status. // SAFETY: Pointer-to-integer transmutes are valid (if you are okay with losing the // provenance). unsafe { mem::transmute(self.cast::<()>()) } } - /// Exposes the "provenance" part of the pointer for future use in - /// [`with_exposed_provenance`][] and returns the "address" portion. + /// Exposes the ["provenance"][crate::ptr#provenance] part of the pointer for future use in + /// [`with_exposed_provenance`] and returns the "address" portion. /// - /// This is equivalent to `self as usize`, which semantically discards *provenance* and - /// *address-space* information. Furthermore, this (like the `as` cast) has the implicit - /// side-effect of marking the provenance as 'exposed', so on platforms that support it you can - /// later call [`with_exposed_provenance`][] to reconstitute the original pointer including its - /// provenance. (Reconstructing address space information, if required, is your responsibility.) + /// This is equivalent to `self as usize`, which semantically discards provenance information. + /// Furthermore, this (like the `as` cast) has the implicit side-effect of marking the + /// provenance as 'exposed', so on platforms that support it you can later call + /// [`with_exposed_provenance`] to reconstitute the original pointer including its provenance. /// - /// Using this method means that code is *not* following [Strict - /// Provenance][super#strict-provenance] rules. Supporting - /// [`with_exposed_provenance`][] complicates specification and reasoning and may not be supported by - /// tools that help you to stay conformant with the Rust memory model, so it is recommended to - /// use [`addr`][pointer::addr] wherever possible. + /// Due to its inherent ambiguity, [`with_exposed_provenance`] may not be supported by tools + /// that help you to stay conformant with the Rust memory model. It is recommended to use + /// [Strict Provenance][crate::ptr#strict-provenance] APIs such as [`with_addr`][pointer::with_addr] + /// wherever possible, in which case [`addr`][pointer::addr] should be used instead of `expose_provenance`. /// /// On most platforms this will produce a value with the same bytes as the original pointer, /// because all the bytes are dedicated to describing the address. Platforms which need to store /// additional information in the pointer may not support this operation, since the 'expose' - /// side-effect which is required for [`with_exposed_provenance`][] to work is typically not + /// side-effect which is required for [`with_exposed_provenance`] to work is typically not /// available. /// - /// It is unclear whether this method can be given a satisfying unambiguous specification. This - /// API and its claimed semantics are part of [Exposed Provenance][super#exposed-provenance]. + /// This is an [Exposed Provenance][crate::ptr#exposed-provenance] API. /// /// [`with_exposed_provenance`]: with_exposed_provenance #[must_use] #[inline(always)] - #[unstable(feature = "exposed_provenance", issue = "95228")] + #[stable(feature = "exposed_provenance", since = "CURRENT_RUSTC_VERSION")] pub fn expose_provenance(self) -> usize { - // FIXME(strict_provenance_magic): I am magic and should be a compiler intrinsic. self.cast::<()>() as usize } - /// Creates a new pointer with the given address. + /// Creates a new pointer with the given address and the [provenance][crate::ptr#provenance] of + /// `self`. /// - /// This performs the same operation as an `addr as ptr` cast, but copies - /// the *address-space* and *provenance* of `self` to the new pointer. - /// This allows us to dynamically preserve and propagate this important - /// information in a way that is otherwise impossible with a unary cast. + /// This is similar to a `addr as *const T` cast, but copies + /// the *provenance* of `self` to the new pointer. + /// This avoids the inherent ambiguity of the unary cast. /// /// This is equivalent to using [`wrapping_offset`][pointer::wrapping_offset] to offset /// `self` to the given address, and therefore has all the same capabilities and restrictions. /// - /// This API and its claimed semantics are part of the Strict Provenance experiment, - /// see the [module documentation][crate::ptr] for details. + /// This is a [Strict Provenance][crate::ptr#strict-provenance] API. #[must_use] #[inline] - #[unstable(feature = "strict_provenance", issue = "95228")] + #[stable(feature = "strict_provenance", since = "CURRENT_RUSTC_VERSION")] pub fn with_addr(self, addr: usize) -> Self { - // FIXME(strict_provenance_magic): I am magic and should be a compiler intrinsic. - // - // In the mean-time, this operation is defined to be "as if" it was - // a wrapping_offset, so we can emulate it as such. This should properly - // restore pointer provenance even under today's compiler. + // This should probably be an intrinsic to avoid doing any sort of arithmetic, but + // meanwhile, we can implement it with `wrapping_offset`, which preserves the pointer's + // provenance. let self_addr = self.addr() as isize; let dest_addr = addr as isize; let offset = dest_addr.wrapping_sub(self_addr); - - // This is the canonical desugaring of this operation self.wrapping_byte_offset(offset) } - /// Creates a new pointer by mapping `self`'s address to a new one. + /// Creates a new pointer by mapping `self`'s address to a new one, preserving the + /// [provenance][crate::ptr#provenance] of `self`. /// /// This is a convenience for [`with_addr`][pointer::with_addr], see that method for details. /// - /// This API and its claimed semantics are part of the Strict Provenance experiment, - /// see the [module documentation][crate::ptr] for details. + /// This is a [Strict Provenance][crate::ptr#strict-provenance] API. #[must_use] #[inline] - #[unstable(feature = "strict_provenance", issue = "95228")] + #[stable(feature = "strict_provenance", since = "CURRENT_RUSTC_VERSION")] pub fn map_addr(self, f: impl FnOnce(usize) -> usize) -> Self { self.with_addr(f(self.addr())) } @@ -379,7 +371,7 @@ impl *const T { /// * The offset in bytes, `count * size_of::()`, computed on mathematical integers (without /// "wrapping around"), must fit in an `isize`. /// - /// * If the computed offset is non-zero, then `self` must be derived from a pointer to some + /// * If the computed offset is non-zero, then `self` must be [derived from][crate::ptr#provenance] a pointer to some /// [allocated object], and the entire memory range between `self` and the result must be in /// bounds of that allocated object. In particular, this range must not "wrap around" the edge /// of the address space. @@ -560,7 +552,7 @@ impl *const T { /// ## Examples /// /// ``` - /// #![feature(ptr_mask, strict_provenance)] + /// #![feature(ptr_mask)] /// let v = 17_u32; /// let ptr: *const u32 = &v; /// @@ -611,7 +603,7 @@ impl *const T { /// * `self` and `origin` must either /// /// * point to the same address, or - /// * both be *derived from* a pointer to the same [allocated object], and the memory range between + /// * both be [derived from][crate::ptr#provenance] a pointer to the same [allocated object], and the memory range between /// the two pointers must be in bounds of that object. (See below for an example.) /// /// * The distance between the pointers, in bytes, must be an exact multiple @@ -871,7 +863,7 @@ impl *const T { /// * The offset in bytes, `count * size_of::()`, computed on mathematical integers (without /// "wrapping around"), must fit in an `isize`. /// - /// * If the computed offset is non-zero, then `self` must be derived from a pointer to some + /// * If the computed offset is non-zero, then `self` must be [derived from][crate::ptr#provenance] a pointer to some /// [allocated object], and the entire memory range between `self` and the result must be in /// bounds of that allocated object. In particular, this range must not "wrap around" the edge /// of the address space. @@ -978,7 +970,7 @@ impl *const T { /// * The offset in bytes, `count * size_of::()`, computed on mathematical integers (without /// "wrapping around"), must fit in an `isize`. /// - /// * If the computed offset is non-zero, then `self` must be derived from a pointer to some + /// * If the computed offset is non-zero, then `self` must be [derived from][crate::ptr#provenance] a pointer to some /// [allocated object], and the entire memory range between `self` and the result must be in /// bounds of that allocated object. In particular, this range must not "wrap around" the edge /// of the address space. diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index f7036f30a99ec..f769b5158771c 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -18,10 +18,11 @@ //! * For operations of [size zero][zst], *every* pointer is valid, including the [null] pointer. //! The following points are only concerned with non-zero-sized accesses. //! * A [null] pointer is *never* valid. -//! * For a pointer to be valid, it is necessary, but not always sufficient, that the pointer -//! be *dereferenceable*: the memory range of the given size starting at the pointer must all be -//! within the bounds of a single allocated object. Note that in Rust, -//! every (stack-allocated) variable is considered a separate allocated object. +//! * For a pointer to be valid, it is necessary, but not always sufficient, that the pointer be +//! *dereferenceable*. The [provenance] of the pointer is used to determine which [allocated +//! object] it is derived from; a pointer is dereferenceable if the memory range of the given size +//! starting at the pointer is entirely contained within the bounds of that allocated object. Note +//! that in Rust, every (stack-allocated) variable is considered a separate allocated object. //! * All accesses performed by functions in this module are *non-atomic* in the sense //! of [atomic operations] used to synchronize between threads. This means it is //! undefined behavior to perform two concurrent accesses to the same location from different @@ -130,123 +131,130 @@ //! //! [`null()`]: null //! -//! # Strict Provenance -//! -//! **The following text is non-normative, insufficiently formal, and is an extremely strict -//! interpretation of provenance. It's ok if your code doesn't strictly conform to it.** -//! -//! [Strict Provenance][] is an experimental set of APIs that help tools that try -//! to validate the memory-safety of your program's execution. Notably this includes [Miri][] -//! and [CHERI][], which can detect when you access out of bounds memory or otherwise violate -//! Rust's memory model. -//! -//! Provenance must exist in some form for any programming -//! language compiled for modern computer architectures, but specifying a model for provenance -//! in a way that is useful to both compilers and programmers is an ongoing challenge. -//! The [Strict Provenance][] experiment seeks to explore the question: *what if we just said you -//! couldn't do all the nasty operations that make provenance so messy?* -//! -//! What APIs would have to be removed? What APIs would have to be added? How much would code -//! have to change, and is it worse or better now? Would any patterns become truly inexpressible? -//! Could we carve out special exceptions for those patterns? Should we? -//! -//! A secondary goal of this project is to see if we can disambiguate the many functions of -//! pointer<->integer casts enough for the definition of `usize` to be loosened so that it -//! isn't *pointer*-sized but address-space/offset/allocation-sized (we'll probably continue -//! to conflate these notions). This would potentially make it possible to more efficiently -//! target platforms where pointers are larger than offsets, such as CHERI and maybe some -//! segmented architectures. -//! -//! ## Provenance -//! -//! **This section is *non-normative* and is part of the [Strict Provenance][] experiment.** +//! # Provenance //! //! Pointers are not *simply* an "integer" or "address". For instance, it's uncontroversial //! to say that a Use After Free is clearly Undefined Behaviour, even if you "get lucky" //! and the freed memory gets reallocated before your read/write (in fact this is the //! worst-case scenario, UAFs would be much less concerning if this didn't happen!). -//! To rationalize this claim, pointers need to somehow be *more* than just their addresses: -//! they must have provenance. +//! As another example, consider that [`wrapping_offset`] is documented to "remember" +//! the allocated object that the original pointer points to, even if it is offset far +//! outside the memory range occupied by that allocated object. +//! To rationalize claims like this, pointers need to somehow be *more* than just their addresses: +//! they must have **provenance**. //! -//! When an allocation is created, that allocation has a unique Original Pointer. For alloc -//! APIs this is literally the pointer the call returns, and for local variables and statics, -//! this is the name of the variable/static. This is mildly overloading the term "pointer" -//! for the sake of brevity/exposition. +//! A pointer value in Rust semantically contains the following information: +//! +//! * The **address** it points to, which can be represented by a `usize`. +//! * The **provenance** it has, defining the memory it has permission to access. Provenance can be +//! absent, in which case the pointer does not have permission to access any memory. //! -//! The Original Pointer for an allocation is guaranteed to have unique access to the entire -//! allocation and *only* that allocation. In this sense, an allocation can be thought of -//! as a "sandbox" that cannot be broken into or out of. *Provenance* is the permission -//! to access an allocation's sandbox and has both a *spatial* and *temporal* component: +//! The exact structure of provenance is not yet specified, but the permission defined by a +//! pointer's provenance have a *spatial* component, a *temporal* component, and a *mutability* +//! component: //! -//! * Spatial: A range of bytes that the pointer is allowed to access. -//! * Temporal: The lifetime (of the allocation) that access to these bytes is tied to. +//! * Spatial: The set of memory addresses that the pointer is allowed to access. +//! * Temporal: The timespan during which the pointer is allowed to access those memory addresses. +//! * Mutability: Whether the pointer may only access the memory for reads, or also access it for +//! writes. Note that this can interact with the other components, e.g. a pointer might permit +//! mutation only for a subset of addresses, or only for a subset of its maximal timespan. //! -//! Spatial provenance makes sure you don't go beyond your sandbox, while temporal provenance -//! makes sure that you can't "get lucky" after your permission to access some memory -//! has been revoked (either through deallocations or borrows expiring). +//! When an [allocated object] is created, it has a unique Original Pointer. For alloc +//! APIs this is literally the pointer the call returns, and for local variables and statics, +//! this is the name of the variable/static. (This is mildly overloading the term "pointer" +//! for the sake of brevity/exposition.) +//! +//! The Original Pointer for an allocated object has provenance that constrains the *spatial* +//! permissions of this pointer to the memory range of the allocation, and the *temporal* +//! permissions to the lifetime of the allocation. Provenance is implicitly inherited by all +//! pointers transitively derived from the Original Pointer through operations like [`offset`], +//! borrowing, and pointer casts. Some operations may *shrink* the permissions of the derived +//! provenance, limiting how much memory it can access or how long it's valid for (i.e. borrowing a +//! subfield and subslicing can shrink the spatial component of provenance, and all borrowing can +//! shrink the temporal component of provenance). However, no operation can ever *grow* the +//! permissions of the derived provenance: even if you "know" there is a larger allocation, you +//! can't derive a pointer with a larger provenance. Similarly, you cannot "recombine" two +//! contiguous provenances back into one (i.e. with a `fn merge(&[T], &[T]) -> &[T]`). +//! +//! A reference to a place always has provenance over at least the memory that place occupies. +//! A reference to a slice always has provenance over at least the range that slice describes. +//! Whether and when exactly the provenance of a reference gets "shrunk" to *exactly* fit +//! the memory it points to is not yet determined. +//! +//! A *shared* reference only ever has provenance that permits reading from memory, +//! and never permits writes, except inside [`UnsafeCell`]. +//! +//! Provenance can affect whether a program has undefined behavior: +//! +//! * It is undefined behavior to access memory through a pointer that does not have provenance over +//! that memory. Note that a pointer "at the end" of its provenance is not actually outside its +//! provenance, it just has 0 bytes it can load/store. Zero-sized accesses do not require any +//! provenance since they access an empty range of memory. +//! +//! * It is undefined behavior to [`offset`] a pointer across a memory range that is not contained +//! in the allocated object it is derived from, or to [`offset_from`] two pointers not derived +//! from the same allocated object. Provenance is used to say what exactly "derived from" even +//! means: the lineage of a pointer is traced back to the Original Pointer it descends from, and +//! that identifies the relevant allocated object. In particular, it's always UB to offset a +//! pointer derived from something that is now deallocated, except if the offset is 0. //! -//! Provenance is implicitly shared with all pointers transitively derived from -//! The Original Pointer through operations like [`offset`], borrowing, and pointer casts. -//! Some operations may *shrink* the derived provenance, limiting how much memory it can -//! access or how long it's valid for (i.e. borrowing a subfield and subslicing). +//! But it *is* still sound to: //! -//! Shrinking provenance cannot be undone: even if you "know" there is a larger allocation, you -//! can't derive a pointer with a larger provenance. Similarly, you cannot "recombine" -//! two contiguous provenances back into one (i.e. with a `fn merge(&[T], &[T]) -> &[T]`). +//! * Create a pointer without provenance from just an address (see [`ptr::dangling`]). Such a +//! pointer cannot be used for memory accesses (except for zero-sized accesses). This can still be +//! useful for sentinel values like `null` *or* to represent a tagged pointer that will never be +//! dereferenceable. In general, it is always sound for an integer to pretend to be a pointer "for +//! fun" as long as you don't use operations on it which require it to be valid (non-zero-sized +//! offset, read, write, etc). //! -//! A reference to a value always has provenance over exactly the memory that field occupies. -//! A reference to a slice always has provenance over exactly the range that slice describes. +//! * Forge an allocation of size zero at any sufficiently aligned non-null address. +//! i.e. the usual "ZSTs are fake, do what you want" rules apply. //! -//! If an allocation is deallocated, all pointers with provenance to that allocation become -//! invalidated, and effectively lose their provenance. +//! * [`wrapping_offset`] a pointer outside its provenance. This includes pointers +//! which have "no" provenance. In particular, this makes it sound to do pointer tagging tricks. //! -//! The strict provenance experiment is mostly only interested in exploring stricter *spatial* -//! provenance. In this sense it can be thought of as a subset of the more ambitious and -//! formal [Stacked Borrows][] research project, which is what tools like [Miri][] are based on. -//! In particular, Stacked Borrows is necessary to properly describe what borrows are allowed -//! to do and when they become invalidated. This necessarily involves much more complex -//! *temporal* reasoning than simply identifying allocations. Adjusting APIs and code -//! for the strict provenance experiment will also greatly help Stacked Borrows. +//! * Compare arbitrary pointers by address. Pointer comparison ignores provenance and addresses +//! *are* just integers, so there is always a coherent answer, even if the pointers are dangling +//! or from different provenances. Note that if you get "lucky" and notice that a pointer at the +//! end of one allocated object is the "same" address as the start of another allocated object, +//! anything you do with that fact is *probably* going to be gibberish. The scope of that +//! gibberish is kept under control by the fact that the two pointers *still* aren't allowed to +//! access the other's allocation (bytes), because they still have different provenance. //! +//! Note that the full definition of provenance in Rust is not decided yet, as this interacts +//! with the as-yet undecided [aliasing] rules. //! -//! ## Pointer Vs Addresses +//! ## Pointers Vs Integers //! -//! **This section is *non-normative* and is part of the [Strict Provenance][] experiment.** +//! From this discussion, it becomes very clear that a `usize` *cannot* accurately represent a pointer, +//! and converting from a pointer to a `usize` is generally an operation which *only* extracts the +//! address. Converting this address back into pointer requires somehow answering the question: +//! which provenance should the resulting pointer have? //! -//! One of the largest historical issues with trying to define provenance is that programmers -//! freely convert between pointers and integers. Once you allow for this, it generally becomes -//! impossible to accurately track and preserve provenance information, and you need to appeal -//! to very complex and unreliable heuristics. But of course, converting between pointers and -//! integers is very useful, so what can we do? +//! Rust provides two ways of dealing with this situation: *Strict Provenance* and *Exposed Provenance*. //! -//! Also did you know WASM is actually a "Harvard Architecture"? As in function pointers are -//! handled completely differently from data pointers? And we kind of just shipped Rust on WASM -//! without really addressing the fact that we let you freely convert between function pointers -//! and data pointers, because it mostly Just Works? Let's just put that on the "pointer casts -//! are dubious" pile. +//! Note that a pointer *can* represent a `usize` (via [`without_provenance`]), so the right type to +//! use in situations where a value is "sometimes a pointer and sometimes a bare `usize`" is a +//! pointer type. //! -//! Strict Provenance attempts to square these circles by decoupling Rust's traditional conflation -//! of pointers and `usize` (and `isize`), and defining a pointer to semantically contain the -//! following information: +//! ## Strict Provenance //! -//! * The **address-space** it is part of (e.g. "data" vs "code" in WASM). -//! * The **address** it points to, which can be represented by a `usize`. -//! * The **provenance** it has, defining the memory it has permission to access. -//! Provenance can be absent, in which case the pointer does not have permission to access any memory. +//! "Strict Provenance" refers to a set of APIs designed to make working with provenance more +//! explicit. They are intended as substitutes for casting a pointer to an integer and back. //! -//! Under Strict Provenance, a `usize` *cannot* accurately represent a pointer, and converting from -//! a pointer to a `usize` is generally an operation which *only* extracts the address. It is -//! therefore *impossible* to construct a valid pointer from a `usize` because there is no way -//! to restore the address-space and provenance. In other words, pointer-integer-pointer -//! roundtrips are not possible (in the sense that the resulting pointer is not dereferenceable). +//! Entirely avoiding integer-to-pointer casts successfully side-steps the inherent ambiguity of +//! that operation. This benefits compiler optimizations, and it is pretty much a requirement for +//! using tools like [Miri] and architectures like [CHERI] that aim to detect and diagnose pointer +//! misuse. //! -//! The key insight to making this model *at all* viable is the [`with_addr`][] method: +//! The key insight to making programming without integer-to-pointer casts *at all* viable is the +//! [`with_addr`] method: //! //! ```text //! /// Creates a new pointer with the given address. //! /// //! /// This performs the same operation as an `addr as ptr` cast, but copies -//! /// the *address-space* and *provenance* of `self` to the new pointer. +//! /// the *provenance* of `self` to the new pointer. //! /// This allows us to dynamically preserve and propagate this important //! /// information in a way that is otherwise impossible with a unary cast. //! /// @@ -257,23 +265,21 @@ //! //! So you're still able to drop down to the address representation and do whatever //! clever bit tricks you want *as long as* you're able to keep around a pointer -//! into the allocation you care about that can "reconstitute" the other parts of the pointer. +//! into the allocation you care about that can "reconstitute" the provenance. //! Usually this is very easy, because you only are taking a pointer, messing with the address, //! and then immediately converting back to a pointer. To make this use case more ergonomic, -//! we provide the [`map_addr`][] method. +//! we provide the [`map_addr`] method. //! //! To help make it clear that code is "following" Strict Provenance semantics, we also provide an -//! [`addr`][] method which promises that the returned address is not part of a -//! pointer-usize-pointer roundtrip. In the future we may provide a lint for pointer<->integer +//! [`addr`] method which promises that the returned address is not part of a +//! pointer-integer-pointer roundtrip. In the future we may provide a lint for pointer<->integer //! casts to help you audit if your code conforms to strict provenance. //! -//! -//! ## Using Strict Provenance +//! ### Using Strict Provenance //! //! Most code needs no changes to conform to strict provenance, as the only really concerning -//! operation that *wasn't* obviously already Undefined Behaviour is casts from usize to a -//! pointer. For code which *does* cast a `usize` to a pointer, the scope of the change depends -//! on exactly what you're doing. +//! operation is casts from usize to a pointer. For code which *does* cast a `usize` to a pointer, +//! the scope of the change depends on exactly what you're doing. //! //! In general, you just need to make sure that if you want to convert a `usize` address to a //! pointer and then use that pointer to read/write memory, you need to keep around a pointer @@ -284,8 +290,6 @@ //! represent the tagged pointer as an actual pointer and not a `usize`*. For instance: //! //! ``` -//! #![feature(strict_provenance)] -//! //! unsafe { //! // A flag we want to pack into our pointer //! static HAS_DATA: usize = 0x1; @@ -314,122 +318,65 @@ //! be using AtomicPtr instead. If that messes up the way you atomically manipulate pointers, //! we would like to know why, and what needs to be done to fix it.) //! -//! Something more complicated and just generally *evil* like an XOR-List requires more significant -//! changes like allocating all nodes in a pre-allocated Vec or Arena and using a pointer -//! to the whole allocation to reconstitute the XORed addresses. -//! //! Situations where a valid pointer *must* be created from just an address, such as baremetal code -//! accessing a memory-mapped interface at a fixed address, are an open question on how to support. -//! These situations *will* still be allowed, but we might require some kind of "I know what I'm -//! doing" annotation to explain the situation to the compiler. It's also possible they need no -//! special attention at all, because they're generally accessing memory outside the scope of -//! "the abstract machine", or already using "I know what I'm doing" annotations like "volatile". -//! -//! Under [Strict Provenance] it is Undefined Behaviour to: -//! -//! * Access memory through a pointer that does not have provenance over that memory. -//! -//! * [`offset`] a pointer to or from an address it doesn't have provenance over. -//! This means it's always UB to offset a pointer derived from something deallocated, -//! even if the offset is 0. Note that a pointer "one past the end" of its provenance -//! is not actually outside its provenance, it just has 0 bytes it can load/store. -//! -//! But it *is* still sound to: -//! -//! * Create a pointer without provenance from just an address (see [`ptr::dangling`][]). Such a -//! pointer cannot be used for memory accesses (except for zero-sized accesses). This can still be -//! useful for sentinel values like `null` *or* to represent a tagged pointer that will never be -//! dereferenceable. In general, it is always sound for an integer to pretend to be a pointer "for -//! fun" as long as you don't use operations on it which require it to be valid (non-zero-sized -//! offset, read, write, etc). -//! -//! * Forge an allocation of size zero at any sufficiently aligned non-null address. -//! i.e. the usual "ZSTs are fake, do what you want" rules apply *but* this only applies -//! for actual forgery (integers cast to pointers). If you borrow some struct's field -//! that *happens* to be zero-sized, the resulting pointer will have provenance tied to -//! that allocation, and it will still get invalidated if the allocation gets deallocated. -//! In the future we may introduce an API to make such a forged allocation explicit. -//! -//! * [`wrapping_offset`][] a pointer outside its provenance. This includes pointers -//! which have "no" provenance. Unfortunately there may be practical limits on this for a -//! particular platform, and it's an open question as to how to specify this (if at all). -//! Notably, [CHERI][] relies on a compression scheme that can't handle a -//! pointer getting offset "too far" out of bounds. If this happens, the address -//! returned by `addr` will be the value you expect, but the provenance will get invalidated -//! and using it to read/write will fault. The details of this are architecture-specific -//! and based on alignment, but the buffer on either side of the pointer's range is pretty -//! generous (think kilobytes, not bytes). -//! -//! * Compare arbitrary pointers by address. Addresses *are* just integers and so there is -//! always a coherent answer, even if the pointers are dangling or from different -//! address-spaces/provenances. Of course, comparing addresses from different address-spaces -//! is generally going to be *meaningless*, but so is comparing Kilograms to Meters, and Rust -//! doesn't prevent that either. Similarly, if you get "lucky" and notice that a pointer -//! one-past-the-end is the "same" address as the start of an unrelated allocation, anything -//! you do with that fact is *probably* going to be gibberish. The scope of that gibberish -//! is kept under control by the fact that the two pointers *still* aren't allowed to access -//! the other's allocation (bytes), because they still have different provenance. -//! -//! * Perform pointer tagging tricks. This falls out of [`wrapping_offset`] but is worth -//! mentioning in more detail because of the limitations of [CHERI][]. Low-bit tagging -//! is very robust, and often doesn't even go out of bounds because types ensure -//! size >= align (and over-aligning actually gives CHERI more flexibility). Anything -//! more complex than this rapidly enters "extremely platform-specific" territory as -//! certain things may or may not be allowed based on specific supported operations. -//! For instance, ARM explicitly supports high-bit tagging, and so CHERI on ARM inherits -//! that and should support it. +//! accessing a memory-mapped interface at a fixed address, cannot currently be handled with strict +//! provenance APIs and should use [exposed provenance](#exposed-provenance). //! //! ## Exposed Provenance //! -//! **This section is *non-normative* and is an extension to the [Strict Provenance] experiment.** -//! -//! As discussed above, pointer-usize-pointer roundtrips are not possible under [Strict Provenance]. +//! As discussed above, integer-to-pointer casts are not possible with Strict Provenance APIs. //! This is by design: the goal of Strict Provenance is to provide a clear specification that we are -//! confident can be formalized unambiguously and can be subject to precise formal reasoning. +//! confident can be formalized unambiguously and can be subject to precise formal reasoning. +//! Integer-to-pointer casts do not (currently) have such a clear specification. //! -//! However, there exist situations where pointer-usize-pointer roundtrips cannot be avoided, or +//! However, there exist situations where integer-to-pointer casts cannot be avoided, or //! where avoiding them would require major refactoring. Legacy platform APIs also regularly assume -//! that `usize` can capture all the information that makes up a pointer. The goal of Strict -//! Provenance is not to rule out such code; the goal is to put all the *other* pointer-manipulating -//! code onto a more solid foundation. Strict Provenance is about improving the situation where -//! possible (all the code that can be written with Strict Provenance) without making things worse -//! for situations where Strict Provenance is insufficient. -//! -//! For these situations, there is a highly experimental extension to Strict Provenance called -//! *Exposed Provenance*. This extension permits pointer-usize-pointer roundtrips. However, its -//! semantics are on much less solid footing than Strict Provenance, and at this point it is not yet -//! clear where a satisfying unambiguous semantics can be defined for Exposed Provenance. -//! Furthermore, Exposed Provenance will not work (well) with tools like [Miri] and [CHERI]. +//! that `usize` can capture all the information that makes up a pointer. +//! Bare-metal platforms can also require the synthesis of a pointer "out of thin air" without +//! anywhere to obtain proper provenance from. +//! +//! Rust's model for dealing with integer-to-pointer casts is called *Exposed Provenance*. However, +//! the semantics of Exposed Provenance are on much less solid footing than Strict Provenance, and +//! at this point it is not yet clear whether a satisfying unambiguous semantics can be defined for +//! Exposed Provenance. (If that sounds bad, be reassured that other popular languages that provide +//! integer-to-pointer casts are not faring any better.) Furthermore, Exposed Provenance will not +//! work (well) with tools like [Miri] and [CHERI]. //! //! Exposed Provenance is provided by the [`expose_provenance`] and [`with_exposed_provenance`] methods, -//! which are meant to replace `as` casts between pointers and integers. [`expose_provenance`] is a lot like -//! [`addr`], but additionally adds the provenance of the pointer to a global list of 'exposed' -//! provenances. (This list is purely conceptual, it exists for the purpose of specifying Rust but -//! is not materialized in actual executions, except in tools like [Miri].) [`with_exposed_provenance`] -//! can be used to construct a pointer with one of these previously 'exposed' provenances. -//! [`with_exposed_provenance`] takes only `addr: usize` as arguments, so unlike in [`with_addr`] there is -//! no indication of what the correct provenance for the returned pointer is -- and that is exactly -//! what makes pointer-usize-pointer roundtrips so tricky to rigorously specify! There is no -//! algorithm that decides which provenance will be used. You can think of this as "guessing" the -//! right provenance, and the guess will be "maximally in your favor", in the sense that if there is -//! any way to avoid undefined behavior, then that is the guess that will be taken. However, if -//! there is *no* previously 'exposed' provenance that justifies the way the returned pointer will -//! be used, the program has undefined behavior. -//! -//! Using [`expose_provenance`] or [`with_exposed_provenance`] (or the `as` casts) means that code is -//! *not* following Strict Provenance rules. The goal of the Strict Provenance experiment is to -//! determine how far one can get in Rust without the use of [`expose_provenance`] and -//! [`with_exposed_provenance`], and to encourage code to be written with Strict Provenance APIs only. -//! Maximizing the amount of such code is a major win for avoiding specification complexity and to -//! facilitate adoption of tools like [CHERI] and [Miri] that can be a big help in increasing the -//! confidence in (unsafe) Rust code. +//! which are equivalent to `as` casts between pointers and integers. +//! - [`expose_provenance`] is a lot like [`addr`], but additionally adds the provenance of the +//! pointer to a global list of 'exposed' provenances. (This list is purely conceptual, it exists +//! for the purpose of specifying Rust but is not materialized in actual executions, except in +//! tools like [Miri].) +//! Memory which is outside the control of the Rust abstract machine (MMIO registers, for example) +//! is always considered to be exposed, so long as this memory is disjoint from memory that will +//! be used by the abstract machine such as the stack, heap, and statics. +//! - [`with_exposed_provenance`] can be used to construct a pointer with one of these previously +//! 'exposed' provenances. [`with_exposed_provenance`] takes only `addr: usize` as arguments, so +//! unlike in [`with_addr`] there is no indication of what the correct provenance for the returned +//! pointer is -- and that is exactly what makes integer-to-pointer casts so tricky to rigorously +//! specify! The compiler will do its best to pick the right provenance for you, but currently we +//! cannot provide any guarantees about which provenance the resulting pointer will have. Only one +//! thing is clear: if there is *no* previously 'exposed' provenance that justifies the way the +//! returned pointer will be used, the program has undefined behavior. +//! +//! If at all possible, we encourage code to be ported to [Strict Provenance] APIs, thus avoiding +//! the need for Exposed Provenance. Maximizing the amount of such code is a major win for avoiding +//! specification complexity and to facilitate adoption of tools like [CHERI] and [Miri] that can be +//! a big help in increasing the confidence in (unsafe) Rust code. However, we acknowledge that this +//! is not always possible, and offer Exposed Provenance as a way to explicit "opt out" of the +//! well-defined semantics of Strict Provenance, and "opt in" to the unclear semantics of +//! integer-to-pointer casts. //! //! [aliasing]: ../../nomicon/aliasing.html +//! [allocated object]: #allocated-object +//! [provenance]: #provenance //! [book]: ../../book/ch19-01-unsafe-rust.html#dereferencing-a-raw-pointer //! [ub]: ../../reference/behavior-considered-undefined.html //! [zst]: ../../nomicon/exotic-sizes.html#zero-sized-types-zsts //! [atomic operations]: crate::sync::atomic //! [`offset`]: pointer::offset +//! [`offset_from`]: pointer::offset_from //! [`wrapping_offset`]: pointer::wrapping_offset //! [`with_addr`]: pointer::with_addr //! [`map_addr`]: pointer::map_addr @@ -439,8 +386,8 @@ //! [`with_exposed_provenance`]: with_exposed_provenance //! [Miri]: https://github.com/rust-lang/miri //! [CHERI]: https://www.cl.cam.ac.uk/research/security/ctsrd/cheri/ -//! [Strict Provenance]: https://github.com/rust-lang/rust/issues/95228 -//! [Stacked Borrows]: https://plv.mpi-sws.org/rustbelt/stacked-borrows/ +//! [Strict Provenance]: #strict-provenance +//! [`UnsafeCell`]: core::cell::UnsafeCell #![stable(feature = "rust1", since = "1.0.0")] // There are many unsafe functions taking pointers that don't dereference them. @@ -629,7 +576,7 @@ pub const fn null_mut() -> *mut T { from_raw_parts_mut(without_provenance_mut::<()>(0), ()) } -/// Creates a pointer with the given address and no provenance. +/// Creates a pointer with the given address and no [provenance][crate::ptr#provenance]. /// /// This is equivalent to `ptr::null().with_addr(addr)`. /// @@ -641,16 +588,15 @@ pub const fn null_mut() -> *mut T { /// This is different from `addr as *const T`, which creates a pointer that picks up a previously /// exposed provenance. See [`with_exposed_provenance`] for more details on that operation. /// -/// This API and its claimed semantics are part of the Strict Provenance experiment, -/// see the [module documentation][crate::ptr] for details. +/// This is a [Strict Provenance][crate::ptr#strict-provenance] API. #[inline(always)] #[must_use] #[rustc_const_stable(feature = "stable_things_using_strict_provenance", since = "1.61.0")] -#[unstable(feature = "strict_provenance", issue = "95228")] +#[stable(feature = "strict_provenance", since = "CURRENT_RUSTC_VERSION")] pub const fn without_provenance(addr: usize) -> *const T { - // FIXME(strict_provenance_magic): I am magic and should be a compiler intrinsic. - // We use transmute rather than a cast so tools like Miri can tell that this - // is *not* the same as with_exposed_provenance. + // An int-to-pointer transmute currently has exactly the intended semantics: it creates a + // pointer without provenance. Note that this is *not* a stable guarantee about transmute + // semantics, it relies on sysroot crates having special status. // SAFETY: every valid integer is also a valid pointer (as long as you don't dereference that // pointer). unsafe { mem::transmute(addr) } @@ -668,12 +614,12 @@ pub const fn without_provenance(addr: usize) -> *const T { #[inline(always)] #[must_use] #[rustc_const_stable(feature = "stable_things_using_strict_provenance", since = "1.61.0")] -#[unstable(feature = "strict_provenance", issue = "95228")] +#[stable(feature = "strict_provenance", since = "CURRENT_RUSTC_VERSION")] pub const fn dangling() -> *const T { without_provenance(mem::align_of::()) } -/// Creates a pointer with the given address and no provenance. +/// Creates a pointer with the given address and no [provenance][crate::ptr#provenance]. /// /// This is equivalent to `ptr::null_mut().with_addr(addr)`. /// @@ -685,16 +631,15 @@ pub const fn dangling() -> *const T { /// This is different from `addr as *mut T`, which creates a pointer that picks up a previously /// exposed provenance. See [`with_exposed_provenance_mut`] for more details on that operation. /// -/// This API and its claimed semantics are part of the Strict Provenance experiment, -/// see the [module documentation][crate::ptr] for details. +/// This is a [Strict Provenance][crate::ptr#strict-provenance] API. #[inline(always)] #[must_use] #[rustc_const_stable(feature = "stable_things_using_strict_provenance", since = "1.61.0")] -#[unstable(feature = "strict_provenance", issue = "95228")] +#[stable(feature = "strict_provenance", since = "CURRENT_RUSTC_VERSION")] pub const fn without_provenance_mut(addr: usize) -> *mut T { - // FIXME(strict_provenance_magic): I am magic and should be a compiler intrinsic. - // We use transmute rather than a cast so tools like Miri can tell that this - // is *not* the same as with_exposed_provenance. + // An int-to-pointer transmute currently has exactly the intended semantics: it creates a + // pointer without provenance. Note that this is *not* a stable guarantee about transmute + // semantics, it relies on sysroot crates having special status. // SAFETY: every valid integer is also a valid pointer (as long as you don't dereference that // pointer). unsafe { mem::transmute(addr) } @@ -712,96 +657,88 @@ pub const fn without_provenance_mut(addr: usize) -> *mut T { #[inline(always)] #[must_use] #[rustc_const_stable(feature = "stable_things_using_strict_provenance", since = "1.61.0")] -#[unstable(feature = "strict_provenance", issue = "95228")] +#[stable(feature = "strict_provenance", since = "CURRENT_RUSTC_VERSION")] pub const fn dangling_mut() -> *mut T { without_provenance_mut(mem::align_of::()) } -/// Converts an address back to a pointer, picking up a previously 'exposed' provenance. +/// Converts an address back to a pointer, picking up some previously 'exposed' +/// [provenance][crate::ptr#provenance]. /// -/// This is a more rigorously specified alternative to `addr as *const T`. The provenance of the -/// returned pointer is that of *any* pointer that was previously exposed by passing it to -/// [`expose_provenance`][pointer::expose_provenance], or a `ptr as usize` cast. In addition, memory which is -/// outside the control of the Rust abstract machine (MMIO registers, for example) is always -/// considered to be exposed, so long as this memory is disjoint from memory that will be used by -/// the abstract machine such as the stack, heap, and statics. +/// This is fully equivalent to `addr as *const T`. The provenance of the returned pointer is that +/// of *some* pointer that was previously exposed by passing it to +/// [`expose_provenance`][pointer::expose_provenance], or a `ptr as usize` cast. In addition, memory +/// which is outside the control of the Rust abstract machine (MMIO registers, for example) is +/// always considered to be accessible with an exposed provenance, so long as this memory is disjoint +/// from memory that will be used by the abstract machine such as the stack, heap, and statics. /// -/// If there is no 'exposed' provenance that justifies the way this pointer will be used, -/// the program has undefined behavior. In particular, the aliasing rules still apply: pointers -/// and references that have been invalidated due to aliasing accesses cannot be used anymore, -/// even if they have been exposed! +/// The exact provenance that gets picked is not specified. The compiler will do its best to pick +/// the "right" provenance for you (whatever that may be), but currently we cannot provide any +/// guarantees about which provenance the resulting pointer will have -- and therefore there +/// is no definite specification for which memory the resulting pointer may access. /// -/// Note that there is no algorithm that decides which provenance will be used. You can think of this -/// as "guessing" the right provenance, and the guess will be "maximally in your favor", in the sense -/// that if there is any way to avoid undefined behavior (while upholding all aliasing requirements), -/// then that is the guess that will be taken. +/// If there is *no* previously 'exposed' provenance that justifies the way the returned pointer +/// will be used, the program has undefined behavior. In particular, the aliasing rules still apply: +/// pointers and references that have been invalidated due to aliasing accesses cannot be used +/// anymore, even if they have been exposed! /// -/// On platforms with multiple address spaces, it is your responsibility to ensure that the -/// address makes sense in the address space that this pointer will be used with. -/// -/// Using this function means that code is *not* following [Strict -/// Provenance][self#strict-provenance] rules. "Guessing" a -/// suitable provenance complicates specification and reasoning and may not be supported by -/// tools that help you to stay conformant with the Rust memory model, so it is recommended to -/// use [`with_addr`][pointer::with_addr] wherever possible. +/// Due to its inherent ambiguity, this operation may not be supported by tools that help you to +/// stay conformant with the Rust memory model. It is recommended to use [Strict +/// Provenance][self#strict-provenance] APIs such as [`with_addr`][pointer::with_addr] wherever +/// possible. /// /// On most platforms this will produce a value with the same bytes as the address. Platforms /// which need to store additional information in a pointer may not support this operation, /// since it is generally not possible to actually *compute* which provenance the returned /// pointer has to pick up. /// -/// It is unclear whether this function can be given a satisfying unambiguous specification. This -/// API and its claimed semantics are part of [Exposed Provenance][self#exposed-provenance]. +/// This is an [Exposed Provenance][crate::ptr#exposed-provenance] API. #[must_use] #[inline(always)] -#[unstable(feature = "exposed_provenance", issue = "95228")] +#[stable(feature = "exposed_provenance", since = "CURRENT_RUSTC_VERSION")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[allow(fuzzy_provenance_casts)] // this *is* the explicit provenance API one should use instead -pub fn with_exposed_provenance(addr: usize) -> *const T -where - T: Sized, -{ - // FIXME(strict_provenance_magic): I am magic and should be a compiler intrinsic. +pub fn with_exposed_provenance(addr: usize) -> *const T { addr as *const T } -/// Converts an address back to a mutable pointer, picking up a previously 'exposed' provenance. +/// Converts an address back to a mutable pointer, picking up some previously 'exposed' +/// [provenance][crate::ptr#provenance]. +/// +/// This is fully equivalent to `addr as *mut T`. The provenance of the returned pointer is that +/// of *some* pointer that was previously exposed by passing it to +/// [`expose_provenance`][pointer::expose_provenance], or a `ptr as usize` cast. In addition, memory +/// which is outside the control of the Rust abstract machine (MMIO registers, for example) is +/// always considered to be accessible with an exposed provenance, so long as this memory is disjoint +/// from memory that will be used by the abstract machine such as the stack, heap, and statics. /// -/// This is a more rigorously specified alternative to `addr as *mut T`. The provenance of the -/// returned pointer is that of *any* pointer that was previously passed to -/// [`expose_provenance`][pointer::expose_provenance] or a `ptr as usize` cast. If there is no previously -/// 'exposed' provenance that justifies the way this pointer will be used, the program has undefined -/// behavior. Note that there is no algorithm that decides which provenance will be used. You can -/// think of this as "guessing" the right provenance, and the guess will be "maximally in your -/// favor", in the sense that if there is any way to avoid undefined behavior, then that is the -/// guess that will be taken. +/// The exact provenance that gets picked is not specified. The compiler will do its best to pick +/// the "right" provenance for you (whatever that may be), but currently we cannot provide any +/// guarantees about which provenance the resulting pointer will have -- and therefore there +/// is no definite specification for which memory the resulting pointer may access. /// -/// On platforms with multiple address spaces, it is your responsibility to ensure that the -/// address makes sense in the address space that this pointer will be used with. +/// If there is *no* previously 'exposed' provenance that justifies the way the returned pointer +/// will be used, the program has undefined behavior. In particular, the aliasing rules still apply: +/// pointers and references that have been invalidated due to aliasing accesses cannot be used +/// anymore, even if they have been exposed! /// -/// Using this function means that code is *not* following [Strict -/// Provenance][self#strict-provenance] rules. "Guessing" a -/// suitable provenance complicates specification and reasoning and may not be supported by -/// tools that help you to stay conformant with the Rust memory model, so it is recommended to -/// use [`with_addr`][pointer::with_addr] wherever possible. +/// Due to its inherent ambiguity, this operation may not be supported by tools that help you to +/// stay conformant with the Rust memory model. It is recommended to use [Strict +/// Provenance][self#strict-provenance] APIs such as [`with_addr`][pointer::with_addr] wherever +/// possible. /// /// On most platforms this will produce a value with the same bytes as the address. Platforms /// which need to store additional information in a pointer may not support this operation, /// since it is generally not possible to actually *compute* which provenance the returned /// pointer has to pick up. /// -/// It is unclear whether this function can be given a satisfying unambiguous specification. This -/// API and its claimed semantics are part of [Exposed Provenance][self#exposed-provenance]. +/// This is an [Exposed Provenance][crate::ptr#exposed-provenance] API. #[must_use] #[inline(always)] -#[unstable(feature = "exposed_provenance", issue = "95228")] +#[stable(feature = "exposed_provenance", since = "CURRENT_RUSTC_VERSION")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[allow(fuzzy_provenance_casts)] // this *is* the explicit provenance API one should use instead -pub fn with_exposed_provenance_mut(addr: usize) -> *mut T -where - T: Sized, -{ - // FIXME(strict_provenance_magic): I am magic and should be a compiler intrinsic. +pub fn with_exposed_provenance_mut(addr: usize) -> *mut T { addr as *mut T } diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index 613d2c91ac63e..782934fc311db 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -124,12 +124,12 @@ impl *mut T { /// Gets the "address" portion of the pointer. /// - /// This is similar to `self as usize`, which semantically discards *provenance* and - /// *address-space* information. However, unlike `self as usize`, casting the returned address - /// back to a pointer yields a [pointer without provenance][without_provenance_mut], which is undefined - /// behavior to dereference. To properly restore the lost information and obtain a - /// dereferenceable pointer, use [`with_addr`][pointer::with_addr] or - /// [`map_addr`][pointer::map_addr]. + /// This is similar to `self as usize`, except that the [provenance][crate::ptr#provenance] of + /// the pointer is discarded and not [exposed][crate::ptr#exposed-provenance]. This means that + /// casting the returned address back to a pointer yields a [pointer without + /// provenance][without_provenance_mut], which is undefined behavior to dereference. To properly + /// restore the lost information and obtain a dereferenceable pointer, use + /// [`with_addr`][pointer::with_addr] or [`map_addr`][pointer::map_addr]. /// /// If using those APIs is not possible because there is no way to preserve a pointer with the /// required provenance, then Strict Provenance might not be for you. Use pointer-integer casts @@ -143,89 +143,80 @@ impl *mut T { /// perform a change of representation to produce a value containing only the address /// portion of the pointer. What that means is up to the platform to define. /// - /// This API and its claimed semantics are part of the Strict Provenance experiment, and as such - /// might change in the future (including possibly weakening this so it becomes wholly - /// equivalent to `self as usize`). See the [module documentation][crate::ptr] for details. + /// This is a [Strict Provenance][crate::ptr#strict-provenance] API. #[must_use] #[inline(always)] - #[unstable(feature = "strict_provenance", issue = "95228")] + #[stable(feature = "strict_provenance", since = "CURRENT_RUSTC_VERSION")] pub fn addr(self) -> usize { - // FIXME(strict_provenance_magic): I am magic and should be a compiler intrinsic. + // A pointer-to-integer transmute currently has exactly the right semantics: it returns the + // address without exposing the provenance. Note that this is *not* a stable guarantee about + // transmute semantics, it relies on sysroot crates having special status. // SAFETY: Pointer-to-integer transmutes are valid (if you are okay with losing the // provenance). unsafe { mem::transmute(self.cast::<()>()) } } - /// Exposes the "provenance" part of the pointer for future use in - /// [`with_exposed_provenance`][] and returns the "address" portion. + /// Exposes the ["provenance"][crate::ptr#provenance] part of the pointer for future use in + /// [`with_exposed_provenance_mut`] and returns the "address" portion. /// - /// This is equivalent to `self as usize`, which semantically discards *provenance* and - /// *address-space* information. Furthermore, this (like the `as` cast) has the implicit - /// side-effect of marking the provenance as 'exposed', so on platforms that support it you can - /// later call [`with_exposed_provenance_mut`][] to reconstitute the original pointer including its - /// provenance. (Reconstructing address space information, if required, is your responsibility.) + /// This is equivalent to `self as usize`, which semantically discards provenance information. + /// Furthermore, this (like the `as` cast) has the implicit side-effect of marking the + /// provenance as 'exposed', so on platforms that support it you can later call + /// [`with_exposed_provenance_mut`] to reconstitute the original pointer including its provenance. /// - /// Using this method means that code is *not* following [Strict - /// Provenance][super#strict-provenance] rules. Supporting - /// [`with_exposed_provenance_mut`][] complicates specification and reasoning and may not be supported - /// by tools that help you to stay conformant with the Rust memory model, so it is recommended - /// to use [`addr`][pointer::addr] wherever possible. + /// Due to its inherent ambiguity, [`with_exposed_provenance_mut`] may not be supported by tools + /// that help you to stay conformant with the Rust memory model. It is recommended to use + /// [Strict Provenance][crate::ptr#strict-provenance] APIs such as [`with_addr`][pointer::with_addr] + /// wherever possible, in which case [`addr`][pointer::addr] should be used instead of `expose_provenance`. /// /// On most platforms this will produce a value with the same bytes as the original pointer, /// because all the bytes are dedicated to describing the address. Platforms which need to store /// additional information in the pointer may not support this operation, since the 'expose' - /// side-effect which is required for [`with_exposed_provenance_mut`][] to work is typically not + /// side-effect which is required for [`with_exposed_provenance_mut`] to work is typically not /// available. /// - /// It is unclear whether this method can be given a satisfying unambiguous specification. This - /// API and its claimed semantics are part of [Exposed Provenance][super#exposed-provenance]. + /// This is an [Exposed Provenance][crate::ptr#exposed-provenance] API. /// /// [`with_exposed_provenance_mut`]: with_exposed_provenance_mut #[inline(always)] - #[unstable(feature = "exposed_provenance", issue = "95228")] + #[stable(feature = "exposed_provenance", since = "CURRENT_RUSTC_VERSION")] pub fn expose_provenance(self) -> usize { - // FIXME(strict_provenance_magic): I am magic and should be a compiler intrinsic. self.cast::<()>() as usize } - /// Creates a new pointer with the given address. + /// Creates a new pointer with the given address and the [provenance][crate::ptr#provenance] of + /// `self`. /// - /// This performs the same operation as an `addr as ptr` cast, but copies - /// the *address-space* and *provenance* of `self` to the new pointer. - /// This allows us to dynamically preserve and propagate this important - /// information in a way that is otherwise impossible with a unary cast. + /// This is similar to a `addr as *mut T` cast, but copies + /// the *provenance* of `self` to the new pointer. + /// This avoids the inherent ambiguity of the unary cast. /// /// This is equivalent to using [`wrapping_offset`][pointer::wrapping_offset] to offset /// `self` to the given address, and therefore has all the same capabilities and restrictions. /// - /// This API and its claimed semantics are an extension to the Strict Provenance experiment, - /// see the [module documentation][crate::ptr] for details. + /// This is a [Strict Provenance][crate::ptr#strict-provenance] API. #[must_use] #[inline] - #[unstable(feature = "strict_provenance", issue = "95228")] + #[stable(feature = "strict_provenance", since = "CURRENT_RUSTC_VERSION")] pub fn with_addr(self, addr: usize) -> Self { - // FIXME(strict_provenance_magic): I am magic and should be a compiler intrinsic. - // - // In the mean-time, this operation is defined to be "as if" it was - // a wrapping_offset, so we can emulate it as such. This should properly - // restore pointer provenance even under today's compiler. + // This should probably be an intrinsic to avoid doing any sort of arithmetic, but + // meanwhile, we can implement it with `wrapping_offset`, which preserves the pointer's + // provenance. let self_addr = self.addr() as isize; let dest_addr = addr as isize; let offset = dest_addr.wrapping_sub(self_addr); - - // This is the canonical desugaring of this operation self.wrapping_byte_offset(offset) } - /// Creates a new pointer by mapping `self`'s address to a new one. + /// Creates a new pointer by mapping `self`'s address to a new one, preserving the original + /// pointer's [provenance][crate::ptr#provenance]. /// /// This is a convenience for [`with_addr`][pointer::with_addr], see that method for details. /// - /// This API and its claimed semantics are part of the Strict Provenance experiment, - /// see the [module documentation][crate::ptr] for details. + /// This is a [Strict Provenance][crate::ptr#strict-provenance] API. #[must_use] #[inline] - #[unstable(feature = "strict_provenance", issue = "95228")] + #[stable(feature = "strict_provenance", since = "CURRENT_RUSTC_VERSION")] pub fn map_addr(self, f: impl FnOnce(usize) -> usize) -> Self { self.with_addr(f(self.addr())) } @@ -376,7 +367,7 @@ impl *mut T { /// * The offset in bytes, `count * size_of::()`, computed on mathematical integers (without /// "wrapping around"), must fit in an `isize`. /// - /// * If the computed offset is non-zero, then `self` must be derived from a pointer to some + /// * If the computed offset is non-zero, then `self` must be [derived from][crate::ptr#provenance] a pointer to some /// [allocated object], and the entire memory range between `self` and the result must be in /// bounds of that allocated object. In particular, this range must not "wrap around" the edge /// of the address space. @@ -558,7 +549,7 @@ impl *mut T { /// ## Examples /// /// ``` - /// #![feature(ptr_mask, strict_provenance)] + /// #![feature(ptr_mask)] /// let mut v = 17_u32; /// let ptr: *mut u32 = &mut v; /// @@ -777,7 +768,7 @@ impl *mut T { /// * `self` and `origin` must either /// /// * point to the same address, or - /// * both be *derived from* a pointer to the same [allocated object], and the memory range between + /// * both be [derived from][crate::ptr#provenance] a pointer to the same [allocated object], and the memory range between /// the two pointers must be in bounds of that object. (See below for an example.) /// /// * The distance between the pointers, in bytes, must be an exact multiple @@ -954,7 +945,7 @@ impl *mut T { /// * The offset in bytes, `count * size_of::()`, computed on mathematical integers (without /// "wrapping around"), must fit in an `isize`. /// - /// * If the computed offset is non-zero, then `self` must be derived from a pointer to some + /// * If the computed offset is non-zero, then `self` must be [derived from][crate::ptr#provenance] a pointer to some /// [allocated object], and the entire memory range between `self` and the result must be in /// bounds of that allocated object. In particular, this range must not "wrap around" the edge /// of the address space. @@ -1061,7 +1052,7 @@ impl *mut T { /// * The offset in bytes, `count * size_of::()`, computed on mathematical integers (without /// "wrapping around"), must fit in an `isize`. /// - /// * If the computed offset is non-zero, then `self` must be derived from a pointer to some + /// * If the computed offset is non-zero, then `self` must be [derived from][crate::ptr#provenance] a pointer to some /// [allocated object], and the entire memory range between `self` and the result must be in /// bounds of that allocated object. In particular, this range must not "wrap around" the edge /// of the address space. diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs index 3e4cae2b3cabd..d91bbe1a5a193 100644 --- a/library/core/src/ptr/non_null.rs +++ b/library/core/src/ptr/non_null.rs @@ -283,40 +283,39 @@ impl NonNull { /// /// For more details see the equivalent method on a raw pointer, [`pointer::addr`]. /// - /// This API and its claimed semantics are part of the Strict Provenance experiment, - /// see the [`ptr` module documentation][crate::ptr]. + /// This is a [Strict Provenance][crate::ptr#strict-provenance] API. #[must_use] #[inline] - #[unstable(feature = "strict_provenance", issue = "95228")] + #[stable(feature = "strict_provenance", since = "CURRENT_RUSTC_VERSION")] pub fn addr(self) -> NonZero { // SAFETY: The pointer is guaranteed by the type to be non-null, // meaning that the address will be non-zero. unsafe { NonZero::new_unchecked(self.pointer.addr()) } } - /// Creates a new pointer with the given address. + /// Creates a new pointer with the given address and the [provenance][crate::ptr#provenance] of + /// `self`. /// /// For more details see the equivalent method on a raw pointer, [`pointer::with_addr`]. /// - /// This API and its claimed semantics are part of the Strict Provenance experiment, - /// see the [`ptr` module documentation][crate::ptr]. + /// This is a [Strict Provenance][crate::ptr#strict-provenance] API. #[must_use] #[inline] - #[unstable(feature = "strict_provenance", issue = "95228")] + #[stable(feature = "strict_provenance", since = "CURRENT_RUSTC_VERSION")] pub fn with_addr(self, addr: NonZero) -> Self { // SAFETY: The result of `ptr::from::with_addr` is non-null because `addr` is guaranteed to be non-zero. unsafe { NonNull::new_unchecked(self.pointer.with_addr(addr.get()) as *mut _) } } - /// Creates a new pointer by mapping `self`'s address to a new one. + /// Creates a new pointer by mapping `self`'s address to a new one, preserving the + /// [provenance][crate::ptr#provenance] of `self`. /// /// For more details see the equivalent method on a raw pointer, [`pointer::map_addr`]. /// - /// This API and its claimed semantics are part of the Strict Provenance experiment, - /// see the [`ptr` module documentation][crate::ptr]. + /// This is a [Strict Provenance][crate::ptr#strict-provenance] API. #[must_use] #[inline] - #[unstable(feature = "strict_provenance", issue = "95228")] + #[stable(feature = "strict_provenance", since = "CURRENT_RUSTC_VERSION")] pub fn map_addr(self, f: impl FnOnce(NonZero) -> NonZero) -> Self { self.with_addr(f(self.addr())) } @@ -749,7 +748,6 @@ impl NonNull { /// *Incorrect* usage: /// /// ```rust,no_run - /// #![feature(strict_provenance)] /// use std::ptr::NonNull; /// /// let ptr1 = NonNull::new(Box::into_raw(Box::new(0u8))).unwrap(); diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs index 42b68e28273e5..17ba18c2a669f 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs @@ -1758,7 +1758,7 @@ impl AtomicPtr { /// # Examples /// /// ``` - /// #![feature(strict_provenance_atomic_ptr, strict_provenance)] + /// #![feature(strict_provenance_atomic_ptr)] /// use core::sync::atomic::{AtomicPtr, Ordering}; /// /// let atom = AtomicPtr::::new(core::ptr::null_mut()); @@ -1838,7 +1838,7 @@ impl AtomicPtr { /// # Examples /// /// ``` - /// #![feature(strict_provenance_atomic_ptr, strict_provenance)] + /// #![feature(strict_provenance_atomic_ptr)] /// use core::sync::atomic::{AtomicPtr, Ordering}; /// /// let atom = AtomicPtr::::new(core::ptr::null_mut()); @@ -1874,7 +1874,7 @@ impl AtomicPtr { /// # Examples /// /// ``` - /// #![feature(strict_provenance_atomic_ptr, strict_provenance)] + /// #![feature(strict_provenance_atomic_ptr)] /// use core::sync::atomic::{AtomicPtr, Ordering}; /// /// let atom = AtomicPtr::::new(core::ptr::without_provenance_mut(1)); @@ -1919,7 +1919,7 @@ impl AtomicPtr { /// # Examples /// /// ``` - /// #![feature(strict_provenance_atomic_ptr, strict_provenance)] + /// #![feature(strict_provenance_atomic_ptr)] /// use core::sync::atomic::{AtomicPtr, Ordering}; /// /// let pointer = &mut 3i64 as *mut i64; @@ -1970,7 +1970,7 @@ impl AtomicPtr { /// # Examples /// /// ``` - /// #![feature(strict_provenance_atomic_ptr, strict_provenance)] + /// #![feature(strict_provenance_atomic_ptr)] /// use core::sync::atomic::{AtomicPtr, Ordering}; /// /// let pointer = &mut 3i64 as *mut i64; @@ -2020,7 +2020,7 @@ impl AtomicPtr { /// # Examples /// /// ``` - /// #![feature(strict_provenance_atomic_ptr, strict_provenance)] + /// #![feature(strict_provenance_atomic_ptr)] /// use core::sync::atomic::{AtomicPtr, Ordering}; /// /// let pointer = &mut 3i64 as *mut i64; diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index 443090097c0eb..5d6921845d0c9 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -1,4 +1,6 @@ // tidy-alphabetical-start +#![cfg_attr(bootstrap, feature(strict_provenance))] +#![cfg_attr(not(bootstrap), feature(strict_provenance_lints))] #![cfg_attr(target_has_atomic = "128", feature(integer_atomics))] #![cfg_attr(test, feature(cfg_match))] #![feature(alloc_layout_extra)] @@ -85,7 +87,6 @@ #![feature(std_internals)] #![feature(step_trait)] #![feature(str_internals)] -#![feature(strict_provenance)] #![feature(strict_provenance_atomic_ptr)] #![feature(test)] #![feature(trait_upcasting)] diff --git a/library/panic_unwind/src/lib.rs b/library/panic_unwind/src/lib.rs index 6cd4dffb8aa30..1981675f40922 100644 --- a/library/panic_unwind/src/lib.rs +++ b/library/panic_unwind/src/lib.rs @@ -19,8 +19,6 @@ #![feature(panic_unwind)] #![feature(staged_api)] #![feature(std_internals)] -#![feature(strict_provenance)] -#![feature(exposed_provenance)] #![feature(rustc_attrs)] #![panic_runtime] #![feature(panic_runtime)] diff --git a/library/portable-simd/crates/core_simd/src/lib.rs b/library/portable-simd/crates/core_simd/src/lib.rs index cc6246b4a0d41..992a7705e3c52 100644 --- a/library/portable-simd/crates/core_simd/src/lib.rs +++ b/library/portable-simd/crates/core_simd/src/lib.rs @@ -9,7 +9,6 @@ repr_simd, simd_ffi, staged_api, - strict_provenance, prelude_import, ptr_metadata )] diff --git a/library/portable-simd/crates/core_simd/tests/pointers.rs b/library/portable-simd/crates/core_simd/tests/pointers.rs index 90bfc5d5fd6a5..d7db4e82b3ca2 100644 --- a/library/portable-simd/crates/core_simd/tests/pointers.rs +++ b/library/portable-simd/crates/core_simd/tests/pointers.rs @@ -1,4 +1,4 @@ -#![feature(portable_simd, strict_provenance, exposed_provenance)] +#![feature(portable_simd)] use core_simd::simd::{ ptr::{SimdConstPtr, SimdMutPtr}, diff --git a/library/proc_macro/src/lib.rs b/library/proc_macro/src/lib.rs index 72b597a8083ba..ae47bb7adf49a 100644 --- a/library/proc_macro/src/lib.rs +++ b/library/proc_macro/src/lib.rs @@ -32,7 +32,6 @@ #![feature(restricted_std)] #![feature(rustc_attrs)] #![feature(min_specialization)] -#![feature(strict_provenance)] #![recursion_limit = "256"] #![allow(internal_features)] #![deny(ffi_unwind_calls)] diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 3ab652383689c..8c1a3c7682930 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -279,6 +279,8 @@ // // Language features: // tidy-alphabetical-start +#![cfg_attr(bootstrap, feature(strict_provenance))] +#![cfg_attr(not(bootstrap), feature(strict_provenance_lints))] #![feature(alloc_error_handler)] #![feature(allocator_internals)] #![feature(allow_internal_unsafe)] @@ -336,7 +338,6 @@ #![feature(error_iter)] #![feature(exact_size_is_empty)] #![feature(exclusive_wrapper)] -#![feature(exposed_provenance)] #![feature(extend_one)] #![feature(float_gamma)] #![feature(float_minimum_maximum)] @@ -362,7 +363,6 @@ #![feature(slice_range)] #![feature(std_internals)] #![feature(str_internals)] -#![feature(strict_provenance)] #![feature(strict_provenance_atomic_ptr)] #![feature(ub_checks)] // tidy-alphabetical-end diff --git a/library/unwind/src/lib.rs b/library/unwind/src/lib.rs index 5a476d5843b2f..79baa5b0b83ec 100644 --- a/library/unwind/src/lib.rs +++ b/library/unwind/src/lib.rs @@ -2,7 +2,6 @@ #![unstable(feature = "panic_unwind", issue = "32837")] #![feature(link_cfg)] #![feature(staged_api)] -#![feature(strict_provenance)] #![cfg_attr(not(target_env = "msvc"), feature(libc))] #![cfg_attr( all(target_family = "wasm", not(target_os = "emscripten")), diff --git a/src/doc/unstable-book/src/language-features/strict-provenance.md b/src/doc/unstable-book/src/language-features/strict-provenance-lints.md similarity index 62% rename from src/doc/unstable-book/src/language-features/strict-provenance.md rename to src/doc/unstable-book/src/language-features/strict-provenance-lints.md index dc60f3f375d3c..81bdf07a86af9 100644 --- a/src/doc/unstable-book/src/language-features/strict-provenance.md +++ b/src/doc/unstable-book/src/language-features/strict-provenance-lints.md @@ -1,18 +1,17 @@ -# `strict_provenance` +# `strict_provenance_lints` The tracking issue for this feature is: [#95228] [#95228]: https://github.com/rust-lang/rust/issues/95228 ----- -The `strict_provenance` feature allows to enable the `fuzzy_provenance_casts` and `lossy_provenance_casts` lints. +The `strict_provenance_lints` feature allows to enable the `fuzzy_provenance_casts` and `lossy_provenance_casts` lints. These lint on casts between integers and pointers, that are recommended against or invalid in the strict provenance model. -The same feature gate is also used for the experimental strict provenance API in `std` (actually `core`). ## Example ```rust -#![feature(strict_provenance)] +#![feature(strict_provenance_lints)] #![warn(fuzzy_provenance_casts)] fn main() { diff --git a/src/tools/linkchecker/main.rs b/src/tools/linkchecker/main.rs index fa77ab1e011cd..833e41df53706 100644 --- a/src/tools/linkchecker/main.rs +++ b/src/tools/linkchecker/main.rs @@ -100,6 +100,7 @@ fn main() { links_ignored_external: 0, links_ignored_exception: 0, intra_doc_exceptions: 0, + has_broken_urls: false, }; checker.walk(&docs, &mut report); report.report(); @@ -116,6 +117,8 @@ struct Checker { struct Report { errors: u32, + // Used to provide help message to remind the user to register a page in `SUMMARY.md`. + has_broken_urls: bool, start: Instant, html_files: u32, html_redirects: u32, @@ -274,6 +277,7 @@ impl Checker { report.links_ignored_exception += 1; } else { report.errors += 1; + report.has_broken_urls = true; println!("{}:{}: broken link - `{}`", pretty_path, i, target_pretty_path); } return; @@ -438,6 +442,13 @@ impl Report { println!("number of links ignored due to exceptions: {}", self.links_ignored_exception); println!("number of intra doc links ignored: {}", self.intra_doc_exceptions); println!("errors found: {}", self.errors); + + if self.has_broken_urls { + eprintln!( + "NOTE: if you are adding or renaming a markdown file in a mdBook, don't forget to \ + register the page in SUMMARY.md" + ); + } } } diff --git a/src/tools/miri/src/lib.rs b/src/tools/miri/src/lib.rs index 9814858beaa90..660f2e493bc0f 100644 --- a/src/tools/miri/src/lib.rs +++ b/src/tools/miri/src/lib.rs @@ -11,8 +11,6 @@ #![feature(let_chains)] #![feature(trait_upcasting)] #![feature(strict_overflow_ops)] -#![feature(strict_provenance)] -#![feature(exposed_provenance)] #![feature(pointer_is_aligned_to)] #![feature(unqualified_local_imports)] // Configure clippy and other lints diff --git a/src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_to_raw_pointer.rs b/src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_to_raw_pointer.rs index 3e20b8da6223b..c63e926376d45 100644 --- a/src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_to_raw_pointer.rs +++ b/src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_to_raw_pointer.rs @@ -1,4 +1,3 @@ -#![feature(strict_provenance)] use std::ptr; fn direct_raw(x: *const (i32, i32)) -> *const i32 { diff --git a/src/tools/miri/tests/fail/dangling_pointers/deref_dangling_box.rs b/src/tools/miri/tests/fail/dangling_pointers/deref_dangling_box.rs index fa40f942b8f2f..b22c1b4c5e81a 100644 --- a/src/tools/miri/tests/fail/dangling_pointers/deref_dangling_box.rs +++ b/src/tools/miri/tests/fail/dangling_pointers/deref_dangling_box.rs @@ -1,6 +1,5 @@ // Should be caught even without retagging //@compile-flags: -Zmiri-disable-stacked-borrows -#![feature(strict_provenance)] use std::ptr::{self, addr_of_mut}; // Deref'ing a dangling raw pointer is fine, but for a dangling box it is not. diff --git a/src/tools/miri/tests/fail/dangling_pointers/deref_dangling_ref.rs b/src/tools/miri/tests/fail/dangling_pointers/deref_dangling_ref.rs index 036ef2580a87f..eeab7c333e597 100644 --- a/src/tools/miri/tests/fail/dangling_pointers/deref_dangling_ref.rs +++ b/src/tools/miri/tests/fail/dangling_pointers/deref_dangling_ref.rs @@ -1,6 +1,5 @@ // Should be caught even without retagging //@compile-flags: -Zmiri-disable-stacked-borrows -#![feature(strict_provenance)] use std::ptr::{self, addr_of_mut}; // Deref'ing a dangling raw pointer is fine, but for a dangling reference it is not. diff --git a/src/tools/miri/tests/fail/intrinsics/ptr_offset_from_different_ints.rs b/src/tools/miri/tests/fail/intrinsics/ptr_offset_from_different_ints.rs index c307dfddb6c1f..0acda559d3a51 100644 --- a/src/tools/miri/tests/fail/intrinsics/ptr_offset_from_different_ints.rs +++ b/src/tools/miri/tests/fail/intrinsics/ptr_offset_from_different_ints.rs @@ -1,4 +1,3 @@ -#![feature(strict_provenance)] use core::ptr; fn main() { diff --git a/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance3.rs b/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance3.rs index d6bbfd7d94c76..da381596284e5 100644 --- a/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance3.rs +++ b/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance3.rs @@ -1,4 +1,3 @@ -#![feature(strict_provenance)] use std::mem; #[repr(C, usize)] diff --git a/src/tools/miri/tests/fail/provenance/provenance_transmute.rs b/src/tools/miri/tests/fail/provenance/provenance_transmute.rs index bc5dd53dcf5e4..d72f10530d7ab 100644 --- a/src/tools/miri/tests/fail/provenance/provenance_transmute.rs +++ b/src/tools/miri/tests/fail/provenance/provenance_transmute.rs @@ -1,5 +1,4 @@ //@compile-flags: -Zmiri-permissive-provenance -#![feature(strict_provenance)] use std::mem; diff --git a/src/tools/miri/tests/fail/provenance/ptr_int_unexposed.rs b/src/tools/miri/tests/fail/provenance/ptr_int_unexposed.rs index f89378fcb3c4c..a43ba13e13d41 100644 --- a/src/tools/miri/tests/fail/provenance/ptr_int_unexposed.rs +++ b/src/tools/miri/tests/fail/provenance/ptr_int_unexposed.rs @@ -1,5 +1,4 @@ //@compile-flags: -Zmiri-permissive-provenance -#![feature(strict_provenance, exposed_provenance)] fn main() { let x: i32 = 3; diff --git a/src/tools/miri/tests/fail/provenance/ptr_invalid.rs b/src/tools/miri/tests/fail/provenance/ptr_invalid.rs index 512473cd89450..d4479f32e56fb 100644 --- a/src/tools/miri/tests/fail/provenance/ptr_invalid.rs +++ b/src/tools/miri/tests/fail/provenance/ptr_invalid.rs @@ -1,4 +1,3 @@ -#![feature(strict_provenance, exposed_provenance)] // Ensure that a `ptr::without_provenance` ptr is truly invalid. fn main() { diff --git a/src/tools/miri/tests/fail/provenance/ptr_invalid_offset.rs b/src/tools/miri/tests/fail/provenance/ptr_invalid_offset.rs index c8be521ef823d..53a16ce5d1b4c 100644 --- a/src/tools/miri/tests/fail/provenance/ptr_invalid_offset.rs +++ b/src/tools/miri/tests/fail/provenance/ptr_invalid_offset.rs @@ -1,5 +1,4 @@ //@compile-flags: -Zmiri-strict-provenance -#![feature(strict_provenance)] fn main() { let x = 22; diff --git a/src/tools/miri/tests/fail/provenance/strict_provenance_cast.rs b/src/tools/miri/tests/fail/provenance/strict_provenance_cast.rs index d7b54f640f653..4674ba841b445 100644 --- a/src/tools/miri/tests/fail/provenance/strict_provenance_cast.rs +++ b/src/tools/miri/tests/fail/provenance/strict_provenance_cast.rs @@ -1,5 +1,4 @@ //@compile-flags: -Zmiri-strict-provenance -#![feature(exposed_provenance)] fn main() { let addr = &0 as *const i32 as usize; diff --git a/src/tools/miri/tests/fail/stacked_borrows/exposed_only_ro.rs b/src/tools/miri/tests/fail/stacked_borrows/exposed_only_ro.rs index 608ab71891942..dfd7d4bb0be92 100644 --- a/src/tools/miri/tests/fail/stacked_borrows/exposed_only_ro.rs +++ b/src/tools/miri/tests/fail/stacked_borrows/exposed_only_ro.rs @@ -1,5 +1,4 @@ //@compile-flags: -Zmiri-permissive-provenance -#![feature(exposed_provenance)] // If we have only exposed read-only pointers, doing a write through a wildcard ptr should fail. diff --git a/src/tools/miri/tests/fail/unaligned_pointers/promise_alignment.rs b/src/tools/miri/tests/fail/unaligned_pointers/promise_alignment.rs index e075db66039bc..009ce1eb88262 100644 --- a/src/tools/miri/tests/fail/unaligned_pointers/promise_alignment.rs +++ b/src/tools/miri/tests/fail/unaligned_pointers/promise_alignment.rs @@ -1,6 +1,5 @@ //@compile-flags: -Zmiri-symbolic-alignment-check //@revisions: call_unaligned_ptr read_unaligned_ptr -#![feature(strict_provenance)] #[path = "../../utils/mod.rs"] mod utils; diff --git a/src/tools/miri/tests/fail/uninit/uninit_alloc_diagnostic_with_provenance.rs b/src/tools/miri/tests/fail/uninit/uninit_alloc_diagnostic_with_provenance.rs index 954571f4a22cf..1cf70d9d9a340 100644 --- a/src/tools/miri/tests/fail/uninit/uninit_alloc_diagnostic_with_provenance.rs +++ b/src/tools/miri/tests/fail/uninit/uninit_alloc_diagnostic_with_provenance.rs @@ -1,7 +1,6 @@ //@compile-flags: -Zmiri-disable-validation //@error-in-other-file: memory is uninitialized at [0x4..0x8] //@normalize-stderr-test: "a[0-9]+" -> "ALLOC" -#![feature(strict_provenance)] #![allow(dropping_copy_types)] // Test printing allocations that contain single-byte provenance. diff --git a/src/tools/miri/tests/pass-dep/libc/libc-affinity.rs b/src/tools/miri/tests/pass-dep/libc/libc-affinity.rs index 8aa8c7dcb8e6a..3c4311efc4cdb 100644 --- a/src/tools/miri/tests/pass-dep/libc/libc-affinity.rs +++ b/src/tools/miri/tests/pass-dep/libc/libc-affinity.rs @@ -3,7 +3,6 @@ //@compile-flags: -Zmiri-disable-isolation -Zmiri-num-cpus=4 #![feature(io_error_more)] #![feature(pointer_is_aligned_to)] -#![feature(strict_provenance)] use std::mem::{size_of, size_of_val}; diff --git a/src/tools/miri/tests/pass-dep/libc/libc-epoll-no-blocking.rs b/src/tools/miri/tests/pass-dep/libc/libc-epoll-no-blocking.rs index 3ea345133769b..288c1d41f3077 100644 --- a/src/tools/miri/tests/pass-dep/libc/libc-epoll-no-blocking.rs +++ b/src/tools/miri/tests/pass-dep/libc/libc-epoll-no-blocking.rs @@ -1,6 +1,5 @@ //@only-target: linux -#![feature(strict_provenance)] use std::convert::TryInto; fn main() { diff --git a/src/tools/miri/tests/pass-dep/libc/libc-mem.rs b/src/tools/miri/tests/pass-dep/libc/libc-mem.rs index c399616b9aee5..10be78798a609 100644 --- a/src/tools/miri/tests/pass-dep/libc/libc-mem.rs +++ b/src/tools/miri/tests/pass-dep/libc/libc-mem.rs @@ -1,4 +1,4 @@ -#![feature(strict_provenance, pointer_is_aligned_to)] +#![feature(pointer_is_aligned_to)] use std::{mem, ptr, slice}; fn test_memcpy() { diff --git a/src/tools/miri/tests/pass-dep/libc/libc-misc.rs b/src/tools/miri/tests/pass-dep/libc/libc-misc.rs index f3261eaa43c92..f07007fa70546 100644 --- a/src/tools/miri/tests/pass-dep/libc/libc-misc.rs +++ b/src/tools/miri/tests/pass-dep/libc/libc-misc.rs @@ -2,7 +2,6 @@ //@compile-flags: -Zmiri-disable-isolation #![feature(io_error_more)] #![feature(pointer_is_aligned_to)] -#![feature(strict_provenance)] use std::mem::transmute; diff --git a/src/tools/miri/tests/pass-dep/libc/mmap.rs b/src/tools/miri/tests/pass-dep/libc/mmap.rs index db305acbf4a7e..bfd840d2fb89d 100644 --- a/src/tools/miri/tests/pass-dep/libc/mmap.rs +++ b/src/tools/miri/tests/pass-dep/libc/mmap.rs @@ -1,6 +1,5 @@ //@ignore-target: windows # No mmap on Windows //@compile-flags: -Zmiri-disable-isolation -Zmiri-permissive-provenance -#![feature(strict_provenance)] use std::io::Error; use std::{ptr, slice}; diff --git a/src/tools/miri/tests/pass/align_offset_symbolic.rs b/src/tools/miri/tests/pass/align_offset_symbolic.rs index 9647277821fa1..c836a3b07cbe7 100644 --- a/src/tools/miri/tests/pass/align_offset_symbolic.rs +++ b/src/tools/miri/tests/pass/align_offset_symbolic.rs @@ -1,5 +1,4 @@ //@compile-flags: -Zmiri-symbolic-alignment-check -#![feature(strict_provenance)] use std::mem; diff --git a/src/tools/miri/tests/pass/atomic.rs b/src/tools/miri/tests/pass/atomic.rs index f84fe825d0106..2b2e89e6d70fc 100644 --- a/src/tools/miri/tests/pass/atomic.rs +++ b/src/tools/miri/tests/pass/atomic.rs @@ -2,7 +2,7 @@ //@[tree]compile-flags: -Zmiri-tree-borrows //@compile-flags: -Zmiri-strict-provenance -#![feature(strict_provenance, strict_provenance_atomic_ptr)] +#![feature(strict_provenance_atomic_ptr)] // FIXME(static_mut_refs): Do not allow `static_mut_refs` lint #![allow(static_mut_refs)] diff --git a/src/tools/miri/tests/pass/box-custom-alloc-aliasing.rs b/src/tools/miri/tests/pass/box-custom-alloc-aliasing.rs index 0a61db960c1d4..633291182839f 100644 --- a/src/tools/miri/tests/pass/box-custom-alloc-aliasing.rs +++ b/src/tools/miri/tests/pass/box-custom-alloc-aliasing.rs @@ -5,7 +5,6 @@ //@revisions: stack tree //@[tree]compile-flags: -Zmiri-tree-borrows #![feature(allocator_api)] -#![feature(strict_provenance)] use std::alloc::{AllocError, Allocator, Layout}; use std::cell::{Cell, UnsafeCell}; diff --git a/src/tools/miri/tests/pass/concurrency/address_reuse_happens_before.rs b/src/tools/miri/tests/pass/concurrency/address_reuse_happens_before.rs index 255f4061abce7..a293dd0bef108 100644 --- a/src/tools/miri/tests/pass/concurrency/address_reuse_happens_before.rs +++ b/src/tools/miri/tests/pass/concurrency/address_reuse_happens_before.rs @@ -1,7 +1,6 @@ //! Regression test for : //! When the address gets reused, there should be a happens-before relation. //@compile-flags: -Zmiri-address-reuse-cross-thread-rate=1.0 -#![feature(strict_provenance)] #![feature(sync_unsafe_cell)] use std::cell::SyncUnsafeCell; diff --git a/src/tools/miri/tests/pass/const-addrs.rs b/src/tools/miri/tests/pass/const-addrs.rs index 727c67ebfb574..af68b28b2b8cb 100644 --- a/src/tools/miri/tests/pass/const-addrs.rs +++ b/src/tools/miri/tests/pass/const-addrs.rs @@ -7,7 +7,6 @@ // MIR inlining will put every evaluation of the const we're repeatedly evaluating into the same // stack frame, breaking this test. //@compile-flags: -Zinline-mir=no -#![feature(strict_provenance)] const EVALS: usize = 256; diff --git a/src/tools/miri/tests/pass/drop_type_without_drop_glue.rs b/src/tools/miri/tests/pass/drop_type_without_drop_glue.rs index 43ddc8a4d8b55..2f8665e8d62c0 100644 --- a/src/tools/miri/tests/pass/drop_type_without_drop_glue.rs +++ b/src/tools/miri/tests/pass/drop_type_without_drop_glue.rs @@ -1,4 +1,4 @@ -#![feature(custom_mir, core_intrinsics, strict_provenance)] +#![feature(custom_mir, core_intrinsics)] use std::intrinsics::mir::*; // The `Drop` terminator on a type with no drop glue should be a NOP. diff --git a/src/tools/miri/tests/pass/extern_types.rs b/src/tools/miri/tests/pass/extern_types.rs index eade5c6ac0874..08e9caf4f1c11 100644 --- a/src/tools/miri/tests/pass/extern_types.rs +++ b/src/tools/miri/tests/pass/extern_types.rs @@ -1,6 +1,6 @@ //@revisions: stack tree //@[tree]compile-flags: -Zmiri-tree-borrows -#![feature(extern_types, strict_provenance)] +#![feature(extern_types)] use std::ptr; diff --git a/src/tools/miri/tests/pass/provenance.rs b/src/tools/miri/tests/pass/provenance.rs index 2e4d240cc48a1..8c52b703190d2 100644 --- a/src/tools/miri/tests/pass/provenance.rs +++ b/src/tools/miri/tests/pass/provenance.rs @@ -1,6 +1,5 @@ //@revisions: stack tree //@[tree]compile-flags: -Zmiri-tree-borrows -#![feature(strict_provenance)] use std::{mem, ptr}; const PTR_SIZE: usize = mem::size_of::<&i32>(); diff --git a/src/tools/miri/tests/pass/ptr_int_from_exposed.rs b/src/tools/miri/tests/pass/ptr_int_from_exposed.rs index ade5f537785b7..9a76c8dd34972 100644 --- a/src/tools/miri/tests/pass/ptr_int_from_exposed.rs +++ b/src/tools/miri/tests/pass/ptr_int_from_exposed.rs @@ -2,7 +2,6 @@ // Tree Borrows doesn't support int2ptr casts, but let's make sure we don't immediately crash either. //@[tree]compile-flags: -Zmiri-tree-borrows //@[stack]compile-flags: -Zmiri-permissive-provenance -#![feature(strict_provenance, exposed_provenance)] use std::ptr; diff --git a/src/tools/miri/tests/pass/ptr_raw.rs b/src/tools/miri/tests/pass/ptr_raw.rs index dcf13d97ce3d1..c958dfddf6912 100644 --- a/src/tools/miri/tests/pass/ptr_raw.rs +++ b/src/tools/miri/tests/pass/ptr_raw.rs @@ -1,4 +1,3 @@ -#![feature(strict_provenance)] use std::mem; use std::ptr::{self, addr_of}; diff --git a/src/tools/miri/tests/pass/shims/ptr_mask.rs b/src/tools/miri/tests/pass/shims/ptr_mask.rs index fb8bb6b13dbc2..6872ba577d251 100644 --- a/src/tools/miri/tests/pass/shims/ptr_mask.rs +++ b/src/tools/miri/tests/pass/shims/ptr_mask.rs @@ -1,5 +1,4 @@ #![feature(ptr_mask)] -#![feature(strict_provenance)] fn main() { let v: u32 = 0xABCDABCD; diff --git a/src/tools/miri/tests/pass/slices.rs b/src/tools/miri/tests/pass/slices.rs index 39e1d1cb97f26..dd18a061cdd51 100644 --- a/src/tools/miri/tests/pass/slices.rs +++ b/src/tools/miri/tests/pass/slices.rs @@ -4,7 +4,6 @@ #![feature(slice_as_chunks)] #![feature(slice_partition_dedup)] #![feature(layout_for_ptr)] -#![feature(strict_provenance)] use std::{ptr, slice}; diff --git a/src/tools/miri/tests/pass/stacked-borrows/int-to-ptr.rs b/src/tools/miri/tests/pass/stacked-borrows/int-to-ptr.rs index c89d79b42e31e..8a05fca3f312f 100644 --- a/src/tools/miri/tests/pass/stacked-borrows/int-to-ptr.rs +++ b/src/tools/miri/tests/pass/stacked-borrows/int-to-ptr.rs @@ -1,5 +1,4 @@ //@compile-flags: -Zmiri-permissive-provenance -#![feature(exposed_provenance)] use std::ptr; // Just to make sure that casting a ref to raw, to int and back to raw diff --git a/src/tools/miri/tests/pass/stacked-borrows/stack-printing.rs b/src/tools/miri/tests/pass/stacked-borrows/stack-printing.rs index 1478b21d6c180..e507f49b955e5 100644 --- a/src/tools/miri/tests/pass/stacked-borrows/stack-printing.rs +++ b/src/tools/miri/tests/pass/stacked-borrows/stack-printing.rs @@ -2,7 +2,6 @@ // printing, not how it interacts with the GC. //@compile-flags: -Zmiri-permissive-provenance -Zmiri-provenance-gc=0 -#![feature(strict_provenance)] use std::alloc::{self, Layout}; use std::mem::ManuallyDrop; diff --git a/src/tools/miri/tests/pass/stacked-borrows/unknown-bottom-gc.rs b/src/tools/miri/tests/pass/stacked-borrows/unknown-bottom-gc.rs index 55356814a1a03..b0f53283cdaf9 100644 --- a/src/tools/miri/tests/pass/stacked-borrows/unknown-bottom-gc.rs +++ b/src/tools/miri/tests/pass/stacked-borrows/unknown-bottom-gc.rs @@ -1,5 +1,4 @@ //@compile-flags: -Zmiri-permissive-provenance -#![feature(exposed_provenance)] use std::ptr; diff --git a/src/tools/miri/tests/pass/transmute_ptr.rs b/src/tools/miri/tests/pass/transmute_ptr.rs index ce6d86b7068a0..0944781c6defa 100644 --- a/src/tools/miri/tests/pass/transmute_ptr.rs +++ b/src/tools/miri/tests/pass/transmute_ptr.rs @@ -1,6 +1,5 @@ //@revisions: stack tree //@[tree]compile-flags: -Zmiri-tree-borrows -#![feature(strict_provenance)] use std::{mem, ptr}; fn t1() { diff --git a/src/tools/miri/tests/pass/underscore_pattern.rs b/src/tools/miri/tests/pass/underscore_pattern.rs index f59bb9f5c82d5..2f203bdc01e45 100644 --- a/src/tools/miri/tests/pass/underscore_pattern.rs +++ b/src/tools/miri/tests/pass/underscore_pattern.rs @@ -1,5 +1,4 @@ // Various tests ensuring that underscore patterns really just construct the place, but don't check its contents. -#![feature(strict_provenance)] #![feature(never_type)] use std::ptr; diff --git a/src/tools/miri/tests/pass/zero-sized-accesses-and-offsets.rs b/src/tools/miri/tests/pass/zero-sized-accesses-and-offsets.rs index a3356b682a6a5..6c0d9bc253aac 100644 --- a/src/tools/miri/tests/pass/zero-sized-accesses-and-offsets.rs +++ b/src/tools/miri/tests/pass/zero-sized-accesses-and-offsets.rs @@ -1,5 +1,4 @@ //! Tests specific for : zero-sized operations. -#![feature(strict_provenance)] use std::ptr; diff --git a/tests/codegen/atomicptr.rs b/tests/codegen/atomicptr.rs index ea8b382c8fcc7..e8c5e6a674970 100644 --- a/tests/codegen/atomicptr.rs +++ b/tests/codegen/atomicptr.rs @@ -6,7 +6,6 @@ //@ compile-flags: -O -Cno-prepopulate-passes #![crate_type = "lib"] -#![feature(strict_provenance)] #![feature(strict_provenance_atomic_ptr)] use std::ptr::without_provenance_mut; diff --git a/tests/codegen/issues/issue-103285-ptr-addr-overflow-check.rs b/tests/codegen/issues/issue-103285-ptr-addr-overflow-check.rs index d4a74b3d78283..122f02fbbc55b 100644 --- a/tests/codegen/issues/issue-103285-ptr-addr-overflow-check.rs +++ b/tests/codegen/issues/issue-103285-ptr-addr-overflow-check.rs @@ -1,7 +1,6 @@ //@ compile-flags: -O -C debug-assertions=yes #![crate_type = "lib"] -#![feature(strict_provenance)] #[no_mangle] pub fn test(src: *const u8, dst: *const u8) -> usize { diff --git a/tests/mir-opt/gvn_ptr_eq_with_constant.rs b/tests/mir-opt/gvn_ptr_eq_with_constant.rs index d8025072ee3d3..05445208e070f 100644 --- a/tests/mir-opt/gvn_ptr_eq_with_constant.rs +++ b/tests/mir-opt/gvn_ptr_eq_with_constant.rs @@ -5,8 +5,6 @@ // Regression for -#![feature(strict_provenance)] - struct Foo(std::marker::PhantomData); impl Foo { diff --git a/tests/run-make/rustc-crates-on-stable/rmake.rs b/tests/run-make/rustc-crates-on-stable/rmake.rs index 81cc775c91997..9fbc675cc9a3e 100644 --- a/tests/run-make/rustc-crates-on-stable/rmake.rs +++ b/tests/run-make/rustc-crates-on-stable/rmake.rs @@ -31,6 +31,10 @@ fn main() { "rustc_pattern_analysis", "-p", "rustc_lexer", + "-p", + "rustc_abi", + "-p", + "rustc_parse_format", ]) .run(); } diff --git a/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/basic.rs b/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/basic.rs index 0c9df7ecd7827..b2b4934aa5f18 100644 --- a/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/basic.rs +++ b/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/basic.rs @@ -2,8 +2,6 @@ //@ compile-flags: -Copt-level=2 //@ run-pass -#![feature(exposed_provenance)] - use std::ptr; fn main() { diff --git a/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/function.rs b/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/function.rs index b188b794d1fc7..bf130c9f75982 100644 --- a/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/function.rs +++ b/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/function.rs @@ -4,8 +4,6 @@ // Based on https://github.com/rust-lang/rust/issues/107975#issuecomment-1434203908 -#![feature(exposed_provenance)] - use std::ptr; fn f() -> usize { diff --git a/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/inline1.rs b/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/inline1.rs index 7f64e23b9c121..cdf07eade8740 100644 --- a/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/inline1.rs +++ b/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/inline1.rs @@ -4,8 +4,6 @@ // Based on https://github.com/rust-lang/rust/issues/107975#issuecomment-1432161340 -#![feature(exposed_provenance)] - use std::ptr; #[inline(never)] diff --git a/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/inline2.rs b/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/inline2.rs index 3417296ce125a..f128e1bb0841a 100644 --- a/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/inline2.rs +++ b/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/inline2.rs @@ -4,8 +4,6 @@ // Based on https://github.com/rust-lang/rust/issues/107975#issuecomment-1432161340 -#![feature(exposed_provenance)] - use std::ptr; #[inline(never)] diff --git a/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/print.rs b/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/print.rs index e1e9e3f46b8ae..0baf8886395e8 100644 --- a/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/print.rs +++ b/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/print.rs @@ -4,8 +4,6 @@ // https://github.com/rust-lang/rust/issues/107975#issuecomment-1430704499 -#![feature(exposed_provenance)] - use std::ptr; fn main() { diff --git a/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/print3.rs b/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/print3.rs index 8d581e8c9e93e..c7f46318aaef7 100644 --- a/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/print3.rs +++ b/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/print3.rs @@ -4,8 +4,6 @@ // https://github.com/rust-lang/rust/issues/107975#issuecomment-1430704499 -#![feature(exposed_provenance)] - use std::ptr; fn main() { diff --git a/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/segfault.rs b/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/segfault.rs index 506f114cd2a41..b163c282d9336 100644 --- a/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/segfault.rs +++ b/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/segfault.rs @@ -4,8 +4,6 @@ // https://github.com/rust-lang/rust/issues/107975#issuecomment-1431758601 -#![feature(exposed_provenance)] - use std::{ cell::{Ref, RefCell}, ptr, diff --git a/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/zero.rs b/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/zero.rs index 603db5e08f4af..7ccff8d0848e9 100644 --- a/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/zero.rs +++ b/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/zero.rs @@ -4,8 +4,6 @@ // Derived from https://github.com/rust-lang/rust/issues/107975#issuecomment-1431758601 -#![feature(exposed_provenance)] - use std::ptr; fn main() { diff --git a/tests/ui/codegen/equal-pointers-unequal/strict-provenance/basic.rs b/tests/ui/codegen/equal-pointers-unequal/strict-provenance/basic.rs index 0243c2bfe9511..4602ec654d107 100644 --- a/tests/ui/codegen/equal-pointers-unequal/strict-provenance/basic.rs +++ b/tests/ui/codegen/equal-pointers-unequal/strict-provenance/basic.rs @@ -2,8 +2,6 @@ //@ compile-flags: -Copt-level=2 //@ run-pass -#![feature(strict_provenance)] - use std::ptr; fn main() { diff --git a/tests/ui/codegen/equal-pointers-unequal/strict-provenance/function.rs b/tests/ui/codegen/equal-pointers-unequal/strict-provenance/function.rs index 29758036a21ed..789a78c15b4e2 100644 --- a/tests/ui/codegen/equal-pointers-unequal/strict-provenance/function.rs +++ b/tests/ui/codegen/equal-pointers-unequal/strict-provenance/function.rs @@ -4,8 +4,6 @@ // Based on https://github.com/rust-lang/rust/issues/107975#issuecomment-1434203908 -#![feature(strict_provenance)] - use std::ptr; fn f() -> usize { diff --git a/tests/ui/codegen/equal-pointers-unequal/strict-provenance/inline1.rs b/tests/ui/codegen/equal-pointers-unequal/strict-provenance/inline1.rs index 11925261a6529..5f4ee731f7d34 100644 --- a/tests/ui/codegen/equal-pointers-unequal/strict-provenance/inline1.rs +++ b/tests/ui/codegen/equal-pointers-unequal/strict-provenance/inline1.rs @@ -4,8 +4,6 @@ // Based on https://github.com/rust-lang/rust/issues/107975#issuecomment-1432161340 -#![feature(strict_provenance)] - use std::ptr; #[inline(never)] diff --git a/tests/ui/codegen/equal-pointers-unequal/strict-provenance/inline2.rs b/tests/ui/codegen/equal-pointers-unequal/strict-provenance/inline2.rs index e628bb90faac3..0414879804a5a 100644 --- a/tests/ui/codegen/equal-pointers-unequal/strict-provenance/inline2.rs +++ b/tests/ui/codegen/equal-pointers-unequal/strict-provenance/inline2.rs @@ -4,8 +4,6 @@ // Based on https://github.com/rust-lang/rust/issues/107975#issuecomment-1432161340 -#![feature(strict_provenance)] - use std::ptr; #[inline(never)] diff --git a/tests/ui/codegen/equal-pointers-unequal/strict-provenance/print.rs b/tests/ui/codegen/equal-pointers-unequal/strict-provenance/print.rs index 075e3475a32cc..b7165ce1e5ce3 100644 --- a/tests/ui/codegen/equal-pointers-unequal/strict-provenance/print.rs +++ b/tests/ui/codegen/equal-pointers-unequal/strict-provenance/print.rs @@ -4,8 +4,6 @@ // https://github.com/rust-lang/rust/issues/107975#issuecomment-1430704499 -#![feature(strict_provenance)] - use std::ptr; fn main() { diff --git a/tests/ui/codegen/equal-pointers-unequal/strict-provenance/print3.rs b/tests/ui/codegen/equal-pointers-unequal/strict-provenance/print3.rs index 6d7b6fa33e026..a02ff30918daf 100644 --- a/tests/ui/codegen/equal-pointers-unequal/strict-provenance/print3.rs +++ b/tests/ui/codegen/equal-pointers-unequal/strict-provenance/print3.rs @@ -4,8 +4,6 @@ // https://github.com/rust-lang/rust/issues/107975#issuecomment-1430704499 -#![feature(strict_provenance)] - use std::ptr; fn main() { diff --git a/tests/ui/codegen/equal-pointers-unequal/strict-provenance/segfault.rs b/tests/ui/codegen/equal-pointers-unequal/strict-provenance/segfault.rs index 67660d285a48a..fea41e0361294 100644 --- a/tests/ui/codegen/equal-pointers-unequal/strict-provenance/segfault.rs +++ b/tests/ui/codegen/equal-pointers-unequal/strict-provenance/segfault.rs @@ -4,8 +4,6 @@ // https://github.com/rust-lang/rust/issues/107975#issuecomment-1431758601 -#![feature(strict_provenance)] - use std::{ cell::{Ref, RefCell}, ptr, diff --git a/tests/ui/codegen/equal-pointers-unequal/strict-provenance/zero.rs b/tests/ui/codegen/equal-pointers-unequal/strict-provenance/zero.rs index a89310f993045..d963e45e4cdf2 100644 --- a/tests/ui/codegen/equal-pointers-unequal/strict-provenance/zero.rs +++ b/tests/ui/codegen/equal-pointers-unequal/strict-provenance/zero.rs @@ -4,8 +4,6 @@ // Derived from https://github.com/rust-lang/rust/issues/107975#issuecomment-1431758601 -#![feature(strict_provenance)] - use std::ptr; fn main() { diff --git a/tests/ui/feature-gates/feature-gate-strict_provenance.rs b/tests/ui/feature-gates/feature-gate-strict_provenance_lints.rs similarity index 100% rename from tests/ui/feature-gates/feature-gate-strict_provenance.rs rename to tests/ui/feature-gates/feature-gate-strict_provenance_lints.rs diff --git a/tests/ui/feature-gates/feature-gate-strict_provenance.stderr b/tests/ui/feature-gates/feature-gate-strict_provenance_lints.stderr similarity index 57% rename from tests/ui/feature-gates/feature-gate-strict_provenance.stderr rename to tests/ui/feature-gates/feature-gate-strict_provenance_lints.stderr index 82078d576ad68..15428cbd4be4c 100644 --- a/tests/ui/feature-gates/feature-gate-strict_provenance.stderr +++ b/tests/ui/feature-gates/feature-gate-strict_provenance_lints.stderr @@ -1,24 +1,24 @@ warning: unknown lint: `fuzzy_provenance_casts` - --> $DIR/feature-gate-strict_provenance.rs:3:1 + --> $DIR/feature-gate-strict_provenance_lints.rs:3:1 | LL | #![deny(fuzzy_provenance_casts)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: the `fuzzy_provenance_casts` lint is unstable - = note: see issue #95228 for more information - = help: add `#![feature(strict_provenance)]` to the crate attributes to enable + = note: see issue #130351 for more information + = help: add `#![feature(strict_provenance_lints)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date = note: `#[warn(unknown_lints)]` on by default warning: unknown lint: `lossy_provenance_casts` - --> $DIR/feature-gate-strict_provenance.rs:5:1 + --> $DIR/feature-gate-strict_provenance_lints.rs:5:1 | LL | #![deny(lossy_provenance_casts)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: the `lossy_provenance_casts` lint is unstable - = note: see issue #95228 for more information - = help: add `#![feature(strict_provenance)]` to the crate attributes to enable + = note: see issue #130351 for more information + = help: add `#![feature(strict_provenance_lints)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date warning: 2 warnings emitted diff --git a/tests/ui/lint/lint-strict-provenance-fuzzy-casts.rs b/tests/ui/lint/lint-strict-provenance-fuzzy-casts.rs index d2d72a68f1396..187209d4e207e 100644 --- a/tests/ui/lint/lint-strict-provenance-fuzzy-casts.rs +++ b/tests/ui/lint/lint-strict-provenance-fuzzy-casts.rs @@ -1,4 +1,4 @@ -#![feature(strict_provenance)] +#![feature(strict_provenance_lints)] #![deny(fuzzy_provenance_casts)] fn main() { diff --git a/tests/ui/lint/lint-strict-provenance-lossy-casts.rs b/tests/ui/lint/lint-strict-provenance-lossy-casts.rs index 9799a05375682..395dc75f82555 100644 --- a/tests/ui/lint/lint-strict-provenance-lossy-casts.rs +++ b/tests/ui/lint/lint-strict-provenance-lossy-casts.rs @@ -1,4 +1,4 @@ -#![feature(strict_provenance)] +#![feature(strict_provenance_lints)] #![deny(lossy_provenance_casts)] fn main() { diff --git a/tests/ui/lint/unit_bindings.deny_level.stderr b/tests/ui/lint/unit_bindings.deny_level.stderr new file mode 100644 index 0000000000000..9062f2e5c1f69 --- /dev/null +++ b/tests/ui/lint/unit_bindings.deny_level.stderr @@ -0,0 +1,40 @@ +error: binding has unit type `()` + --> $DIR/unit_bindings.rs:50:5 + | +LL | let _ = expr; + | ^^^^-^^^^^^^^ + | | + | this pattern is inferred to be the unit type `()` + | +note: the lint level is defined here + --> $DIR/unit_bindings.rs:22:30 + | +LL | #![cfg_attr(deny_level, deny(unit_bindings))] + | ^^^^^^^^^^^^^ + +error: binding has unit type `()` + --> $DIR/unit_bindings.rs:51:5 + | +LL | let pat = expr; + | ^^^^---^^^^^^^^ + | | + | this pattern is inferred to be the unit type `()` + +error: binding has unit type `()` + --> $DIR/unit_bindings.rs:52:5 + | +LL | let _pat = expr; + | ^^^^----^^^^^^^^ + | | + | this pattern is inferred to be the unit type `()` + +error: binding has unit type `()` + --> $DIR/unit_bindings.rs:55:5 + | +LL | let list = v.sort(); + | ^^^^----^^^^^^^^^^^^ + | | + | this pattern is inferred to be the unit type `()` + +error: aborting due to 4 previous errors + diff --git a/tests/ui/lint/unit_bindings.rs b/tests/ui/lint/unit_bindings.rs new file mode 100644 index 0000000000000..9a682a2244cbf --- /dev/null +++ b/tests/ui/lint/unit_bindings.rs @@ -0,0 +1,60 @@ +//! Basic checks for `unit_bindings` lint. +//! +//! The `unit_bindings` lint tries to detect cases like `let list = list.sort()`. The lint will +//! trigger on bindings that have the unit `()` type **except** if: +//! +//! - The user wrote `()` on either side, i.e. +//! - `let () = ;` or `let = ();` +//! - `let _ = ();` +//! - The binding occurs within macro expansions, e.g. `foo!();`. +//! - The user explicitly provided type annotations, e.g. `let x: () = `. +//! +//! Examples where the lint *should* fire on include: +//! +//! - `let _ = ;` +//! - `let pat = ;` +//! - `let _pat = ;` + +//@ revisions: default_level deny_level +//@[default_level] check-pass (`unit_bindings` is currently allow-by-default) + +#![allow(unused)] +#![cfg_attr(deny_level, deny(unit_bindings))] + +// The `list` binding below should trigger the lint if it's not contained in a macro expansion. +macro_rules! expands_to_sus { + () => { + let mut v = [1, 2, 3]; + let list = v.sort(); + } +} + +// No warning for `y` and `z` because it is provided as type parameter. +fn ty_param_check(x: T) { + let y = x; + let z: T = x; +} + +fn main() { + // No warning if user explicitly wrote `()` on either side. + let expr = (); + let () = expr; + let _ = (); + // No warning if user explicitly annotates the unit type on the binding. + let pat: () = expr; + // No warning for let bindings with unit type in macro expansions. + expands_to_sus!(); + // No warning for unit bindings in generic fns. + ty_param_check(()); + + let _ = expr; //[deny_level]~ ERROR binding has unit type + let pat = expr; //[deny_level]~ ERROR binding has unit type + let _pat = expr; //[deny_level]~ ERROR binding has unit type + + let mut v = [1, 2, 3]; + let list = v.sort(); //[deny_level]~ ERROR binding has unit type + + // Limitation: the lint currently does not fire on nested unit LHS bindings, i.e. + // this will not currently trigger the lint. + let (nested, _) = (expr, 0i32); +} diff --git a/tests/ui/mir/alignment/i686-pc-windows-msvc.rs b/tests/ui/mir/alignment/i686-pc-windows-msvc.rs index 379f61ae818f2..c6b47a6d679fb 100644 --- a/tests/ui/mir/alignment/i686-pc-windows-msvc.rs +++ b/tests/ui/mir/alignment/i686-pc-windows-msvc.rs @@ -7,8 +7,6 @@ // that will fail on dereferencing of a pointer to u64 which is not 8-byte-aligned but is // 4-byte-aligned. -#![feature(strict_provenance)] - fn main() { let mut x = [0u64; 2]; let ptr = x.as_mut_ptr(); diff --git a/tests/ui/mir/alignment/packed.rs b/tests/ui/mir/alignment/packed.rs index 1a12425f11a96..cf908365e1a5d 100644 --- a/tests/ui/mir/alignment/packed.rs +++ b/tests/ui/mir/alignment/packed.rs @@ -1,8 +1,6 @@ //@ run-pass //@ compile-flags: -C debug-assertions -#![feature(strict_provenance)] - #[repr(packed)] struct Misaligner { _head: u8, diff --git a/tests/ui/structs-enums/type-sizes.rs b/tests/ui/structs-enums/type-sizes.rs index f49ce33841af3..1961f10bd0aa4 100644 --- a/tests/ui/structs-enums/type-sizes.rs +++ b/tests/ui/structs-enums/type-sizes.rs @@ -5,7 +5,6 @@ #![allow(dead_code)] #![feature(never_type)] #![feature(pointer_is_aligned_to)] -#![feature(strict_provenance)] use std::mem::size_of; use std::num::NonZero; diff --git a/tests/ui/traits/fully-qualified-syntax-cast.rs b/tests/ui/traits/fully-qualified-syntax-cast.rs new file mode 100644 index 0000000000000..740220a074b33 --- /dev/null +++ b/tests/ui/traits/fully-qualified-syntax-cast.rs @@ -0,0 +1,15 @@ +// Regression test for #98565: Provide diagnostics when the user uses +// the built-in type `str` in a cast where a trait is expected. + +trait Foo { + fn foo(&self); +} + +impl Foo for String { + fn foo(&self) { + ::trim(self); + //~^ ERROR expected trait, found builtin type `str` + } +} + +fn main() {} diff --git a/tests/ui/traits/fully-qualified-syntax-cast.stderr b/tests/ui/traits/fully-qualified-syntax-cast.stderr new file mode 100644 index 0000000000000..1848c9184c6e7 --- /dev/null +++ b/tests/ui/traits/fully-qualified-syntax-cast.stderr @@ -0,0 +1,9 @@ +error[E0404]: expected trait, found builtin type `str` + --> $DIR/fully-qualified-syntax-cast.rs:10:18 + | +LL | ::trim(self); + | ^^^ not a trait + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0404`. diff --git a/tests/ui/traits/next-solver/canonical/do-not-bail-due-to-placeholders.rs b/tests/ui/traits/next-solver/canonical/do-not-bail-due-to-placeholders.rs new file mode 100644 index 0000000000000..3fc11f27d1fc6 --- /dev/null +++ b/tests/ui/traits/next-solver/canonical/do-not-bail-due-to-placeholders.rs @@ -0,0 +1,16 @@ +//@ compile-flags: -Znext-solver +//@ check-pass + +// When canonicalizing responses, we bail if there are too many inference variables. +// We previously also counted placeholders, which is incorrect. +#![recursion_limit = "8"] + +fn foo() {} + +fn bar() { + // The query response will contain 10 placeholders, which previously + // caused us to bail here. + foo::<(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9)>(); +} + +fn main() {} diff --git a/tests/ui/traits/next-solver/normalize/normalize-allow-too-many-vars.rs b/tests/ui/traits/next-solver/normalize/normalize-allow-too-many-vars.rs new file mode 100644 index 0000000000000..5284220ac38fe --- /dev/null +++ b/tests/ui/traits/next-solver/normalize/normalize-allow-too-many-vars.rs @@ -0,0 +1,52 @@ +//@ check-pass + +// When canonicalizing a response in the trait solver, we bail with overflow +// if there are too many non-region inference variables. Doing so in normalizes-to +// goals ends up hiding inference constraints in cases which we want to support, +// see #131969. To prevent this issue we do not check for too many inference +// variables in normalizes-to goals. +#![recursion_limit = "8"] + +trait Bound {} +trait Trait { + type Assoc; +} + + +impl Trait for (T0, T1, T2, T3, T4, T5, T6, T7) +where + T0: Trait, + T1: Trait, + T2: Trait, + T3: Trait, + T4: Trait, + T5: Trait, + T6: Trait, + T7: Trait, + ( + T0::Assoc, + T1::Assoc, + T2::Assoc, + T3::Assoc, + T4::Assoc, + T5::Assoc, + T6::Assoc, + T7::Assoc, + ): Clone, +{ + type Assoc = ( + T0::Assoc, + T1::Assoc, + T2::Assoc, + T3::Assoc, + T4::Assoc, + T5::Assoc, + T6::Assoc, + T7::Assoc, + ); +} + +trait Overlap {} +impl> Overlap for T {} +impl Overlap for (T0, T1, T2, T3, T4, T5, T6, T7) {} +fn main() {} diff --git a/tests/ui/traits/next-solver/overflow/coherence-alias-hang.rs b/tests/ui/traits/next-solver/overflow/coherence-alias-hang.rs index 0d5f42231e4ad..f88f74680b9db 100644 --- a/tests/ui/traits/next-solver/overflow/coherence-alias-hang.rs +++ b/tests/ui/traits/next-solver/overflow/coherence-alias-hang.rs @@ -1,8 +1,5 @@ //@ check-pass -//@ revisions: ai_current ai_next ia_current ia_next ii_current ii_next -//@[ai_next] compile-flags: -Znext-solver -//@[ia_next] compile-flags: -Znext-solver -//@[ii_next] compile-flags: -Znext-solver +//@ revisions: ai ia ii // Regression test for nalgebra hang . @@ -17,11 +14,11 @@ trait Trait { type Assoc: ?Sized; } impl Trait for W { - #[cfg(any(ai_current, ai_next))] + #[cfg(ai)] type Assoc = W>; - #[cfg(any(ia_current, ia_next))] + #[cfg(ia)] type Assoc = W, T::Assoc>; - #[cfg(any(ii_current, ii_next))] + #[cfg(ii)] type Assoc = W, Id>; } diff --git a/tests/ui/traits/next-solver/overflow/recursion-limit-zero-issue-115351.rs b/tests/ui/traits/next-solver/overflow/recursion-limit-zero-issue-115351.rs index 86d428cc0f059..dd8ad3c2dfe86 100644 --- a/tests/ui/traits/next-solver/overflow/recursion-limit-zero-issue-115351.rs +++ b/tests/ui/traits/next-solver/overflow/recursion-limit-zero-issue-115351.rs @@ -1,8 +1,8 @@ -//~ ERROR overflow evaluating the requirement `Self: Trait` -//~^ ERROR overflow evaluating the requirement `Self well-formed` -// This is a non-regression test for issue #115351, where a recursion limit of 0 caused an ICE. +//@ check-pass //@ compile-flags: -Znext-solver --crate-type=lib +// This is a non-regression test for issue #115351, where a recursion limit of 0 caused an ICE. + #![recursion_limit = "0"] trait Trait {} impl Trait for u32 {} diff --git a/tests/ui/traits/next-solver/overflow/recursion-limit-zero-issue-115351.stderr b/tests/ui/traits/next-solver/overflow/recursion-limit-zero-issue-115351.stderr deleted file mode 100644 index 2eed7e8f7233e..0000000000000 --- a/tests/ui/traits/next-solver/overflow/recursion-limit-zero-issue-115351.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error[E0275]: overflow evaluating the requirement `Self: Trait` - | - = help: consider increasing the recursion limit by adding a `#![recursion_limit = "2"]` attribute to your crate (`recursion_limit_zero_issue_115351`) - -error[E0275]: overflow evaluating the requirement `Self well-formed` - | - = help: consider increasing the recursion limit by adding a `#![recursion_limit = "2"]` attribute to your crate (`recursion_limit_zero_issue_115351`) - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0275`.