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