1use hir::def_id::DefId;
2use rustc_abi::Integer::{I8, I32};
3use rustc_abi::Primitive::{self, Float, Int, Pointer};
4use rustc_abi::{
5 AddressSpace, BackendRepr, FIRST_VARIANT, FieldIdx, FieldsShape, HasDataLayout, Layout,
6 LayoutCalculatorError, LayoutData, Niche, ReprOptions, ScalableElt, Scalar, Size, StructKind,
7 TagEncoding, VariantIdx, Variants, WrappingRange,
8};
9use rustc_hashes::Hash64;
10use rustc_hir::find_attr;
11use rustc_index::{Idx as _, IndexVec};
12use rustc_middle::bug;
13use rustc_middle::query::Providers;
14use rustc_middle::traits::ObligationCause;
15use rustc_middle::ty::layout::{
16 FloatExt, HasTyCtxt, IntegerExt, LayoutCx, LayoutError, LayoutOf, SimdLayoutError, TyAndLayout,
17};
18use rustc_middle::ty::print::with_no_trimmed_paths;
19use rustc_middle::ty::{
20 self, AdtDef, CoroutineArgsExt, EarlyBinder, PseudoCanonicalInput, Ty, TyCtxt, TypeVisitableExt,
21};
22use rustc_session::{DataTypeKind, FieldInfo, FieldKind, SizeKind, VariantInfo};
23use rustc_span::{Symbol, sym};
24use tracing::{debug, instrument};
25use {rustc_abi as abi, rustc_hir as hir};
26
27use crate::errors::NonPrimitiveSimdType;
28
29mod invariant;
30
31pub(crate) fn provide(providers: &mut Providers) {
32 *providers = Providers { layout_of, ..*providers };
33}
34
35#[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("layout_of",
"rustc_ty_utils::layout", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_ty_utils/src/layout.rs"),
::tracing_core::__macro_support::Option::Some(35u32),
::tracing_core::__macro_support::Option::Some("rustc_ty_utils::layout"),
::tracing_core::field::FieldSet::new(&[],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{ meta.fields().value_set(&[]) })
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy ::
needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return:
Result<TyAndLayout<'tcx>, &'tcx LayoutError<'tcx>> =
loop {};
return __tracing_attr_fake_return;
}
{
let PseudoCanonicalInput { typing_env, value: ty } = query;
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_ty_utils/src/layout.rs:41",
"rustc_ty_utils::layout", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_ty_utils/src/layout.rs"),
::tracing_core::__macro_support::Option::Some(41u32),
::tracing_core::__macro_support::Option::Some("rustc_ty_utils::layout"),
::tracing_core::field::FieldSet::new(&["ty"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&ty) as
&dyn Value))])
});
} else { ; }
};
let typing_env = typing_env.with_post_analysis_normalized(tcx);
let unnormalized_ty = ty;
let ty =
match tcx.try_normalize_erasing_regions(typing_env, ty) {
Ok(t) => t,
Err(normalization_error) => {
return Err(tcx.arena.alloc(LayoutError::NormalizationFailure(ty,
normalization_error)));
}
};
if ty != unnormalized_ty {
return tcx.layout_of(typing_env.as_query_input(ty));
}
let cx = LayoutCx::new(tcx, typing_env);
let layout = layout_of_uncached(&cx, ty)?;
let layout = TyAndLayout { ty, layout };
if cx.tcx().sess.opts.unstable_opts.print_type_sizes {
record_layout_for_printing(&cx, layout);
}
invariant::layout_sanity_check(&cx, &layout);
Ok(layout)
}
}
}#[instrument(skip(tcx, query), level = "debug")]
36fn layout_of<'tcx>(
37 tcx: TyCtxt<'tcx>,
38 query: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>,
39) -> Result<TyAndLayout<'tcx>, &'tcx LayoutError<'tcx>> {
40 let PseudoCanonicalInput { typing_env, value: ty } = query;
41 debug!(?ty);
42
43 let typing_env = typing_env.with_post_analysis_normalized(tcx);
47 let unnormalized_ty = ty;
48
49 let ty = match tcx.try_normalize_erasing_regions(typing_env, ty) {
54 Ok(t) => t,
55 Err(normalization_error) => {
56 return Err(tcx
57 .arena
58 .alloc(LayoutError::NormalizationFailure(ty, normalization_error)));
59 }
60 };
61
62 if ty != unnormalized_ty {
63 return tcx.layout_of(typing_env.as_query_input(ty));
65 }
66
67 let cx = LayoutCx::new(tcx, typing_env);
68
69 let layout = layout_of_uncached(&cx, ty)?;
70 let layout = TyAndLayout { ty, layout };
71
72 if cx.tcx().sess.opts.unstable_opts.print_type_sizes {
75 record_layout_for_printing(&cx, layout);
76 }
77
78 invariant::layout_sanity_check(&cx, &layout);
79
80 Ok(layout)
81}
82
83fn error<'tcx>(cx: &LayoutCx<'tcx>, err: LayoutError<'tcx>) -> &'tcx LayoutError<'tcx> {
84 cx.tcx().arena.alloc(err)
85}
86
87fn map_error<'tcx>(
88 cx: &LayoutCx<'tcx>,
89 ty: Ty<'tcx>,
90 err: LayoutCalculatorError<TyAndLayout<'tcx>>,
91) -> &'tcx LayoutError<'tcx> {
92 let err = match err {
93 LayoutCalculatorError::SizeOverflow => {
94 LayoutError::SizeOverflow(ty)
97 }
98 LayoutCalculatorError::UnexpectedUnsized(field) => {
99 if !field.layout.is_unsized() {
{
::core::panicking::panic_fmt(format_args!("invalid layout error {0:#?}",
err));
}
};assert!(field.layout.is_unsized(), "invalid layout error {err:#?}");
102 if cx.typing_env.param_env.caller_bounds().is_empty() {
103 cx.tcx().dcx().delayed_bug(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("encountered unexpected unsized field in layout of {0:?}: {1:#?}",
ty, field))
})format!(
104 "encountered unexpected unsized field in layout of {ty:?}: {field:#?}"
105 ));
106 }
107 LayoutError::Unknown(ty)
108 }
109 LayoutCalculatorError::EmptyUnion => {
110 let guar =
112 cx.tcx().dcx().delayed_bug(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("computed layout of empty union: {0:?}",
ty))
})format!("computed layout of empty union: {ty:?}"));
113 LayoutError::ReferencesError(guar)
114 }
115 LayoutCalculatorError::ReprConflict => {
116 let guar = cx
118 .tcx()
119 .dcx()
120 .delayed_bug(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("computed impossible repr (packed enum?): {0:?}",
ty))
})format!("computed impossible repr (packed enum?): {ty:?}"));
121 LayoutError::ReferencesError(guar)
122 }
123 LayoutCalculatorError::ZeroLengthSimdType => {
124 LayoutError::InvalidSimd { ty, kind: SimdLayoutError::ZeroLength }
126 }
127 LayoutCalculatorError::OversizedSimdType { max_lanes } => {
128 LayoutError::InvalidSimd { ty, kind: SimdLayoutError::TooManyLanes(max_lanes) }
130 }
131 LayoutCalculatorError::NonPrimitiveSimdType(field) => {
132 cx.tcx().dcx().emit_fatal(NonPrimitiveSimdType { ty, e_ty: field.ty })
135 }
136 };
137 error(cx, err)
138}
139
140fn extract_const_value<'tcx>(
141 cx: &LayoutCx<'tcx>,
142 ty: Ty<'tcx>,
143 ct: ty::Const<'tcx>,
144) -> Result<ty::Value<'tcx>, &'tcx LayoutError<'tcx>> {
145 match ct.kind() {
146 ty::ConstKind::Value(cv) => Ok(cv),
147 ty::ConstKind::Param(_) | ty::ConstKind::Expr(_) => {
148 if !ct.has_param() {
149 ::rustc_middle::util::bug::bug_fmt(format_args!("failed to normalize const, but it is not generic: {0:?}",
ct));bug!("failed to normalize const, but it is not generic: {ct:?}");
150 }
151 Err(error(cx, LayoutError::TooGeneric(ty)))
152 }
153 ty::ConstKind::Unevaluated(_) => {
154 let err = if ct.has_param() {
155 LayoutError::TooGeneric(ty)
156 } else {
157 LayoutError::Unknown(ty)
163 };
164 Err(error(cx, err))
165 }
166 ty::ConstKind::Infer(_)
167 | ty::ConstKind::Bound(..)
168 | ty::ConstKind::Placeholder(_)
169 | ty::ConstKind::Error(_) => {
170 ::rustc_middle::util::bug::bug_fmt(format_args!("layout_of: unexpected const: {0:?}",
ct));bug!("layout_of: unexpected const: {ct:?}");
173 }
174 }
175}
176
177fn layout_of_uncached<'tcx>(
178 cx: &LayoutCx<'tcx>,
179 ty: Ty<'tcx>,
180) -> Result<Layout<'tcx>, &'tcx LayoutError<'tcx>> {
181 if let Err(guar) = ty.error_reported() {
185 return Err(error(cx, LayoutError::ReferencesError(guar)));
186 }
187
188 let tcx = cx.tcx();
189
190 let dl = cx.data_layout();
194 let map_layout = |result: Result<_, _>| match result {
195 Ok(layout) => Ok(tcx.mk_layout(layout)),
196 Err(err) => Err(map_error(cx, ty, err)),
197 };
198 let scalar_unit = |value: Primitive| {
199 let size = value.size(dl);
200 if !(size.bits() <= 128) {
::core::panicking::panic("assertion failed: size.bits() <= 128")
};assert!(size.bits() <= 128);
201 Scalar::Initialized { value, valid_range: WrappingRange::full(size) }
202 };
203 let scalar = |value: Primitive| tcx.mk_layout(LayoutData::scalar(cx, scalar_unit(value)));
204
205 let univariant = |tys: &[Ty<'tcx>], kind| {
206 let fields = tys.iter().map(|ty| cx.layout_of(*ty)).try_collect::<IndexVec<_, _>>()?;
207 let repr = ReprOptions::default();
208 map_layout(cx.calc.univariant(&fields, &repr, kind))
209 };
210 if true {
if !!ty.has_non_region_infer() {
::core::panicking::panic("assertion failed: !ty.has_non_region_infer()")
};
};debug_assert!(!ty.has_non_region_infer());
211
212 Ok(match *ty.kind() {
213 ty::Pat(ty, pat) => {
214 let layout = cx.layout_of(ty)?.layout;
215 let mut layout = LayoutData::clone(&layout.0);
216 match *pat {
217 ty::PatternKind::Range { start, end } => {
218 if let BackendRepr::Scalar(scalar) = &mut layout.backend_repr {
219 scalar.valid_range_mut().start = extract_const_value(cx, ty, start)?
220 .try_to_bits(tcx, cx.typing_env)
221 .ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?;
222
223 scalar.valid_range_mut().end = extract_const_value(cx, ty, end)?
224 .try_to_bits(tcx, cx.typing_env)
225 .ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?;
226
227 if scalar.is_signed() {
233 let range = scalar.valid_range_mut();
234 let start = layout.size.sign_extend(range.start);
235 let end = layout.size.sign_extend(range.end);
236 if end < start {
237 let guar = tcx.dcx().err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("pattern type ranges cannot wrap: {0}..={1}",
start, end))
})format!(
238 "pattern type ranges cannot wrap: {start}..={end}"
239 ));
240
241 return Err(error(cx, LayoutError::ReferencesError(guar)));
242 }
243 } else {
244 let range = scalar.valid_range_mut();
245 if range.end < range.start {
246 let guar = tcx.dcx().err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("pattern type ranges cannot wrap: {0}..={1}",
range.start, range.end))
})format!(
247 "pattern type ranges cannot wrap: {}..={}",
248 range.start, range.end
249 ));
250
251 return Err(error(cx, LayoutError::ReferencesError(guar)));
252 }
253 };
254
255 let niche = Niche {
256 offset: Size::ZERO,
257 value: scalar.primitive(),
258 valid_range: scalar.valid_range(cx),
259 };
260
261 layout.largest_niche = Some(niche);
262 } else {
263 ::rustc_middle::util::bug::bug_fmt(format_args!("pattern type with range but not scalar layout: {0:?}, {1:?}",
ty, layout))bug!("pattern type with range but not scalar layout: {ty:?}, {layout:?}")
264 }
265 }
266 ty::PatternKind::NotNull => {
267 if let BackendRepr::Scalar(scalar) | BackendRepr::ScalarPair(scalar, _) =
268 &mut layout.backend_repr
269 {
270 scalar.valid_range_mut().start = 1;
271 let niche = Niche {
272 offset: Size::ZERO,
273 value: scalar.primitive(),
274 valid_range: scalar.valid_range(cx),
275 };
276
277 layout.largest_niche = Some(niche);
278 } else {
279 ::rustc_middle::util::bug::bug_fmt(format_args!("pattern type with `!null` pattern but not scalar/pair layout: {0:?}, {1:?}",
ty, layout))bug!(
280 "pattern type with `!null` pattern but not scalar/pair layout: {ty:?}, {layout:?}"
281 )
282 }
283 }
284
285 ty::PatternKind::Or(variants) => match *variants[0] {
286 ty::PatternKind::Range { .. } => {
287 if let BackendRepr::Scalar(scalar) = &mut layout.backend_repr {
288 let variants: Result<Vec<_>, _> = variants
289 .iter()
290 .map(|pat| match *pat {
291 ty::PatternKind::Range { start, end } => Ok((
292 extract_const_value(cx, ty, start)
293 .unwrap()
294 .try_to_bits(tcx, cx.typing_env)
295 .ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?,
296 extract_const_value(cx, ty, end)
297 .unwrap()
298 .try_to_bits(tcx, cx.typing_env)
299 .ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?,
300 )),
301 ty::PatternKind::NotNull | ty::PatternKind::Or(_) => {
302 {
::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
format_args!("mixed or patterns are not allowed")));
}unreachable!("mixed or patterns are not allowed")
303 }
304 })
305 .collect();
306 let mut variants = variants?;
307 if !scalar.is_signed() {
308 let guar = tcx.dcx().err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("only signed integer base types are allowed for or-pattern pattern types at present"))
})format!(
309 "only signed integer base types are allowed for or-pattern pattern types at present"
310 ));
311
312 return Err(error(cx, LayoutError::ReferencesError(guar)));
313 }
314 variants.sort();
315 if variants.len() != 2 {
316 let guar = tcx
317 .dcx()
318 .err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("the only or-pattern types allowed are two range patterns that are directly connected at their overflow site"))
})format!("the only or-pattern types allowed are two range patterns that are directly connected at their overflow site"));
319
320 return Err(error(cx, LayoutError::ReferencesError(guar)));
321 }
322
323 let mut first = variants[0];
325 let mut second = variants[1];
326 if second.0
327 == layout.size.truncate(layout.size.signed_int_min() as u128)
328 {
329 (second, first) = (first, second);
330 }
331
332 if layout.size.sign_extend(first.1) >= layout.size.sign_extend(second.0)
333 {
334 let guar = tcx.dcx().err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("only non-overlapping pattern type ranges are allowed at present"))
})format!(
335 "only non-overlapping pattern type ranges are allowed at present"
336 ));
337
338 return Err(error(cx, LayoutError::ReferencesError(guar)));
339 }
340 if layout.size.signed_int_max() as u128 != second.1 {
341 let guar = tcx.dcx().err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("one pattern needs to end at `{1}::MAX`, but was {0} instead",
second.1, ty))
})format!(
342 "one pattern needs to end at `{ty}::MAX`, but was {} instead",
343 second.1
344 ));
345
346 return Err(error(cx, LayoutError::ReferencesError(guar)));
347 }
348
349 scalar.valid_range_mut().start = second.0;
351 scalar.valid_range_mut().end = first.1;
352
353 let niche = Niche {
354 offset: Size::ZERO,
355 value: scalar.primitive(),
356 valid_range: scalar.valid_range(cx),
357 };
358
359 layout.largest_niche = Some(niche);
360 } else {
361 ::rustc_middle::util::bug::bug_fmt(format_args!("pattern type with range but not scalar layout: {0:?}, {1:?}",
ty, layout))bug!(
362 "pattern type with range but not scalar layout: {ty:?}, {layout:?}"
363 )
364 }
365 }
366 ty::PatternKind::NotNull => ::rustc_middle::util::bug::bug_fmt(format_args!("or patterns can\'t contain `!null` patterns"))bug!("or patterns can't contain `!null` patterns"),
367 ty::PatternKind::Or(..) => ::rustc_middle::util::bug::bug_fmt(format_args!("patterns cannot have nested or patterns"))bug!("patterns cannot have nested or patterns"),
368 },
369 }
370 layout.fields = FieldsShape::Arbitrary {
375 offsets: [Size::ZERO].into_iter().collect(),
376 in_memory_order: [FieldIdx::new(0)].into_iter().collect(),
377 };
378 tcx.mk_layout(layout)
379 }
380
381 ty::Bool => tcx.mk_layout(LayoutData::scalar(
383 cx,
384 Scalar::Initialized {
385 value: Int(I8, false),
386 valid_range: WrappingRange { start: 0, end: 1 },
387 },
388 )),
389 ty::Char => tcx.mk_layout(LayoutData::scalar(
390 cx,
391 Scalar::Initialized {
392 value: Int(I32, false),
393 valid_range: WrappingRange { start: 0, end: 0x10FFFF },
394 },
395 )),
396 ty::Int(ity) => scalar(Int(abi::Integer::from_int_ty(dl, ity), true)),
397 ty::Uint(ity) => scalar(Int(abi::Integer::from_uint_ty(dl, ity), false)),
398 ty::Float(fty) => scalar(Float(abi::Float::from_float_ty(fty))),
399 ty::FnPtr(..) => {
400 let mut ptr = scalar_unit(Pointer(dl.instruction_address_space));
401 ptr.valid_range_mut().start = 1;
402 tcx.mk_layout(LayoutData::scalar(cx, ptr))
403 }
404
405 ty::Never => tcx.mk_layout(LayoutData::never_type(cx)),
407
408 ty::Ref(_, pointee, _) | ty::RawPtr(pointee, _) => {
410 let mut data_ptr = scalar_unit(Pointer(AddressSpace::ZERO));
411 if !ty.is_raw_ptr() {
412 data_ptr.valid_range_mut().start = 1;
413 }
414
415 if pointee.is_sized(tcx, cx.typing_env) {
416 return Ok(tcx.mk_layout(LayoutData::scalar(cx, data_ptr)));
417 }
418
419 let metadata = if let Some(metadata_def_id) = tcx.lang_items().metadata_type() {
420 let pointee_metadata = Ty::new_projection(tcx, metadata_def_id, [pointee]);
421 let metadata_ty = match tcx
422 .try_normalize_erasing_regions(cx.typing_env, pointee_metadata)
423 {
424 Ok(metadata_ty) => metadata_ty,
425 Err(mut err) => {
426 match tcx.try_normalize_erasing_regions(
435 cx.typing_env,
436 tcx.struct_tail_raw(pointee, &ObligationCause::dummy(), |ty| ty, || {}),
437 ) {
438 Ok(_) => {}
439 Err(better_err) => {
440 err = better_err;
441 }
442 }
443 return Err(error(cx, LayoutError::NormalizationFailure(pointee, err)));
444 }
445 };
446
447 let metadata_layout = cx.layout_of(metadata_ty)?;
448 if metadata_layout.is_1zst() {
450 return Ok(tcx.mk_layout(LayoutData::scalar(cx, data_ptr)));
451 }
452
453 let BackendRepr::Scalar(metadata) = metadata_layout.backend_repr else {
454 return Err(error(cx, LayoutError::Unknown(pointee)));
455 };
456
457 metadata
458 } else {
459 let unsized_part = tcx.struct_tail_for_codegen(pointee, cx.typing_env);
460
461 match unsized_part.kind() {
462 ty::Foreign(..) => {
463 return Ok(tcx.mk_layout(LayoutData::scalar(cx, data_ptr)));
464 }
465 ty::Slice(_) | ty::Str => scalar_unit(Int(dl.ptr_sized_integer(), false)),
466 ty::Dynamic(..) => {
467 let mut vtable = scalar_unit(Pointer(AddressSpace::ZERO));
468 vtable.valid_range_mut().start = 1;
469 vtable
470 }
471 _ => {
472 return Err(error(cx, LayoutError::Unknown(pointee)));
473 }
474 }
475 };
476
477 tcx.mk_layout(LayoutData::scalar_pair(cx, data_ptr, metadata))
479 }
480
481 ty::Array(element, count) => {
483 let count = extract_const_value(cx, ty, count)?
484 .try_to_target_usize(tcx)
485 .ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?;
486
487 let element = cx.layout_of(element)?;
488 map_layout(cx.calc.array_like(&element, Some(count)))?
489 }
490 ty::Slice(element) => {
491 let element = cx.layout_of(element)?;
492 map_layout(cx.calc.array_like(&element, None).map(|mut layout| {
493 layout.randomization_seed = Hash64::new(0x2dcba99c39784102);
495 layout
496 }))?
497 }
498 ty::Str => {
499 let element = scalar(Int(I8, false));
500 map_layout(cx.calc.array_like(&element, None).map(|mut layout| {
501 layout.randomization_seed = Hash64::new(0xc1325f37d127be22);
503 layout
504 }))?
505 }
506
507 ty::FnDef(..) | ty::Dynamic(_, _) | ty::Foreign(..) => {
509 let sized = #[allow(non_exhaustive_omitted_patterns)] match ty.kind() {
ty::FnDef(..) => true,
_ => false,
}matches!(ty.kind(), ty::FnDef(..));
510 tcx.mk_layout(LayoutData::unit(cx, sized))
511 }
512
513 ty::Coroutine(def_id, args) => {
514 use rustc_middle::ty::layout::PrimitiveExt as _;
515
516 let info = tcx.coroutine_layout(def_id, args)?;
517
518 let local_layouts = info
519 .field_tys
520 .iter()
521 .map(|local| {
522 let field_ty = EarlyBinder::bind(local.ty);
523 let uninit_ty = Ty::new_maybe_uninit(tcx, field_ty.instantiate(tcx, args));
524 cx.spanned_layout_of(uninit_ty, local.source_info.span)
525 })
526 .try_collect::<IndexVec<_, _>>()?;
527
528 let prefix_layouts = args
529 .as_coroutine()
530 .prefix_tys()
531 .iter()
532 .map(|ty| cx.layout_of(ty))
533 .try_collect::<IndexVec<_, _>>()?;
534
535 let layout = cx
536 .calc
537 .coroutine(
538 &local_layouts,
539 prefix_layouts,
540 &info.variant_fields,
541 &info.storage_conflicts,
542 |tag| TyAndLayout {
543 ty: tag.primitive().to_ty(tcx),
544 layout: tcx.mk_layout(LayoutData::scalar(cx, tag)),
545 },
546 )
547 .map(|mut layout| {
548 layout.randomization_seed = tcx.def_path_hash(def_id).0.to_smaller_hash();
550 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_ty_utils/src/layout.rs:550",
"rustc_ty_utils::layout", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_ty_utils/src/layout.rs"),
::tracing_core::__macro_support::Option::Some(550u32),
::tracing_core::__macro_support::Option::Some("rustc_ty_utils::layout"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("coroutine layout ({0:?}): {1:#?}",
ty, layout) as &dyn Value))])
});
} else { ; }
};debug!("coroutine layout ({:?}): {:#?}", ty, layout);
551 layout
552 });
553 map_layout(layout)?
554 }
555
556 ty::Closure(_, args) => univariant(args.as_closure().upvar_tys(), StructKind::AlwaysSized)?,
557
558 ty::CoroutineClosure(_, args) => {
559 univariant(args.as_coroutine_closure().upvar_tys(), StructKind::AlwaysSized)?
560 }
561
562 ty::Tuple(tys) => {
563 let kind =
564 if tys.len() == 0 { StructKind::AlwaysSized } else { StructKind::MaybeUnsized };
565
566 univariant(tys, kind)?
567 }
568
569 ty::Adt(def, args)
576 if #[allow(non_exhaustive_omitted_patterns)] match def.repr().scalable {
Some(ScalableElt::ElementCount(..)) => true,
_ => false,
}matches!(def.repr().scalable, Some(ScalableElt::ElementCount(..))) =>
577 {
578 let Some(element_ty) = def
579 .is_struct()
580 .then(|| &def.variant(FIRST_VARIANT).fields)
581 .filter(|fields| fields.len() == 1)
582 .map(|fields| fields[FieldIdx::ZERO].ty(tcx, args))
583 else {
584 let guar = tcx
585 .dcx()
586 .delayed_bug("#[rustc_scalable_vector] was applied to an invalid type");
587 return Err(error(cx, LayoutError::ReferencesError(guar)));
588 };
589 let Some(ScalableElt::ElementCount(element_count)) = def.repr().scalable else {
590 let guar = tcx
591 .dcx()
592 .delayed_bug("#[rustc_scalable_vector] was applied to an invalid type");
593 return Err(error(cx, LayoutError::ReferencesError(guar)));
594 };
595
596 let element_layout = cx.layout_of(element_ty)?;
597 map_layout(cx.calc.scalable_vector_type(element_layout, element_count as u64))?
598 }
599
600 ty::Adt(def, args) if def.repr().simd() => {
602 let Some(ty::Array(e_ty, e_len)) = def
608 .is_struct()
609 .then(|| &def.variant(FIRST_VARIANT).fields)
610 .filter(|fields| fields.len() == 1)
611 .map(|fields| *fields[FieldIdx::ZERO].ty(tcx, args).kind())
612 else {
613 let guar = tcx.dcx().delayed_bug("#[repr(simd)] was applied to an invalid ADT");
615 return Err(error(cx, LayoutError::ReferencesError(guar)));
616 };
617
618 let e_len = extract_const_value(cx, ty, e_len)?
619 .try_to_target_usize(tcx)
620 .ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?;
621
622 let e_ly = cx.layout_of(e_ty)?;
623
624 if let Some(limit) = {
#[allow(deprecated)]
{
{
'done:
{
for i in tcx.get_all_attrs(def.did()) {
#[allow(unused_imports)]
use rustc_hir::attrs::AttributeKind::*;
let i: &rustc_hir::Attribute = i;
match i {
rustc_hir::Attribute::Parsed(RustcSimdMonomorphizeLaneLimit(limit))
=> {
break 'done Some(limit);
}
rustc_hir::Attribute::Unparsed(..) =>
{}
#[deny(unreachable_patterns)]
_ => {}
}
}
None
}
}
}
}find_attr!(
626 tcx, def.did(),
627 RustcSimdMonomorphizeLaneLimit(limit) => limit
628 ) {
629 if !limit.value_within_limit(e_len as usize) {
630 return Err(map_error(
631 &cx,
632 ty,
633 rustc_abi::LayoutCalculatorError::OversizedSimdType {
634 max_lanes: limit.0 as u64,
635 },
636 ));
637 }
638 }
639
640 map_layout(cx.calc.simd_type(e_ly, e_len, def.repr().packed()))?
641 }
642
643 ty::Adt(def, args) => {
645 let variants = def
647 .variants()
648 .iter()
649 .map(|v| {
650 v.fields
651 .iter()
652 .map(|field| cx.layout_of(field.ty(tcx, args)))
653 .try_collect::<IndexVec<_, _>>()
654 })
655 .try_collect::<IndexVec<VariantIdx, _>>()?;
656
657 if def.is_union() {
658 if def.repr().pack.is_some() && def.repr().align.is_some() {
659 let guar = tcx.dcx().span_delayed_bug(
660 tcx.def_span(def.did()),
661 "union cannot be packed and aligned",
662 );
663 return Err(error(cx, LayoutError::ReferencesError(guar)));
664 }
665
666 return map_layout(cx.calc.layout_of_union(&def.repr(), &variants));
667 }
668
669 let is_special_no_niche = def.is_unsafe_cell() || def.is_unsafe_pinned();
671
672 let discr_range_of_repr =
673 |min, max| abi::Integer::discr_range_of_repr(tcx, ty, &def.repr(), min, max);
674
675 let discriminants_iter = || {
676 def.is_enum()
677 .then(|| def.discriminants(tcx).map(|(v, d)| (v, d.val as i128)))
678 .into_iter()
679 .flatten()
680 };
681
682 let maybe_unsized = def.is_struct()
683 && def.non_enum_variant().tail_opt().is_some_and(|last_field| {
684 let typing_env = ty::TypingEnv::post_analysis(tcx, def.did());
685 !tcx.type_of(last_field.did).instantiate_identity().is_sized(tcx, typing_env)
686 });
687
688 let layout = cx
689 .calc
690 .layout_of_struct_or_enum(
691 &def.repr(),
692 &variants,
693 def.is_enum(),
694 is_special_no_niche,
695 tcx.layout_scalar_valid_range(def.did()),
696 discr_range_of_repr,
697 discriminants_iter(),
698 !maybe_unsized,
699 )
700 .map_err(|err| map_error(cx, ty, err))?;
701
702 if !maybe_unsized && layout.is_unsized() {
703 ::rustc_middle::util::bug::bug_fmt(format_args!("got unsized layout for type that cannot be unsized {0:?}: {1:#?}",
ty, layout));bug!("got unsized layout for type that cannot be unsized {ty:?}: {layout:#?}");
704 }
705
706 if truecfg!(debug_assertions)
708 && maybe_unsized
709 && def.non_enum_variant().tail().ty(tcx, args).is_sized(tcx, cx.typing_env)
710 {
711 let mut variants = variants;
712 let tail_replacement = cx.layout_of(Ty::new_slice(tcx, tcx.types.u8)).unwrap();
713 *variants[FIRST_VARIANT].raw.last_mut().unwrap() = tail_replacement;
714
715 let Ok(unsized_layout) = cx.calc.layout_of_struct_or_enum(
716 &def.repr(),
717 &variants,
718 def.is_enum(),
719 is_special_no_niche,
720 tcx.layout_scalar_valid_range(def.did()),
721 discr_range_of_repr,
722 discriminants_iter(),
723 !maybe_unsized,
724 ) else {
725 ::rustc_middle::util::bug::bug_fmt(format_args!("failed to compute unsized layout of {0:?}",
ty));bug!("failed to compute unsized layout of {ty:?}");
726 };
727
728 let FieldsShape::Arbitrary { offsets: sized_offsets, .. } = &layout.fields else {
729 ::rustc_middle::util::bug::bug_fmt(format_args!("unexpected FieldsShape for sized layout of {1:?}: {0:?}",
layout.fields, ty));bug!("unexpected FieldsShape for sized layout of {ty:?}: {:?}", layout.fields);
730 };
731 let FieldsShape::Arbitrary { offsets: unsized_offsets, .. } =
732 &unsized_layout.fields
733 else {
734 ::rustc_middle::util::bug::bug_fmt(format_args!("unexpected FieldsShape for unsized layout of {1:?}: {0:?}",
unsized_layout.fields, ty));bug!(
735 "unexpected FieldsShape for unsized layout of {ty:?}: {:?}",
736 unsized_layout.fields
737 );
738 };
739
740 let (sized_tail, sized_fields) = sized_offsets.raw.split_last().unwrap();
741 let (unsized_tail, unsized_fields) = unsized_offsets.raw.split_last().unwrap();
742
743 if sized_fields != unsized_fields {
744 ::rustc_middle::util::bug::bug_fmt(format_args!("unsizing {0:?} changed field order!\n{1:?}\n{2:?}",
ty, layout, unsized_layout));bug!("unsizing {ty:?} changed field order!\n{layout:?}\n{unsized_layout:?}");
745 }
746
747 if sized_tail < unsized_tail {
748 ::rustc_middle::util::bug::bug_fmt(format_args!("unsizing {0:?} moved tail backwards!\n{1:?}\n{2:?}",
ty, layout, unsized_layout));bug!("unsizing {ty:?} moved tail backwards!\n{layout:?}\n{unsized_layout:?}");
749 }
750 }
751
752 tcx.mk_layout(layout)
753 }
754
755 ty::UnsafeBinder(bound_ty) => {
756 let ty = tcx.instantiate_bound_regions_with_erased(bound_ty.into());
757 cx.layout_of(ty)?.layout
758 }
759
760 ty::Param(_) | ty::Placeholder(..) => {
762 return Err(error(cx, LayoutError::TooGeneric(ty)));
763 }
764
765 ty::Alias(..) => {
766 let err = if ty.has_param() || !cx.typing_env.param_env.caller_bounds().is_empty() {
777 LayoutError::TooGeneric(ty)
778 } else {
779 LayoutError::ReferencesError(cx.tcx().dcx().delayed_bug(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("unexpected rigid alias in layout_of after normalization: {0:?}",
ty))
})format!(
780 "unexpected rigid alias in layout_of after normalization: {ty:?}"
781 )))
782 };
783 return Err(error(cx, err));
784 }
785
786 ty::Bound(..) | ty::CoroutineWitness(..) | ty::Infer(_) | ty::Error(_) => {
787 ::rustc_middle::util::bug::bug_fmt(format_args!("layout_of: unexpected type `{0}`",
ty))bug!("layout_of: unexpected type `{ty}`")
789 }
790 })
791}
792
793fn record_layout_for_printing<'tcx>(cx: &LayoutCx<'tcx>, layout: TyAndLayout<'tcx>) {
794 if layout.ty.has_non_region_param() || !cx.typing_env.param_env.caller_bounds().is_empty() {
798 return;
799 }
800
801 let record = |kind, packed, opt_discr_size, variants| {
803 let type_desc = {
let _guard = NoTrimmedGuard::new();
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}", layout.ty))
})
}with_no_trimmed_paths!(format!("{}", layout.ty));
804 cx.tcx().sess.code_stats.record_type_size(
805 kind,
806 type_desc,
807 layout.align.abi,
808 layout.size,
809 packed,
810 opt_discr_size,
811 variants,
812 );
813 };
814
815 match *layout.ty.kind() {
816 ty::Adt(adt_def, _) => {
817 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_ty_utils/src/layout.rs:817",
"rustc_ty_utils::layout", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_ty_utils/src/layout.rs"),
::tracing_core::__macro_support::Option::Some(817u32),
::tracing_core::__macro_support::Option::Some("rustc_ty_utils::layout"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("print-type-size t: `{0:?}` process adt",
layout.ty) as &dyn Value))])
});
} else { ; }
};debug!("print-type-size t: `{:?}` process adt", layout.ty);
818 let adt_kind = adt_def.adt_kind();
819 let adt_packed = adt_def.repr().pack.is_some();
820 let (variant_infos, opt_discr_size) = variant_info_for_adt(cx, layout, adt_def);
821 record(adt_kind.into(), adt_packed, opt_discr_size, variant_infos);
822 }
823
824 ty::Coroutine(def_id, args) => {
825 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_ty_utils/src/layout.rs:825",
"rustc_ty_utils::layout", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_ty_utils/src/layout.rs"),
::tracing_core::__macro_support::Option::Some(825u32),
::tracing_core::__macro_support::Option::Some("rustc_ty_utils::layout"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("print-type-size t: `{0:?}` record coroutine",
layout.ty) as &dyn Value))])
});
} else { ; }
};debug!("print-type-size t: `{:?}` record coroutine", layout.ty);
826 let (variant_infos, opt_discr_size) =
828 variant_info_for_coroutine(cx, layout, def_id, args);
829 record(DataTypeKind::Coroutine, false, opt_discr_size, variant_infos);
830 }
831
832 ty::Closure(..) => {
833 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_ty_utils/src/layout.rs:833",
"rustc_ty_utils::layout", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_ty_utils/src/layout.rs"),
::tracing_core::__macro_support::Option::Some(833u32),
::tracing_core::__macro_support::Option::Some("rustc_ty_utils::layout"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("print-type-size t: `{0:?}` record closure",
layout.ty) as &dyn Value))])
});
} else { ; }
};debug!("print-type-size t: `{:?}` record closure", layout.ty);
834 record(DataTypeKind::Closure, false, None, ::alloc::vec::Vec::new()vec![]);
835 }
836
837 _ => {
838 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_ty_utils/src/layout.rs:838",
"rustc_ty_utils::layout", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_ty_utils/src/layout.rs"),
::tracing_core::__macro_support::Option::Some(838u32),
::tracing_core::__macro_support::Option::Some("rustc_ty_utils::layout"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("print-type-size t: `{0:?}` skip non-nominal",
layout.ty) as &dyn Value))])
});
} else { ; }
};debug!("print-type-size t: `{:?}` skip non-nominal", layout.ty);
839 }
840 };
841}
842
843fn variant_info_for_adt<'tcx>(
844 cx: &LayoutCx<'tcx>,
845 layout: TyAndLayout<'tcx>,
846 adt_def: AdtDef<'tcx>,
847) -> (Vec<VariantInfo>, Option<Size>) {
848 let build_variant_info = |n: Option<Symbol>, flds: &[Symbol], layout: TyAndLayout<'tcx>| {
849 let mut min_size = Size::ZERO;
850 let field_info: Vec<_> = flds
851 .iter()
852 .enumerate()
853 .map(|(i, &name)| {
854 let field_layout = layout.field(cx, i);
855 let offset = layout.fields.offset(i);
856 min_size = min_size.max(offset + field_layout.size);
857 FieldInfo {
858 kind: FieldKind::AdtField,
859 name,
860 offset: offset.bytes(),
861 size: field_layout.size.bytes(),
862 align: field_layout.align.bytes(),
863 type_name: None,
864 }
865 })
866 .collect();
867
868 VariantInfo {
869 name: n,
870 kind: if layout.is_unsized() { SizeKind::Min } else { SizeKind::Exact },
871 align: layout.align.bytes(),
872 size: if min_size.bytes() == 0 { layout.size.bytes() } else { min_size.bytes() },
873 fields: field_info,
874 }
875 };
876
877 match layout.variants {
878 Variants::Empty => (::alloc::vec::Vec::new()vec![], None),
879
880 Variants::Single { index } => {
881 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_ty_utils/src/layout.rs:881",
"rustc_ty_utils::layout", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_ty_utils/src/layout.rs"),
::tracing_core::__macro_support::Option::Some(881u32),
::tracing_core::__macro_support::Option::Some("rustc_ty_utils::layout"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("print-type-size `{0:#?}` variant {1}",
layout, adt_def.variant(index).name) as &dyn Value))])
});
} else { ; }
};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 (::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[build_variant_info(Some(variant_def.name), &fields, layout)]))vec![build_variant_info(Some(variant_def.name), &fields, layout)], None)
885 }
886
887 Variants::Multiple { tag, ref tag_encoding, .. } => {
888 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_ty_utils/src/layout.rs:888",
"rustc_ty_utils::layout", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_ty_utils/src/layout.rs"),
::tracing_core::__macro_support::Option::Some(888u32),
::tracing_core::__macro_support::Option::Some("rustc_ty_utils::layout"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("print-type-size `{0:#?}` adt general variants def {1}",
layout.ty, adt_def.variants().len()) as &dyn Value))])
});
} else { ; }
};debug!(
889 "print-type-size `{:#?}` adt general variants def {}",
890 layout.ty,
891 adt_def.variants().len()
892 );
893 let variant_infos: Vec<_> = adt_def
894 .variants()
895 .iter_enumerated()
896 .map(|(i, variant_def)| {
897 let fields: Vec<_> = variant_def.fields.iter().map(|f| f.name).collect();
898 build_variant_info(Some(variant_def.name), &fields, layout.for_variant(cx, i))
899 })
900 .collect();
901
902 (
903 variant_infos,
904 match tag_encoding {
905 TagEncoding::Direct => Some(tag.size(cx)),
906 _ => None,
907 },
908 )
909 }
910 }
911}
912
913fn variant_info_for_coroutine<'tcx>(
914 cx: &LayoutCx<'tcx>,
915 layout: TyAndLayout<'tcx>,
916 def_id: DefId,
917 args: ty::GenericArgsRef<'tcx>,
918) -> (Vec<VariantInfo>, Option<Size>) {
919 use itertools::Itertools;
920
921 let Variants::Multiple { tag, ref tag_encoding, tag_field, .. } = layout.variants else {
922 return (::alloc::vec::Vec::new()vec![], None);
923 };
924
925 let coroutine = cx.tcx().coroutine_layout(def_id, args).unwrap();
926 let upvar_names = cx.tcx().closure_saved_names_of_captured_variables(def_id);
927
928 let mut upvars_size = Size::ZERO;
929 let upvar_fields: Vec<_> = args
930 .as_coroutine()
931 .upvar_tys()
932 .iter()
933 .zip_eq(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 kind: FieldKind::Upvar,
941 name: *name,
942 offset: offset.bytes(),
943 size: field_layout.size.bytes(),
944 align: field_layout.align.bytes(),
945 type_name: None,
946 }
947 })
948 .collect();
949
950 let mut variant_infos: Vec<_> = coroutine
951 .variant_fields
952 .iter_enumerated()
953 .map(|(variant_idx, variant_def)| {
954 let variant_layout = layout.for_variant(cx, variant_idx);
955 let mut variant_size = Size::ZERO;
956 let fields = variant_def
957 .iter()
958 .enumerate()
959 .map(|(field_idx, local)| {
960 let field_name = coroutine.field_names[*local];
961 let field_layout = variant_layout.field(cx, field_idx);
962 let offset = variant_layout.fields.offset(field_idx);
963 variant_size = variant_size.max(offset + field_layout.size);
965 FieldInfo {
966 kind: FieldKind::CoroutineLocal,
967 name: field_name.unwrap_or_else(|| {
968 Symbol::intern(&::alloc::__export::must_use({
::alloc::fmt::format(format_args!(".coroutine_field{0}",
local.as_usize()))
})format!(".coroutine_field{}", local.as_usize()))
969 }),
970 offset: offset.bytes(),
971 size: field_layout.size.bytes(),
972 align: field_layout.align.bytes(),
973 type_name: (field_name.is_none() || field_name == Some(sym::__awaitee))
976 .then(|| Symbol::intern(&field_layout.ty.to_string())),
977 }
978 })
979 .chain(upvar_fields.iter().copied())
980 .collect();
981
982 if variant_size == Size::ZERO {
984 variant_size = upvars_size;
985 }
986
987 if layout.fields.offset(tag_field.as_usize()) >= variant_size {
1003 variant_size += match tag_encoding {
1004 TagEncoding::Direct => tag.size(cx),
1005 _ => Size::ZERO,
1006 };
1007 }
1008
1009 VariantInfo {
1010 name: Some(Symbol::intern(&ty::CoroutineArgs::variant_name(variant_idx))),
1011 kind: SizeKind::Exact,
1012 size: variant_size.bytes(),
1013 align: variant_layout.align.bytes(),
1014 fields,
1015 }
1016 })
1017 .collect();
1018
1019 let end_states = variant_infos.drain(1..=2);
1024 let end_states: Vec<_> = end_states.collect();
1025 variant_infos.extend(end_states);
1026
1027 (
1028 variant_infos,
1029 match tag_encoding {
1030 TagEncoding::Direct => Some(tag.size(cx)),
1031 _ => None,
1032 },
1033 )
1034}