Skip to content

Commit bafff1b

Browse files
authored
Rollup merge of #137218 - lukas-code:layout_of_cleanup, r=compiler-errors
misc `layout_of` cleanup See individual commits for details. r? `@oli-obk` but feel free to reassign
2 parents a66ef2f + 2fbc413 commit bafff1b

File tree

8 files changed

+174
-104
lines changed

8 files changed

+174
-104
lines changed

compiler/rustc_middle/messages.ftl

+14-14
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,6 @@ middle_autodiff_unsafe_inner_const_ref = reading from a `Duplicated` const {$ty}
3737
middle_bounds_check =
3838
index out of bounds: the length is {$len} but the index is {$index}
3939
40-
middle_cannot_be_normalized =
41-
unable to determine layout for `{$ty}` because `{$failure_ty}` cannot be normalized
42-
4340
middle_conflict_types =
4441
this expression supplies two conflicting concrete types for the same opaque type
4542
@@ -52,9 +49,6 @@ middle_const_eval_non_int =
5249
middle_const_not_used_in_type_alias =
5350
const parameter `{$ct}` is part of concrete type but not used in parameter list for the `impl Trait` type alias
5451
55-
middle_cycle =
56-
a cycle occurred during layout computation
57-
5852
middle_deprecated = use of deprecated {$kind} `{$path}`{$has_note ->
5953
[true] : {$note}
6054
*[other] {""}
@@ -78,9 +72,23 @@ middle_erroneous_constant = erroneous constant encountered
7872
middle_failed_writing_file =
7973
failed to write file {$path}: {$error}"
8074
75+
middle_layout_cycle =
76+
a cycle occurred during layout computation
77+
78+
middle_layout_normalization_failure =
79+
unable to determine layout for `{$ty}` because `{$failure_ty}` cannot be normalized
80+
8181
middle_layout_references_error =
8282
the type has an unknown layout
8383
84+
middle_layout_size_overflow =
85+
values of the type `{$ty}` are too big for the target architecture
86+
87+
middle_layout_too_generic = the type `{$ty}` does not have a fixed layout
88+
89+
middle_layout_unknown =
90+
the type `{$ty}` has an unknown layout
91+
8492
middle_opaque_hidden_type_mismatch =
8593
concrete type differs from previous defining opaque type use
8694
.label = expected `{$self_ty}`, got `{$other_ty}`
@@ -98,16 +106,8 @@ middle_strict_coherence_needs_negative_coherence =
98106
to use `strict_coherence` on this trait, the `with_negative_coherence` feature must be enabled
99107
.label = due to this attribute
100108
101-
middle_too_generic = `{$ty}` does not have a fixed size
102-
103109
middle_type_length_limit = reached the type-length limit while instantiating `{$shrunk}`
104110
105-
middle_unknown_layout =
106-
the type `{$ty}` has an unknown layout
107-
108111
middle_unsupported_union = we don't support unions yet: '{$ty_name}'
109112
110-
middle_values_too_big =
111-
values of the type `{$ty}` are too big for the target architecture
112-
113113
middle_written_to_path = the full type name has been written to '{$path}'

compiler/rustc_middle/src/error.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -132,19 +132,19 @@ impl fmt::Debug for CustomSubdiagnostic<'_> {
132132

133133
#[derive(Diagnostic)]
134134
pub enum LayoutError<'tcx> {
135-
#[diag(middle_unknown_layout)]
135+
#[diag(middle_layout_unknown)]
136136
Unknown { ty: Ty<'tcx> },
137137

138-
#[diag(middle_too_generic)]
138+
#[diag(middle_layout_too_generic)]
139139
TooGeneric { ty: Ty<'tcx> },
140140

141-
#[diag(middle_values_too_big)]
141+
#[diag(middle_layout_size_overflow)]
142142
Overflow { ty: Ty<'tcx> },
143143

144-
#[diag(middle_cannot_be_normalized)]
144+
#[diag(middle_layout_normalization_failure)]
145145
NormalizationFailure { ty: Ty<'tcx>, failure_ty: String },
146146

147-
#[diag(middle_cycle)]
147+
#[diag(middle_layout_cycle)]
148148
Cycle,
149149

150150
#[diag(middle_layout_references_error)]

compiler/rustc_middle/src/ty/layout.rs

+27-6
Original file line numberDiff line numberDiff line change
@@ -229,11 +229,32 @@ impl fmt::Display for ValidityRequirement {
229229

230230
#[derive(Copy, Clone, Debug, HashStable, TyEncodable, TyDecodable)]
231231
pub enum LayoutError<'tcx> {
232+
/// A type doesn't have a sensible layout.
233+
///
234+
/// This variant is used for layout errors that don't necessarily cause
235+
/// compile errors.
236+
///
237+
/// For example, this can happen if a struct contains an unsized type in a
238+
/// non-tail field, but has an unsatisfiable bound like `str: Sized`.
232239
Unknown(Ty<'tcx>),
240+
/// The size of a type exceeds [`TargetDataLayout::obj_size_bound`].
233241
SizeOverflow(Ty<'tcx>),
242+
/// The layout can vary due to a generic parameter.
243+
///
244+
/// Unlike `Unknown`, this variant is a "soft" error and indicates that the layout
245+
/// may become computable after further instantiating the generic parameter(s).
234246
TooGeneric(Ty<'tcx>),
247+
/// An alias failed to normalize.
248+
///
249+
/// This variant is necessary, because, due to trait solver incompleteness, it is
250+
/// possible than an alias that was rigid during analysis fails to normalize after
251+
/// revealing opaque types.
252+
///
253+
/// See `tests/ui/layout/normalization-failure.rs` for an example.
235254
NormalizationFailure(Ty<'tcx>, NormalizationError<'tcx>),
255+
/// A non-layout error is reported elsewhere.
236256
ReferencesError(ErrorGuaranteed),
257+
/// A type has cyclic layout, i.e. the type contains itself without indirection.
237258
Cycle(ErrorGuaranteed),
238259
}
239260

@@ -243,11 +264,11 @@ impl<'tcx> LayoutError<'tcx> {
243264

244265
use crate::fluent_generated::*;
245266
match self {
246-
Unknown(_) => middle_unknown_layout,
247-
SizeOverflow(_) => middle_values_too_big,
248-
TooGeneric(_) => middle_too_generic,
249-
NormalizationFailure(_, _) => middle_cannot_be_normalized,
250-
Cycle(_) => middle_cycle,
267+
Unknown(_) => middle_layout_unknown,
268+
SizeOverflow(_) => middle_layout_size_overflow,
269+
TooGeneric(_) => middle_layout_too_generic,
270+
NormalizationFailure(_, _) => middle_layout_normalization_failure,
271+
Cycle(_) => middle_layout_cycle,
251272
ReferencesError(_) => middle_layout_references_error,
252273
}
253274
}
@@ -276,7 +297,7 @@ impl<'tcx> fmt::Display for LayoutError<'tcx> {
276297
match *self {
277298
LayoutError::Unknown(ty) => write!(f, "the type `{ty}` has an unknown layout"),
278299
LayoutError::TooGeneric(ty) => {
279-
write!(f, "`{ty}` does not have a fixed size")
300+
write!(f, "the type `{ty}` does not have a fixed layout")
280301
}
281302
LayoutError::SizeOverflow(ty) => {
282303
write!(f, "values of the type `{ty}` are too big for the target architecture")

compiler/rustc_ty_utils/src/layout.rs

+47-78
Original file line numberDiff line numberDiff line change
@@ -134,42 +134,32 @@ fn univariant_uninterned<'tcx>(
134134
cx: &LayoutCx<'tcx>,
135135
ty: Ty<'tcx>,
136136
fields: &IndexSlice<FieldIdx, TyAndLayout<'tcx>>,
137-
repr: &ReprOptions,
138137
kind: StructKind,
139138
) -> Result<LayoutData<FieldIdx, VariantIdx>, &'tcx LayoutError<'tcx>> {
140-
let pack = repr.pack;
141-
if pack.is_some() && repr.align.is_some() {
142-
cx.tcx().dcx().bug("struct cannot be packed and aligned");
143-
}
144-
145-
cx.calc.univariant(fields, repr, kind).map_err(|err| map_error(cx, ty, err))
139+
let repr = ReprOptions::default();
140+
cx.calc.univariant(fields, &repr, kind).map_err(|err| map_error(cx, ty, err))
146141
}
147142

148143
fn extract_const_value<'tcx>(
149-
const_: ty::Const<'tcx>,
150-
ty: Ty<'tcx>,
151144
cx: &LayoutCx<'tcx>,
145+
ty: Ty<'tcx>,
146+
ct: ty::Const<'tcx>,
152147
) -> Result<ty::Value<'tcx>, &'tcx LayoutError<'tcx>> {
153-
match const_.kind() {
148+
match ct.kind() {
154149
ty::ConstKind::Value(cv) => Ok(cv),
155-
ty::ConstKind::Error(guar) => {
156-
return Err(error(cx, LayoutError::ReferencesError(guar)));
157-
}
158-
ty::ConstKind::Param(_) | ty::ConstKind::Expr(_) => {
159-
if !const_.has_param() {
160-
bug!("no generic type found in the type: {ty:?}");
161-
}
162-
return Err(error(cx, LayoutError::TooGeneric(ty)));
163-
}
164-
ty::ConstKind::Unevaluated(_) => {
165-
if !const_.has_param() {
166-
return Err(error(cx, LayoutError::Unknown(ty)));
167-
} else {
168-
return Err(error(cx, LayoutError::TooGeneric(ty)));
150+
ty::ConstKind::Param(_) | ty::ConstKind::Expr(_) | ty::ConstKind::Unevaluated(_) => {
151+
if !ct.has_param() {
152+
bug!("failed to normalize const, but it is not generic: {ct:?}");
169153
}
154+
Err(error(cx, LayoutError::TooGeneric(ty)))
170155
}
171-
ty::ConstKind::Infer(_) | ty::ConstKind::Bound(..) | ty::ConstKind::Placeholder(_) => {
172-
bug!("unexpected type: {ty:?}");
156+
ty::ConstKind::Infer(_)
157+
| ty::ConstKind::Bound(..)
158+
| ty::ConstKind::Placeholder(_)
159+
| ty::ConstKind::Error(_) => {
160+
// `ty::ConstKind::Error` is handled at the top of `layout_of_uncached`
161+
// (via `ty.error_reported()`).
162+
bug!("layout_of: unexpected const: {ct:?}");
173163
}
174164
}
175165
}
@@ -194,10 +184,9 @@ fn layout_of_uncached<'tcx>(
194184
};
195185
let scalar = |value: Primitive| tcx.mk_layout(LayoutData::scalar(cx, scalar_unit(value)));
196186

197-
let univariant =
198-
|fields: &IndexSlice<FieldIdx, TyAndLayout<'tcx>>, repr: &ReprOptions, kind| {
199-
Ok(tcx.mk_layout(univariant_uninterned(cx, ty, fields, repr, kind)?))
200-
};
187+
let univariant = |fields: &IndexSlice<FieldIdx, TyAndLayout<'tcx>>, kind| {
188+
Ok(tcx.mk_layout(univariant_uninterned(cx, ty, fields, kind)?))
189+
};
201190
debug_assert!(!ty.has_non_region_infer());
202191

203192
Ok(match *ty.kind() {
@@ -210,12 +199,12 @@ fn layout_of_uncached<'tcx>(
210199
&mut layout.backend_repr
211200
{
212201
if let Some(start) = start {
213-
scalar.valid_range_mut().start = extract_const_value(start, ty, cx)?
202+
scalar.valid_range_mut().start = extract_const_value(cx, ty, start)?
214203
.try_to_bits(tcx, cx.typing_env)
215204
.ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?;
216205
}
217206
if let Some(end) = end {
218-
let mut end = extract_const_value(end, ty, cx)?
207+
let mut end = extract_const_value(cx, ty, end)?
219208
.try_to_bits(tcx, cx.typing_env)
220209
.ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?;
221210
if !include_end {
@@ -274,16 +263,11 @@ fn layout_of_uncached<'tcx>(
274263
data_ptr.valid_range_mut().start = 1;
275264
}
276265

277-
let pointee = tcx.normalize_erasing_regions(cx.typing_env, pointee);
278266
if pointee.is_sized(tcx, cx.typing_env) {
279267
return Ok(tcx.mk_layout(LayoutData::scalar(cx, data_ptr)));
280268
}
281269

282-
let metadata = if let Some(metadata_def_id) = tcx.lang_items().metadata_type()
283-
// Projection eagerly bails out when the pointee references errors,
284-
// fall back to structurally deducing metadata.
285-
&& !pointee.references_error()
286-
{
270+
let metadata = if let Some(metadata_def_id) = tcx.lang_items().metadata_type() {
287271
let pointee_metadata = Ty::new_projection(tcx, metadata_def_id, [pointee]);
288272
let metadata_ty =
289273
match tcx.try_normalize_erasing_regions(cx.typing_env, pointee_metadata) {
@@ -354,7 +338,7 @@ fn layout_of_uncached<'tcx>(
354338

355339
// Arrays and slices.
356340
ty::Array(element, count) => {
357-
let count = extract_const_value(count, ty, cx)?
341+
let count = extract_const_value(cx, ty, count)?
358342
.try_to_target_usize(tcx)
359343
.ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?;
360344

@@ -415,17 +399,10 @@ fn layout_of_uncached<'tcx>(
415399
}),
416400

417401
// Odd unit types.
418-
ty::FnDef(..) => {
419-
univariant(IndexSlice::empty(), &ReprOptions::default(), StructKind::AlwaysSized)?
420-
}
402+
ty::FnDef(..) => univariant(IndexSlice::empty(), StructKind::AlwaysSized)?,
421403
ty::Dynamic(_, _, ty::Dyn) | ty::Foreign(..) => {
422-
let mut unit = univariant_uninterned(
423-
cx,
424-
ty,
425-
IndexSlice::empty(),
426-
&ReprOptions::default(),
427-
StructKind::AlwaysSized,
428-
)?;
404+
let mut unit =
405+
univariant_uninterned(cx, ty, IndexSlice::empty(), StructKind::AlwaysSized)?;
429406
match unit.backend_repr {
430407
BackendRepr::Memory { ref mut sized } => *sized = false,
431408
_ => bug!(),
@@ -439,7 +416,6 @@ fn layout_of_uncached<'tcx>(
439416
let tys = args.as_closure().upvar_tys();
440417
univariant(
441418
&tys.iter().map(|ty| cx.layout_of(ty)).try_collect::<IndexVec<_, _>>()?,
442-
&ReprOptions::default(),
443419
StructKind::AlwaysSized,
444420
)?
445421
}
@@ -448,7 +424,6 @@ fn layout_of_uncached<'tcx>(
448424
let tys = args.as_coroutine_closure().upvar_tys();
449425
univariant(
450426
&tys.iter().map(|ty| cx.layout_of(ty)).try_collect::<IndexVec<_, _>>()?,
451-
&ReprOptions::default(),
452427
StructKind::AlwaysSized,
453428
)?
454429
}
@@ -457,11 +432,7 @@ fn layout_of_uncached<'tcx>(
457432
let kind =
458433
if tys.len() == 0 { StructKind::AlwaysSized } else { StructKind::MaybeUnsized };
459434

460-
univariant(
461-
&tys.iter().map(|k| cx.layout_of(k)).try_collect::<IndexVec<_, _>>()?,
462-
&ReprOptions::default(),
463-
kind,
464-
)?
435+
univariant(&tys.iter().map(|k| cx.layout_of(k)).try_collect::<IndexVec<_, _>>()?, kind)?
465436
}
466437

467438
// SIMD vector types.
@@ -719,25 +690,30 @@ fn layout_of_uncached<'tcx>(
719690
}
720691

721692
// Types with no meaningful known layout.
693+
ty::Param(_) => {
694+
return Err(error(cx, LayoutError::TooGeneric(ty)));
695+
}
696+
722697
ty::Alias(..) => {
723-
if ty.has_param() {
724-
return Err(error(cx, LayoutError::TooGeneric(ty)));
725-
}
726698
// NOTE(eddyb) `layout_of` query should've normalized these away,
727699
// if that was possible, so there's no reason to try again here.
728-
return Err(error(cx, LayoutError::Unknown(ty)));
729-
}
730-
731-
ty::Bound(..) | ty::CoroutineWitness(..) | ty::Infer(_) | ty::Error(_) => {
732-
bug!("Layout::compute: unexpected type `{}`", ty)
733-
}
734-
735-
ty::Param(_) => {
736-
return Err(error(cx, LayoutError::TooGeneric(ty)));
700+
let err = if ty.has_param() {
701+
LayoutError::TooGeneric(ty)
702+
} else {
703+
// This is only reachable with unsatisfiable predicates. For example, if we have
704+
// `u8: Iterator`, then we can't compute the layout of `<u8 as Iterator>::Item`.
705+
LayoutError::Unknown(ty)
706+
};
707+
return Err(error(cx, err));
737708
}
738709

739-
ty::Placeholder(..) => {
740-
return Err(error(cx, LayoutError::Unknown(ty)));
710+
ty::Placeholder(..)
711+
| ty::Bound(..)
712+
| ty::CoroutineWitness(..)
713+
| ty::Infer(_)
714+
| ty::Error(_) => {
715+
// `ty::Error` is handled at the top of this function.
716+
bug!("layout_of: unexpected type `{ty}`")
741717
}
742718
})
743719
}
@@ -911,13 +887,7 @@ fn coroutine_layout<'tcx>(
911887
.chain(iter::once(Ok(tag_layout)))
912888
.chain(promoted_layouts)
913889
.try_collect::<IndexVec<_, _>>()?;
914-
let prefix = univariant_uninterned(
915-
cx,
916-
ty,
917-
&prefix_layouts,
918-
&ReprOptions::default(),
919-
StructKind::AlwaysSized,
920-
)?;
890+
let prefix = univariant_uninterned(cx, ty, &prefix_layouts, StructKind::AlwaysSized)?;
921891

922892
let (prefix_size, prefix_align) = (prefix.size, prefix.align);
923893

@@ -982,7 +952,6 @@ fn coroutine_layout<'tcx>(
982952
cx,
983953
ty,
984954
&variant_only_tys.map(|ty| cx.layout_of(ty)).try_collect::<IndexVec<_, _>>()?,
985-
&ReprOptions::default(),
986955
StructKind::Prefixed(prefix_size, prefix_align.abi),
987956
)?;
988957
variant.variants = Variants::Single { index };

tests/ui/layout/debug.rs

+5
Original file line numberDiff line numberDiff line change
@@ -82,3 +82,8 @@ type Impossible = (str, str); //~ ERROR: cannot be known at compilation time
8282
#[rustc_layout(debug)]
8383
union EmptyUnion {} //~ ERROR: has an unknown layout
8484
//~^ ERROR: unions cannot have zero fields
85+
86+
// Test the error message of `LayoutError::TooGeneric`
87+
// (this error is never emitted to users).
88+
#[rustc_layout(debug)]
89+
type TooGeneric<T> = T; //~ ERROR: does not have a fixed layout

0 commit comments

Comments
 (0)