From d6ca5c3dc016b17eff17e3faff85106e638a86a7 Mon Sep 17 00:00:00 2001 From: Waffle Lapkin Date: Mon, 2 Mar 2026 16:26:44 +0100 Subject: [PATCH] strip readonly/captures from `MaybeDangling<&T>` --- compiler/rustc_abi/src/lib.rs | 8 ++------ compiler/rustc_middle/src/ty/layout.rs | 25 ++++++++--------------- compiler/rustc_ty_utils/src/abi.rs | 11 +++++----- tests/codegen-llvm/maybe_dangling_refs.rs | 4 ++-- 4 files changed, 17 insertions(+), 31 deletions(-) diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index 4dc2f8e8c952..59cc852d7a32 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -2153,18 +2153,14 @@ pub enum PointerKind { pub struct PointeeInfo { /// If this is `None`, then this is a raw pointer. pub safe: Option, - /// If this is true, the pointer is wrapped in `MaybeDangling` and thus can't be assumed to - /// not alias. Having this as separate state from `safe: None` allows us to keep `readonly` and - /// `captures(address, read_provenance)` llvm attributes. - pub may_dangle: bool, /// If `size` is not zero, then the pointer is either null or dereferenceable for this many bytes - /// (independent of `safe` and `may_dangle`). + /// (independent of `safe`). /// /// On a function argument, "dereferenceable" here means "dereferenceable for the entire duration /// of this function call", i.e. it is UB for the memory that this pointer points to be freed /// while this function is still running. pub size: Size, - /// The pointer is guaranteed to be aligned this much (independent of `safe` and `may_dangle`). + /// The pointer is guaranteed to be aligned this much (independent of `safe`). pub align: Align, } diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 637d913b086b..915566c08886 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -1028,12 +1028,9 @@ fn ty_and_layout_pointee_info_at( let optimize = tcx.sess.opts.optimize != OptLevel::No; let pointee_info = match *this.ty.kind() { - ty::RawPtr(_, _) | ty::FnPtr(..) if offset.bytes() == 0 => Some(PointeeInfo { - safe: None, - size: Size::ZERO, - align: Align::ONE, - may_dangle: false, - }), + ty::RawPtr(_, _) | ty::FnPtr(..) if offset.bytes() == 0 => { + Some(PointeeInfo { safe: None, size: Size::ZERO, align: Align::ONE }) + } ty::Ref(_, ty, mt) if offset.bytes() == 0 => { tcx.layout_of(typing_env.as_query_input(ty)).ok().map(|layout| { let (size, kind); @@ -1062,12 +1059,7 @@ fn ty_and_layout_pointee_info_at( kind = PointerKind::MutableRef { unpin }; } }; - PointeeInfo { - safe: Some(kind), - size, - align: layout.align.abi, - may_dangle: false, - } + PointeeInfo { safe: Some(kind), size, align: layout.align.abi } }) } @@ -1090,20 +1082,19 @@ fn ty_and_layout_pointee_info_at( size: Size::ZERO, align: layout.align.abi, - may_dangle: false, }) } ty::Adt(adt_def, ..) if adt_def.is_maybe_dangling() => { Self::ty_and_layout_pointee_info_at(this.field(cx, 0), cx, offset).map(|info| { PointeeInfo { - // Mark the pointer as possibly dangling - // (thus removing noalias in case of llvm backend) - may_dangle: true, + // Mark the pointer as raw + // (thus removing noalias/readonly/etc in case of the llvm backend) + safe: None, // Make sure we don't assert dereferenceability of the pointer. size: Size::ZERO, // Preserve the alignment assertion! That is required even inside `MaybeDangling`. - ..info + align: info.align, } }) } diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs index 0484e1430fdc..3cc0edc6007e 100644 --- a/compiler/rustc_ty_utils/src/abi.rs +++ b/compiler/rustc_ty_utils/src/abi.rs @@ -351,12 +351,11 @@ fn arg_attrs_for_rust_scalar<'tcx>( // not return values. // // `&mut T` and `Box` where `T: Unpin` are unique and hence `noalias`. - let no_alias = !pointee.may_dangle - && match kind { - PointerKind::SharedRef { frozen } => frozen, - PointerKind::MutableRef { unpin } => unpin && noalias_mut_ref, - PointerKind::Box { unpin, global } => unpin && global && noalias_for_box, - }; + let no_alias = match kind { + PointerKind::SharedRef { frozen } => frozen, + PointerKind::MutableRef { unpin } => unpin && noalias_mut_ref, + PointerKind::Box { unpin, global } => unpin && global && noalias_for_box, + }; // We can never add `noalias` in return position; that LLVM attribute has some very surprising semantics // (see ). if no_alias && !is_return { diff --git a/tests/codegen-llvm/maybe_dangling_refs.rs b/tests/codegen-llvm/maybe_dangling_refs.rs index f1ddc7ec237c..07493ecac79c 100644 --- a/tests/codegen-llvm/maybe_dangling_refs.rs +++ b/tests/codegen-llvm/maybe_dangling_refs.rs @@ -15,7 +15,7 @@ pub fn f(x: MaybeDangling>) -> MaybeDangling> { x } -// CHECK: define {{(dso_local )?}}noundef nonnull ptr @g(ptr noundef nonnull readonly captures(address, read_provenance) %x) unnamed_addr +// CHECK: define {{(dso_local )?}}noundef nonnull ptr @g(ptr noundef nonnull %x) unnamed_addr #[no_mangle] pub fn g(x: MaybeDangling<&u8>) -> MaybeDangling<&u8> { x @@ -33,7 +33,7 @@ pub fn i(x: MaybeDangling>) -> MaybeDangling> { x } -// CHECK: define {{(dso_local )?}}noundef nonnull align 4 ptr @j(ptr noundef nonnull readonly align 4 captures(address, read_provenance) %x) unnamed_addr +// CHECK: define {{(dso_local )?}}noundef nonnull align 4 ptr @j(ptr noundef nonnull align 4 %x) unnamed_addr #[no_mangle] pub fn j(x: MaybeDangling<&u32>) -> MaybeDangling<&u32> { x