Skip to content

Commit 7d23e29

Browse files
Pull out logic into distinct functions
1 parent 57b7226 commit 7d23e29

File tree

1 file changed

+165
-184
lines changed

1 file changed

+165
-184
lines changed

compiler/rustc_ty_utils/src/layout.rs

+165-184
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use hir::def_id::DefId;
12
use rustc_hir as hir;
23
use rustc_index::bit_set::BitSet;
34
use rustc_index::vec::{Idx, IndexVec};
@@ -6,7 +7,7 @@ use rustc_middle::ty::layout::{
67
IntegerExt, LayoutCx, LayoutError, LayoutOf, TyAndLayout, MAX_SIMD_LANES,
78
};
89
use rustc_middle::ty::{
9-
self, subst::SubstsRef, EarlyBinder, ReprOptions, Ty, TyCtxt, TypeVisitable,
10+
self, subst::SubstsRef, AdtDef, EarlyBinder, ReprOptions, Ty, TyCtxt, TypeVisitable,
1011
};
1112
use rustc_session::{DataTypeKind, FieldInfo, SizeKind, VariantInfo};
1213
use rustc_span::symbol::Symbol;
@@ -815,206 +816,186 @@ fn record_layout_for_printing_outlined<'tcx>(
815816
};
816817

817818
match *layout.ty.kind() {
818-
ty::Adt(ref adt_def, _) => {
819+
ty::Adt(adt_def, _) => {
819820
debug!("print-type-size t: `{:?}` process adt", layout.ty);
820821
let adt_kind = adt_def.adt_kind();
821822
let adt_packed = adt_def.repr().pack.is_some();
822-
823-
let build_variant_info =
824-
|n: Option<Symbol>, flds: &[Symbol], layout: TyAndLayout<'tcx>| {
825-
let mut min_size = Size::ZERO;
826-
let field_info: Vec<_> = flds
827-
.iter()
828-
.enumerate()
829-
.map(|(i, &name)| {
830-
let field_layout = layout.field(cx, i);
831-
let offset = layout.fields.offset(i);
832-
min_size = min_size.max(offset + field_layout.size);
833-
FieldInfo {
834-
name,
835-
offset: offset.bytes(),
836-
size: field_layout.size.bytes(),
837-
align: field_layout.align.abi.bytes(),
838-
}
839-
})
840-
.collect();
841-
842-
VariantInfo {
843-
name: n,
844-
kind: if layout.is_unsized() { SizeKind::Min } else { SizeKind::Exact },
845-
align: layout.align.abi.bytes(),
846-
size: if min_size.bytes() == 0 {
847-
layout.size.bytes()
848-
} else {
849-
min_size.bytes()
850-
},
851-
fields: field_info,
852-
}
853-
};
854-
855-
match layout.variants {
856-
Variants::Single { index } => {
857-
if !adt_def.variants().is_empty() && layout.fields != FieldsShape::Primitive {
858-
debug!(
859-
"print-type-size `{:#?}` variant {}",
860-
layout,
861-
adt_def.variant(index).name
862-
);
863-
let variant_def = &adt_def.variant(index);
864-
let fields: Vec<_> = variant_def.fields.iter().map(|f| f.name).collect();
865-
record(
866-
adt_kind.into(),
867-
adt_packed,
868-
None,
869-
vec![build_variant_info(Some(variant_def.name), &fields, layout)],
870-
);
871-
} else {
872-
// (This case arises for *empty* enums; so give it
873-
// zero variants.)
874-
record(adt_kind.into(), adt_packed, None, vec![]);
875-
}
876-
}
877-
878-
Variants::Multiple { tag, ref tag_encoding, .. } => {
879-
debug!(
880-
"print-type-size `{:#?}` adt general variants def {}",
881-
layout.ty,
882-
adt_def.variants().len()
883-
);
884-
let variant_infos: Vec<_> = adt_def
885-
.variants()
886-
.iter_enumerated()
887-
.map(|(i, variant_def)| {
888-
let fields: Vec<_> =
889-
variant_def.fields.iter().map(|f| f.name).collect();
890-
build_variant_info(
891-
Some(variant_def.name),
892-
&fields,
893-
layout.for_variant(cx, i),
894-
)
895-
})
896-
.collect();
897-
record(
898-
adt_kind.into(),
899-
adt_packed,
900-
match tag_encoding {
901-
TagEncoding::Direct => Some(tag.size(cx)),
902-
_ => None,
903-
},
904-
variant_infos,
905-
);
906-
}
907-
}
823+
let (variant_infos, opt_discr_size) = variant_info_for_adt(cx, layout, adt_def);
824+
record(adt_kind.into(), adt_packed, opt_discr_size, variant_infos);
908825
}
909826

910827
ty::Generator(def_id, substs, _) => {
911828
debug!("print-type-size t: `{:?}` record generator", layout.ty);
912829
// Generators always have a begin/poisoned/end state with additional suspend points
913-
match layout.variants {
914-
Variants::Multiple { tag, ref tag_encoding, .. } => {
915-
let (generator, state_specific_names) =
916-
cx.tcx.generator_layout_and_saved_local_names(def_id);
917-
let upvar_names = cx.tcx.closure_saved_names_of_captured_variables(def_id);
918-
919-
let mut upvars_size = Size::ZERO;
920-
let upvar_fields: Vec<_> = substs
921-
.as_generator()
922-
.upvar_tys()
923-
.zip(upvar_names)
924-
.enumerate()
925-
.map(|(field_idx, (_, name))| {
926-
let field_layout = layout.field(cx, field_idx);
927-
let offset = layout.fields.offset(field_idx);
928-
upvars_size = upvars_size.max(offset + field_layout.size);
929-
FieldInfo {
930-
name: Symbol::intern(&name),
931-
offset: offset.bytes(),
932-
size: field_layout.size.bytes(),
933-
align: field_layout.align.abi.bytes(),
934-
}
935-
})
936-
.collect();
937-
938-
let variant_infos: Vec<_> = generator
939-
.variant_fields
940-
.iter_enumerated()
941-
.map(|(variant_idx, variant_def)| {
942-
let variant_layout = layout.for_variant(cx, variant_idx);
943-
let mut variant_size = Size::ZERO;
944-
let fields = variant_def
945-
.iter()
946-
.enumerate()
947-
.map(|(field_idx, local)| {
948-
let field_layout = variant_layout.field(cx, field_idx);
949-
let offset = variant_layout.fields.offset(field_idx);
950-
// The struct is as large as the last field's end
951-
variant_size = variant_size.max(offset + field_layout.size);
952-
FieldInfo {
953-
name: state_specific_names
954-
.get(*local)
955-
.copied()
956-
.flatten()
957-
.unwrap_or(Symbol::intern(&format!(
958-
".generator_field{}",
959-
local.as_usize()
960-
))),
961-
offset: offset.bytes(),
962-
size: field_layout.size.bytes(),
963-
align: field_layout.align.abi.bytes(),
964-
}
965-
})
966-
.chain(upvar_fields.iter().copied())
967-
.collect();
968-
969-
// If the variant has no state-specific fields, then it's the size of the upvars.
970-
if variant_size == Size::ZERO {
971-
variant_size = upvars_size;
972-
}
973-
// We need to add the discriminant size back into min_size, since it is subtracted
974-
// later during printing.
975-
variant_size += match tag_encoding {
976-
TagEncoding::Direct => tag.size(cx),
977-
_ => Size::ZERO,
978-
};
979-
980-
VariantInfo {
981-
name: Some(Symbol::intern(&ty::GeneratorSubsts::variant_name(
982-
variant_idx,
983-
))),
984-
kind: SizeKind::Exact,
985-
size: variant_size.bytes(),
986-
align: variant_layout.align.abi.bytes(),
987-
fields,
988-
}
989-
})
990-
.collect();
991-
record(
992-
DataTypeKind::Generator,
993-
false,
994-
match tag_encoding {
995-
TagEncoding::Direct => Some(tag.size(cx)),
996-
_ => None,
997-
},
998-
variant_infos,
999-
);
1000-
}
1001-
_ => {
1002-
// This should never happen, but I would rather not panic.
1003-
record(DataTypeKind::Generator, false, None, vec![]);
1004-
return;
1005-
}
1006-
}
830+
let (variant_infos, opt_discr_size) =
831+
variant_info_for_generator(cx, layout, def_id, substs);
832+
record(DataTypeKind::Generator, false, opt_discr_size, variant_infos);
1007833
}
1008834

1009835
ty::Closure(..) => {
1010836
debug!("print-type-size t: `{:?}` record closure", layout.ty);
1011837
record(DataTypeKind::Closure, false, None, vec![]);
1012-
return;
1013838
}
1014839

1015840
_ => {
1016841
debug!("print-type-size t: `{:?}` skip non-nominal", layout.ty);
1017-
return;
1018842
}
1019843
};
1020844
}
845+
846+
fn variant_info_for_adt<'tcx>(
847+
cx: &LayoutCx<'tcx, TyCtxt<'tcx>>,
848+
layout: TyAndLayout<'tcx>,
849+
adt_def: AdtDef<'tcx>,
850+
) -> (Vec<VariantInfo>, Option<Size>) {
851+
let build_variant_info = |n: Option<Symbol>, flds: &[Symbol], layout: TyAndLayout<'tcx>| {
852+
let mut min_size = Size::ZERO;
853+
let field_info: Vec<_> = flds
854+
.iter()
855+
.enumerate()
856+
.map(|(i, &name)| {
857+
let field_layout = layout.field(cx, i);
858+
let offset = layout.fields.offset(i);
859+
min_size = min_size.max(offset + field_layout.size);
860+
FieldInfo {
861+
name,
862+
offset: offset.bytes(),
863+
size: field_layout.size.bytes(),
864+
align: field_layout.align.abi.bytes(),
865+
}
866+
})
867+
.collect();
868+
869+
VariantInfo {
870+
name: n,
871+
kind: if layout.is_unsized() { SizeKind::Min } else { SizeKind::Exact },
872+
align: layout.align.abi.bytes(),
873+
size: if min_size.bytes() == 0 { layout.size.bytes() } else { min_size.bytes() },
874+
fields: field_info,
875+
}
876+
};
877+
878+
match layout.variants {
879+
Variants::Single { index } => {
880+
if !adt_def.variants().is_empty() && layout.fields != FieldsShape::Primitive {
881+
debug!("print-type-size `{:#?}` variant {}", layout, adt_def.variant(index).name);
882+
let variant_def = &adt_def.variant(index);
883+
let fields: Vec<_> = variant_def.fields.iter().map(|f| f.name).collect();
884+
(vec![build_variant_info(Some(variant_def.name), &fields, layout)], None)
885+
} else {
886+
(vec![], None)
887+
}
888+
}
889+
890+
Variants::Multiple { tag, ref tag_encoding, .. } => {
891+
debug!(
892+
"print-type-size `{:#?}` adt general variants def {}",
893+
layout.ty,
894+
adt_def.variants().len()
895+
);
896+
let variant_infos: Vec<_> = adt_def
897+
.variants()
898+
.iter_enumerated()
899+
.map(|(i, variant_def)| {
900+
let fields: Vec<_> = variant_def.fields.iter().map(|f| f.name).collect();
901+
build_variant_info(Some(variant_def.name), &fields, layout.for_variant(cx, i))
902+
})
903+
.collect();
904+
905+
(
906+
variant_infos,
907+
match tag_encoding {
908+
TagEncoding::Direct => Some(tag.size(cx)),
909+
_ => None,
910+
},
911+
)
912+
}
913+
}
914+
}
915+
916+
fn variant_info_for_generator<'tcx>(
917+
cx: &LayoutCx<'tcx, TyCtxt<'tcx>>,
918+
layout: TyAndLayout<'tcx>,
919+
def_id: DefId,
920+
substs: ty::SubstsRef<'tcx>,
921+
) -> (Vec<VariantInfo>, Option<Size>) {
922+
let Variants::Multiple { tag, ref tag_encoding, .. } = layout.variants else {
923+
return (vec![], None);
924+
};
925+
926+
let (generator, state_specific_names) = cx.tcx.generator_layout_and_saved_local_names(def_id);
927+
let upvar_names = cx.tcx.closure_saved_names_of_captured_variables(def_id);
928+
929+
let mut upvars_size = Size::ZERO;
930+
let upvar_fields: Vec<_> = substs
931+
.as_generator()
932+
.upvar_tys()
933+
.zip(upvar_names)
934+
.enumerate()
935+
.map(|(field_idx, (_, name))| {
936+
let field_layout = layout.field(cx, field_idx);
937+
let offset = layout.fields.offset(field_idx);
938+
upvars_size = upvars_size.max(offset + field_layout.size);
939+
FieldInfo {
940+
name: Symbol::intern(&name),
941+
offset: offset.bytes(),
942+
size: field_layout.size.bytes(),
943+
align: field_layout.align.abi.bytes(),
944+
}
945+
})
946+
.collect();
947+
948+
let variant_infos: Vec<_> = generator
949+
.variant_fields
950+
.iter_enumerated()
951+
.map(|(variant_idx, variant_def)| {
952+
let variant_layout = layout.for_variant(cx, variant_idx);
953+
let mut variant_size = Size::ZERO;
954+
let fields = variant_def
955+
.iter()
956+
.enumerate()
957+
.map(|(field_idx, local)| {
958+
let field_layout = variant_layout.field(cx, field_idx);
959+
let offset = variant_layout.fields.offset(field_idx);
960+
// The struct is as large as the last field's end
961+
variant_size = variant_size.max(offset + field_layout.size);
962+
FieldInfo {
963+
name: state_specific_names.get(*local).copied().flatten().unwrap_or(
964+
Symbol::intern(&format!(".generator_field{}", local.as_usize())),
965+
),
966+
offset: offset.bytes(),
967+
size: field_layout.size.bytes(),
968+
align: field_layout.align.abi.bytes(),
969+
}
970+
})
971+
.chain(upvar_fields.iter().copied())
972+
.collect();
973+
974+
// If the variant has no state-specific fields, then it's the size of the upvars.
975+
if variant_size == Size::ZERO {
976+
variant_size = upvars_size;
977+
}
978+
// We need to add the discriminant size back into min_size, since it is subtracted
979+
// later during printing.
980+
variant_size += match tag_encoding {
981+
TagEncoding::Direct => tag.size(cx),
982+
_ => Size::ZERO,
983+
};
984+
985+
VariantInfo {
986+
name: Some(Symbol::intern(&ty::GeneratorSubsts::variant_name(variant_idx))),
987+
kind: SizeKind::Exact,
988+
size: variant_size.bytes(),
989+
align: variant_layout.align.abi.bytes(),
990+
fields,
991+
}
992+
})
993+
.collect();
994+
(
995+
variant_infos,
996+
match tag_encoding {
997+
TagEncoding::Direct => Some(tag.size(cx)),
998+
_ => None,
999+
},
1000+
)
1001+
}

0 commit comments

Comments
 (0)