about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2022-12-07 20:30:42 +0000
committerMichael Goulet <michael@errs.io>2022-12-08 04:59:10 +0000
commit7d23e29f9fb61985aca0227acbabb62f95208c01 (patch)
treeab55f3a542900404040835e8513434288e9763f6
parent57b722688d03fc8115987375eee1d076cc89bc68 (diff)
downloadrust-7d23e29f9fb61985aca0227acbabb62f95208c01.tar.gz
rust-7d23e29f9fb61985aca0227acbabb62f95208c01.zip
Pull out logic into distinct functions
-rw-r--r--compiler/rustc_ty_utils/src/layout.rs349
1 files changed, 165 insertions, 184 deletions
diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs
index 8bbbf26f470..f4672a70072 100644
--- a/compiler/rustc_ty_utils/src/layout.rs
+++ b/compiler/rustc_ty_utils/src/layout.rs
@@ -1,3 +1,4 @@
+use hir::def_id::DefId;
 use rustc_hir as hir;
 use rustc_index::bit_set::BitSet;
 use rustc_index::vec::{Idx, IndexVec};
@@ -6,7 +7,7 @@ use rustc_middle::ty::layout::{
     IntegerExt, LayoutCx, LayoutError, LayoutOf, TyAndLayout, MAX_SIMD_LANES,
 };
 use rustc_middle::ty::{
-    self, subst::SubstsRef, EarlyBinder, ReprOptions, Ty, TyCtxt, TypeVisitable,
+    self, subst::SubstsRef, AdtDef, EarlyBinder, ReprOptions, Ty, TyCtxt, TypeVisitable,
 };
 use rustc_session::{DataTypeKind, FieldInfo, SizeKind, VariantInfo};
 use rustc_span::symbol::Symbol;
@@ -815,206 +816,186 @@ fn record_layout_for_printing_outlined<'tcx>(
     };
 
     match *layout.ty.kind() {
-        ty::Adt(ref adt_def, _) => {
+        ty::Adt(adt_def, _) => {
             debug!("print-type-size t: `{:?}` process adt", layout.ty);
             let adt_kind = adt_def.adt_kind();
             let adt_packed = adt_def.repr().pack.is_some();
-
-            let build_variant_info =
-                |n: Option<Symbol>, flds: &[Symbol], layout: TyAndLayout<'tcx>| {
-                    let mut min_size = Size::ZERO;
-                    let field_info: Vec<_> = flds
-                        .iter()
-                        .enumerate()
-                        .map(|(i, &name)| {
-                            let field_layout = layout.field(cx, i);
-                            let offset = layout.fields.offset(i);
-                            min_size = min_size.max(offset + field_layout.size);
-                            FieldInfo {
-                                name,
-                                offset: offset.bytes(),
-                                size: field_layout.size.bytes(),
-                                align: field_layout.align.abi.bytes(),
-                            }
-                        })
-                        .collect();
-
-                    VariantInfo {
-                        name: n,
-                        kind: if layout.is_unsized() { SizeKind::Min } else { SizeKind::Exact },
-                        align: layout.align.abi.bytes(),
-                        size: if min_size.bytes() == 0 {
-                            layout.size.bytes()
-                        } else {
-                            min_size.bytes()
-                        },
-                        fields: field_info,
-                    }
-                };
-
-            match layout.variants {
-                Variants::Single { index } => {
-                    if !adt_def.variants().is_empty() && layout.fields != FieldsShape::Primitive {
-                        debug!(
-                            "print-type-size `{:#?}` variant {}",
-                            layout,
-                            adt_def.variant(index).name
-                        );
-                        let variant_def = &adt_def.variant(index);
-                        let fields: Vec<_> = variant_def.fields.iter().map(|f| f.name).collect();
-                        record(
-                            adt_kind.into(),
-                            adt_packed,
-                            None,
-                            vec![build_variant_info(Some(variant_def.name), &fields, layout)],
-                        );
-                    } else {
-                        // (This case arises for *empty* enums; so give it
-                        // zero variants.)
-                        record(adt_kind.into(), adt_packed, None, vec![]);
-                    }
-                }
-
-                Variants::Multiple { tag, ref tag_encoding, .. } => {
-                    debug!(
-                        "print-type-size `{:#?}` adt general variants def {}",
-                        layout.ty,
-                        adt_def.variants().len()
-                    );
-                    let variant_infos: Vec<_> = adt_def
-                        .variants()
-                        .iter_enumerated()
-                        .map(|(i, variant_def)| {
-                            let fields: Vec<_> =
-                                variant_def.fields.iter().map(|f| f.name).collect();
-                            build_variant_info(
-                                Some(variant_def.name),
-                                &fields,
-                                layout.for_variant(cx, i),
-                            )
-                        })
-                        .collect();
-                    record(
-                        adt_kind.into(),
-                        adt_packed,
-                        match tag_encoding {
-                            TagEncoding::Direct => Some(tag.size(cx)),
-                            _ => None,
-                        },
-                        variant_infos,
-                    );
-                }
-            }
+            let (variant_infos, opt_discr_size) = variant_info_for_adt(cx, layout, adt_def);
+            record(adt_kind.into(), adt_packed, opt_discr_size, variant_infos);
         }
 
         ty::Generator(def_id, substs, _) => {
             debug!("print-type-size t: `{:?}` record generator", layout.ty);
             // Generators always have a begin/poisoned/end state with additional suspend points
-            match layout.variants {
-                Variants::Multiple { tag, ref tag_encoding, .. } => {
-                    let (generator, state_specific_names) =
-                        cx.tcx.generator_layout_and_saved_local_names(def_id);
-                    let upvar_names = cx.tcx.closure_saved_names_of_captured_variables(def_id);
-
-                    let mut upvars_size = Size::ZERO;
-                    let upvar_fields: Vec<_> = substs
-                        .as_generator()
-                        .upvar_tys()
-                        .zip(upvar_names)
-                        .enumerate()
-                        .map(|(field_idx, (_, name))| {
-                            let field_layout = layout.field(cx, field_idx);
-                            let offset = layout.fields.offset(field_idx);
-                            upvars_size = upvars_size.max(offset + field_layout.size);
-                            FieldInfo {
-                                name: Symbol::intern(&name),
-                                offset: offset.bytes(),
-                                size: field_layout.size.bytes(),
-                                align: field_layout.align.abi.bytes(),
-                            }
-                        })
-                        .collect();
-
-                    let variant_infos: Vec<_> = generator
-                        .variant_fields
-                        .iter_enumerated()
-                        .map(|(variant_idx, variant_def)| {
-                            let variant_layout = layout.for_variant(cx, variant_idx);
-                            let mut variant_size = Size::ZERO;
-                            let fields = variant_def
-                                .iter()
-                                .enumerate()
-                                .map(|(field_idx, local)| {
-                                    let field_layout = variant_layout.field(cx, field_idx);
-                                    let offset = variant_layout.fields.offset(field_idx);
-                                    // The struct is as large as the last field's end
-                                    variant_size = variant_size.max(offset + field_layout.size);
-                                    FieldInfo {
-                                        name: state_specific_names
-                                            .get(*local)
-                                            .copied()
-                                            .flatten()
-                                            .unwrap_or(Symbol::intern(&format!(
-                                                ".generator_field{}",
-                                                local.as_usize()
-                                            ))),
-                                        offset: offset.bytes(),
-                                        size: field_layout.size.bytes(),
-                                        align: field_layout.align.abi.bytes(),
-                                    }
-                                })
-                                .chain(upvar_fields.iter().copied())
-                                .collect();
-
-                            // If the variant has no state-specific fields, then it's the size of the upvars.
-                            if variant_size == Size::ZERO {
-                                variant_size = upvars_size;
-                            }
-                            // We need to add the discriminant size back into min_size, since it is subtracted
-                            // later during printing.
-                            variant_size += match tag_encoding {
-                                TagEncoding::Direct => tag.size(cx),
-                                _ => Size::ZERO,
-                            };
-
-                            VariantInfo {
-                                name: Some(Symbol::intern(&ty::GeneratorSubsts::variant_name(
-                                    variant_idx,
-                                ))),
-                                kind: SizeKind::Exact,
-                                size: variant_size.bytes(),
-                                align: variant_layout.align.abi.bytes(),
-                                fields,
-                            }
-                        })
-                        .collect();
-                    record(
-                        DataTypeKind::Generator,
-                        false,
-                        match tag_encoding {
-                            TagEncoding::Direct => Some(tag.size(cx)),
-                            _ => None,
-                        },
-                        variant_infos,
-                    );
-                }
-                _ => {
-                    // This should never happen, but I would rather not panic.
-                    record(DataTypeKind::Generator, false, None, vec![]);
-                    return;
-                }
-            }
+            let (variant_infos, opt_discr_size) =
+                variant_info_for_generator(cx, layout, def_id, substs);
+            record(DataTypeKind::Generator, false, opt_discr_size, variant_infos);
         }
 
         ty::Closure(..) => {
             debug!("print-type-size t: `{:?}` record closure", layout.ty);
             record(DataTypeKind::Closure, false, None, vec![]);
-            return;
         }
 
         _ => {
             debug!("print-type-size t: `{:?}` skip non-nominal", layout.ty);
-            return;
         }
     };
 }
+
+fn variant_info_for_adt<'tcx>(
+    cx: &LayoutCx<'tcx, TyCtxt<'tcx>>,
+    layout: TyAndLayout<'tcx>,
+    adt_def: AdtDef<'tcx>,
+) -> (Vec<VariantInfo>, Option<Size>) {
+    let build_variant_info = |n: Option<Symbol>, flds: &[Symbol], layout: TyAndLayout<'tcx>| {
+        let mut min_size = Size::ZERO;
+        let field_info: Vec<_> = flds
+            .iter()
+            .enumerate()
+            .map(|(i, &name)| {
+                let field_layout = layout.field(cx, i);
+                let offset = layout.fields.offset(i);
+                min_size = min_size.max(offset + field_layout.size);
+                FieldInfo {
+                    name,
+                    offset: offset.bytes(),
+                    size: field_layout.size.bytes(),
+                    align: field_layout.align.abi.bytes(),
+                }
+            })
+            .collect();
+
+        VariantInfo {
+            name: n,
+            kind: if layout.is_unsized() { SizeKind::Min } else { SizeKind::Exact },
+            align: layout.align.abi.bytes(),
+            size: if min_size.bytes() == 0 { layout.size.bytes() } else { min_size.bytes() },
+            fields: field_info,
+        }
+    };
+
+    match layout.variants {
+        Variants::Single { index } => {
+            if !adt_def.variants().is_empty() && layout.fields != FieldsShape::Primitive {
+                debug!("print-type-size `{:#?}` variant {}", layout, adt_def.variant(index).name);
+                let variant_def = &adt_def.variant(index);
+                let fields: Vec<_> = variant_def.fields.iter().map(|f| f.name).collect();
+                (vec![build_variant_info(Some(variant_def.name), &fields, layout)], None)
+            } else {
+                (vec![], None)
+            }
+        }
+
+        Variants::Multiple { tag, ref tag_encoding, .. } => {
+            debug!(
+                "print-type-size `{:#?}` adt general variants def {}",
+                layout.ty,
+                adt_def.variants().len()
+            );
+            let variant_infos: Vec<_> = adt_def
+                .variants()
+                .iter_enumerated()
+                .map(|(i, variant_def)| {
+                    let fields: Vec<_> = variant_def.fields.iter().map(|f| f.name).collect();
+                    build_variant_info(Some(variant_def.name), &fields, layout.for_variant(cx, i))
+                })
+                .collect();
+
+            (
+                variant_infos,
+                match tag_encoding {
+                    TagEncoding::Direct => Some(tag.size(cx)),
+                    _ => None,
+                },
+            )
+        }
+    }
+}
+
+fn variant_info_for_generator<'tcx>(
+    cx: &LayoutCx<'tcx, TyCtxt<'tcx>>,
+    layout: TyAndLayout<'tcx>,
+    def_id: DefId,
+    substs: ty::SubstsRef<'tcx>,
+) -> (Vec<VariantInfo>, Option<Size>) {
+    let Variants::Multiple { tag, ref tag_encoding, .. } = layout.variants else {
+        return (vec![], None);
+    };
+
+    let (generator, state_specific_names) = cx.tcx.generator_layout_and_saved_local_names(def_id);
+    let upvar_names = cx.tcx.closure_saved_names_of_captured_variables(def_id);
+
+    let mut upvars_size = Size::ZERO;
+    let upvar_fields: Vec<_> = substs
+        .as_generator()
+        .upvar_tys()
+        .zip(upvar_names)
+        .enumerate()
+        .map(|(field_idx, (_, name))| {
+            let field_layout = layout.field(cx, field_idx);
+            let offset = layout.fields.offset(field_idx);
+            upvars_size = upvars_size.max(offset + field_layout.size);
+            FieldInfo {
+                name: Symbol::intern(&name),
+                offset: offset.bytes(),
+                size: field_layout.size.bytes(),
+                align: field_layout.align.abi.bytes(),
+            }
+        })
+        .collect();
+
+    let variant_infos: Vec<_> = generator
+        .variant_fields
+        .iter_enumerated()
+        .map(|(variant_idx, variant_def)| {
+            let variant_layout = layout.for_variant(cx, variant_idx);
+            let mut variant_size = Size::ZERO;
+            let fields = variant_def
+                .iter()
+                .enumerate()
+                .map(|(field_idx, local)| {
+                    let field_layout = variant_layout.field(cx, field_idx);
+                    let offset = variant_layout.fields.offset(field_idx);
+                    // The struct is as large as the last field's end
+                    variant_size = variant_size.max(offset + field_layout.size);
+                    FieldInfo {
+                        name: state_specific_names.get(*local).copied().flatten().unwrap_or(
+                            Symbol::intern(&format!(".generator_field{}", local.as_usize())),
+                        ),
+                        offset: offset.bytes(),
+                        size: field_layout.size.bytes(),
+                        align: field_layout.align.abi.bytes(),
+                    }
+                })
+                .chain(upvar_fields.iter().copied())
+                .collect();
+
+            // If the variant has no state-specific fields, then it's the size of the upvars.
+            if variant_size == Size::ZERO {
+                variant_size = upvars_size;
+            }
+            // We need to add the discriminant size back into min_size, since it is subtracted
+            // later during printing.
+            variant_size += match tag_encoding {
+                TagEncoding::Direct => tag.size(cx),
+                _ => Size::ZERO,
+            };
+
+            VariantInfo {
+                name: Some(Symbol::intern(&ty::GeneratorSubsts::variant_name(variant_idx))),
+                kind: SizeKind::Exact,
+                size: variant_size.bytes(),
+                align: variant_layout.align.abi.bytes(),
+                fields,
+            }
+        })
+        .collect();
+    (
+        variant_infos,
+        match tag_encoding {
+            TagEncoding::Direct => Some(tag.size(cx)),
+            _ => None,
+        },
+    )
+}