-
Notifications
You must be signed in to change notification settings - Fork 13k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[rustc_ty_utils] Add the LLVM noalias
parameter attribute to drop_in_place
in certain cases.
#103614
[rustc_ty_utils] Add the LLVM noalias
parameter attribute to drop_in_place
in certain cases.
#103614
Changes from 4 commits
5ce1a00
ecfb332
67ddb33
02cfabe
53f21aa
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -436,23 +436,41 @@ mod mut_ptr; | |||||||||||||
/// | ||||||||||||||
/// # Safety | ||||||||||||||
/// | ||||||||||||||
/// Behavior is undefined if any of the following conditions are violated: | ||||||||||||||
/// Immediately upon executing, `drop_in_place` takes out a mutable borrow on the | ||||||||||||||
/// pointed-to-value. Effectively, this function is implemented like so: | ||||||||||||||
/// | ||||||||||||||
/// ``` | ||||||||||||||
/// # struct Foo { x: i32 } | ||||||||||||||
/// fn drop_in_place(to_drop: *mut Foo) { | ||||||||||||||
/// let mut value = &mut *to_drop; | ||||||||||||||
/// // ... drop the fields of `value` ... | ||||||||||||||
/// } | ||||||||||||||
/// ``` | ||||||||||||||
/// | ||||||||||||||
/// This implies that the behavior is undefined if any of the following | ||||||||||||||
/// conditions are violated: | ||||||||||||||
/// | ||||||||||||||
/// * `to_drop` must be [valid] for both reads and writes. | ||||||||||||||
/// | ||||||||||||||
/// * `to_drop` must be properly aligned. | ||||||||||||||
/// * `to_drop` must be properly aligned, even if T has size 0. | ||||||||||||||
/// | ||||||||||||||
/// * `to_drop` must be nonnull, even if T has size 0. | ||||||||||||||
Comment on lines
+455
to
+457
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||
/// | ||||||||||||||
/// * The value `to_drop` points to must be valid for dropping, which may mean | ||||||||||||||
/// it must uphold additional invariants. These invariants depend on the type | ||||||||||||||
/// of the value being dropped. For instance, when dropping a Box, the box's | ||||||||||||||
/// pointer to the heap must be valid. | ||||||||||||||
/// | ||||||||||||||
/// * The value `to_drop` points to must be valid for dropping, which may mean it must uphold | ||||||||||||||
/// additional invariants - this is type-dependent. | ||||||||||||||
/// * While `drop_in_place` is executing, the only way to access parts of | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @RalfJung Would it be better to say
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What is the difference you are getting at here? One |
||||||||||||||
/// `to_drop` is through the `&mut self` references supplied to the | ||||||||||||||
/// `Drop::drop` methods that `drop_in_place` invokes. | ||||||||||||||
/// | ||||||||||||||
/// Additionally, if `T` is not [`Copy`], using the pointed-to value after | ||||||||||||||
/// calling `drop_in_place` can cause undefined behavior. Note that `*to_drop = | ||||||||||||||
/// foo` counts as a use because it will cause the value to be dropped | ||||||||||||||
/// again. [`write()`] can be used to overwrite data without causing it to be | ||||||||||||||
/// dropped. | ||||||||||||||
/// | ||||||||||||||
/// Note that even if `T` has size `0`, the pointer must be non-null and properly aligned. | ||||||||||||||
/// | ||||||||||||||
/// [valid]: self#safety | ||||||||||||||
/// | ||||||||||||||
/// # Examples | ||||||||||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
// Tests that the compiler can mark `drop_in_place` as `noalias` when safe to do so. | ||
|
||
#![crate_type="lib"] | ||
|
||
use std::hint::black_box; | ||
|
||
// CHECK: define{{.*}}core{{.*}}ptr{{.*}}drop_in_place{{.*}}Foo{{.*}}({{.*}}noalias {{.*}} align 4 dereferenceable(12){{.*}}) | ||
|
||
#[repr(C)] | ||
pub struct Foo { | ||
a: i32, | ||
b: i32, | ||
c: i32, | ||
} | ||
|
||
impl Drop for Foo { | ||
#[inline(never)] | ||
fn drop(&mut self) { | ||
black_box(self.a); | ||
} | ||
} | ||
|
||
extern { | ||
fn bar(); | ||
fn baz(foo: Foo); | ||
} | ||
|
||
pub fn haha() { | ||
let foo = Foo { a: 1, b: 2, c: 3 }; | ||
unsafe { | ||
bar(); | ||
baz(foo); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.