Unnamed repository; edit this file 'description' to name the repository.
Don't implement sizedness check via `all_field_tys()`
Since we don't implement it currently for perf reasons, but here we only need a struct's tail field, it will be wrong.
Chayim Refael Friedman 5 months ago
parent d4f45d7 · commit 3172d19
-rw-r--r--crates/hir-ty/src/next_solver/interner.rs13
-rw-r--r--crates/hir-ty/src/next_solver/util.rs8
-rw-r--r--crates/hir-ty/src/tests/method_resolution.rs29
3 files changed, 36 insertions, 14 deletions
diff --git a/crates/hir-ty/src/next_solver/interner.rs b/crates/hir-ty/src/next_solver/interner.rs
index 2e52dcea6c..e77b77bf4a 100644
--- a/crates/hir-ty/src/next_solver/interner.rs
+++ b/crates/hir-ty/src/next_solver/interner.rs
@@ -690,15 +690,10 @@ impl<'db> inherent::AdtDef<DbInterner<'db>> for AdtDef {
interner: DbInterner<'db>,
sizedness: SizedTraitKind,
) -> Option<EarlyBinder<DbInterner<'db>, Ty<'db>>> {
- if self.is_struct() {
- let tail_ty = self.all_field_tys(interner).skip_binder().into_iter().last()?;
-
- let constraint_ty = sizedness_constraint_for_ty(interner, sizedness, tail_ty)?;
-
- Some(EarlyBinder::bind(constraint_ty))
- } else {
- None
- }
+ let tail_ty = self.struct_tail_ty(interner)?;
+ tail_ty
+ .map_bound(|tail_ty| sizedness_constraint_for_ty(interner, sizedness, tail_ty))
+ .transpose()
}
fn destructor(
diff --git a/crates/hir-ty/src/next_solver/util.rs b/crates/hir-ty/src/next_solver/util.rs
index 972c8e2da7..bc4b5fdbfc 100644
--- a/crates/hir-ty/src/next_solver/util.rs
+++ b/crates/hir-ty/src/next_solver/util.rs
@@ -422,12 +422,10 @@ pub fn sizedness_constraint_for_ty<'db>(
.next_back()
.and_then(|ty| sizedness_constraint_for_ty(interner, sizedness, ty)),
- Adt(adt, args) => {
- let tail_ty =
- EarlyBinder::bind(adt.all_field_tys(interner).skip_binder().into_iter().last()?)
- .instantiate(interner, args);
+ Adt(adt, args) => adt.struct_tail_ty(interner).and_then(|tail_ty| {
+ let tail_ty = tail_ty.instantiate(interner, args);
sizedness_constraint_for_ty(interner, sizedness, tail_ty)
- }
+ }),
Placeholder(..) | Bound(..) | Infer(..) => {
panic!("unexpected type `{ty:?}` in sizedness_constraint_for_ty")
diff --git a/crates/hir-ty/src/tests/method_resolution.rs b/crates/hir-ty/src/tests/method_resolution.rs
index 274d33a211..c8ed8aa258 100644
--- a/crates/hir-ty/src/tests/method_resolution.rs
+++ b/crates/hir-ty/src/tests/method_resolution.rs
@@ -2229,3 +2229,32 @@ fn test(x: *mut u8) {
"#,
);
}
+
+#[test]
+fn unsized_struct() {
+ check_types(
+ r#"
+//- minicore: sized, phantom_data
+use core::marker::PhantomData;
+
+const UI_DEV_CREATE: Ioctl = Ioctl(PhantomData);
+
+struct Ioctl<T: ?Sized = NoArgs>(PhantomData<T>);
+
+struct NoArgs([u8]);
+
+impl<T> Ioctl<T> {
+ fn ioctl(self) {}
+}
+
+impl Ioctl<NoArgs> {
+ fn ioctl(self) -> u32 { 0 }
+}
+
+fn main() {
+ UI_DEV_CREATE.ioctl();
+ // ^^^^^^^^^^^^^^^^^^^^^ u32
+}
+ "#,
+ );
+}