Unnamed repository; edit this file 'description' to name the repository.
Merge pull request #19122 from Austaras/master
pass struct fields to chalk
Lukas Wirth 2025-02-17
parent 09db657 · parent a48cb25 · commit efdfdc4
-rw-r--r--crates/hir-ty/src/chalk_db.rs20
-rw-r--r--crates/hir-ty/src/tests/coercion.rs25
-rw-r--r--crates/hir-ty/src/tests/traits.rs12
3 files changed, 37 insertions, 20 deletions
diff --git a/crates/hir-ty/src/chalk_db.rs b/crates/hir-ty/src/chalk_db.rs
index c8ff6cba3d..6d4753ea38 100644
--- a/crates/hir-ty/src/chalk_db.rs
+++ b/crates/hir-ty/src/chalk_db.rs
@@ -768,23 +768,21 @@ pub(crate) fn adt_datum_query(
phantom_data,
};
- // this slows down rust-analyzer by quite a bit unfortunately, so enabling this is currently not worth it
- let _variant_id_to_fields = |id: VariantId| {
+ let variant_id_to_fields = |id: VariantId| {
let variant_data = &id.variant_data(db.upcast());
- let fields = if variant_data.fields().is_empty() {
+ let fields = if variant_data.fields().is_empty() || bound_vars_subst.is_empty(Interner) {
vec![]
} else {
- let field_types = db.field_types(id);
- variant_data
- .fields()
- .iter()
- .map(|(idx, _)| field_types[idx].clone().substitute(Interner, &bound_vars_subst))
- .filter(|it| !it.contains_unknown())
- .collect()
+ // HACK: provide full struct type info slows down rust-analyzer by quite a bit unfortunately,
+ // so we trick chalk into thinking that our struct impl Unsize
+ if let Some(ty) = bound_vars_subst.at(Interner, 0).ty(Interner) {
+ vec![ty.clone()]
+ } else {
+ vec![]
+ }
};
rust_ir::AdtVariantDatum { fields }
};
- let variant_id_to_fields = |_: VariantId| rust_ir::AdtVariantDatum { fields: vec![] };
let (kind, variants) = match adt_id {
hir_def::AdtId::StructId(id) => {
diff --git a/crates/hir-ty/src/tests/coercion.rs b/crates/hir-ty/src/tests/coercion.rs
index 7e7c1f835c..ef94814d58 100644
--- a/crates/hir-ty/src/tests/coercion.rs
+++ b/crates/hir-ty/src/tests/coercion.rs
@@ -535,7 +535,7 @@ fn test() {
#[test]
fn coerce_unsize_generic() {
- check(
+ check_no_mismatches(
r#"
//- minicore: coerce_unsized
struct Foo<T> { t: T };
@@ -543,9 +543,7 @@ struct Bar<T>(Foo<T>);
fn test() {
let _: &Foo<[usize]> = &Foo { t: [1, 2, 3] };
- //^^^^^^^^^^^^^^^^^^^^^ expected &'? Foo<[usize]>, got &'? Foo<[i32; 3]>
let _: &Bar<[usize]> = &Bar(Foo { t: [1, 2, 3] });
- //^^^^^^^^^^^^^^^^^^^^^^^^^^ expected &'? Bar<[usize]>, got &'? Bar<[i32; 3]>
}
"#,
);
@@ -957,3 +955,24 @@ fn f() {
"#,
);
}
+
+#[test]
+fn coerce_nested_unsized_struct() {
+ check_types(
+ r#"
+//- minicore: fn, coerce_unsized, dispatch_from_dyn, sized
+use core::marker::Unsize;
+
+struct Foo<T: ?Sized>(T);
+
+fn need(_: &Foo<dyn Fn(i32) -> i32>) {
+}
+
+fn test() {
+ let callback = |x| x;
+ //^ i32
+ need(&Foo(callback));
+}
+"#,
+ )
+}
diff --git a/crates/hir-ty/src/tests/traits.rs b/crates/hir-ty/src/tests/traits.rs
index dda7bfb2ba..f0eb41b1ce 100644
--- a/crates/hir-ty/src/tests/traits.rs
+++ b/crates/hir-ty/src/tests/traits.rs
@@ -4694,21 +4694,21 @@ fn f<T: Send, U>() {
Struct::<T>::IS_SEND;
//^^^^^^^^^^^^^^^^^^^^Yes
Struct::<U>::IS_SEND;
- //^^^^^^^^^^^^^^^^^^^^Yes
+ //^^^^^^^^^^^^^^^^^^^^{unknown}
Struct::<*const T>::IS_SEND;
- //^^^^^^^^^^^^^^^^^^^^^^^^^^^Yes
+ //^^^^^^^^^^^^^^^^^^^^^^^^^^^{unknown}
Enum::<T>::IS_SEND;
//^^^^^^^^^^^^^^^^^^Yes
Enum::<U>::IS_SEND;
- //^^^^^^^^^^^^^^^^^^Yes
+ //^^^^^^^^^^^^^^^^^^{unknown}
Enum::<*const T>::IS_SEND;
- //^^^^^^^^^^^^^^^^^^^^^^^^^Yes
+ //^^^^^^^^^^^^^^^^^^^^^^^^^{unknown}
Union::<T>::IS_SEND;
//^^^^^^^^^^^^^^^^^^^Yes
Union::<U>::IS_SEND;
- //^^^^^^^^^^^^^^^^^^^Yes
+ //^^^^^^^^^^^^^^^^^^^{unknown}
Union::<*const T>::IS_SEND;
- //^^^^^^^^^^^^^^^^^^^^^^^^^^Yes
+ //^^^^^^^^^^^^^^^^^^^^^^^^^^{unknown}
PhantomData::<T>::IS_SEND;
//^^^^^^^^^^^^^^^^^^^^^^^^^Yes
PhantomData::<U>::IS_SEND;