1use hir::def_id::DefId;
2use rustc_abi as abi;
3use rustc_abi::Integer::{I8, I32};
4use rustc_abi::Primitive::{self, Float, Int, Pointer};
5use rustc_abi::{
6 AddressSpace, BackendRepr, FIRST_VARIANT, FieldIdx, FieldsShape, HasDataLayout, Layout,
7 LayoutCalculatorError, LayoutData, Niche, ReprOptions, Scalar, Size, StructKind, TagEncoding,
8 VariantIdx, Variants, WrappingRange,
9};
10use rustc_hashes::Hash64;
11use rustc_hir as hir;
12use rustc_hir::find_attr;
13use rustc_index::{Idx as _, IndexVec};
14use rustc_middle::bug;
15use rustc_middle::query::Providers;
16use rustc_middle::traits::ObligationCause;
17use rustc_middle::ty::layout::{
18 FloatExt, HasTyCtxt, IntegerExt, LayoutCx, LayoutError, LayoutOf, SimdLayoutError, TyAndLayout,
19};
20use rustc_middle::ty::print::with_no_trimmed_paths;
21use rustc_middle::ty::{
22 self, AdtDef, CoroutineArgsExt, EarlyBinder, PseudoCanonicalInput, Ty, TyCtxt,
23 TypeVisitableExt, Unnormalized,
24};
25use rustc_session::{DataTypeKind, FieldInfo, FieldKind, SizeKind, VariantInfo};
26use rustc_span::{Symbol, sym};
27use tracing::{debug, instrument};
28
29use crate::errors::NonPrimitiveSimdType;
30
31mod invariant;
32
33pub(crate) fn provide(providers: &mut Providers) {
34 *providers = Providers { layout_of, ..*providers };
35}
36
37#[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(37u32),
::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:43",
"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(43u32),
::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,
Unnormalized::new_wip(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));
}
match typing_env.typing_mode() {
ty::TypingMode::Codegen => {
let with_postanalysis =
ty::TypingEnv::new(typing_env.param_env,
ty::TypingMode::PostAnalysis);
let res =
tcx.layout_of(with_postanalysis.as_query_input(ty));
match res {
Err(LayoutError::TooGeneric(_)) => {}
_ => return res,
};
}
ty::TypingMode::Coherence | ty::TypingMode::Analysis { .. } |
ty::TypingMode::Borrowck { .. } |
ty::TypingMode::PostBorrowckAnalysis { .. } |
ty::TypingMode::ErasedNotCoherence(_) |
ty::TypingMode::PostAnalysis => {}
}
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")]
38fn layout_of<'tcx>(
39 tcx: TyCtxt<'tcx>,
40 query: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>,
41) -> Result<TyAndLayout<'tcx>, &'tcx LayoutError<'tcx>> {
42 let PseudoCanonicalInput { typing_env, value: ty } = query;
43 debug!(?ty);
44
45 let typing_env = typing_env.with_post_analysis_normalized(tcx);
49 let unnormalized_ty = ty;
50
51 let ty = match tcx.try_normalize_erasing_regions(typing_env, Unnormalized::new_wip(ty)) {
56 Ok(t) => t,
57 Err(normalization_error) => {
58 return Err(tcx
59 .arena
60 .alloc(LayoutError::NormalizationFailure(ty, normalization_error)));
61 }
62 };
63
64 if ty != unnormalized_ty {
65 return tcx.layout_of(typing_env.as_query_input(ty));
67 }
68
69 match typing_env.typing_mode() {
70 ty::TypingMode::Codegen => {
71 let with_postanalysis =
72 ty::TypingEnv::new(typing_env.param_env, ty::TypingMode::PostAnalysis);
73 let res = tcx.layout_of(with_postanalysis.as_query_input(ty));
74 match res {
75 Err(LayoutError::TooGeneric(_)) => {}
76 _ => return res,
77 };
78 }
79 ty::TypingMode::Coherence
80 | ty::TypingMode::Analysis { .. }
81 | ty::TypingMode::Borrowck { .. }
82 | ty::TypingMode::PostBorrowckAnalysis { .. }
83 | ty::TypingMode::ErasedNotCoherence(_)
84 | ty::TypingMode::PostAnalysis => {}
85 }
86
87 let cx = LayoutCx::new(tcx, typing_env);
88
89 let layout = layout_of_uncached(&cx, ty)?;
90 let layout = TyAndLayout { ty, layout };
91
92 if cx.tcx().sess.opts.unstable_opts.print_type_sizes {
95 record_layout_for_printing(&cx, layout);
96 }
97
98 invariant::layout_sanity_check(&cx, &layout);
99
100 Ok(layout)
101}
102
103fn error<'tcx>(cx: &LayoutCx<'tcx>, err: LayoutError<'tcx>) -> &'tcx LayoutError<'tcx> {
104 cx.tcx().arena.alloc(err)
105}
106
107fn map_error<'tcx>(
108 cx: &LayoutCx<'tcx>,
109 ty: Ty<'tcx>,
110 err: LayoutCalculatorError<TyAndLayout<'tcx>>,
111) -> &'tcx LayoutError<'tcx> {
112 let err = match err {
113 LayoutCalculatorError::SizeOverflow => {
114 LayoutError::SizeOverflow(ty)
117 }
118 LayoutCalculatorError::UnexpectedUnsized(field) => {
119 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:#?}");
122 if cx.typing_env.param_env.caller_bounds().is_empty() {
123 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!(
124 "encountered unexpected unsized field in layout of {ty:?}: {field:#?}"
125 ));
126 }
127 LayoutError::Unknown(ty)
128 }
129 LayoutCalculatorError::EmptyUnion => {
130 let guar =
132 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:?}"));
133 LayoutError::ReferencesError(guar)
134 }
135 LayoutCalculatorError::ReprConflict => {
136 let guar = cx
138 .tcx()
139 .dcx()
140 .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:?}"));
141 LayoutError::ReferencesError(guar)
142 }
143 LayoutCalculatorError::ZeroLengthSimdType => {
144 LayoutError::InvalidSimd { ty, kind: SimdLayoutError::ZeroLength }
146 }
147 LayoutCalculatorError::OversizedSimdType { max_lanes } => {
148 LayoutError::InvalidSimd { ty, kind: SimdLayoutError::TooManyLanes(max_lanes) }
150 }
151 LayoutCalculatorError::NonPrimitiveSimdType(field) => {
152 cx.tcx().dcx().emit_fatal(NonPrimitiveSimdType { ty, e_ty: field.ty })
155 }
156 };
157 error(cx, err)
158}
159
160fn extract_const_value<'tcx>(
161 cx: &LayoutCx<'tcx>,
162 ty: Ty<'tcx>,
163 ct: ty::Const<'tcx>,
164) -> Result<ty::Value<'tcx>, &'tcx LayoutError<'tcx>> {
165 match ct.kind() {
166 ty::ConstKind::Value(cv) => Ok(cv),
167 ty::ConstKind::Param(_) | ty::ConstKind::Expr(_) => {
168 if !ct.has_param() {
169 ::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:?}");
170 }
171 Err(error(cx, LayoutError::TooGeneric(ty)))
172 }
173 ty::ConstKind::Unevaluated(_) => {
174 let err = if ct.has_param() {
175 LayoutError::TooGeneric(ty)
176 } else {
177 LayoutError::Unknown(ty)
183 };
184 Err(error(cx, err))
185 }
186 ty::ConstKind::Infer(_)
187 | ty::ConstKind::Bound(..)
188 | ty::ConstKind::Placeholder(_)
189 | ty::ConstKind::Error(_) => {
190 ::rustc_middle::util::bug::bug_fmt(format_args!("layout_of: unexpected const: {0:?}",
ct));bug!("layout_of: unexpected const: {ct:?}");
193 }
194 }
195}
196
197fn layout_of_uncached<'tcx>(
198 cx: &LayoutCx<'tcx>,
199 ty: Ty<'tcx>,
200) -> Result<Layout<'tcx>, &'tcx LayoutError<'tcx>> {
201 if let Err(guar) = ty.error_reported() {
205 return Err(error(cx, LayoutError::ReferencesError(guar)));
206 }
207
208 let tcx = cx.tcx();
209
210 let dl = cx.data_layout();
214 let map_layout = |result: Result<_, _>| match result {
215 Ok(layout) => Ok(tcx.mk_layout(layout)),
216 Err(err) => Err(map_error(cx, ty, err)),
217 };
218 let scalar_unit = |value: Primitive| {
219 let size = value.size(dl);
220 if !(size.bits() <= 128) {
::core::panicking::panic("assertion failed: size.bits() <= 128")
};assert!(size.bits() <= 128);
221 Scalar::Initialized { value, valid_range: WrappingRange::full(size) }
222 };
223 let scalar = |value: Primitive| tcx.mk_layout(LayoutData::scalar(cx, scalar_unit(value)));
224
225 let univariant = |tys: &[Ty<'tcx>], kind| {
226 let fields = tys.iter().map(|ty| cx.layout_of(*ty)).try_collect::<IndexVec<_, _>>()?;
227 let repr = ReprOptions::default();
228 map_layout(cx.calc.univariant(&fields, &repr, kind))
229 };
230 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());
231
232 Ok(match *ty.kind() {
233 ty::Pat(ty, pat) => {
234 let layout = cx.layout_of(ty)?.layout;
235 let mut layout = LayoutData::clone(&layout.0);
236 match *pat {
237 ty::PatternKind::Range { start, end } => {
238 if let BackendRepr::Scalar(scalar) = &mut layout.backend_repr {
239 scalar.valid_range_mut().start = extract_const_value(cx, ty, start)?
240 .try_to_bits(tcx, cx.typing_env)
241 .ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?;
242
243 scalar.valid_range_mut().end = extract_const_value(cx, ty, end)?
244 .try_to_bits(tcx, cx.typing_env)
245 .ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?;
246
247 if scalar.is_signed() {
253 let range = scalar.valid_range_mut();
254 let start = layout.size.sign_extend(range.start);
255 let end = layout.size.sign_extend(range.end);
256 if end < start {
257 let guar = tcx.dcx().err(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("pattern type ranges cannot wrap: {0}..={1}",
start, end))
})format!(
258 "pattern type ranges cannot wrap: {start}..={end}"
259 ));
260
261 return Err(error(cx, LayoutError::ReferencesError(guar)));
262 }
263 } else {
264 let range = scalar.valid_range_mut();
265 if range.end < range.start {
266 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!(
267 "pattern type ranges cannot wrap: {}..={}",
268 range.start, range.end
269 ));
270
271 return Err(error(cx, LayoutError::ReferencesError(guar)));
272 }
273 };
274
275 let niche = Niche {
276 offset: Size::ZERO,
277 value: scalar.primitive(),
278 valid_range: scalar.valid_range(cx),
279 };
280
281 layout.largest_niche = Some(niche);
282 } else {
283 ::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:?}")
284 }
285 }
286 ty::PatternKind::NotNull => {
287 if let BackendRepr::Scalar(scalar) | BackendRepr::ScalarPair(scalar, _) =
288 &mut layout.backend_repr
289 {
290 scalar.valid_range_mut().start = 1;
291 let niche = Niche {
292 offset: Size::ZERO,
293 value: scalar.primitive(),
294 valid_range: scalar.valid_range(cx),
295 };
296
297 layout.largest_niche = Some(niche);
298 } else {
299 ::rustc_middle::util::bug::bug_fmt(format_args!("pattern type with `!null` pattern but not scalar/pair layout: {0:?}, {1:?}",
ty, layout))bug!(
300 "pattern type with `!null` pattern but not scalar/pair layout: {ty:?}, {layout:?}"
301 )
302 }
303 }
304
305 ty::PatternKind::Or(variants) => match *variants[0] {
306 ty::PatternKind::Range { .. } => {
307 if let BackendRepr::Scalar(scalar) = &mut layout.backend_repr {
308 let variants: Result<Vec<_>, _> = variants
309 .iter()
310 .map(|pat| match *pat {
311 ty::PatternKind::Range { start, end } => Ok((
312 extract_const_value(cx, ty, start)
313 .unwrap()
314 .try_to_bits(tcx, cx.typing_env)
315 .ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?,
316 extract_const_value(cx, ty, end)
317 .unwrap()
318 .try_to_bits(tcx, cx.typing_env)
319 .ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?,
320 )),
321 ty::PatternKind::NotNull | ty::PatternKind::Or(_) => {
322 {
::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")
323 }
324 })
325 .collect();
326 let mut variants = variants?;
327 if !scalar.is_signed() {
328 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!(
329 "only signed integer base types are allowed for or-pattern pattern types at present"
330 ));
331
332 return Err(error(cx, LayoutError::ReferencesError(guar)));
333 }
334 variants.sort();
335 if variants.len() != 2 {
336 let guar = tcx
337 .dcx()
338 .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"));
339
340 return Err(error(cx, LayoutError::ReferencesError(guar)));
341 }
342
343 let mut first = variants[0];
345 let mut second = variants[1];
346 if second.0
347 == layout.size.truncate(layout.size.signed_int_min() as u128)
348 {
349 (second, first) = (first, second);
350 }
351
352 if layout.size.sign_extend(first.1) >= layout.size.sign_extend(second.0)
353 {
354 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!(
355 "only non-overlapping pattern type ranges are allowed at present"
356 ));
357
358 return Err(error(cx, LayoutError::ReferencesError(guar)));
359 }
360 if layout.size.signed_int_max() as u128 != second.1 {
361 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!(
362 "one pattern needs to end at `{ty}::MAX`, but was {} instead",
363 second.1
364 ));
365
366 return Err(error(cx, LayoutError::ReferencesError(guar)));
367 }
368
369 scalar.valid_range_mut().start = second.0;
371 scalar.valid_range_mut().end = first.1;
372
373 let niche = Niche {
374 offset: Size::ZERO,
375 value: scalar.primitive(),
376 valid_range: scalar.valid_range(cx),
377 };
378
379 layout.largest_niche = Some(niche);
380 } else {
381 ::rustc_middle::util::bug::bug_fmt(format_args!("pattern type with range but not scalar layout: {0:?}, {1:?}",
ty, layout))bug!(
382 "pattern type with range but not scalar layout: {ty:?}, {layout:?}"
383 )
384 }
385 }
386 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"),
387 ty::PatternKind::Or(..) => ::rustc_middle::util::bug::bug_fmt(format_args!("patterns cannot have nested or patterns"))bug!("patterns cannot have nested or patterns"),
388 },
389 }
390 layout.fields = FieldsShape::Arbitrary {
395 offsets: [Size::ZERO].into_iter().collect(),
396 in_memory_order: [FieldIdx::new(0)].into_iter().collect(),
397 };
398 tcx.mk_layout(layout)
399 }
400
401 ty::Bool => tcx.mk_layout(LayoutData::scalar(
403 cx,
404 Scalar::Initialized {
405 value: Int(I8, false),
406 valid_range: WrappingRange { start: 0, end: 1 },
407 },
408 )),
409 ty::Char => tcx.mk_layout(LayoutData::scalar(
410 cx,
411 Scalar::Initialized {
412 value: Int(I32, false),
413 valid_range: WrappingRange { start: 0, end: 0x10FFFF },
414 },
415 )),
416 ty::Int(ity) => scalar(Int(abi::Integer::from_int_ty(dl, ity), true)),
417 ty::Uint(ity) => scalar(Int(abi::Integer::from_uint_ty(dl, ity), false)),
418 ty::Float(fty) => scalar(Float(abi::Float::from_float_ty(fty))),
419 ty::FnPtr(..) => {
420 let mut ptr = scalar_unit(Pointer(dl.instruction_address_space));
421 ptr.valid_range_mut().start = 1;
422 tcx.mk_layout(LayoutData::scalar(cx, ptr))
423 }
424
425 ty::Never => tcx.mk_layout(LayoutData::never_type(cx)),
427
428 ty::Ref(_, pointee, _) | ty::RawPtr(pointee, _) => {
430 let mut data_ptr = scalar_unit(Pointer(AddressSpace::ZERO));
431 if !ty.is_raw_ptr() {
432 data_ptr.valid_range_mut().start = 1;
433 }
434
435 if pointee.is_sized(tcx, cx.typing_env) {
436 return Ok(tcx.mk_layout(LayoutData::scalar(cx, data_ptr)));
437 }
438
439 let metadata = if let Some(metadata_def_id) = tcx.lang_items().metadata_type() {
440 let pointee_metadata = Ty::new_projection(tcx, metadata_def_id, [pointee]);
441 let metadata_ty = match tcx.try_normalize_erasing_regions(
442 cx.typing_env,
443 Unnormalized::new_wip(pointee_metadata),
444 ) {
445 Ok(metadata_ty) => metadata_ty,
446 Err(mut err) => {
447 match tcx.try_normalize_erasing_regions(
456 cx.typing_env,
457 Unnormalized::new_wip(tcx.struct_tail_raw(
458 pointee,
459 &ObligationCause::dummy(),
460 |ty| ty.skip_norm_wip(),
461 || {},
462 )),
463 ) {
464 Ok(_) => {}
465 Err(better_err) => {
466 err = better_err;
467 }
468 }
469 return Err(error(cx, LayoutError::NormalizationFailure(pointee, err)));
470 }
471 };
472
473 let metadata_layout = cx.layout_of(metadata_ty)?;
474 if metadata_layout.is_1zst() {
476 return Ok(tcx.mk_layout(LayoutData::scalar(cx, data_ptr)));
477 }
478
479 let BackendRepr::Scalar(metadata) = metadata_layout.backend_repr else {
480 return Err(error(cx, LayoutError::Unknown(pointee)));
481 };
482
483 metadata
484 } else {
485 let unsized_part = tcx.struct_tail_for_codegen(pointee, cx.typing_env);
486
487 match unsized_part.kind() {
488 ty::Foreign(..) => {
489 return Ok(tcx.mk_layout(LayoutData::scalar(cx, data_ptr)));
490 }
491 ty::Slice(_) | ty::Str => scalar_unit(Int(dl.ptr_sized_integer(), false)),
492 ty::Dynamic(..) => {
493 let mut vtable = scalar_unit(Pointer(AddressSpace::ZERO));
494 vtable.valid_range_mut().start = 1;
495 vtable
496 }
497 _ => {
498 return Err(error(cx, LayoutError::Unknown(pointee)));
499 }
500 }
501 };
502
503 tcx.mk_layout(LayoutData::scalar_pair(cx, data_ptr, metadata))
505 }
506
507 ty::Array(element, count) => {
509 let count = extract_const_value(cx, ty, count)?
510 .try_to_target_usize(tcx)
511 .ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?;
512
513 let element = cx.layout_of(element)?;
514 map_layout(cx.calc.array_like(&element, Some(count)))?
515 }
516 ty::Slice(element) => {
517 let element = cx.layout_of(element)?;
518 map_layout(cx.calc.array_like(&element, None).map(|mut layout| {
519 layout.randomization_seed = Hash64::new(0x2dcba99c39784102);
521 layout
522 }))?
523 }
524 ty::Str => {
525 let element = scalar(Int(I8, false));
526 map_layout(cx.calc.array_like(&element, None).map(|mut layout| {
527 layout.randomization_seed = Hash64::new(0xc1325f37d127be22);
529 layout
530 }))?
531 }
532
533 ty::FnDef(..) | ty::Dynamic(_, _) | ty::Foreign(..) => {
535 let sized = #[allow(non_exhaustive_omitted_patterns)] match ty.kind() {
ty::FnDef(..) => true,
_ => false,
}matches!(ty.kind(), ty::FnDef(..));
536 tcx.mk_layout(LayoutData::unit(cx, sized))
537 }
538
539 ty::Coroutine(def_id, args) => {
540 match cx.typing_env.typing_mode() {
541 ty::TypingMode::Codegen => {}
542 ty::TypingMode::Coherence
543 | ty::TypingMode::Analysis { .. }
544 | ty::TypingMode::Borrowck { .. }
545 | ty::TypingMode::PostBorrowckAnalysis { .. }
546 | ty::TypingMode::ErasedNotCoherence(_)
547 | ty::TypingMode::PostAnalysis => {
548 return Err(error(cx, LayoutError::TooGeneric(ty)));
549 }
550 }
551
552 use rustc_middle::ty::layout::PrimitiveExt as _;
553
554 let info = tcx.coroutine_layout(def_id, args)?;
555
556 let local_layouts = info
557 .field_tys
558 .iter()
559 .map(|local| {
560 let field_ty = EarlyBinder::bind(local.ty);
561 let uninit_ty =
562 Ty::new_maybe_uninit(tcx, field_ty.instantiate(tcx, args).skip_norm_wip());
563 cx.spanned_layout_of(uninit_ty, local.source_info.span)
564 })
565 .try_collect::<IndexVec<_, _>>()?;
566
567 let prefix_layouts = args
568 .as_coroutine()
569 .prefix_tys()
570 .iter()
571 .map(|ty| cx.layout_of(ty))
572 .try_collect::<IndexVec<_, _>>()?;
573
574 let layout = cx
575 .calc
576 .coroutine(
577 &local_layouts,
578 prefix_layouts,
579 &info.variant_fields,
580 &info.storage_conflicts,
581 |tag| TyAndLayout {
582 ty: tag.primitive().to_ty(tcx),
583 layout: tcx.mk_layout(LayoutData::scalar(cx, tag)),
584 },
585 )
586 .map(|mut layout| {
587 layout.randomization_seed = tcx.def_path_hash(def_id).0.to_smaller_hash();
589 {
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:589",
"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(589u32),
::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);
590 layout
591 });
592 map_layout(layout)?
593 }
594
595 ty::Closure(_, args) => univariant(args.as_closure().upvar_tys(), StructKind::AlwaysSized)?,
596
597 ty::CoroutineClosure(_, args) => {
598 univariant(args.as_coroutine_closure().upvar_tys(), StructKind::AlwaysSized)?
599 }
600
601 ty::Tuple(tys) => {
602 let kind =
603 if tys.len() == 0 { StructKind::AlwaysSized } else { StructKind::MaybeUnsized };
604
605 univariant(tys, kind)?
606 }
607
608 ty::Adt(def, _args) if def.repr().scalable() => {
618 let Some((element_count, element_ty, number_of_vectors)) =
619 ty.scalable_vector_parts(tcx)
620 else {
621 let guar = tcx
622 .dcx()
623 .delayed_bug("`#[rustc_scalable_vector]` was applied to an invalid type");
624 return Err(error(cx, LayoutError::ReferencesError(guar)));
625 };
626
627 let element_layout = cx.layout_of(element_ty)?;
628 map_layout(cx.calc.scalable_vector_type(
629 element_layout,
630 element_count as u64,
631 number_of_vectors,
632 ))?
633 }
634
635 ty::Adt(def, args) if def.repr().simd() => {
637 let Some(ty::Array(e_ty, e_len)) = def
643 .is_struct()
644 .then(|| &def.variant(FIRST_VARIANT).fields)
645 .filter(|fields| fields.len() == 1)
646 .map(|fields| *fields[FieldIdx::ZERO].ty(tcx, args).skip_norm_wip().kind())
647 else {
648 let guar = tcx.dcx().delayed_bug("#[repr(simd)] was applied to an invalid ADT");
650 return Err(error(cx, LayoutError::ReferencesError(guar)));
651 };
652
653 let e_len = extract_const_value(cx, ty, e_len)?
654 .try_to_target_usize(tcx)
655 .ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?;
656
657 let e_ly = cx.layout_of(e_ty)?;
658
659 if let Some(limit) = {
{
'done:
{
for i in ::rustc_hir::attrs::HasAttrs::get_attrs(def.did(), &tcx)
{
#[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!(
661 tcx, def.did(),
662 RustcSimdMonomorphizeLaneLimit(limit) => limit
663 ) {
664 if !limit.value_within_limit(e_len as usize) {
665 return Err(map_error(
666 &cx,
667 ty,
668 rustc_abi::LayoutCalculatorError::OversizedSimdType {
669 max_lanes: limit.0 as u64,
670 },
671 ));
672 }
673 }
674
675 map_layout(cx.calc.simd_type(e_ly, e_len, def.repr().packed()))?
676 }
677
678 ty::Adt(def, args) => {
680 let variants = def
682 .variants()
683 .iter()
684 .map(|v| {
685 v.fields
686 .iter()
687 .map(|field| cx.layout_of(field.ty(tcx, args).skip_norm_wip()))
688 .try_collect::<IndexVec<_, _>>()
689 })
690 .try_collect::<IndexVec<VariantIdx, _>>()?;
691
692 if def.is_union() {
693 if def.repr().pack.is_some() && def.repr().align.is_some() {
694 let guar = tcx.dcx().span_delayed_bug(
695 tcx.def_span(def.did()),
696 "union cannot be packed and aligned",
697 );
698 return Err(error(cx, LayoutError::ReferencesError(guar)));
699 }
700
701 return map_layout(cx.calc.layout_of_union(&def.repr(), &variants));
702 }
703
704 let is_special_no_niche = def.is_unsafe_cell() || def.is_unsafe_pinned();
706
707 let discr_range_of_repr =
708 |min, max| abi::Integer::discr_range_of_repr(tcx, ty, &def.repr(), min, max);
709
710 let discriminants_iter = || {
711 def.is_enum()
712 .then(|| def.discriminants(tcx).map(|(v, d)| (v, d.val as i128)))
713 .into_iter()
714 .flatten()
715 };
716
717 let maybe_unsized = def.is_struct()
718 && def.non_enum_variant().tail_opt().is_some_and(|last_field| {
719 let typing_env = ty::TypingEnv::new(
720 tcx.param_env_normalized_for_post_analysis(def.did()),
721 cx.typing_env.typing_mode(),
722 );
723 !tcx.type_of(last_field.did)
724 .instantiate_identity()
725 .skip_norm_wip()
726 .is_sized(tcx, typing_env)
727 });
728
729 let layout = cx
730 .calc
731 .layout_of_struct_or_enum(
732 &def.repr(),
733 &variants,
734 def.is_enum(),
735 is_special_no_niche,
736 discr_range_of_repr,
737 discriminants_iter(),
738 !maybe_unsized,
739 )
740 .map_err(|err| map_error(cx, ty, err))?;
741
742 if !maybe_unsized && layout.is_unsized() {
743 ::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:#?}");
744 }
745
746 if truecfg!(debug_assertions)
748 && maybe_unsized
749 && def
750 .non_enum_variant()
751 .tail()
752 .ty(tcx, args)
753 .skip_norm_wip()
754 .is_sized(tcx, cx.typing_env)
755 {
756 let mut variants = variants;
757 let tail_replacement = cx.layout_of(Ty::new_slice(tcx, tcx.types.u8)).unwrap();
758 *variants[FIRST_VARIANT].raw.last_mut().unwrap() = tail_replacement;
759
760 let Ok(unsized_layout) = cx.calc.layout_of_struct_or_enum(
761 &def.repr(),
762 &variants,
763 def.is_enum(),
764 is_special_no_niche,
765 discr_range_of_repr,
766 discriminants_iter(),
767 !maybe_unsized,
768 ) else {
769 ::rustc_middle::util::bug::bug_fmt(format_args!("failed to compute unsized layout of {0:?}",
ty));bug!("failed to compute unsized layout of {ty:?}");
770 };
771
772 let FieldsShape::Arbitrary { offsets: sized_offsets, .. } = &layout.fields else {
773 ::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);
774 };
775 let FieldsShape::Arbitrary { offsets: unsized_offsets, .. } =
776 &unsized_layout.fields
777 else {
778 ::rustc_middle::util::bug::bug_fmt(format_args!("unexpected FieldsShape for unsized layout of {1:?}: {0:?}",
unsized_layout.fields, ty));bug!(
779 "unexpected FieldsShape for unsized layout of {ty:?}: {:?}",
780 unsized_layout.fields
781 );
782 };
783
784 let (sized_tail, sized_fields) = sized_offsets.raw.split_last().unwrap();
785 let (unsized_tail, unsized_fields) = unsized_offsets.raw.split_last().unwrap();
786
787 if sized_fields != unsized_fields {
788 ::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:?}");
789 }
790
791 if sized_tail < unsized_tail {
792 ::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:?}");
793 }
794 }
795
796 tcx.mk_layout(layout)
797 }
798
799 ty::UnsafeBinder(bound_ty) => {
800 let ty = tcx.instantiate_bound_regions_with_erased(bound_ty.into());
801 cx.layout_of(ty)?.layout
802 }
803
804 ty::Param(_) | ty::Placeholder(..) => {
806 return Err(error(cx, LayoutError::TooGeneric(ty)));
807 }
808
809 ty::Alias(..) => {
810 let err = if ty.has_param() || !cx.typing_env.param_env.caller_bounds().is_empty() {
821 LayoutError::TooGeneric(ty)
822 } else {
823 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!(
824 "unexpected rigid alias in layout_of after normalization: {ty:?}"
825 )))
826 };
827 return Err(error(cx, err));
828 }
829
830 ty::Bound(..) | ty::CoroutineWitness(..) | ty::Infer(_) | ty::Error(_) => {
831 ::rustc_middle::util::bug::bug_fmt(format_args!("layout_of: unexpected type `{0}`",
ty))bug!("layout_of: unexpected type `{ty}`")
833 }
834 })
835}
836
837fn record_layout_for_printing<'tcx>(cx: &LayoutCx<'tcx>, layout: TyAndLayout<'tcx>) {
838 if layout.ty.has_non_region_param() || !cx.typing_env.param_env.caller_bounds().is_empty() {
842 return;
843 }
844
845 let record = |kind, packed, opt_discr_size, variants| {
847 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));
848 cx.tcx().sess.code_stats.record_type_size(
849 kind,
850 type_desc,
851 layout.align.abi,
852 layout.size,
853 packed,
854 opt_discr_size,
855 variants,
856 );
857 };
858
859 match *layout.ty.kind() {
860 ty::Adt(adt_def, _) => {
861 {
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:861",
"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(861u32),
::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);
862 let adt_kind = adt_def.adt_kind();
863 let adt_packed = adt_def.repr().pack.is_some();
864 let (variant_infos, opt_discr_size) = variant_info_for_adt(cx, layout, adt_def);
865 record(adt_kind.into(), adt_packed, opt_discr_size, variant_infos);
866 }
867
868 ty::Coroutine(def_id, args) => {
869 {
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:869",
"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(869u32),
::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);
870 let (variant_infos, opt_discr_size) =
872 variant_info_for_coroutine(cx, layout, def_id, args);
873 record(DataTypeKind::Coroutine, false, opt_discr_size, variant_infos);
874 }
875
876 ty::Closure(..) => {
877 {
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:877",
"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(877u32),
::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);
878 record(DataTypeKind::Closure, false, None, ::alloc::vec::Vec::new()vec![]);
879 }
880
881 _ => {
882 {
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:882",
"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(882u32),
::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);
883 }
884 };
885}
886
887fn variant_info_for_adt<'tcx>(
888 cx: &LayoutCx<'tcx>,
889 layout: TyAndLayout<'tcx>,
890 adt_def: AdtDef<'tcx>,
891) -> (Vec<VariantInfo>, Option<Size>) {
892 let build_variant_info = |n: Option<Symbol>, flds: &[Symbol], layout: TyAndLayout<'tcx>| {
893 let mut min_size = Size::ZERO;
894 let field_info: Vec<_> = flds
895 .iter()
896 .enumerate()
897 .map(|(i, &name)| {
898 let field_layout = layout.field(cx, i);
899 let offset = layout.fields.offset(i);
900 min_size = min_size.max(offset + field_layout.size);
901 FieldInfo {
902 kind: FieldKind::AdtField,
903 name,
904 offset: offset.bytes(),
905 size: field_layout.size.bytes(),
906 align: field_layout.align.bytes(),
907 type_name: None,
908 }
909 })
910 .collect();
911
912 VariantInfo {
913 name: n,
914 kind: if layout.is_unsized() { SizeKind::Min } else { SizeKind::Exact },
915 align: layout.align.bytes(),
916 size: if min_size.bytes() == 0 { layout.size.bytes() } else { min_size.bytes() },
917 fields: field_info,
918 }
919 };
920
921 match layout.variants {
922 Variants::Empty => (::alloc::vec::Vec::new()vec![], None),
923
924 Variants::Single { index } => {
925 {
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:925",
"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(925u32),
::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);
926 let variant_def = &adt_def.variant(index);
927 let fields: Vec<_> = variant_def.fields.iter().map(|f| f.name).collect();
928 (::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)
929 }
930
931 Variants::Multiple { tag, ref tag_encoding, .. } => {
932 {
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:932",
"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(932u32),
::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!(
933 "print-type-size `{:#?}` adt general variants def {}",
934 layout.ty,
935 adt_def.variants().len()
936 );
937 let variant_infos: Vec<_> = adt_def
938 .variants()
939 .iter_enumerated()
940 .map(|(i, variant_def)| {
941 let fields: Vec<_> = variant_def.fields.iter().map(|f| f.name).collect();
942 build_variant_info(Some(variant_def.name), &fields, layout.for_variant(cx, i))
943 })
944 .collect();
945
946 (
947 variant_infos,
948 match tag_encoding {
949 TagEncoding::Direct => Some(tag.size(cx)),
950 _ => None,
951 },
952 )
953 }
954 }
955}
956
957fn variant_info_for_coroutine<'tcx>(
958 cx: &LayoutCx<'tcx>,
959 layout: TyAndLayout<'tcx>,
960 def_id: DefId,
961 args: ty::GenericArgsRef<'tcx>,
962) -> (Vec<VariantInfo>, Option<Size>) {
963 use itertools::Itertools;
964
965 let Variants::Multiple { tag, ref tag_encoding, tag_field, .. } = layout.variants else {
966 return (::alloc::vec::Vec::new()vec![], None);
967 };
968
969 let coroutine = cx.tcx().coroutine_layout(def_id, args).unwrap();
970 let upvar_names = cx.tcx().closure_saved_names_of_captured_variables(def_id);
971
972 let mut upvars_size = Size::ZERO;
973 let upvar_fields: Vec<_> = args
974 .as_coroutine()
975 .upvar_tys()
976 .iter()
977 .zip_eq(upvar_names)
978 .enumerate()
979 .map(|(field_idx, (_, name))| {
980 let field_layout = layout.field(cx, field_idx);
981 let offset = layout.fields.offset(field_idx);
982 upvars_size = upvars_size.max(offset + field_layout.size);
983 FieldInfo {
984 kind: FieldKind::Upvar,
985 name: *name,
986 offset: offset.bytes(),
987 size: field_layout.size.bytes(),
988 align: field_layout.align.bytes(),
989 type_name: None,
990 }
991 })
992 .collect();
993
994 let mut variant_infos: Vec<_> = coroutine
995 .variant_fields
996 .iter_enumerated()
997 .map(|(variant_idx, variant_def)| {
998 let variant_layout = layout.for_variant(cx, variant_idx);
999 let mut variant_size = Size::ZERO;
1000 let fields = variant_def
1001 .iter()
1002 .enumerate()
1003 .map(|(field_idx, local)| {
1004 let field_name = coroutine.field_tys[*local].debuginfo_name;
1005 let field_layout = variant_layout.field(cx, field_idx);
1006 let offset = variant_layout.fields.offset(field_idx);
1007 variant_size = variant_size.max(offset + field_layout.size);
1009 FieldInfo {
1010 kind: FieldKind::CoroutineLocal,
1011 name: field_name.unwrap_or_else(|| {
1012 Symbol::intern(&::alloc::__export::must_use({
::alloc::fmt::format(format_args!(".coroutine_field{0}",
local.as_usize()))
})format!(".coroutine_field{}", local.as_usize()))
1013 }),
1014 offset: offset.bytes(),
1015 size: field_layout.size.bytes(),
1016 align: field_layout.align.bytes(),
1017 type_name: (field_name.is_none() || field_name == Some(sym::__awaitee))
1020 .then(|| Symbol::intern(&field_layout.ty.to_string())),
1021 }
1022 })
1023 .chain(upvar_fields.iter().copied())
1024 .collect();
1025
1026 if variant_size == Size::ZERO {
1028 variant_size = upvars_size;
1029 }
1030
1031 if layout.fields.offset(tag_field.as_usize()) >= variant_size {
1047 variant_size += match tag_encoding {
1048 TagEncoding::Direct => tag.size(cx),
1049 _ => Size::ZERO,
1050 };
1051 }
1052
1053 VariantInfo {
1054 name: Some(Symbol::intern(&ty::CoroutineArgs::variant_name(variant_idx))),
1055 kind: SizeKind::Exact,
1056 size: variant_size.bytes(),
1057 align: variant_layout.align.bytes(),
1058 fields,
1059 }
1060 })
1061 .collect();
1062
1063 let end_states = variant_infos.drain(1..=2);
1068 let end_states: Vec<_> = end_states.collect();
1069 variant_infos.extend(end_states);
1070
1071 (
1072 variant_infos,
1073 match tag_encoding {
1074 TagEncoding::Direct => Some(tag.size(cx)),
1075 _ => None,
1076 },
1077 )
1078}