strip readonly/captures from MaybeDangling<&T>

This commit is contained in:
Waffle Lapkin
2026-03-02 16:26:44 +01:00
parent 8aafa53504
commit d6ca5c3dc0
4 changed files with 17 additions and 31 deletions
+2 -6
View File
@@ -2153,18 +2153,14 @@ pub enum PointerKind {
pub struct PointeeInfo {
/// If this is `None`, then this is a raw pointer.
pub safe: Option<PointerKind>,
/// 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,
}
+8 -17
View File
@@ -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,
}
})
}
+5 -6
View File
@@ -351,12 +351,11 @@ fn arg_attrs_for_rust_scalar<'tcx>(
// not return values.
//
// `&mut T` and `Box<T>` 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 <https://github.com/rust-lang/unsafe-code-guidelines/issues/385#issuecomment-1368055745>).
if no_alias && !is_return {
+2 -2
View File
@@ -15,7 +15,7 @@ pub fn f(x: MaybeDangling<Box<u8>>) -> MaybeDangling<Box<u8>> {
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<Box<u32>>) -> MaybeDangling<Box<u32>> {
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