From 1b76bb03fe9fd0803efeea9964b61d3c1b7e96ae Mon Sep 17 00:00:00 2001 From: CAD97 Date: Fri, 21 Feb 2020 15:38:29 -0500 Subject: [PATCH 1/7] Stabilize some of alloc_layout_extras --- src/libcore/alloc/layout.rs | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/src/libcore/alloc/layout.rs b/src/libcore/alloc/layout.rs index fa644cfe99ed6..98f9054588a87 100644 --- a/src/libcore/alloc/layout.rs +++ b/src/libcore/alloc/layout.rs @@ -162,7 +162,7 @@ impl Layout { /// Returns an error if the combination of `self.size()` and the given /// `align` violates the conditions listed in /// [`Layout::from_size_align`](#method.from_size_align). - #[unstable(feature = "alloc_layout_extra", issue = "55724")] + #[stable(feature = "alloc_layout_manipulation", since = "1.44.0")] #[inline] pub fn align_to(&self, align: usize) -> Result { Layout::from_size_align(self.size(), cmp::max(self.align(), align)) @@ -218,7 +218,7 @@ impl Layout { /// /// This is equivalent to adding the result of `padding_needed_for` /// to the layout's current size. - #[unstable(feature = "alloc_layout_extra", issue = "55724")] + #[stable(feature = "alloc_layout_manipulation", since = "1.44.0")] #[inline] pub fn pad_to_align(&self) -> Layout { let pad = self.padding_needed_for(self.align()); @@ -258,19 +258,17 @@ impl Layout { /// Creates a layout describing the record for `self` followed by /// `next`, including any necessary padding to ensure that `next` - /// will be properly aligned. Note that the resulting layout will - /// satisfy the alignment properties of both `self` and `next`. - /// - /// The resulting layout will be the same as that of a C struct containing - /// two fields with the layouts of `self` and `next`, in that order. + /// will be properly aligned, but no trailing padding. Note that + /// the resulting layout will satisfy the alignment properties of + /// both `self` and `next`, in order to ensure field alignment. /// - /// Returns `Some((k, offset))`, where `k` is layout of the concatenated + /// Returns `Ok((k, offset))`, where `k` is layout of the concatenated /// record and `offset` is the relative location, in bytes, of the /// start of the `next` embedded within the concatenated record /// (assuming that the record itself starts at offset 0). /// /// On arithmetic overflow, returns `LayoutErr`. - #[unstable(feature = "alloc_layout_extra", issue = "55724")] + #[stable(feature = "alloc_layout_manipulation", since = "1.44.0")] #[inline] pub fn extend(&self, next: Self) -> Result<(Self, usize), LayoutErr> { let new_align = cmp::max(self.align(), next.align()); @@ -318,13 +316,12 @@ impl Layout { /// Creates a layout describing the record for a `[T; n]`. /// /// On arithmetic overflow, returns `LayoutErr`. - #[unstable(feature = "alloc_layout_extra", issue = "55724")] + #[stable(feature = "alloc_layout_manipulation", since = "1.44.0")] #[inline] pub fn array(n: usize) -> Result { - Layout::new::().repeat(n).map(|(k, offs)| { - debug_assert!(offs == mem::size_of::()); - k - }) + let (layout, offset) = Layout::new::().repeat(n)?; + debug_assert_eq!(offset, mem::size_of::()); + Ok(layout.pad_to_align()) } } From c266b8b98c763984c6d1183e3518379c0cf2751f Mon Sep 17 00:00:00 2001 From: Christopher Durham Date: Wed, 15 Apr 2020 15:50:31 -0400 Subject: [PATCH 2/7] emphasize *no trailing padding* --- src/libcore/alloc/layout.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/alloc/layout.rs b/src/libcore/alloc/layout.rs index 98f9054588a87..ec3a42469bc11 100644 --- a/src/libcore/alloc/layout.rs +++ b/src/libcore/alloc/layout.rs @@ -258,7 +258,7 @@ impl Layout { /// Creates a layout describing the record for `self` followed by /// `next`, including any necessary padding to ensure that `next` - /// will be properly aligned, but no trailing padding. Note that + /// will be properly aligned, but *no trailing padding*. Note that /// the resulting layout will satisfy the alignment properties of /// both `self` and `next`, in order to ensure field alignment. /// From 053c2dddda209444e7dd0bc8df2f4b0f8337e9f5 Mon Sep 17 00:00:00 2001 From: CAD97 Date: Wed, 15 Apr 2020 19:54:55 -0400 Subject: [PATCH 3/7] Add note about Layout::pad_to_align to Layout::extend --- src/libcore/alloc/layout.rs | 34 +++++++++++++++++++++++++++++++--- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/src/libcore/alloc/layout.rs b/src/libcore/alloc/layout.rs index ec3a42469bc11..2ad3662740308 100644 --- a/src/libcore/alloc/layout.rs +++ b/src/libcore/alloc/layout.rs @@ -258,9 +258,12 @@ impl Layout { /// Creates a layout describing the record for `self` followed by /// `next`, including any necessary padding to ensure that `next` - /// will be properly aligned, but *no trailing padding*. Note that - /// the resulting layout will satisfy the alignment properties of - /// both `self` and `next`, in order to ensure field alignment. + /// will be properly aligned, but *no trailing padding*. In order to + /// match C representation layout, you should call `pad_to_align` + /// after extending the layout with all fields. + /// + /// Note that the resulting layout will satisfy the alignment properties + /// of both `self` and `next`, in order to ensure alignment of both parts. /// /// Returns `Ok((k, offset))`, where `k` is layout of the concatenated /// record and `offset` is the relative location, in bytes, of the @@ -268,6 +271,31 @@ impl Layout { /// (assuming that the record itself starts at offset 0). /// /// On arithmetic overflow, returns `LayoutErr`. + /// + /// # Examples + /// + /// To calculate the layout of a `#[repr(C)]` structure from its fields' layouts: + /// + /// ```rust + /// # use std::alloc::{Layout, LayoutErr}; + /// pub fn repr_c(fields: &[Layout]) -> Result<(Layout, Vec), LayoutErr> { + /// let mut offsets = Vec::new(); + /// let mut layout = Layout::from_size_align(0, 1)?; + /// for &field in fields { + /// let (new_layout, offset) = layout.extend(field)?; + /// layout = new_layout; + /// offsets.push(offset); + /// } + /// Ok((layout.pad_to_align(), offsets)) + /// } + /// # // test that it works + /// # #[repr(C)] struct S { a: u64, b: u32, c: u16, d: u32 } + /// # let s = Layout::new::(); + /// # let u16 = Layout::new::(); + /// # let u32 = Layout::new::(); + /// # let u64 = Layout::new::(); + /// # assert_eq!(repr_c(&[u64, u32, u16, u32]), Ok((s, vec![0, 8, 12, 16]))); + /// ``` #[stable(feature = "alloc_layout_manipulation", since = "1.44.0")] #[inline] pub fn extend(&self, next: Self) -> Result<(Self, usize), LayoutErr> { From 5f1fd9da5488cc2fe88dc89e5ca3f183526388a9 Mon Sep 17 00:00:00 2001 From: Christopher Durham Date: Thu, 16 Apr 2020 16:44:30 -0400 Subject: [PATCH 4/7] Apply suggestions from code review Co-Authored-By: Ralf Jung --- src/libcore/alloc/layout.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/libcore/alloc/layout.rs b/src/libcore/alloc/layout.rs index 2ad3662740308..be62671f59f41 100644 --- a/src/libcore/alloc/layout.rs +++ b/src/libcore/alloc/layout.rs @@ -274,7 +274,8 @@ impl Layout { /// /// # Examples /// - /// To calculate the layout of a `#[repr(C)]` structure from its fields' layouts: + /// To calculate the layout of a `#[repr(C)]` structure and the offsets of + /// the fields from its fields' layouts: /// /// ```rust /// # use std::alloc::{Layout, LayoutErr}; @@ -286,6 +287,7 @@ impl Layout { /// layout = new_layout; /// offsets.push(offset); /// } + /// // Remember to finalize with `pad_to_align`! /// Ok((layout.pad_to_align(), offsets)) /// } /// # // test that it works From a01b00faf877deab0ef3896ce655351398fe4a47 Mon Sep 17 00:00:00 2001 From: CAD97 Date: Fri, 17 Apr 2020 18:59:36 -0400 Subject: [PATCH 5/7] Clarify layout information in Layout::extend --- src/libcore/alloc/layout.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/libcore/alloc/layout.rs b/src/libcore/alloc/layout.rs index be62671f59f41..b2a109d1cd1db 100644 --- a/src/libcore/alloc/layout.rs +++ b/src/libcore/alloc/layout.rs @@ -258,9 +258,11 @@ impl Layout { /// Creates a layout describing the record for `self` followed by /// `next`, including any necessary padding to ensure that `next` - /// will be properly aligned, but *no trailing padding*. In order to - /// match C representation layout, you should call `pad_to_align` - /// after extending the layout with all fields. + /// will be properly aligned, but *no trailing padding*. In order + /// to match C representation layout `repr(C)`, you should call + /// `pad_to_align` after extending the layout with all fields. + /// (There is no way to match the default Rust representation + /// layout `repr(Rust)`, as it is unspecified.) /// /// Note that the resulting layout will satisfy the alignment properties /// of both `self` and `next`, in order to ensure alignment of both parts. From 9c3adaf89c48931229aca910c6909e6a1c4ddedf Mon Sep 17 00:00:00 2001 From: Christopher Durham Date: Mon, 20 Apr 2020 12:28:30 -0400 Subject: [PATCH 6/7] Update src/libcore/alloc/layout.rs Co-Authored-By: Amanieu d'Antras --- src/libcore/alloc/layout.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libcore/alloc/layout.rs b/src/libcore/alloc/layout.rs index b2a109d1cd1db..3881f0685d4ca 100644 --- a/src/libcore/alloc/layout.rs +++ b/src/libcore/alloc/layout.rs @@ -264,8 +264,8 @@ impl Layout { /// (There is no way to match the default Rust representation /// layout `repr(Rust)`, as it is unspecified.) /// - /// Note that the resulting layout will satisfy the alignment properties - /// of both `self` and `next`, in order to ensure alignment of both parts. + /// Note that the alignment of the resulting layout will be the maximum of + /// those of `self` and `next`, in order to ensure alignment of both parts. /// /// Returns `Ok((k, offset))`, where `k` is layout of the concatenated /// record and `offset` is the relative location, in bytes, of the From 98f0a8241b621b28ac58c7a5e80de4ead13ab0bb Mon Sep 17 00:00:00 2001 From: CAD97 Date: Mon, 20 Apr 2020 12:30:35 -0400 Subject: [PATCH 7/7] Improve Layout::extend docs --- src/libcore/alloc/layout.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/libcore/alloc/layout.rs b/src/libcore/alloc/layout.rs index 3881f0685d4ca..6200cd242667f 100644 --- a/src/libcore/alloc/layout.rs +++ b/src/libcore/alloc/layout.rs @@ -258,9 +258,10 @@ impl Layout { /// Creates a layout describing the record for `self` followed by /// `next`, including any necessary padding to ensure that `next` - /// will be properly aligned, but *no trailing padding*. In order - /// to match C representation layout `repr(C)`, you should call - /// `pad_to_align` after extending the layout with all fields. + /// will be properly aligned, but *no trailing padding*. + /// + /// In order to match C representation layout `repr(C)`, you should + /// call `pad_to_align` after extending the layout with all fields. /// (There is no way to match the default Rust representation /// layout `repr(Rust)`, as it is unspecified.) ///