@@ -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 } ;
@@ -330,6 +362,14 @@ impl Layout {
330362 #[ must_use = "this returns a new `Layout`, \
331363 without modifying the original"]
332364 #[ inline]
365+ // FIXME: requires `&self` to be `'static`
366+ // #[rustc_allow_const_fn_unstable(contracts)]
367+ // #[core::contracts::ensures(
368+ // move |result: &Layout|
369+ // result.size() >= self.size() &&
370+ // result.align() == self.align() &&
371+ // result.size() % result.align() == 0 &&
372+ // self.size() + self.padding_needed_for(self.align()) == result.size())]
333373 pub const fn pad_to_align ( & self ) -> Layout {
334374 // This cannot overflow. Quoting from the invariant of Layout:
335375 // > `size`, when rounded up to the nearest multiple of `align`,
@@ -370,6 +410,12 @@ impl Layout {
370410 /// ```
371411 #[ unstable( feature = "alloc_layout_extra" , issue = "55724" ) ]
372412 #[ inline]
413+ #[ rustc_allow_const_fn_unstable( contracts) ]
414+ #[ core:: contracts:: ensures(
415+ move |result: & Result <( Self , usize ) , LayoutError >|
416+ result. is_err( ) || (
417+ ( n == 0 || result. as_ref( ) . unwrap( ) . 0 . size( ) % n == 0 ) &&
418+ result. as_ref( ) . unwrap( ) . 0 . size( ) == n * result. as_ref( ) . unwrap( ) . 1 ) ) ]
373419 pub const fn repeat ( & self , n : usize ) -> Result < ( Self , usize ) , LayoutError > {
374420 let padded = self . pad_to_align ( ) ;
375421 if let Ok ( repeated) = padded. repeat_packed ( n) {
@@ -427,6 +473,15 @@ impl Layout {
427473 #[ stable( feature = "alloc_layout_manipulation" , since = "1.44.0" ) ]
428474 #[ rustc_const_stable( feature = "const_alloc_layout" , since = "1.85.0" ) ]
429475 #[ inline]
476+ // FIXME: requires `&self` to be `'static`
477+ // #[rustc_allow_const_fn_unstable(contracts)]
478+ // #[core::contracts::ensures(
479+ // move |result: &Result<(Self, usize), LayoutError>|
480+ // result.is_err() || (
481+ // result.as_ref().unwrap().0.align() == cmp::max(self.align(), next.align()) &&
482+ // result.as_ref().unwrap().0.size() >= self.size() + next.size() &&
483+ // result.as_ref().unwrap().1 >= self.size() &&
484+ // result.as_ref().unwrap().1 <= result.as_ref().unwrap().0.size()))]
430485 pub const fn extend ( & self , next : Self ) -> Result < ( Self , usize ) , LayoutError > {
431486 let new_align = Alignment :: max ( self . align , next. align ) ;
432487 let offset = self . size_rounded_up_to_custom_align ( next. align ) ;
@@ -458,6 +513,13 @@ impl Layout {
458513 /// On arithmetic overflow, returns `LayoutError`.
459514 #[ unstable( feature = "alloc_layout_extra" , issue = "55724" ) ]
460515 #[ inline]
516+ // FIXME: requires `&self` to be `'static`
517+ // #[rustc_allow_const_fn_unstable(contracts)]
518+ // #[core::contracts::ensures(
519+ // move |result: &Result<Self, LayoutError>|
520+ // result.is_err() || (
521+ // result.as_ref().unwrap().size() == n * self.size() &&
522+ // result.as_ref().unwrap().align() == self.align()))]
461523 pub const fn repeat_packed ( & self , n : usize ) -> Result < Self , LayoutError > {
462524 if let Some ( size) = self . size . checked_mul ( n) {
463525 // The safe constructor is called here to enforce the isize size limit.
@@ -475,6 +537,13 @@ impl Layout {
475537 /// On arithmetic overflow, returns `LayoutError`.
476538 #[ unstable( feature = "alloc_layout_extra" , issue = "55724" ) ]
477539 #[ inline]
540+ // FIXME: requires `&self` to be `'static`
541+ // #[rustc_allow_const_fn_unstable(contracts)]
542+ // #[core::contracts::ensures(
543+ // move |result: &Result<Self, LayoutError>|
544+ // result.is_err() || (
545+ // result.as_ref().unwrap().size() == self.size() + next.size() &&
546+ // result.as_ref().unwrap().align() == self.align()))]
478547 pub const fn extend_packed ( & self , next : Self ) -> Result < Self , LayoutError > {
479548 // SAFETY: each `size` is at most `isize::MAX == usize::MAX/2`, so the
480549 // sum is at most `usize::MAX/2*2 == usize::MAX - 1`, and cannot overflow.
@@ -490,6 +559,12 @@ impl Layout {
490559 #[ stable( feature = "alloc_layout_manipulation" , since = "1.44.0" ) ]
491560 #[ rustc_const_stable( feature = "const_alloc_layout" , since = "1.85.0" ) ]
492561 #[ inline]
562+ #[ rustc_allow_const_fn_unstable( contracts) ]
563+ #[ core:: contracts:: ensures(
564+ move |result: & Result <Self , LayoutError >|
565+ result. is_err( ) || (
566+ result. as_ref( ) . unwrap( ) . size( ) == n * mem:: size_of:: <T >( ) &&
567+ result. as_ref( ) . unwrap( ) . align( ) == mem:: align_of:: <T >( ) ) ) ]
493568 pub const fn array < T > ( n : usize ) -> Result < Self , LayoutError > {
494569 // Reduce the amount of code we need to monomorphize per `T`.
495570 return inner ( T :: LAYOUT , n) ;
0 commit comments