@@ -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,11 @@ impl Layout {
127135 #[ must_use]
128136 #[ inline]
129137 #[ track_caller]
138+ #[ rustc_allow_const_fn_unstable( contracts) ]
139+ #[ allow( unused_parens) ]
140+ #[ core:: contracts:: requires( Layout :: from_size_align( size, align) . is_ok( ) ) ]
141+ #[ core:: contracts:: ensures(
142+ move |result: & Self | result. size( ) == size && result. align( ) == align) ]
130143 pub const unsafe fn from_size_align_unchecked ( size : usize , align : usize ) -> Self {
131144 assert_unsafe_precondition ! (
132145 check_library_ub,
@@ -167,6 +180,10 @@ impl Layout {
167180 #[ rustc_const_stable( feature = "alloc_layout_const_new" , since = "1.42.0" ) ]
168181 #[ must_use]
169182 #[ inline]
183+ #[ rustc_allow_const_fn_unstable( contracts) ]
184+ #[ core:: contracts:: ensures(
185+ |result: & Self |
186+ result. size( ) == mem:: size_of:: <T >( ) && result. align( ) == mem:: align_of:: <T >( ) ) ]
170187 pub const fn new < T > ( ) -> Self {
171188 let ( size, align) = size_align :: < T > ( ) ;
172189 // SAFETY: if the type is instantiated, rustc already ensures that its
@@ -182,6 +199,11 @@ impl Layout {
182199 #[ rustc_const_stable( feature = "const_alloc_layout" , since = "1.85.0" ) ]
183200 #[ must_use]
184201 #[ inline]
202+ #[ rustc_allow_const_fn_unstable( contracts) ]
203+ #[ allow( unused_parens) ]
204+ #[ core:: contracts:: requires( mem:: align_of_val( t) . is_power_of_two( ) ) ]
205+ // FIXME: requires `&self` to be `'static`
206+ // #[core::contracts::ensures(move |result: &Self| result.align() == mem::align_of_val(t))]
185207 pub const fn for_value < T : ?Sized > ( t : & T ) -> Self {
186208 let ( size, align) = ( size_of_val ( t) , align_of_val ( t) ) ;
187209 // SAFETY: see rationale in `new` for why this is using the unsafe variant
@@ -217,6 +239,8 @@ impl Layout {
217239 /// [extern type]: ../../unstable-book/language-features/extern-types.html
218240 #[ unstable( feature = "layout_for_ptr" , issue = "69835" ) ]
219241 #[ must_use]
242+ #[ rustc_allow_const_fn_unstable( contracts) ]
243+ #[ core:: contracts:: ensures( |result: & Self | result. align( ) . is_power_of_two( ) ) ]
220244 pub const unsafe fn for_value_raw < T : ?Sized > ( t : * const T ) -> Self {
221245 // SAFETY: we pass along the prerequisites of these functions to the caller
222246 let ( size, align) = unsafe { ( mem:: size_of_val_raw ( t) , mem:: align_of_val_raw ( t) ) } ;
@@ -233,6 +257,8 @@ impl Layout {
233257 #[ unstable( feature = "alloc_layout_extra" , issue = "55724" ) ]
234258 #[ must_use]
235259 #[ inline]
260+ #[ rustc_allow_const_fn_unstable( contracts) ]
261+ #[ core:: contracts:: ensures( |result: & NonNull <u8 >| result. is_aligned( ) ) ]
236262 pub const fn dangling ( & self ) -> NonNull < u8 > {
237263 NonNull :: without_provenance ( self . align . as_nonzero ( ) )
238264 }
@@ -254,6 +280,12 @@ impl Layout {
254280 #[ stable( feature = "alloc_layout_manipulation" , since = "1.44.0" ) ]
255281 #[ rustc_const_stable( feature = "const_alloc_layout" , since = "1.85.0" ) ]
256282 #[ inline]
283+ #[ rustc_allow_const_fn_unstable( contracts) ]
284+ #[ core:: contracts:: ensures(
285+ move |result: & Result <Self , LayoutError >|
286+ result. is_err( ) || (
287+ result. as_ref( ) . unwrap( ) . align( ) >= align &&
288+ result. as_ref( ) . unwrap( ) . align( ) . is_power_of_two( ) ) ) ]
257289 pub const fn align_to ( & self , align : usize ) -> Result < Self , LayoutError > {
258290 if let Some ( align) = Alignment :: new ( align) {
259291 Layout :: from_size_alignment ( self . size , Alignment :: max ( self . align , align) )
@@ -282,6 +314,8 @@ impl Layout {
282314 #[ must_use = "this returns the padding needed, \
283315 without modifying the `Layout`"]
284316 #[ inline]
317+ #[ rustc_allow_const_fn_unstable( contracts) ]
318+ #[ core:: contracts:: ensures( move |result| * result <= align) ]
285319 pub const fn padding_needed_for ( & self , align : usize ) -> usize {
286320 // FIXME: Can we just change the type on this to `Alignment`?
287321 let Some ( align) = Alignment :: new ( align) else { return usize:: MAX } ;
@@ -331,6 +365,14 @@ impl Layout {
331365 #[ must_use = "this returns a new `Layout`, \
332366 without modifying the original"]
333367 #[ inline]
368+ // FIXME: requires `&self` to be `'static`
369+ // #[rustc_allow_const_fn_unstable(contracts)]
370+ // #[core::contracts::ensures(
371+ // move |result: &Layout|
372+ // result.size() >= self.size() &&
373+ // result.align() == self.align() &&
374+ // result.size() % result.align() == 0 &&
375+ // self.size() + self.padding_needed_for(self.align()) == result.size())]
334376 pub const fn pad_to_align ( & self ) -> Layout {
335377 // This cannot overflow. Quoting from the invariant of Layout:
336378 // > `size`, when rounded up to the nearest multiple of `align`,
@@ -371,6 +413,12 @@ impl Layout {
371413 /// ```
372414 #[ unstable( feature = "alloc_layout_extra" , issue = "55724" ) ]
373415 #[ inline]
416+ #[ rustc_allow_const_fn_unstable( contracts) ]
417+ #[ core:: contracts:: ensures(
418+ move |result: & Result <( Self , usize ) , LayoutError >|
419+ result. is_err( ) || (
420+ ( n == 0 || result. as_ref( ) . unwrap( ) . 0 . size( ) % n == 0 ) &&
421+ result. as_ref( ) . unwrap( ) . 0 . size( ) == n * result. as_ref( ) . unwrap( ) . 1 ) ) ]
374422 pub const fn repeat ( & self , n : usize ) -> Result < ( Self , usize ) , LayoutError > {
375423 let padded = self . pad_to_align ( ) ;
376424 if let Ok ( repeated) = padded. repeat_packed ( n) {
@@ -428,6 +476,15 @@ impl Layout {
428476 #[ stable( feature = "alloc_layout_manipulation" , since = "1.44.0" ) ]
429477 #[ rustc_const_stable( feature = "const_alloc_layout" , since = "1.85.0" ) ]
430478 #[ inline]
479+ // FIXME: requires `&self` to be `'static`
480+ // #[rustc_allow_const_fn_unstable(contracts)]
481+ // #[core::contracts::ensures(
482+ // move |result: &Result<(Self, usize), LayoutError>|
483+ // result.is_err() || (
484+ // result.as_ref().unwrap().0.align() == cmp::max(self.align(), next.align()) &&
485+ // result.as_ref().unwrap().0.size() >= self.size() + next.size() &&
486+ // result.as_ref().unwrap().1 >= self.size() &&
487+ // result.as_ref().unwrap().1 <= result.as_ref().unwrap().0.size()))]
431488 pub const fn extend ( & self , next : Self ) -> Result < ( Self , usize ) , LayoutError > {
432489 let new_align = Alignment :: max ( self . align , next. align ) ;
433490 let offset = self . size_rounded_up_to_custom_align ( next. align ) ;
@@ -459,6 +516,13 @@ impl Layout {
459516 /// On arithmetic overflow, returns `LayoutError`.
460517 #[ unstable( feature = "alloc_layout_extra" , issue = "55724" ) ]
461518 #[ inline]
519+ // FIXME: requires `&self` to be `'static`
520+ // #[rustc_allow_const_fn_unstable(contracts)]
521+ // #[core::contracts::ensures(
522+ // move |result: &Result<Self, LayoutError>|
523+ // result.is_err() || (
524+ // result.as_ref().unwrap().size() == n * self.size() &&
525+ // result.as_ref().unwrap().align() == self.align()))]
462526 pub const fn repeat_packed ( & self , n : usize ) -> Result < Self , LayoutError > {
463527 if let Some ( size) = self . size . checked_mul ( n) {
464528 // The safe constructor is called here to enforce the isize size limit.
@@ -476,6 +540,13 @@ impl Layout {
476540 /// On arithmetic overflow, returns `LayoutError`.
477541 #[ unstable( feature = "alloc_layout_extra" , issue = "55724" ) ]
478542 #[ inline]
543+ // FIXME: requires `&self` to be `'static`
544+ // #[rustc_allow_const_fn_unstable(contracts)]
545+ // #[core::contracts::ensures(
546+ // move |result: &Result<Self, LayoutError>|
547+ // result.is_err() || (
548+ // result.as_ref().unwrap().size() == self.size() + next.size() &&
549+ // result.as_ref().unwrap().align() == self.align()))]
479550 pub const fn extend_packed ( & self , next : Self ) -> Result < Self , LayoutError > {
480551 // SAFETY: each `size` is at most `isize::MAX == usize::MAX/2`, so the
481552 // sum is at most `usize::MAX/2*2 == usize::MAX - 1`, and cannot overflow.
@@ -491,6 +562,12 @@ impl Layout {
491562 #[ stable( feature = "alloc_layout_manipulation" , since = "1.44.0" ) ]
492563 #[ rustc_const_stable( feature = "const_alloc_layout" , since = "1.85.0" ) ]
493564 #[ inline]
565+ #[ rustc_allow_const_fn_unstable( contracts) ]
566+ #[ core:: contracts:: ensures(
567+ move |result: & Result <Self , LayoutError >|
568+ result. is_err( ) || (
569+ result. as_ref( ) . unwrap( ) . size( ) == n * mem:: size_of:: <T >( ) &&
570+ result. as_ref( ) . unwrap( ) . align( ) == mem:: align_of:: <T >( ) ) ) ]
494571 pub const fn array < T > ( n : usize ) -> Result < Self , LayoutError > {
495572 // Reduce the amount of code we need to monomorphize per `T`.
496573 return inner ( T :: LAYOUT , n) ;
0 commit comments