Skip to content

Commit 51a5c77

Browse files
committed
add semantics to MaybeDangling
1 parent 8af71d2 commit 51a5c77

6 files changed

Lines changed: 62 additions & 20 deletions

File tree

compiler/rustc_abi/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2153,6 +2153,8 @@ pub enum PointerKind {
21532153
pub struct PointeeInfo {
21542154
/// If this is `None`, then this is a raw pointer.
21552155
pub safe: Option<PointerKind>,
2156+
/// If this is true, the pointer is wrapped in `MaybeDangling`.
2157+
pub may_dangle: bool,
21562158
/// If `size` is not zero, then the pointer is either null or dereferenceable for this many bytes.
21572159
///
21582160
/// On a function argument, "dereferenceable" here means "dereferenceable for the entire duration

compiler/rustc_middle/src/ty/layout.rs

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1023,9 +1023,12 @@ where
10231023
let typing_env = cx.typing_env();
10241024

10251025
let pointee_info = match *this.ty.kind() {
1026-
ty::RawPtr(_, _) | ty::FnPtr(..) if offset.bytes() == 0 => {
1027-
Some(PointeeInfo { safe: None, size: Size::ZERO, align: Align::ONE })
1028-
}
1026+
ty::RawPtr(_, _) | ty::FnPtr(..) if offset.bytes() == 0 => Some(PointeeInfo {
1027+
safe: None,
1028+
size: Size::ZERO,
1029+
align: Align::ONE,
1030+
may_dangle: false,
1031+
}),
10291032
ty::Ref(_, ty, mt) if offset.bytes() == 0 => {
10301033
tcx.layout_of(typing_env.as_query_input(ty)).ok().map(|layout| {
10311034
// Use conservative pointer kind if not optimizing. This saves us the
@@ -1059,7 +1062,12 @@ where
10591062
PointerKind::MutableRef { unpin }
10601063
}
10611064
};
1062-
PointeeInfo { safe: Some(kind), size, align: layout.align.abi }
1065+
PointeeInfo {
1066+
safe: Some(kind),
1067+
size,
1068+
align: layout.align.abi,
1069+
may_dangle: false,
1070+
}
10631071
})
10641072
}
10651073

@@ -1083,6 +1091,20 @@ where
10831091
size: Size::ZERO,
10841092

10851093
align: layout.align.abi,
1094+
may_dangle: false,
1095+
})
1096+
}
1097+
1098+
ty::Adt(adt_def, ..) if adt_def.is_maybe_dangling() => {
1099+
Self::ty_and_layout_pointee_info_at(this.field(cx, 0), cx, offset).map(|info| {
1100+
PointeeInfo {
1101+
// Mark the pointer as possibly dangling
1102+
// (thus removing noalias in case of llvm backend)
1103+
may_dangle: true,
1104+
// Make sure we don't assert dereferenceability of the pointer.
1105+
size: Size::ZERO,
1106+
..info
1107+
}
10861108
})
10871109
}
10881110

compiler/rustc_ty_utils/src/abi.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -344,11 +344,12 @@ fn arg_attrs_for_rust_scalar<'tcx>(
344344
// not return values.
345345
//
346346
// `&mut T` and `Box<T>` where `T: Unpin` are unique and hence `noalias`.
347-
let no_alias = match kind {
348-
PointerKind::SharedRef { frozen } => frozen,
349-
PointerKind::MutableRef { unpin } => unpin && noalias_mut_ref,
350-
PointerKind::Box { unpin, global } => unpin && global && noalias_for_box,
351-
};
347+
let no_alias = !pointee.may_dangle
348+
&& match kind {
349+
PointerKind::SharedRef { frozen } => frozen,
350+
PointerKind::MutableRef { unpin } => unpin && noalias_mut_ref,
351+
PointerKind::Box { unpin, global } => unpin && global && noalias_for_box,
352+
};
352353
// We can never add `noalias` in return position; that LLVM attribute has some very surprising semantics
353354
// (see <https://github.com/rust-lang/unsafe-code-guidelines/issues/385#issuecomment-1368055745>).
354355
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 {{(dso_local )?}}noundef nonnull ptr @f(ptr noalias noundef nonnull readnone returned {{(captures\(ret: address, provenance\))?}} %x) unnamed_addr
9+
// CHECK: define {{(dso_local )?}}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 {{(dso_local )?}}noundef nonnull ptr @g(ptr noalias noundef readonly returned {{(captures\(ret: address, read_provenance\))?}} dereferenceable(1) %x) unnamed_addr
18+
// CHECK: define {{(dso_local )?}}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 {{(dso_local )?}}noundef nonnull ptr @h(ptr noalias noundef readnone returned {{(captures\(ret: address, provenance\))?}} dereferenceable(1) %x) unnamed_addr
27+
// CHECK: define {{(dso_local )?}}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 {{(dso_local )?}}noundef nonnull align 4 ptr @i(ptr noalias noundef nonnull readnone returned align 4 {{(captures\(ret: address, provenance\))?}} %x) unnamed_addr
36+
// CHECK: define {{(dso_local )?}}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 {{(dso_local )?}}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 {{(dso_local )?}}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 {{(dso_local )?}}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 {{(dso_local )?}}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

tests/codegen-llvm/vtable-upcast.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ pub fn upcast_diamond_to_a(x: &dyn Diamond) -> &dyn A {
5656
}
5757

5858
// CHECK-LABEL: upcast_diamond_to_b
59-
// CHECK-SAME: (ptr [[DATA_PTR:%.+]], ptr align 8 [[VTABLE_PTR:%.+]])
59+
// CHECK-SAME: (ptr [[DATA_PTR:%.+]], ptr align {{[0-9]+}} [[VTABLE_PTR:%.+]])
6060
#[no_mangle]
6161
pub fn upcast_diamond_to_b(x: &dyn Diamond) -> &dyn B {
6262
// Requires adjustment, since it's a non-first supertrait.

0 commit comments

Comments
 (0)