Rollup merge of #122964 - joboet:pointer_expose, r=Amanieu

Rename `expose_addr` to `expose_provenance`

`expose_addr` is a bad name, an address is just a number and cannot be exposed. The operation is actually about the provenance of the pointer.

This PR thus changes the name of the method to `expose_provenance` without changing its return type. There is sufficient precedence for returning a useful value from an operation that does something else without the name indicating such, e.g. [`Option::insert`](https://doc.rust-lang.org/nightly/std/option/enum.Option.html#method.insert) and [`MaybeUninit::write`](https://doc.rust-lang.org/nightly/std/mem/union.MaybeUninit.html#method.write).

Returning the address is merely convenient, not a fundamental part of the operation. This is implied by the fact that integers do not have provenance since
```rust
let addr = ptr.addr();
ptr.expose_provenance();
let new = ptr::with_exposed_provenance(addr);
```
must behave exactly like
```rust
let addr = ptr.expose_provenance();
let new = ptr::with_exposed_provenance(addr);
```
as the result of `ptr.expose_provenance()` and `ptr.addr()` is the same integer. Therefore, this PR removes the `#[must_use]` annotation on the function and updates the documentation to reflect the important part.

~~An alternative name would be `expose_provenance`. I'm not at all opposed to that, but it makes a stronger implication than we might want that the provenance of the pointer returned by `ptr::with_exposed_provenance`[^1] is the same as that what was exposed, which is not yet specified as such IIUC. IMHO `expose` does not make that connection.~~

A previous version of this PR suggested `expose` as name, libs-api [decided on](https://github.com/rust-lang/rust/pull/122964#issuecomment-2033194319) `expose_provenance` to keep the symmetry with `with_exposed_provenance`.

CC `@RalfJung`
r? libs-api

[^1]: I'm using the new name for `from_exposed_addr` suggested by #122935 here.
This commit is contained in:
Matthias Krüger 2024-04-03 22:11:00 +02:00 committed by GitHub
commit 80d592cc24
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
49 changed files with 105 additions and 99 deletions

View file

@ -2261,7 +2261,7 @@ fn check_rvalue(&mut self, body: &Body<'tcx>, rvalue: &Rvalue<'tcx>, location: L
}
}
CastKind::PointerExposeAddress => {
CastKind::PointerExposeProvenance => {
let ty_from = op.ty(body, tcx);
let cast_ty_from = CastTy::from_ty(ty_from);
let cast_ty_to = CastTy::from_ty(*ty);
@ -2271,7 +2271,7 @@ fn check_rvalue(&mut self, body: &Body<'tcx>, rvalue: &Rvalue<'tcx>, location: L
span_mirbug!(
self,
rvalue,
"Invalid PointerExposeAddress cast {:?} -> {:?}",
"Invalid PointerExposeProvenance cast {:?} -> {:?}",
ty_from,
ty
)

View file

@ -649,7 +649,7 @@ fn codegen_stmt<'tcx>(
| CastKind::IntToFloat
| CastKind::FnPtrToPtr
| CastKind::PtrToPtr
| CastKind::PointerExposeAddress
| CastKind::PointerExposeProvenance
| CastKind::PointerWithExposedProvenance,
ref operand,
to_ty,

View file

@ -965,7 +965,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
});
}
sym::simd_expose_addr | sym::simd_with_exposed_provenance | sym::simd_cast_ptr => {
sym::simd_expose_provenance | sym::simd_with_exposed_provenance | sym::simd_cast_ptr => {
intrinsic_args!(fx, args => (arg); intrinsic);
ret.write_cvalue_transmute(fx, arg);
}

View file

@ -2111,7 +2111,7 @@ macro_rules! bitwise_red {
return Ok(args[0].immediate());
}
if name == sym::simd_expose_addr {
if name == sym::simd_expose_provenance {
let (out_len, out_elem) = require_simd!(ret_ty, SimdReturn);
require!(
in_len == out_len,

View file

@ -405,7 +405,7 @@ pub fn codegen_rvalue_operand(
let cast = bx.cx().layout_of(self.monomorphize(mir_cast_ty));
let val = match *kind {
mir::CastKind::PointerExposeAddress => {
mir::CastKind::PointerExposeProvenance => {
assert!(bx.cx().is_backend_immediate(cast));
let llptr = operand.immediate();
let llcast_ty = bx.cx().immediate_backend_type(cast);

View file

@ -34,9 +34,9 @@ pub fn cast(
self.unsize_into(src, cast_layout, dest)?;
}
CastKind::PointerExposeAddress => {
CastKind::PointerExposeProvenance => {
let src = self.read_immediate(src)?;
let res = self.pointer_expose_address_cast(&src, cast_layout)?;
let res = self.pointer_expose_provenance_cast(&src, cast_layout)?;
self.write_immediate(*res, dest)?;
}
@ -225,7 +225,7 @@ pub fn ptr_to_ptr(
}
}
pub fn pointer_expose_address_cast(
pub fn pointer_expose_provenance_cast(
&mut self,
src: &ImmTy<'tcx, M::Provenance>,
cast_to: TyAndLayout<'tcx>,

View file

@ -544,7 +544,7 @@ fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
// Unsizing is implemented for CTFE.
}
Rvalue::Cast(CastKind::PointerExposeAddress, _, _) => {
Rvalue::Cast(CastKind::PointerExposeProvenance, _, _) => {
self.check_op(ops::RawPtrToIntCast);
}
Rvalue::Cast(CastKind::PointerWithExposedProvenance, _, _) => {

View file

@ -1077,7 +1077,7 @@ macro_rules! check_kinds {
}
// FIXME: Add Checks for these
CastKind::PointerWithExposedProvenance
| CastKind::PointerExposeAddress
| CastKind::PointerExposeProvenance
| CastKind::PointerCoercion(_) => {}
CastKind::IntToInt | CastKind::IntToFloat => {
let input_valid = op_ty.is_integral() || op_ty.is_char() || op_ty.is_bool();

View file

@ -627,7 +627,7 @@ pub fn check_intrinsic_type(
sym::simd_cast
| sym::simd_as
| sym::simd_cast_ptr
| sym::simd_expose_addr
| sym::simd_expose_provenance
| sym::simd_with_exposed_provenance => (2, 0, vec![param(0)], param(1)),
sym::simd_bitmask => (2, 0, vec![param(0)], param(1)),
sym::simd_select | sym::simd_select_bitmask => {

View file

@ -91,7 +91,7 @@ hir_typeck_lossy_provenance_int2ptr =
hir_typeck_lossy_provenance_ptr2int =
under strict provenance it is considered bad style to cast pointer `{$expr_ty}` to integer `{$cast_ty}`
.suggestion = use `.addr()` to obtain the address of a pointer
.help = if you can't comply with strict provenance and need to expose the pointer provenance you can use `.expose_addr()` instead
.help = if you can't comply with strict provenance and need to expose the pointer provenance you can use `.expose_provenance()` instead
hir_typeck_method_call_on_unknown_raw_pointee =
cannot call a method on a raw pointer with an unknown pointee type

View file

@ -2797,17 +2797,17 @@
/// Since this cast is lossy, it is considered good style to use the
/// [`ptr::addr`] method instead, which has a similar effect, but doesn't
/// "expose" the pointer provenance. This improves optimisation potential.
/// See the docs of [`ptr::addr`] and [`ptr::expose_addr`] for more information
/// See the docs of [`ptr::addr`] and [`ptr::expose_provenance`] for more information
/// about exposing pointer provenance.
///
/// If your code can't comply with strict provenance and needs to expose
/// the provenance, then there is [`ptr::expose_addr`] as an escape hatch,
/// the provenance, then there is [`ptr::expose_provenance`] as an escape hatch,
/// which preserves the behaviour of `as usize` casts while being explicit
/// about the semantics.
///
/// [issue #95228]: https://github.com/rust-lang/rust/issues/95228
/// [`ptr::addr`]: https://doc.rust-lang.org/core/primitive.pointer.html#method.addr
/// [`ptr::expose_addr`]: https://doc.rust-lang.org/core/primitive.pointer.html#method.expose_addr
/// [`ptr::expose_provenance`]: https://doc.rust-lang.org/core/primitive.pointer.html#method.expose_provenance
pub LOSSY_PROVENANCE_CASTS,
Allow,
"a lossy pointer to integer cast is used",

View file

@ -409,7 +409,7 @@ pub fn is_safe_to_remove(&self) -> bool {
// Pointer to int casts may be side-effects due to exposing the provenance.
// While the model is undecided, we should be conservative. See
// <https://www.ralfj.de/blog/2022/04/11/provenance-exposed.html>
Rvalue::Cast(CastKind::PointerExposeAddress, _, _) => false,
Rvalue::Cast(CastKind::PointerExposeProvenance, _, _) => false,
Rvalue::Use(_)
| Rvalue::CopyForDeref(_)

View file

@ -1309,8 +1309,8 @@ pub enum Rvalue<'tcx> {
pub enum CastKind {
/// An exposing pointer to address cast. A cast between a pointer and an integer type, or
/// between a function pointer and an integer type.
/// See the docs on `expose_addr` for more details.
PointerExposeAddress,
/// See the docs on `expose_provenance` for more details.
PointerExposeProvenance,
/// An address-to-pointer cast that picks up an exposed provenance.
/// See the docs on `with_exposed_provenance` for more details.
PointerWithExposedProvenance,

View file

@ -83,7 +83,7 @@ pub fn mir_cast_kind<'tcx>(from_ty: Ty<'tcx>, cast_ty: Ty<'tcx>) -> mir::CastKin
let cast = CastTy::from_ty(cast_ty);
let cast_kind = match (from, cast) {
(Some(CastTy::Ptr(_) | CastTy::FnPtr), Some(CastTy::Int(_))) => {
mir::CastKind::PointerExposeAddress
mir::CastKind::PointerExposeProvenance
}
(Some(CastTy::Int(_)), Some(CastTy::Ptr(_))) => mir::CastKind::PointerWithExposedProvenance,
(_, Some(CastTy::DynStar)) => mir::CastKind::DynStar,

View file

@ -434,7 +434,7 @@ fn validate_rvalue(&mut self, rvalue: &Rvalue<'tcx>) -> Result<(), Unpromotable>
Rvalue::ThreadLocalRef(_) => return Err(Unpromotable),
// ptr-to-int casts are not possible in consts and thus not promotable
Rvalue::Cast(CastKind::PointerExposeAddress, _, _) => return Err(Unpromotable),
Rvalue::Cast(CastKind::PointerExposeProvenance, _, _) => return Err(Unpromotable),
// all other casts including int-to-ptr casts are fine, they just use the integer value
// at pointer type.

View file

@ -985,7 +985,7 @@ fn build_fn_ptr_addr_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, self_ty: Ty<'t
let locals = local_decls_for_sig(&sig, span);
let source_info = SourceInfo::outermost(span);
// FIXME: use `expose_addr` once we figure out whether function pointers have meaningful provenance.
// FIXME: use `expose_provenance` once we figure out whether function pointers have meaningful provenance.
let rvalue = Rvalue::Cast(
CastKind::FnPtrToPtr,
Operand::Move(Place::from(Local::new(1))),

View file

@ -267,7 +267,7 @@ impl<'tcx> Stable<'tcx> for mir::CastKind {
fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
use rustc_middle::mir::CastKind::*;
match self {
PointerExposeAddress => stable_mir::mir::CastKind::PointerExposeAddress,
PointerExposeProvenance => stable_mir::mir::CastKind::PointerExposeAddress,
PointerWithExposedProvenance => stable_mir::mir::CastKind::PointerWithExposedProvenance,
PointerCoercion(c) => stable_mir::mir::CastKind::PointerCoercion(c.stable(tables)),
DynStar => stable_mir::mir::CastKind::DynStar,

View file

@ -1659,7 +1659,7 @@
simd_cttz,
simd_div,
simd_eq,
simd_expose_addr,
simd_expose_provenance,
simd_extract,
simd_fabs,
simd_fcos,

View file

@ -971,6 +971,7 @@ pub enum PointerCoercion {
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum CastKind {
// FIXME(smir-rename): rename this to PointerExposeProvenance
PointerExposeAddress,
PointerWithExposedProvenance,
PointerCoercion(PointerCoercion),

View file

@ -2438,8 +2438,8 @@ fn fmt(&self, f: &mut Formatter<'_>) -> Result {
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> Pointer for *const T {
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
// Cast is needed here because `.expose_addr()` requires `T: Sized`.
pointer_fmt_inner((*self as *const ()).expose_addr(), f)
// Cast is needed here because `.expose_provenance()` requires `T: Sized`.
pointer_fmt_inner((*self as *const ()).expose_provenance(), f)
}
}

View file

@ -540,6 +540,10 @@
/// `T` must be a vector of pointers.
///
/// `U` must be a vector of `usize` with the same length as `T`.
#[cfg(not(bootstrap))]
#[rustc_nounwind]
pub fn simd_expose_provenance<T, U>(ptr: T) -> U;
#[cfg(bootstrap)]
#[rustc_nounwind]
pub fn simd_expose_addr<T, U>(ptr: T) -> U;
@ -660,5 +664,7 @@
pub fn simd_flog<T>(a: T) -> T;
}
#[cfg(bootstrap)]
pub use simd_expose_addr as simd_expose_provenance;
#[cfg(bootstrap)]
pub use simd_from_exposed_addr as simd_with_exposed_provenance;

View file

@ -136,7 +136,7 @@ pub const fn cast_mut(self) -> *mut T {
#[unstable(feature = "ptr_to_from_bits", issue = "91126")]
#[deprecated(
since = "1.67.0",
note = "replaced by the `expose_addr` method, or update your code \
note = "replaced by the `expose_provenance` method, or update your code \
to follow the strict provenance rules using its APIs"
)]
#[inline(always)]
@ -187,7 +187,7 @@ pub fn from_bits(bits: usize) -> Self
///
/// 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
/// or [`expose_addr`][pointer::expose_addr] and [`with_exposed_provenance`][with_exposed_provenance]
/// or [`expose_provenance`][pointer::expose_provenance] and [`with_exposed_provenance`][with_exposed_provenance]
/// instead. However, note that this makes your code less portable and less amenable to tools
/// that check for compliance with the Rust memory model.
///
@ -210,8 +210,8 @@ pub fn addr(self) -> usize {
unsafe { mem::transmute(self.cast::<()>()) }
}
/// Gets the "address" portion of the pointer, and 'exposes' the "provenance" part for future
/// use in [`with_exposed_provenance`][].
/// Exposes the "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
@ -238,7 +238,7 @@ pub fn addr(self) -> usize {
#[must_use]
#[inline(always)]
#[unstable(feature = "exposed_provenance", issue = "95228")]
pub fn expose_addr(self) -> usize {
pub fn expose_provenance(self) -> usize {
// FIXME(strict_provenance_magic): I am magic and should be a compiler intrinsic.
self.cast::<()>() as usize
}

View file

@ -340,8 +340,8 @@
//! 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].
//!
//! Exposed Provenance is provided by the [`expose_addr`] and [`with_exposed_provenance`] methods, which
//! are meant to replace `as` casts between pointers and integers. [`expose_addr`] is a lot like
//! 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`]
@ -355,9 +355,9 @@
//! there is *no* previously 'exposed' provenance that justifies the way the returned pointer will
//! be used, the program has undefined behavior.
//!
//! Using [`expose_addr`] or [`with_exposed_provenance`] (or the `as` casts) means that code is
//! 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_addr`] and
//! 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
@ -374,7 +374,7 @@
//! [`map_addr`]: pointer::map_addr
//! [`addr`]: pointer::addr
//! [`ptr::dangling`]: core::ptr::dangling
//! [`expose_addr`]: pointer::expose_addr
//! [`expose_provenance`]: pointer::expose_provenance
//! [`with_exposed_provenance`]: with_exposed_provenance
//! [Miri]: https://github.com/rust-lang/miri
//! [CHERI]: https://www.cl.cam.ac.uk/research/security/ctsrd/cheri/
@ -663,7 +663,7 @@ pub const fn dangling_mut<T>() -> *mut T {
///
/// 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_addr`][pointer::expose_addr], or a `ptr as usize` cast. In addition, memory which is
/// [`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.
@ -711,7 +711,7 @@ pub fn with_exposed_provenance<T>(addr: usize) -> *const T
///
/// 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_addr`][pointer::expose_addr] or a `ptr as usize` cast. If there is no previously
/// [`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

View file

@ -142,7 +142,7 @@ pub const fn cast_const(self) -> *const T {
#[unstable(feature = "ptr_to_from_bits", issue = "91126")]
#[deprecated(
since = "1.67.0",
note = "replaced by the `expose_addr` method, or update your code \
note = "replaced by the `expose_provenance` method, or update your code \
to follow the strict provenance rules using its APIs"
)]
#[inline(always)]
@ -194,7 +194,7 @@ pub fn from_bits(bits: usize) -> Self
///
/// 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
/// or [`expose_addr`][pointer::expose_addr] and [`with_exposed_provenance`][with_exposed_provenance]
/// or [`expose_provenance`][pointer::expose_provenance] and [`with_exposed_provenance`][with_exposed_provenance]
/// instead. However, note that this makes your code less portable and less amenable to tools
/// that check for compliance with the Rust memory model.
///
@ -217,8 +217,8 @@ pub fn addr(self) -> usize {
unsafe { mem::transmute(self.cast::<()>()) }
}
/// Gets the "address" portion of the pointer, and 'exposes' the "provenance" part for future
/// use in [`with_exposed_provenance`][].
/// Exposes the "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
@ -242,10 +242,9 @@ pub fn addr(self) -> usize {
/// API and its claimed semantics are part of [Exposed Provenance][super#exposed-provenance].
///
/// [`with_exposed_provenance_mut`]: with_exposed_provenance_mut
#[must_use]
#[inline(always)]
#[unstable(feature = "exposed_provenance", issue = "95228")]
pub fn expose_addr(self) -> usize {
pub fn expose_provenance(self) -> usize {
// FIXME(strict_provenance_magic): I am magic and should be a compiler intrinsic.
self.cast::<()>() as usize
}

View file

@ -50,9 +50,9 @@ pub trait SimdConstPtr: Copy + Sealed {
/// Equivalent to calling [`pointer::with_addr`] on each element.
fn with_addr(self, addr: Self::Usize) -> Self;
/// Gets the "address" portion of the pointer, and "exposes" the provenance part for future use
/// in [`Self::with_exposed_provenance`].
fn expose_addr(self) -> Self::Usize;
/// Exposes the "provenance" part of the pointer for future use in
/// [`Self::with_exposed_provenance`] and returns the "address" portion.
fn expose_provenance(self) -> Self::Usize;
/// Convert an address back to a pointer, picking up a previously "exposed" provenance.
///
@ -131,9 +131,9 @@ fn with_addr(self, addr: Self::Usize) -> Self {
}
#[inline]
fn expose_addr(self) -> Self::Usize {
fn expose_provenance(self) -> Self::Usize {
// Safety: `self` is a pointer vector
unsafe { core::intrinsics::simd::simd_expose_addr(self) }
unsafe { core::intrinsics::simd::simd_expose_provenance(self) }
}
#[inline]

View file

@ -47,9 +47,9 @@ pub trait SimdMutPtr: Copy + Sealed {
/// Equivalent to calling [`pointer::with_addr`] on each element.
fn with_addr(self, addr: Self::Usize) -> Self;
/// Gets the "address" portion of the pointer, and "exposes" the provenance part for future use
/// in [`Self::with_exposed_provenance`].
fn expose_addr(self) -> Self::Usize;
/// Exposes the "provenance" part of the pointer for future use in
/// [`Self::with_exposed_provenance`] and returns the "address" portion.
fn expose_provenance(self) -> Self::Usize;
/// Convert an address back to a pointer, picking up a previously "exposed" provenance.
///
@ -128,9 +128,9 @@ fn with_addr(self, addr: Self::Usize) -> Self {
}
#[inline]
fn expose_addr(self) -> Self::Usize {
fn expose_provenance(self) -> Self::Usize {
// Safety: `self` is a pointer vector
unsafe { core::intrinsics::simd::simd_expose_addr(self) }
unsafe { core::intrinsics::simd::simd_expose_provenance(self) }
}
#[inline]

View file

@ -32,10 +32,10 @@ fn with_addr<const LANES: usize>() {
);
}
fn expose_addr<const LANES: usize>() {
fn expose_provenance<const LANES: usize>() {
test_helpers::test_unary_elementwise(
&Simd::<*$constness u32, LANES>::expose_addr,
&<*$constness u32>::expose_addr,
&Simd::<*$constness u32, LANES>::expose_provenance,
&<*$constness u32>::expose_provenance,
&|_| true,
);
}

View file

@ -29,7 +29,7 @@ pub unsafe fn new_with_coreid(
let p = Box::into_raw(Box::new(p));
let tid = abi::spawn2(
thread_start,
p.expose_addr(),
p.expose_provenance(),
abi::Priority::into(abi::NORMAL_PRIO),
stack,
core_id,

View file

@ -181,7 +181,7 @@ pub unsafe fn new(stack: usize, p: Box<dyn FnOnce()>) -> io::Result<Thread> {
abi::acre_tsk(&abi::T_CTSK {
// Activate this task immediately
tskatr: abi::TA_ACT,
exinf: p_inner.as_ptr().expose_addr() as abi::EXINF,
exinf: p_inner.as_ptr().expose_provenance() as abi::EXINF,
// The entry point
task: Some(trampoline),
// Inherit the calling task's base priority

View file

@ -149,7 +149,7 @@ fn check_rvalue<'tcx>(
Err((span, "unsizing casts are not allowed in const fn".into()))
}
},
Rvalue::Cast(CastKind::PointerExposeAddress, _, _) => {
Rvalue::Cast(CastKind::PointerExposeProvenance, _, _) => {
Err((span, "casting pointers to ints is unstable in const fn".into()))
},
Rvalue::Cast(CastKind::DynStar, _, _) => {

View file

@ -18,8 +18,8 @@
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum ProvenanceMode {
/// We support `expose_addr`/`with_exposed_provenance` via "wildcard" provenance.
/// However, we want on `with_exposed_provenance` to alert the user of the precision loss.
/// We support `expose_provenance`/`with_exposed_provenance` via "wildcard" provenance.
/// However, we warn on `with_exposed_provenance` to alert the user of the precision loss.
Default,
/// Like `Default`, but without the warning.
Permissive,

View file

@ -514,7 +514,7 @@ enum Op {
dest.transmute(this.machine.layouts.uint(dest.layout.size).unwrap(), this)?;
this.write_int(res, &dest)?;
}
"cast" | "as" | "cast_ptr" | "expose_addr" | "with_exposed_provenance" => {
"cast" | "as" | "cast_ptr" | "expose_provenance" | "with_exposed_provenance" => {
let [op] = check_arg_count(args)?;
let (op, op_len) = this.operand_to_simd(op)?;
let (dest, dest_len) = this.mplace_to_simd(dest)?;
@ -524,7 +524,7 @@ enum Op {
let unsafe_cast = intrinsic_name == "cast";
let safe_cast = intrinsic_name == "as";
let ptr_cast = intrinsic_name == "cast_ptr";
let expose_cast = intrinsic_name == "expose_addr";
let expose_cast = intrinsic_name == "expose_provenance";
let from_exposed_cast = intrinsic_name == "with_exposed_provenance";
for i in 0..dest_len {
@ -557,7 +557,7 @@ enum Op {
this.ptr_to_ptr(&op, dest.layout)?,
// Ptr/Int casts
(ty::RawPtr(..), ty::Int(_) | ty::Uint(_)) if expose_cast =>
this.pointer_expose_address_cast(&op, dest.layout)?,
this.pointer_expose_provenance_cast(&op, dest.layout)?,
(ty::Int(_) | ty::Uint(_), ty::RawPtr(..)) if from_exposed_cast =>
this.pointer_with_exposed_provenance_cast(&op, dest.layout)?,
// Error otherwise

View file

@ -4,6 +4,6 @@
fn main() {
let x = 42;
let xptr = &x as *const i32;
let xptr_invalid = std::ptr::without_provenance::<i32>(xptr.expose_addr());
let xptr_invalid = std::ptr::without_provenance::<i32>(xptr.expose_provenance());
let _val = unsafe { *xptr_invalid }; //~ ERROR: is a dangling pointer
}

View file

@ -6,7 +6,7 @@
fn main() {
let mut x = 0;
let _fool = &mut x as *mut i32; // this would have fooled the old untagged pointer logic
let addr = (&x as *const i32).expose_addr();
let addr = (&x as *const i32).expose_provenance();
let ptr = std::ptr::with_exposed_provenance_mut::<i32>(addr);
unsafe { *ptr = 0 }; //~ ERROR: /write access using <wildcard> .* no exposed tags have suitable permission in the borrow stack/
}

View file

@ -7,6 +7,6 @@
fn main() {
// Pointer casts
let _val: Simd<*const u8, 4> = Simd::<*const i32, 4>::splat(ptr::null()).cast();
let addrs = Simd::<*const i32, 4>::splat(ptr::null()).expose_addr();
let addrs = Simd::<*const i32, 4>::splat(ptr::null()).expose_provenance();
let _ptrs = Simd::<*const i32, 4>::with_exposed_provenance(addrs);
}

View file

@ -10,7 +10,7 @@ fn ptr_roundtrip_out_of_bounds() {
let x: i32 = 3;
let x_ptr = &x as *const i32;
let x_usize = x_ptr.wrapping_offset(128).expose_addr();
let x_usize = x_ptr.wrapping_offset(128).expose_provenance();
let ptr = ptr::with_exposed_provenance::<i32>(x_usize).wrapping_offset(-128);
assert_eq!(unsafe { *ptr }, 3);
@ -24,8 +24,8 @@ fn ptr_roundtrip_confusion() {
let x_ptr = &x as *const i32;
let y_ptr = &y as *const i32;
let x_usize = x_ptr.expose_addr();
let y_usize = y_ptr.expose_addr();
let x_usize = x_ptr.expose_provenance();
let y_usize = y_ptr.expose_provenance();
let ptr = ptr::with_exposed_provenance::<i32>(y_usize);
let ptr = ptr.with_addr(x_usize);
@ -37,7 +37,7 @@ fn ptr_roundtrip_imperfect() {
let x: u8 = 3;
let x_ptr = &x as *const u8;
let x_usize = x_ptr.expose_addr() + 128;
let x_usize = x_ptr.expose_provenance() + 128;
let ptr = ptr::with_exposed_provenance::<u8>(x_usize).wrapping_offset(-128);
assert_eq!(unsafe { *ptr }, 3);
@ -48,7 +48,7 @@ fn ptr_roundtrip_null() {
let x = &42;
let x_ptr = x as *const i32;
let x_null_ptr = x_ptr.with_addr(0); // addr 0, but still the provenance of x
let null = x_null_ptr.expose_addr();
let null = x_null_ptr.expose_provenance();
assert_eq!(null, 0);
let x_null_ptr_copy = ptr::with_exposed_provenance::<i32>(null); // just a roundtrip, so has provenance of x (angelically)

View file

@ -17,7 +17,7 @@ fn example(variant: bool) {
unsafe {
fn not_so_innocent(x: &mut u32) -> usize {
let x_raw4 = x as *mut u32;
x_raw4.expose_addr()
x_raw4.expose_provenance()
}
let mut c = 42u32;
@ -26,7 +26,7 @@ fn not_so_innocent(x: &mut u32) -> usize {
// stack: [..., Unique(1)]
let x_raw2 = x_unique1 as *mut u32;
let x_raw2_addr = x_raw2.expose_addr();
let x_raw2_addr = x_raw2.expose_provenance();
// stack: [..., Unique(1), SharedRW(2)]
let x_unique3 = &mut *x_raw2;

View file

@ -9,7 +9,7 @@ fn main() {
// Expose the allocation and use the exposed pointer, creating an unknown bottom
unsafe {
let p: *mut u8 = ptr::with_exposed_provenance::<u8>(ptr.expose_addr()) as *mut u8;
let p: *mut u8 = ptr::with_exposed_provenance::<u8>(ptr.expose_provenance()) as *mut u8;
*p = 1;
}

View file

@ -19,7 +19,7 @@
StorageLive(_3);
_3 = const main::FOO;
_2 = &raw const (*_3);
_1 = move _2 as usize (PointerExposeAddress);
_1 = move _2 as usize (PointerExposeProvenance);
StorageDead(_2);
StorageDead(_3);
StorageLive(_4);

View file

@ -19,7 +19,7 @@
StorageLive(_3);
_3 = const main::FOO;
_2 = &raw const (*_3);
_1 = move _2 as usize (PointerExposeAddress);
_1 = move _2 as usize (PointerExposeProvenance);
StorageDead(_2);
StorageDead(_3);
StorageLive(_4);

View file

@ -4,12 +4,12 @@
#[inline(never)]
fn read(_: usize) { }
// EMIT_MIR pointer_expose_address.main.GVN.diff
// EMIT_MIR pointer_expose_provenance.main.GVN.diff
fn main() {
// CHECK-LABEL: fn main(
// CHECK: [[ptr:_.*]] = const main::FOO;
// CHECK: [[ref:_.*]] = &raw const (*[[ptr]]);
// CHECK: [[x:_.*]] = move [[ref]] as usize (PointerExposeAddress);
// CHECK: [[x:_.*]] = move [[ref]] as usize (PointerExposeProvenance);
// CHECK: = read([[x]])
const FOO: &i32 = &1;
let x = FOO as *const i32 as usize;

View file

@ -14,7 +14,7 @@
StorageLive(_2);
StorageLive(_3);
_3 = main as fn() (PointerCoercion(ReifyFnPointer));
_2 = move _3 as usize (PointerExposeAddress);
_2 = move _3 as usize (PointerExposeProvenance);
StorageDead(_3);
_1 = move _2 as *const fn() (PointerWithExposedProvenance);
StorageDead(_2);

View file

@ -4,7 +4,7 @@
fn main() {
// CHECK-LABEL: fn main(
// CHECK: [[ptr:_.*]] = main as fn() (PointerCoercion(ReifyFnPointer));
// CHECK: [[addr:_.*]] = move [[ptr]] as usize (PointerExposeAddress);
// CHECK: [[addr:_.*]] = move [[ptr]] as usize (PointerExposeProvenance);
// CHECK: [[back:_.*]] = move [[addr]] as *const fn() (PointerWithExposedProvenance);
let _ = main as usize as *const fn();
}

View file

@ -19,12 +19,12 @@
StorageLive(_2);
StorageLive(_3);
_3 = _1;
_2 = move _3 as usize (PointerExposeAddress);
_2 = move _3 as usize (PointerExposeProvenance);
StorageDead(_3);
StorageLive(_4);
StorageLive(_5);
_5 = _1;
_4 = move _5 as isize (PointerExposeAddress);
_4 = move _5 as isize (PointerExposeProvenance);
StorageDead(_5);
_0 = const ();
StorageDead(_4);

View file

@ -5,8 +5,8 @@
// EMIT_MIR provenance_soundness.pointer_to_int.DeadStoreElimination-initial.diff
fn pointer_to_int(p: *mut i32) {
// CHECK-LABEL: fn pointer_to_int(
// CHECK: {{_.*}} = {{.*}} as usize (PointerExposeAddress);
// CHECK: {{_.*}} = {{.*}} as isize (PointerExposeAddress);
// CHECK: {{_.*}} = {{.*}} as usize (PointerExposeProvenance);
// CHECK: {{_.*}} = {{.*}} as isize (PointerExposeProvenance);
let _x = p as usize;
let _y = p as isize;
}

View file

@ -1,7 +1,7 @@
- // MIR for `expose_addr` before SimplifyLocals-before-const-prop
+ // MIR for `expose_addr` after SimplifyLocals-before-const-prop
- // MIR for `expose_provenance` before SimplifyLocals-before-const-prop
+ // MIR for `expose_provenance` after SimplifyLocals-before-const-prop
fn expose_addr(_1: *const usize) -> () {
fn expose_provenance(_1: *const usize) -> () {
debug p => _1;
let mut _0: ();
let _2: usize;
@ -11,7 +11,7 @@
StorageLive(_2);
StorageLive(_3);
_3 = _1;
_2 = move _3 as usize (PointerExposeAddress);
_2 = move _3 as usize (PointerExposeProvenance);
StorageDead(_3);
StorageDead(_2);
_0 = const ();

View file

@ -63,8 +63,8 @@ fn t4() -> u32 {
unsafe { X + 1 }
}
// EMIT_MIR simplify_locals.expose_addr.SimplifyLocals-before-const-prop.diff
fn expose_addr(p: *const usize) {
// EMIT_MIR simplify_locals.expose_provenance.SimplifyLocals-before-const-prop.diff
fn expose_provenance(p: *const usize) {
// Used pointer to address cast. Has a side effect of exposing the provenance.
p as usize;
}
@ -78,5 +78,5 @@ fn main() {
t2();
t3();
t4();
expose_addr(&0);
expose_provenance(&0);
}

View file

@ -4,7 +4,7 @@ error: under strict provenance it is considered bad style to cast pointer `*cons
LL | let addr: usize = &x as *const u8 as usize;
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: if you can't comply with strict provenance and need to expose the pointer provenance you can use `.expose_addr()` instead
= help: if you can't comply with strict provenance and need to expose the pointer provenance you can use `.expose_provenance()` instead
note: the lint level is defined here
--> $DIR/lint-strict-provenance-lossy-casts.rs:2:9
|
@ -21,7 +21,7 @@ error: under strict provenance it is considered bad style to cast pointer `*cons
LL | let addr_32bit = &x as *const u8 as u32;
| ^^^^^^^^^^^^^^^^^^^^^^
|
= help: if you can't comply with strict provenance and need to expose the pointer provenance you can use `.expose_addr()` instead
= help: if you can't comply with strict provenance and need to expose the pointer provenance you can use `.expose_provenance()` instead
help: use `.addr()` to obtain the address of a pointer
|
LL | let addr_32bit = (&x as *const u8).addr() as u32;
@ -35,7 +35,7 @@ LL | let ptr_addr = ptr as usize;
| |
| help: use `.addr()` to obtain the address of a pointer: `.addr()`
|
= help: if you can't comply with strict provenance and need to expose the pointer provenance you can use `.expose_addr()` instead
= help: if you can't comply with strict provenance and need to expose the pointer provenance you can use `.expose_provenance()` instead
error: under strict provenance it is considered bad style to cast pointer `*const u8` to integer `u32`
--> $DIR/lint-strict-provenance-lossy-casts.rs:16:26
@ -45,7 +45,7 @@ LL | let ptr_addr_32bit = ptr as u32;
| |
| help: use `.addr()` to obtain the address of a pointer: `.addr() as u32`
|
= help: if you can't comply with strict provenance and need to expose the pointer provenance you can use `.expose_addr()` instead
= help: if you can't comply with strict provenance and need to expose the pointer provenance you can use `.expose_provenance()` instead
error: aborting due to 4 previous errors

View file

@ -4,7 +4,7 @@
extern "rust-intrinsic" {
fn simd_cast_ptr<T, U>(x: T) -> U;
fn simd_expose_addr<T, U>(x: T) -> U;
fn simd_expose_provenance<T, U>(x: T) -> U;
fn simd_with_exposed_provenance<T, U>(x: T) -> U;
}
@ -22,7 +22,7 @@ fn main() {
// change constness and type
let const_ptrs: V<*const u8> = simd_cast_ptr(ptrs);
let exposed_addr: V<usize> = simd_expose_addr(const_ptrs);
let exposed_addr: V<usize> = simd_expose_provenance(const_ptrs);
let with_exposed_provenance: V<*mut i8> = simd_with_exposed_provenance(exposed_addr);