@@ -66,6 +66,14 @@ impl Layout {
6666 #[ stable( feature = "alloc_layout" , since = "1.28.0" ) ]
6767 #[ rustc_const_stable( feature = "const_alloc_layout_size_align" , since = "1.50.0" ) ]
6868 #[ inline]
69+ #[ rustc_allow_const_fn_unstable( contracts) ]
70+ #[ core:: contracts:: ensures(
71+ move |result: & Result <Self , LayoutError >|
72+ result. is_err( ) || (
73+ align. is_power_of_two( ) &&
74+ size <= isize :: MAX as usize - ( align - 1 ) &&
75+ result. as_ref( ) . unwrap( ) . size( ) == size &&
76+ result. as_ref( ) . unwrap( ) . align( ) == align) ) ]
6977 pub const fn from_size_align ( size : usize , align : usize ) -> Result < Self , LayoutError > {
7078 if Layout :: is_size_align_valid ( size, align) {
7179 // SAFETY: Layout::is_size_align_valid checks the preconditions for this call.
@@ -127,6 +135,10 @@ impl Layout {
127135 #[ must_use]
128136 #[ inline]
129137 #[ track_caller]
138+ #[ rustc_allow_const_fn_unstable( contracts) ]
139+ #[ core:: contracts:: requires( Layout :: from_size_align( size, align) . is_ok( ) ) ]
140+ #[ core:: contracts:: ensures(
141+ move |result: & Self | result. size( ) == size && result. align( ) == align) ]
130142 pub const unsafe fn from_size_align_unchecked ( size : usize , align : usize ) -> Self {
131143 assert_unsafe_precondition ! (
132144 check_library_ub,
@@ -167,6 +179,10 @@ impl Layout {
167179 #[ rustc_const_stable( feature = "alloc_layout_const_new" , since = "1.42.0" ) ]
168180 #[ must_use]
169181 #[ inline]
182+ #[ rustc_allow_const_fn_unstable( contracts) ]
183+ #[ core:: contracts:: ensures(
184+ |result: & Self |
185+ result. size( ) == mem:: size_of:: <T >( ) && result. align( ) == mem:: align_of:: <T >( ) ) ]
170186 pub const fn new < T > ( ) -> Self {
171187 let ( size, align) = size_align :: < T > ( ) ;
172188 // SAFETY: if the type is instantiated, rustc already ensures that its
@@ -182,6 +198,10 @@ impl Layout {
182198 #[ rustc_const_stable( feature = "const_alloc_layout" , since = "1.85.0" ) ]
183199 #[ must_use]
184200 #[ inline]
201+ #[ rustc_allow_const_fn_unstable( contracts) ]
202+ #[ core:: contracts:: requires( mem:: align_of_val( t) . is_power_of_two( ) ) ]
203+ // FIXME: requires `&self` to be `'static`
204+ // #[core::contracts::ensures(move |result: &Self| result.align() == mem::align_of_val(t))]
185205 pub const fn for_value < T : ?Sized > ( t : & T ) -> Self {
186206 let ( size, align) = ( size_of_val ( t) , align_of_val ( t) ) ;
187207 // SAFETY: see rationale in `new` for why this is using the unsafe variant
@@ -217,6 +237,8 @@ impl Layout {
217237 /// [extern type]: ../../unstable-book/language-features/extern-types.html
218238 #[ unstable( feature = "layout_for_ptr" , issue = "69835" ) ]
219239 #[ must_use]
240+ #[ rustc_allow_const_fn_unstable( contracts) ]
241+ #[ core:: contracts:: ensures( |result: & Self | result. align( ) . is_power_of_two( ) ) ]
220242 pub const unsafe fn for_value_raw < T : ?Sized > ( t : * const T ) -> Self {
221243 // SAFETY: we pass along the prerequisites of these functions to the caller
222244 let ( size, align) = unsafe { ( mem:: size_of_val_raw ( t) , mem:: align_of_val_raw ( t) ) } ;
@@ -233,6 +255,8 @@ impl Layout {
233255 #[ unstable( feature = "alloc_layout_extra" , issue = "55724" ) ]
234256 #[ must_use]
235257 #[ inline]
258+ #[ rustc_allow_const_fn_unstable( contracts) ]
259+ #[ core:: contracts:: ensures( |result: & NonNull <u8 >| result. is_aligned( ) ) ]
236260 pub const fn dangling ( & self ) -> NonNull < u8 > {
237261 NonNull :: without_provenance ( self . align . as_nonzero ( ) )
238262 }
@@ -254,6 +278,12 @@ impl Layout {
254278 #[ stable( feature = "alloc_layout_manipulation" , since = "1.44.0" ) ]
255279 #[ rustc_const_stable( feature = "const_alloc_layout" , since = "1.85.0" ) ]
256280 #[ inline]
281+ #[ rustc_allow_const_fn_unstable( contracts) ]
282+ #[ core:: contracts:: ensures(
283+ move |result: & Result <Self , LayoutError >|
284+ result. is_err( ) || (
285+ result. as_ref( ) . unwrap( ) . align( ) >= align &&
286+ result. as_ref( ) . unwrap( ) . align( ) . is_power_of_two( ) ) ) ]
257287 pub const fn align_to ( & self , align : usize ) -> Result < Self , LayoutError > {
258288 if let Some ( align) = Alignment :: new ( align) {
259289 Layout :: from_size_alignment ( self . size , Alignment :: max ( self . align , align) )
@@ -282,6 +312,8 @@ impl Layout {
282312 #[ must_use = "this returns the padding needed, \
283313 without modifying the `Layout`"]
284314 #[ inline]
315+ #[ rustc_allow_const_fn_unstable( contracts) ]
316+ #[ core:: contracts:: ensures( move |result| * result <= align) ]
285317 pub const fn padding_needed_for ( & self , align : usize ) -> usize {
286318 // FIXME: Can we just change the type on this to `Alignment`?
287319 let Some ( align) = Alignment :: new ( align) else { return usize:: MAX } ;
@@ -331,6 +363,14 @@ impl Layout {
331363 #[ must_use = "this returns a new `Layout`, \
332364 without modifying the original"]
333365 #[ inline]
366+ // FIXME: requires `&self` to be `'static`
367+ // #[rustc_allow_const_fn_unstable(contracts)]
368+ // #[core::contracts::ensures(
369+ // move |result: &Layout|
370+ // result.size() >= self.size() &&
371+ // result.align() == self.align() &&
372+ // result.size() % result.align() == 0 &&
373+ // self.size() + self.padding_needed_for(self.align()) == result.size())]
334374 pub const fn pad_to_align ( & self ) -> Layout {
335375 // This cannot overflow. Quoting from the invariant of Layout:
336376 // > `size`, when rounded up to the nearest multiple of `align`,
@@ -371,6 +411,12 @@ impl Layout {
371411 /// ```
372412 #[ unstable( feature = "alloc_layout_extra" , issue = "55724" ) ]
373413 #[ inline]
414+ #[ rustc_allow_const_fn_unstable( contracts) ]
415+ #[ core:: contracts:: ensures(
416+ move |result: & Result <( Self , usize ) , LayoutError >|
417+ result. is_err( ) || (
418+ ( n == 0 || result. as_ref( ) . unwrap( ) . 0 . size( ) % n == 0 ) &&
419+ result. as_ref( ) . unwrap( ) . 0 . size( ) == n * result. as_ref( ) . unwrap( ) . 1 ) ) ]
374420 pub const fn repeat ( & self , n : usize ) -> Result < ( Self , usize ) , LayoutError > {
375421 let padded = self . pad_to_align ( ) ;
376422 if let Ok ( repeated) = padded. repeat_packed ( n) {
@@ -428,6 +474,15 @@ impl Layout {
428474 #[ stable( feature = "alloc_layout_manipulation" , since = "1.44.0" ) ]
429475 #[ rustc_const_stable( feature = "const_alloc_layout" , since = "1.85.0" ) ]
430476 #[ inline]
477+ // FIXME: requires `&self` to be `'static`
478+ // #[rustc_allow_const_fn_unstable(contracts)]
479+ // #[core::contracts::ensures(
480+ // move |result: &Result<(Self, usize), LayoutError>|
481+ // result.is_err() || (
482+ // result.as_ref().unwrap().0.align() == cmp::max(self.align(), next.align()) &&
483+ // result.as_ref().unwrap().0.size() >= self.size() + next.size() &&
484+ // result.as_ref().unwrap().1 >= self.size() &&
485+ // result.as_ref().unwrap().1 <= result.as_ref().unwrap().0.size()))]
431486 pub const fn extend ( & self , next : Self ) -> Result < ( Self , usize ) , LayoutError > {
432487 let new_align = Alignment :: max ( self . align , next. align ) ;
433488 let offset = self . size_rounded_up_to_custom_align ( next. align ) ;
@@ -459,6 +514,13 @@ impl Layout {
459514 /// On arithmetic overflow, returns `LayoutError`.
460515 #[ unstable( feature = "alloc_layout_extra" , issue = "55724" ) ]
461516 #[ inline]
517+ // FIXME: requires `&self` to be `'static`
518+ // #[rustc_allow_const_fn_unstable(contracts)]
519+ // #[core::contracts::ensures(
520+ // move |result: &Result<Self, LayoutError>|
521+ // result.is_err() || (
522+ // result.as_ref().unwrap().size() == n * self.size() &&
523+ // result.as_ref().unwrap().align() == self.align()))]
462524 pub const fn repeat_packed ( & self , n : usize ) -> Result < Self , LayoutError > {
463525 if let Some ( size) = self . size . checked_mul ( n) {
464526 // The safe constructor is called here to enforce the isize size limit.
@@ -476,6 +538,13 @@ impl Layout {
476538 /// On arithmetic overflow, returns `LayoutError`.
477539 #[ unstable( feature = "alloc_layout_extra" , issue = "55724" ) ]
478540 #[ inline]
541+ // FIXME: requires `&self` to be `'static`
542+ // #[rustc_allow_const_fn_unstable(contracts)]
543+ // #[core::contracts::ensures(
544+ // move |result: &Result<Self, LayoutError>|
545+ // result.is_err() || (
546+ // result.as_ref().unwrap().size() == self.size() + next.size() &&
547+ // result.as_ref().unwrap().align() == self.align()))]
479548 pub const fn extend_packed ( & self , next : Self ) -> Result < Self , LayoutError > {
480549 // SAFETY: each `size` is at most `isize::MAX == usize::MAX/2`, so the
481550 // sum is at most `usize::MAX/2*2 == usize::MAX - 1`, and cannot overflow.
@@ -491,6 +560,12 @@ impl Layout {
491560 #[ stable( feature = "alloc_layout_manipulation" , since = "1.44.0" ) ]
492561 #[ rustc_const_stable( feature = "const_alloc_layout" , since = "1.85.0" ) ]
493562 #[ inline]
563+ #[ rustc_allow_const_fn_unstable( contracts) ]
564+ #[ core:: contracts:: ensures(
565+ move |result: & Result <Self , LayoutError >|
566+ result. is_err( ) || (
567+ result. as_ref( ) . unwrap( ) . size( ) == n * mem:: size_of:: <T >( ) &&
568+ result. as_ref( ) . unwrap( ) . align( ) == mem:: align_of:: <T >( ) ) ) ]
494569 pub const fn array < T > ( n : usize ) -> Result < Self , LayoutError > {
495570 // Reduce the amount of code we need to monomorphize per `T`.
496571 return inner ( T :: LAYOUT , n) ;
0 commit comments