about summary refs log tree commit diff
path: root/compiler/rustc_abi/src/layout.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_abi/src/layout.rs')
-rw-r--r--compiler/rustc_abi/src/layout.rs61
1 files changed, 34 insertions, 27 deletions
diff --git a/compiler/rustc_abi/src/layout.rs b/compiler/rustc_abi/src/layout.rs
index 4bc578c7985..e8257544498 100644
--- a/compiler/rustc_abi/src/layout.rs
+++ b/compiler/rustc_abi/src/layout.rs
@@ -36,12 +36,14 @@ enum NicheBias {
 }
 
 #[derive(Copy, Clone, Debug)]
-pub enum LayoutCalculatorError {
+pub enum LayoutCalculatorError<F> {
     /// An unsized type was found in a location where a sized type was expected.
     ///
     /// This is not always a compile error, for example if there is a `[T]: Sized`
     /// bound in a where clause.
-    UnexpectedUnsized,
+    ///
+    /// Contains the field that was unexpectedly unsized.
+    UnexpectedUnsized(F),
 
     /// A type was too large for the target platform.
     SizeOverflow,
@@ -50,8 +52,8 @@ pub enum LayoutCalculatorError {
     EmptyUnion,
 }
 
-type LayoutCalculatorResult<FieldIdx, VariantIdx> =
-    Result<LayoutS<FieldIdx, VariantIdx>, LayoutCalculatorError>;
+type LayoutCalculatorResult<FieldIdx, VariantIdx, F> =
+    Result<LayoutS<FieldIdx, VariantIdx>, LayoutCalculatorError<F>>;
 
 #[derive(Clone, Copy, Debug)]
 pub struct LayoutCalculator<Cx> {
@@ -100,13 +102,13 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
         'a,
         FieldIdx: Idx,
         VariantIdx: Idx,
-        F: Deref<Target = &'a LayoutS<FieldIdx, VariantIdx>> + fmt::Debug,
+        F: Deref<Target = &'a LayoutS<FieldIdx, VariantIdx>> + fmt::Debug + Copy,
     >(
         &self,
         fields: &IndexSlice<FieldIdx, F>,
         repr: &ReprOptions,
         kind: StructKind,
-    ) -> LayoutCalculatorResult<FieldIdx, VariantIdx> {
+    ) -> LayoutCalculatorResult<FieldIdx, VariantIdx, F> {
         let dl = self.cx.data_layout();
         let layout = self.univariant_biased(fields, repr, kind, NicheBias::Start);
         // Enums prefer niches close to the beginning or the end of the variants so that other
@@ -191,7 +193,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
         'a,
         FieldIdx: Idx,
         VariantIdx: Idx,
-        F: Deref<Target = &'a LayoutS<FieldIdx, VariantIdx>> + fmt::Debug,
+        F: Deref<Target = &'a LayoutS<FieldIdx, VariantIdx>> + fmt::Debug + Copy,
     >(
         &self,
         repr: &ReprOptions,
@@ -203,7 +205,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
         discriminants: impl Iterator<Item = (VariantIdx, i128)>,
         dont_niche_optimize_enum: bool,
         always_sized: bool,
-    ) -> LayoutCalculatorResult<FieldIdx, VariantIdx> {
+    ) -> LayoutCalculatorResult<FieldIdx, VariantIdx, F> {
         let (present_first, present_second) = {
             let mut present_variants = variants
                 .iter_enumerated()
@@ -254,12 +256,12 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
         'a,
         FieldIdx: Idx,
         VariantIdx: Idx,
-        F: Deref<Target = &'a LayoutS<FieldIdx, VariantIdx>> + fmt::Debug,
+        F: Deref<Target = &'a LayoutS<FieldIdx, VariantIdx>> + fmt::Debug + Copy,
     >(
         &self,
         repr: &ReprOptions,
         variants: &IndexSlice<VariantIdx, IndexVec<FieldIdx, F>>,
-    ) -> LayoutCalculatorResult<FieldIdx, VariantIdx> {
+    ) -> LayoutCalculatorResult<FieldIdx, VariantIdx, F> {
         let dl = self.cx.data_layout();
         let mut align = if repr.pack.is_some() { dl.i8_align } else { dl.aggregate_align };
         let mut max_repr_align = repr.align;
@@ -279,7 +281,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
         let only_variant = &variants[only_variant_idx];
         for field in only_variant {
             if field.is_unsized() {
-                return Err(LayoutCalculatorError::UnexpectedUnsized);
+                return Err(LayoutCalculatorError::UnexpectedUnsized(*field));
             }
 
             align = align.max(field.align);
@@ -359,7 +361,12 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
     }
 
     /// single-variant enums are just structs, if you think about it
-    fn layout_of_struct<'a, FieldIdx: Idx, VariantIdx: Idx, F>(
+    fn layout_of_struct<
+        'a,
+        FieldIdx: Idx,
+        VariantIdx: Idx,
+        F: Deref<Target = &'a LayoutS<FieldIdx, VariantIdx>> + fmt::Debug + Copy,
+    >(
         &self,
         repr: &ReprOptions,
         variants: &IndexSlice<VariantIdx, IndexVec<FieldIdx, F>>,
@@ -368,10 +375,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
         scalar_valid_range: (Bound<u128>, Bound<u128>),
         always_sized: bool,
         present_first: VariantIdx,
-    ) -> LayoutCalculatorResult<FieldIdx, VariantIdx>
-    where
-        F: Deref<Target = &'a LayoutS<FieldIdx, VariantIdx>> + fmt::Debug,
-    {
+    ) -> LayoutCalculatorResult<FieldIdx, VariantIdx, F> {
         // Struct, or univariant enum equivalent to a struct.
         // (Typechecking will reject discriminant-sizing attrs.)
 
@@ -457,17 +461,19 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
         Ok(st)
     }
 
-    fn layout_of_enum<'a, FieldIdx: Idx, VariantIdx: Idx, F>(
+    fn layout_of_enum<
+        'a,
+        FieldIdx: Idx,
+        VariantIdx: Idx,
+        F: Deref<Target = &'a LayoutS<FieldIdx, VariantIdx>> + fmt::Debug + Copy,
+    >(
         &self,
         repr: &ReprOptions,
         variants: &IndexSlice<VariantIdx, IndexVec<FieldIdx, F>>,
         discr_range_of_repr: impl Fn(i128, i128) -> (Integer, bool),
         discriminants: impl Iterator<Item = (VariantIdx, i128)>,
         dont_niche_optimize_enum: bool,
-    ) -> LayoutCalculatorResult<FieldIdx, VariantIdx>
-    where
-        F: Deref<Target = &'a LayoutS<FieldIdx, VariantIdx>> + fmt::Debug,
-    {
+    ) -> LayoutCalculatorResult<FieldIdx, VariantIdx, F> {
         // Until we've decided whether to use the tagged or
         // niche filling LayoutS, we don't want to intern the
         // variant layouts, so we can't store them in the
@@ -972,14 +978,14 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
         'a,
         FieldIdx: Idx,
         VariantIdx: Idx,
-        F: Deref<Target = &'a LayoutS<FieldIdx, VariantIdx>> + fmt::Debug,
+        F: Deref<Target = &'a LayoutS<FieldIdx, VariantIdx>> + fmt::Debug + Copy,
     >(
         &self,
         fields: &IndexSlice<FieldIdx, F>,
         repr: &ReprOptions,
         kind: StructKind,
         niche_bias: NicheBias,
-    ) -> LayoutCalculatorResult<FieldIdx, VariantIdx> {
+    ) -> LayoutCalculatorResult<FieldIdx, VariantIdx, F> {
         let dl = self.cx.data_layout();
         let pack = repr.pack;
         let mut align = if pack.is_some() { dl.i8_align } else { dl.aggregate_align };
@@ -1124,7 +1130,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
         // field 5 with offset 0 puts 0 in offsets[5].
         // At the bottom of this function, we invert `inverse_memory_index` to
         // produce `memory_index` (see `invert_mapping`).
-        let mut sized = true;
+        let mut unsized_field = None::<&F>;
         let mut offsets = IndexVec::from_elem(Size::ZERO, fields);
         let mut offset = Size::ZERO;
         let mut largest_niche = None;
@@ -1137,12 +1143,12 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
         }
         for &i in &inverse_memory_index {
             let field = &fields[i];
-            if !sized {
-                return Err(LayoutCalculatorError::UnexpectedUnsized);
+            if let Some(unsized_field) = unsized_field {
+                return Err(LayoutCalculatorError::UnexpectedUnsized(*unsized_field));
             }
 
             if field.is_unsized() {
-                sized = false;
+                unsized_field = Some(field);
             }
 
             // Invariant: offset < dl.obj_size_bound() <= 1<<61
@@ -1206,6 +1212,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
             return Err(LayoutCalculatorError::SizeOverflow);
         }
         let mut layout_of_single_non_zst_field = None;
+        let sized = unsized_field.is_none();
         let mut abi = Abi::Aggregate { sized };
 
         let optimize_abi = !repr.inhibit_newtype_abi_optimization();