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