Skip to content

Commit f399322

Browse files
committed
add semantics to MaybeDangling
1 parent 9014cc5 commit f399322

5 files changed

Lines changed: 51 additions & 17 deletions

File tree

compiler/rustc_abi/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2140,6 +2140,8 @@ pub enum PointerKind {
21402140
pub struct PointeeInfo {
21412141
/// If this is `None`, then this is a raw pointer.
21422142
pub safe: Option<PointerKind>,
2143+
/// If this is true, the pointer is wrapped in `MaybeDangling`.
2144+
pub may_dangle: bool,
21432145
/// If `size` is not zero, then the pointer is either null or dereferenceable for this many bytes.
21442146
///
21452147
/// On a function argument, "dereferenceable" here means "dereferenceable for the entire duration

compiler/rustc_middle/src/ty/layout.rs

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1024,7 +1024,7 @@ where
10241024

10251025
let pointee_info = match *this.ty.kind() {
10261026
ty::RawPtr(_, _) | ty::FnPtr(..) if offset.bytes() == 0 => {
1027-
Some(PointeeInfo { safe: None, size: Size::ZERO, align: Align::ONE })
1027+
Some(PointeeInfo { safe: None, size: Size::ZERO, align: Align::ONE, may_dangle: false })
10281028
}
10291029
ty::Ref(_, ty, mt) if offset.bytes() == 0 => {
10301030
tcx.layout_of(typing_env.as_query_input(ty)).ok().map(|layout| {
@@ -1059,7 +1059,7 @@ where
10591059
PointerKind::MutableRef { unpin }
10601060
}
10611061
};
1062-
PointeeInfo { safe: Some(kind), size, align: layout.align.abi }
1062+
PointeeInfo { safe: Some(kind), size, align: layout.align.abi, may_dangle: false }
10631063
})
10641064
}
10651065

@@ -1083,6 +1083,20 @@ where
10831083
size: Size::ZERO,
10841084

10851085
align: layout.align.abi,
1086+
may_dangle: false,
1087+
})
1088+
}
1089+
1090+
ty::Adt(adt_def, ..) if adt_def.is_maybe_dangling() => {
1091+
Self::ty_and_layout_pointee_info_at(this.field(cx, 0), cx, offset).map(|info| {
1092+
PointeeInfo {
1093+
// Mark the pointer as possibly dangling
1094+
// (thus removing noalias in case of llvm backend)
1095+
may_dangle: true,
1096+
// Make sure we don't assert dereferenceability of the pointer.
1097+
size: Size::ZERO,
1098+
..info
1099+
}
10861100
})
10871101
}
10881102

compiler/rustc_ty_utils/src/abi.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -342,11 +342,12 @@ fn arg_attrs_for_rust_scalar<'tcx>(
342342
// not return values.
343343
//
344344
// `&mut T` and `Box<T>` where `T: Unpin` are unique and hence `noalias`.
345-
let no_alias = match kind {
346-
PointerKind::SharedRef { frozen } => frozen,
347-
PointerKind::MutableRef { unpin } => unpin && noalias_mut_ref,
348-
PointerKind::Box { unpin, global } => unpin && global && noalias_for_box,
349-
};
345+
let no_alias = !pointee.may_dangle
346+
&& match kind {
347+
PointerKind::SharedRef { frozen } => frozen,
348+
PointerKind::MutableRef { unpin } => unpin && noalias_mut_ref,
349+
PointerKind::Box { unpin, global } => unpin && global && noalias_for_box,
350+
};
350351
// We can never add `noalias` in return position; that LLVM attribute has some very surprising semantics
351352
// (see <https://github.com/rust-lang/unsafe-code-guidelines/issues/385#issuecomment-1368055745>).
352353
if no_alias && !is_return {

library/core/src/mem/maybe_dangling.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,6 @@ use crate::{mem, ptr};
44

55
/// Allows wrapped [references] and [boxes] to dangle.
66
///
7-
/// <section class="warning">
8-
/// This type is not properly implemented yet, and the documentation below is thus not accurate.
9-
/// </section>
10-
///
117
/// That is, if a reference (or a `Box`) is wrapped in `MaybeDangling` (including when in a
128
/// (nested) field of a compound type wrapped in `MaybeDangling`), it does not have to follow
139
/// pointer aliasing rules or be dereferenceable.

tests/codegen-llvm/manually_drop_refs.rs

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,37 +6,58 @@
66

77
use std::mem::ManuallyDrop;
88

9-
// CHECK: define noundef nonnull ptr @f(ptr noalias noundef nonnull readnone returned {{(captures\(ret: address, provenance\))?}} %x) unnamed_addr
9+
// CHECK: define noundef nonnull ptr @f
10+
// CHECK-NOT: noalias
11+
// CHECK-NOT: dereferenceable
12+
// CHECK-SAME: unnamed_addr
1013
#[no_mangle]
1114
pub fn f(x: ManuallyDrop<Box<u8>>) -> ManuallyDrop<Box<u8>> {
1215
x
1316
}
1417

15-
// CHECK: define noundef nonnull ptr @g(ptr noalias noundef readonly returned {{(captures\(ret: address, read_provenance\))?}} dereferenceable(1) %x) unnamed_addr
18+
// CHECK: define noundef nonnull ptr @g
19+
// CHECK-NOT: noalias
20+
// CHECK-NOT: dereferenceable
21+
// CHECK-SAME: unnamed_addr
1622
#[no_mangle]
1723
pub fn g(x: ManuallyDrop<&u8>) -> ManuallyDrop<&u8> {
1824
x
1925
}
2026

21-
// CHECK: define noundef nonnull ptr @h(ptr noalias noundef readnone returned {{(captures\(ret: address, provenance\))?}} dereferenceable(1) %x) unnamed_addr
27+
// CHECK: define noundef nonnull ptr @h
28+
// CHECK-NOT: noalias
29+
// CHECK-NOT: dereferenceable
30+
// CHECK-SAME: unnamed_addr
2231
#[no_mangle]
2332
pub fn h(x: ManuallyDrop<&mut u8>) -> ManuallyDrop<&mut u8> {
2433
x
2534
}
2635

27-
// CHECK: define noundef nonnull align 4 ptr @i(ptr noalias noundef nonnull readnone returned align 4 {{(captures\(ret: address, provenance\))?}} %x) unnamed_addr
36+
// CHECK: define noundef nonnull align 4 ptr @i
37+
// CHECK-NOT: noalias
38+
// CHECK-NOT: dereferenceable
39+
// CHECK-SAME: align 4
40+
// CHECK-SAME: unnamed_addr
2841
#[no_mangle]
2942
pub fn i(x: ManuallyDrop<Box<u32>>) -> ManuallyDrop<Box<u32>> {
3043
x
3144
}
3245

33-
// CHECK: define noundef nonnull align 4 ptr @j(ptr noalias noundef readonly returned align 4 {{(captures\(ret: address, read_provenance\))?}} dereferenceable(4) %x) unnamed_addr
46+
// CHECK: define noundef nonnull align 4 ptr @j
47+
// CHECK-NOT: noalias
48+
// CHECK-NOT: dereferenceable
49+
// CHECK-SAME: align 4
50+
// CHECK-SAME: unnamed_addr
3451
#[no_mangle]
3552
pub fn j(x: ManuallyDrop<&u32>) -> ManuallyDrop<&u32> {
3653
x
3754
}
3855

39-
// CHECK: define noundef nonnull align 4 ptr @k(ptr noalias noundef readnone returned align 4 {{(captures\(ret: address, provenance\))?}} dereferenceable(4) %x) unnamed_addr
56+
// CHECK: define noundef nonnull align 4 ptr @k
57+
// CHECK-NOT: noalias
58+
// CHECK-NOT: dereferenceable
59+
// CHECK-SAME: align 4
60+
// CHECK-SAME: unnamed_addr
4061
#[no_mangle]
4162
pub fn k(x: ManuallyDrop<&mut u32>) -> ManuallyDrop<&mut u32> {
4263
x

0 commit comments

Comments
 (0)