-
Notifications
You must be signed in to change notification settings - Fork 14k
Add contracts for all functions in Alignment
#136578
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
base: main
Are you sure you want to change the base?
Changes from all commits
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 |
|---|---|---|
|
|
@@ -507,6 +507,8 @@ pub const fn align_of<T>() -> usize { | |
| #[must_use] | ||
| #[stable(feature = "rust1", since = "1.0.0")] | ||
| #[rustc_const_stable(feature = "const_align_of_val", since = "1.85.0")] | ||
| #[rustc_allow_const_fn_unstable(contracts)] | ||
|
Contributor
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. I wonder if we should add
Member
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. Which functions would that affect? Ah, #136925 anyway needs to be resolved first.
Member
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. I'd still like to find a solution that does not require
Contributor
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. @tautschnig did you try to make this change?
Contributor
Author
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. I finally tried adding where the proposed fix won't actually work as the function is already marked with
Member
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. Yeah you'll have to add |
||
| #[core::contracts::ensures(|result: &usize| result.is_power_of_two())] | ||
| pub const fn align_of_val<T: ?Sized>(val: &T) -> usize { | ||
| // SAFETY: val is a reference, so it's a valid raw pointer | ||
| unsafe { intrinsics::align_of_val(val) } | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -45,6 +45,8 @@ impl Alignment { | |||||||||||||||||
| #[unstable(feature = "ptr_alignment_type", issue = "102070")] | ||||||||||||||||||
| #[inline] | ||||||||||||||||||
| #[must_use] | ||||||||||||||||||
| #[rustc_allow_const_fn_unstable(contracts)] | ||||||||||||||||||
| #[core::contracts::ensures(|result: &Alignment| result.as_usize().is_power_of_two())] | ||||||||||||||||||
|
Member
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. This is an odd contract, since the statement is true about all |
||||||||||||||||||
| pub const fn of<T>() -> Self { | ||||||||||||||||||
| // This can't actually panic since type alignment is always a power of two. | ||||||||||||||||||
| const { Alignment::new(align_of::<T>()).unwrap() } | ||||||||||||||||||
|
|
@@ -56,6 +58,11 @@ impl Alignment { | |||||||||||||||||
| /// Note that `0` is not a power of two, nor a valid alignment. | ||||||||||||||||||
| #[unstable(feature = "ptr_alignment_type", issue = "102070")] | ||||||||||||||||||
| #[inline] | ||||||||||||||||||
| #[rustc_allow_const_fn_unstable(contracts)] | ||||||||||||||||||
| #[core::contracts::ensures( | ||||||||||||||||||
| move |result: &Option<Alignment>| | ||||||||||||||||||
| align.is_power_of_two() == result.is_some() && | ||||||||||||||||||
| (result.is_none() || result.unwrap().as_usize() == align))] | ||||||||||||||||||
|
Comment on lines
+62
to
+65
Member
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. The formatting here is not great, with the code having the same indentation level as the closure header. What about something like this?
Suggested change
|
||||||||||||||||||
| pub const fn new(align: usize) -> Option<Self> { | ||||||||||||||||||
| if align.is_power_of_two() { | ||||||||||||||||||
| // SAFETY: Just checked it only has one bit set | ||||||||||||||||||
|
|
@@ -76,6 +83,11 @@ impl Alignment { | |||||||||||||||||
| #[unstable(feature = "ptr_alignment_type", issue = "102070")] | ||||||||||||||||||
| #[inline] | ||||||||||||||||||
| #[track_caller] | ||||||||||||||||||
| #[rustc_allow_const_fn_unstable(contracts)] | ||||||||||||||||||
| #[core::contracts::requires(align.is_power_of_two())] | ||||||||||||||||||
| #[core::contracts::ensures( | ||||||||||||||||||
| move |result: &Alignment| | ||||||||||||||||||
| result.as_usize() == align && result.as_usize().is_power_of_two())] | ||||||||||||||||||
|
Member
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.
|
||||||||||||||||||
| pub const unsafe fn new_unchecked(align: usize) -> Self { | ||||||||||||||||||
| assert_unsafe_precondition!( | ||||||||||||||||||
| check_language_ub, | ||||||||||||||||||
|
|
@@ -91,13 +103,19 @@ impl Alignment { | |||||||||||||||||
| /// Returns the alignment as a [`usize`]. | ||||||||||||||||||
| #[unstable(feature = "ptr_alignment_type", issue = "102070")] | ||||||||||||||||||
| #[inline] | ||||||||||||||||||
| #[rustc_allow_const_fn_unstable(contracts)] | ||||||||||||||||||
| #[core::contracts::ensures(|result: &usize| result.is_power_of_two())] | ||||||||||||||||||
| pub const fn as_usize(self) -> usize { | ||||||||||||||||||
| self.0 as usize | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| /// Returns the alignment as a <code>[NonZero]<[usize]></code>. | ||||||||||||||||||
| #[unstable(feature = "ptr_alignment_type", issue = "102070")] | ||||||||||||||||||
| #[inline] | ||||||||||||||||||
| #[rustc_allow_const_fn_unstable(contracts)] | ||||||||||||||||||
| #[core::contracts::ensures( | ||||||||||||||||||
| move |result: &NonZero<usize>| | ||||||||||||||||||
| result.get().is_power_of_two() && result.get() == self.as_usize())] | ||||||||||||||||||
|
Member
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.
Contributor
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 we really need is Type invariant. This is basically repeating the type invariant which should be implied.
Member
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. Well that would be even nicer, sure. But even with the status quo, I don't get the point of this contract. To make use of the |
||||||||||||||||||
| pub const fn as_nonzero(self) -> NonZero<usize> { | ||||||||||||||||||
| // This transmutes directly to avoid the UbCheck in `NonZero::new_unchecked` | ||||||||||||||||||
| // since there's no way for the user to trip that check anyway -- the | ||||||||||||||||||
|
|
@@ -123,6 +141,11 @@ impl Alignment { | |||||||||||||||||
| /// ``` | ||||||||||||||||||
| #[unstable(feature = "ptr_alignment_type", issue = "102070")] | ||||||||||||||||||
| #[inline] | ||||||||||||||||||
| #[rustc_const_unstable(feature = "contracts", issue = "128044")] | ||||||||||||||||||
| #[core::contracts::requires(self.as_usize().is_power_of_two())] | ||||||||||||||||||
| #[core::contracts::ensures( | ||||||||||||||||||
| move |result: &u32| | ||||||||||||||||||
| *result < usize::BITS && (1usize << *result) == self.as_usize())] | ||||||||||||||||||
| pub const fn log2(self) -> u32 { | ||||||||||||||||||
| self.as_nonzero().trailing_zeros() | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
@@ -152,6 +175,11 @@ impl Alignment { | |||||||||||||||||
| /// ``` | ||||||||||||||||||
| #[unstable(feature = "ptr_alignment_type", issue = "102070")] | ||||||||||||||||||
| #[inline] | ||||||||||||||||||
| #[rustc_const_unstable(feature = "contracts", issue = "128044")] | ||||||||||||||||||
| #[core::contracts::ensures( | ||||||||||||||||||
| move |result: &usize| | ||||||||||||||||||
| *result > 0 && *result == !(self.as_usize() -1) && | ||||||||||||||||||
|
Contributor
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
Formatting nit |
||||||||||||||||||
| self.as_usize() & *result == self.as_usize())] | ||||||||||||||||||
| pub const fn mask(self) -> usize { | ||||||||||||||||||
| // SAFETY: The alignment is always nonzero, and therefore decrementing won't overflow. | ||||||||||||||||||
| !(unsafe { self.as_usize().unchecked_sub(1) }) | ||||||||||||||||||
|
|
||||||||||||||||||
Uh oh!
There was an error while loading. Please reload this page.