@@ -162,7 +162,7 @@ impl Layout {
162
162
/// Returns an error if the combination of `self.size()` and the given
163
163
/// `align` violates the conditions listed in
164
164
/// [`Layout::from_size_align`](#method.from_size_align).
165
- #[ unstable ( feature = "alloc_layout_extra " , issue = "55724 " ) ]
165
+ #[ stable ( feature = "alloc_layout_manipulation " , since = "1.44.0 " ) ]
166
166
#[ inline]
167
167
pub fn align_to ( & self , align : usize ) -> Result < Self , LayoutErr > {
168
168
Layout :: from_size_align ( self . size ( ) , cmp:: max ( self . align ( ) , align) )
@@ -218,7 +218,7 @@ impl Layout {
218
218
///
219
219
/// This is equivalent to adding the result of `padding_needed_for`
220
220
/// to the layout's current size.
221
- #[ unstable ( feature = "alloc_layout_extra " , issue = "55724 " ) ]
221
+ #[ stable ( feature = "alloc_layout_manipulation " , since = "1.44.0 " ) ]
222
222
#[ inline]
223
223
pub fn pad_to_align ( & self ) -> Layout {
224
224
let pad = self . padding_needed_for ( self . align ( ) ) ;
@@ -258,19 +258,50 @@ impl Layout {
258
258
259
259
/// Creates a layout describing the record for `self` followed by
260
260
/// `next`, including any necessary padding to ensure that `next`
261
- /// will be properly aligned. Note that the resulting layout will
262
- /// satisfy the alignment properties of both `self` and `next`.
261
+ /// will be properly aligned, but *no trailing padding*.
263
262
///
264
- /// The resulting layout will be the same as that of a C struct containing
265
- /// two fields with the layouts of `self` and `next`, in that order.
263
+ /// In order to match C representation layout `repr(C)`, you should
264
+ /// call `pad_to_align` after extending the layout with all fields.
265
+ /// (There is no way to match the default Rust representation
266
+ /// layout `repr(Rust)`, as it is unspecified.)
266
267
///
267
- /// Returns `Some((k, offset))`, where `k` is layout of the concatenated
268
+ /// Note that the alignment of the resulting layout will be the maximum of
269
+ /// those of `self` and `next`, in order to ensure alignment of both parts.
270
+ ///
271
+ /// Returns `Ok((k, offset))`, where `k` is layout of the concatenated
268
272
/// record and `offset` is the relative location, in bytes, of the
269
273
/// start of the `next` embedded within the concatenated record
270
274
/// (assuming that the record itself starts at offset 0).
271
275
///
272
276
/// On arithmetic overflow, returns `LayoutErr`.
273
- #[ unstable( feature = "alloc_layout_extra" , issue = "55724" ) ]
277
+ ///
278
+ /// # Examples
279
+ ///
280
+ /// To calculate the layout of a `#[repr(C)]` structure and the offsets of
281
+ /// the fields from its fields' layouts:
282
+ ///
283
+ /// ```rust
284
+ /// # use std::alloc::{Layout, LayoutErr};
285
+ /// pub fn repr_c(fields: &[Layout]) -> Result<(Layout, Vec<usize>), LayoutErr> {
286
+ /// let mut offsets = Vec::new();
287
+ /// let mut layout = Layout::from_size_align(0, 1)?;
288
+ /// for &field in fields {
289
+ /// let (new_layout, offset) = layout.extend(field)?;
290
+ /// layout = new_layout;
291
+ /// offsets.push(offset);
292
+ /// }
293
+ /// // Remember to finalize with `pad_to_align`!
294
+ /// Ok((layout.pad_to_align(), offsets))
295
+ /// }
296
+ /// # // test that it works
297
+ /// # #[repr(C)] struct S { a: u64, b: u32, c: u16, d: u32 }
298
+ /// # let s = Layout::new::<S>();
299
+ /// # let u16 = Layout::new::<u16>();
300
+ /// # let u32 = Layout::new::<u32>();
301
+ /// # let u64 = Layout::new::<u64>();
302
+ /// # assert_eq!(repr_c(&[u64, u32, u16, u32]), Ok((s, vec![0, 8, 12, 16])));
303
+ /// ```
304
+ #[ stable( feature = "alloc_layout_manipulation" , since = "1.44.0" ) ]
274
305
#[ inline]
275
306
pub fn extend ( & self , next : Self ) -> Result < ( Self , usize ) , LayoutErr > {
276
307
let new_align = cmp:: max ( self . align ( ) , next. align ( ) ) ;
@@ -318,13 +349,12 @@ impl Layout {
318
349
/// Creates a layout describing the record for a `[T; n]`.
319
350
///
320
351
/// On arithmetic overflow, returns `LayoutErr`.
321
- #[ unstable ( feature = "alloc_layout_extra " , issue = "55724 " ) ]
352
+ #[ stable ( feature = "alloc_layout_manipulation " , since = "1.44.0 " ) ]
322
353
#[ inline]
323
354
pub fn array < T > ( n : usize ) -> Result < Self , LayoutErr > {
324
- Layout :: new :: < T > ( ) . repeat ( n) . map ( |( k, offs) | {
325
- debug_assert ! ( offs == mem:: size_of:: <T >( ) ) ;
326
- k
327
- } )
355
+ let ( layout, offset) = Layout :: new :: < T > ( ) . repeat ( n) ?;
356
+ debug_assert_eq ! ( offset, mem:: size_of:: <T >( ) ) ;
357
+ Ok ( layout. pad_to_align ( ) )
328
358
}
329
359
}
330
360
0 commit comments