Unnamed repository; edit this file 'description' to name the repository.
Auto merge of #15173 - HKalbasi:mir, r=HKalbasi
Fix data layout of reference to nested unsized structs
bors 2023-06-30
parent b9c3d09 · parent 302bb3c · commit 769c80d
-rw-r--r--crates/hir-ty/src/consteval/tests.rs31
-rw-r--r--crates/hir-ty/src/layout.rs5
-rw-r--r--crates/hir-ty/src/layout/tests.rs18
3 files changed, 53 insertions, 1 deletions
diff --git a/crates/hir-ty/src/consteval/tests.rs b/crates/hir-ty/src/consteval/tests.rs
index de3a947f35..e50dfdf965 100644
--- a/crates/hir-ty/src/consteval/tests.rs
+++ b/crates/hir-ty/src/consteval/tests.rs
@@ -2491,6 +2491,37 @@ fn type_error() {
}
#[test]
+fn unsized_field() {
+ check_number(
+ r#"
+ //- minicore: coerce_unsized, index, slice, transmute
+ use core::mem::transmute;
+
+ struct Slice([u8]);
+ struct Slice2(Slice);
+
+ impl Slice2 {
+ fn as_inner(&self) -> &Slice {
+ &self.0
+ }
+
+ fn as_bytes(&self) -> &[u8] {
+ &self.as_inner().0
+ }
+ }
+
+ const GOAL: u8 = unsafe {
+ let x: &[u8] = &[1, 2, 3];
+ let x: &Slice2 = transmute(x);
+ let x = x.as_bytes();
+ x[0] + x[1] + x[2]
+ };
+ "#,
+ 6,
+ );
+}
+
+#[test]
fn unsized_local() {
check_fail(
r#"
diff --git a/crates/hir-ty/src/layout.rs b/crates/hir-ty/src/layout.rs
index 35d3407c16..a566c06a54 100644
--- a/crates/hir-ty/src/layout.rs
+++ b/crates/hir-ty/src/layout.rs
@@ -315,7 +315,10 @@ fn struct_tail_erasing_lifetimes(db: &dyn HirDatabase, pointee: Ty) -> Ty {
let data = db.struct_data(*i);
let mut it = data.variant_data.fields().iter().rev();
match it.next() {
- Some((f, _)) => field_ty(db, (*i).into(), f, subst),
+ Some((f, _)) => {
+ let last_field_ty = field_ty(db, (*i).into(), f, subst);
+ struct_tail_erasing_lifetimes(db, last_field_ty)
+ }
None => pointee,
}
}
diff --git a/crates/hir-ty/src/layout/tests.rs b/crates/hir-ty/src/layout/tests.rs
index b75f213df2..0257aef7a4 100644
--- a/crates/hir-ty/src/layout/tests.rs
+++ b/crates/hir-ty/src/layout/tests.rs
@@ -344,6 +344,24 @@ fn return_position_impl_trait() {
}
#[test]
+fn unsized_ref() {
+ size_and_align! {
+ struct S1([u8]);
+ struct S2(S1);
+ struct S3(i32, str);
+ struct S4(u64, S3);
+ #[allow(dead_code)]
+ struct S5 {
+ field1: u8,
+ field2: i16,
+ field_last: S4,
+ }
+
+ struct Goal(&'static S1, &'static S2, &'static S3, &'static S4, &'static S5);
+ }
+}
+
+#[test]
fn enums() {
size_and_align! {
enum Goal {