Skip to content

Commit 705d602

Browse files
committed
Auto merge of #129970 - lukas-code:LayoutCalculator, r=compiler-errors
layout computation: gracefully handle unsized types in unexpected locations This PR reworks the layout computation to eagerly return an error when encountering an unsized field where a sized field was expected, rather than delaying a bug and attempting to recover a layout. This is required, because with trivially false where clauses like `[T]: Sized`, any field can possible be an unsized type, without causing a compile error. Since this PR removes the `delayed_bug` method from the `LayoutCalculator` trait, it essentially becomes the same as the `HasDataLayout` trait, so I've also refactored the `LayoutCalculator` to be a simple wrapper struct around a type that implements `HasDataLayout`. The majority of the diff is whitespace changes, so viewing with whitespace ignored is advised. implements rust-lang/rust#123169 (comment) r? `@compiler-errors` or compiler fixes rust-lang/rust#123134 fixes rust-lang/rust#124182 fixes rust-lang/rust#126939 fixes rust-lang/rust#127737
2 parents 4e34f33 + cd442a0 commit 705d602

File tree

2 files changed

+40
-38
lines changed

2 files changed

+40
-38
lines changed

crates/hir-ty/src/layout.rs

Lines changed: 34 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,20 @@
11
//! Compute the binary representation of a type
22
3-
use std::{borrow::Cow, fmt};
3+
use std::fmt;
44

55
use base_db::salsa::Cycle;
66
use chalk_ir::{AdtId, FloatTy, IntTy, TyKind, UintTy};
77
use hir_def::{
88
layout::{
9-
Abi, FieldsShape, Float, Integer, LayoutCalculator, LayoutS, Primitive, ReprOptions,
10-
Scalar, Size, StructKind, TargetDataLayout, WrappingRange,
9+
Abi, FieldsShape, Float, Integer, LayoutCalculator, LayoutCalculatorError, LayoutS,
10+
Primitive, ReprOptions, Scalar, Size, StructKind, TargetDataLayout, WrappingRange,
1111
},
1212
LocalFieldId, StructId,
1313
};
1414
use la_arena::{Idx, RawIdx};
1515
use rustc_abi::AddressSpace;
1616
use rustc_index::{IndexSlice, IndexVec};
1717

18-
use stdx::never;
1918
use triomphe::Arc;
2019

2120
use crate::{
@@ -107,19 +106,24 @@ impl fmt::Display for LayoutError {
107106
}
108107
}
109108

110-
struct LayoutCx<'a> {
111-
target: &'a TargetDataLayout,
109+
impl<F> From<LayoutCalculatorError<F>> for LayoutError {
110+
fn from(err: LayoutCalculatorError<F>) -> Self {
111+
match err {
112+
LayoutCalculatorError::UnexpectedUnsized(_) | LayoutCalculatorError::EmptyUnion => {
113+
LayoutError::Unknown
114+
}
115+
LayoutCalculatorError::SizeOverflow => LayoutError::SizeOverflow,
116+
}
117+
}
112118
}
113119

114-
impl<'a> LayoutCalculator for LayoutCx<'a> {
115-
type TargetDataLayoutRef = &'a TargetDataLayout;
116-
117-
fn delayed_bug(&self, txt: impl Into<Cow<'static, str>>) {
118-
never!("{}", txt.into());
119-
}
120+
struct LayoutCx<'a> {
121+
calc: LayoutCalculator<&'a TargetDataLayout>,
122+
}
120123

121-
fn current_data_layout(&self) -> &'a TargetDataLayout {
122-
self.target
124+
impl<'a> LayoutCx<'a> {
125+
fn new(target: &'a TargetDataLayout) -> Self {
126+
Self { calc: LayoutCalculator::new(target) }
123127
}
124128
}
125129

@@ -205,8 +209,8 @@ pub fn layout_of_ty_query(
205209
let Ok(target) = db.target_data_layout(krate) else {
206210
return Err(LayoutError::TargetLayoutNotAvailable);
207211
};
208-
let cx = LayoutCx { target: &target };
209-
let dl = cx.current_data_layout();
212+
let dl = &*target;
213+
let cx = LayoutCx::new(dl);
210214
let ty = normalize(db, trait_env.clone(), ty);
211215
let result = match ty.kind(Interner) {
212216
TyKind::Adt(AdtId(def), subst) => {
@@ -281,7 +285,7 @@ pub fn layout_of_ty_query(
281285
.collect::<Result<Vec<_>, _>>()?;
282286
let fields = fields.iter().map(|it| &**it).collect::<Vec<_>>();
283287
let fields = fields.iter().collect::<IndexVec<_, _>>();
284-
cx.univariant(dl, &fields, &ReprOptions::default(), kind).ok_or(LayoutError::Unknown)?
288+
cx.calc.univariant(&fields, &ReprOptions::default(), kind)?
285289
}
286290
TyKind::Array(element, count) => {
287291
let count = try_const_usize(db, count).ok_or(LayoutError::HasErrorConst)? as u64;
@@ -367,12 +371,12 @@ pub fn layout_of_ty_query(
367371
};
368372

369373
// Effectively a (ptr, meta) tuple.
370-
cx.scalar_pair(data_ptr, metadata)
374+
cx.calc.scalar_pair(data_ptr, metadata)
371375
}
372-
TyKind::FnDef(_, _) => layout_of_unit(&cx, dl)?,
373-
TyKind::Never => cx.layout_of_never_type(),
376+
TyKind::FnDef(_, _) => layout_of_unit(&cx)?,
377+
TyKind::Never => cx.calc.layout_of_never_type(),
374378
TyKind::Dyn(_) | TyKind::Foreign(_) => {
375-
let mut unit = layout_of_unit(&cx, dl)?;
379+
let mut unit = layout_of_unit(&cx)?;
376380
match &mut unit.abi {
377381
Abi::Aggregate { sized } => *sized = false,
378382
_ => return Err(LayoutError::Unknown),
@@ -414,8 +418,7 @@ pub fn layout_of_ty_query(
414418
.collect::<Result<Vec<_>, _>>()?;
415419
let fields = fields.iter().map(|it| &**it).collect::<Vec<_>>();
416420
let fields = fields.iter().collect::<IndexVec<_, _>>();
417-
cx.univariant(dl, &fields, &ReprOptions::default(), StructKind::AlwaysSized)
418-
.ok_or(LayoutError::Unknown)?
421+
cx.calc.univariant(&fields, &ReprOptions::default(), StructKind::AlwaysSized)?
419422
}
420423
TyKind::Coroutine(_, _) | TyKind::CoroutineWitness(_, _) => {
421424
return Err(LayoutError::NotImplemented)
@@ -447,14 +450,14 @@ pub fn layout_of_ty_recover(
447450
Err(LayoutError::RecursiveTypeWithoutIndirection)
448451
}
449452

450-
fn layout_of_unit(cx: &LayoutCx<'_>, dl: &TargetDataLayout) -> Result<Layout, LayoutError> {
451-
cx.univariant::<RustcFieldIdx, RustcEnumVariantIdx, &&Layout>(
452-
dl,
453-
IndexSlice::empty(),
454-
&ReprOptions::default(),
455-
StructKind::AlwaysSized,
456-
)
457-
.ok_or(LayoutError::Unknown)
453+
fn layout_of_unit(cx: &LayoutCx<'_>) -> Result<Layout, LayoutError> {
454+
cx.calc
455+
.univariant::<RustcFieldIdx, RustcEnumVariantIdx, &&Layout>(
456+
IndexSlice::empty(),
457+
&ReprOptions::default(),
458+
StructKind::AlwaysSized,
459+
)
460+
.map_err(Into::into)
458461
}
459462

460463
fn struct_tail_erasing_lifetimes(db: &dyn HirDatabase, pointee: Ty) -> Ty {

crates/hir-ty/src/layout/adt.rs

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use std::{cmp, ops::Bound};
55
use base_db::salsa::Cycle;
66
use hir_def::{
77
data::adt::VariantData,
8-
layout::{Integer, LayoutCalculator, ReprOptions, TargetDataLayout},
8+
layout::{Integer, ReprOptions, TargetDataLayout},
99
AdtId, VariantId,
1010
};
1111
use intern::sym;
@@ -36,8 +36,8 @@ pub fn layout_of_adt_query(
3636
let Ok(target) = db.target_data_layout(krate) else {
3737
return Err(LayoutError::TargetLayoutNotAvailable);
3838
};
39-
let cx = LayoutCx { target: &target };
40-
let dl = cx.current_data_layout();
39+
let dl = &*target;
40+
let cx = LayoutCx::new(dl);
4141
let handle_variant = |def: VariantId, var: &VariantData| {
4242
var.fields()
4343
.iter()
@@ -73,9 +73,9 @@ pub fn layout_of_adt_query(
7373
.collect::<SmallVec<[_; 1]>>();
7474
let variants = variants.iter().map(|it| it.iter().collect()).collect::<IndexVec<_, _>>();
7575
let result = if matches!(def, AdtId::UnionId(..)) {
76-
cx.layout_of_union(&repr, &variants).ok_or(LayoutError::Unknown)?
76+
cx.calc.layout_of_union(&repr, &variants)?
7777
} else {
78-
cx.layout_of_struct_or_enum(
78+
cx.calc.layout_of_struct_or_enum(
7979
&repr,
8080
&variants,
8181
matches!(def, AdtId::EnumId(..)),
@@ -103,8 +103,7 @@ pub fn layout_of_adt_query(
103103
.next()
104104
.and_then(|it| it.iter().last().map(|it| !it.is_unsized()))
105105
.unwrap_or(true),
106-
)
107-
.ok_or(LayoutError::SizeOverflow)?
106+
)?
108107
};
109108
Ok(Arc::new(result))
110109
}

0 commit comments

Comments
 (0)