about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs20
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/tests/coercion.rs25
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/tests/traits.rs12
3 files changed, 20 insertions, 37 deletions
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs b/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs
index 6d4753ea389..c8ff6cba3dd 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs
@@ -768,21 +768,23 @@ pub(crate) fn adt_datum_query(
         phantom_data,
     };
 
-    let variant_id_to_fields = |id: VariantId| {
+    // 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_data = &id.variant_data(db.upcast());
-        let fields = if variant_data.fields().is_empty() || bound_vars_subst.is_empty(Interner) {
+        let fields = if variant_data.fields().is_empty() {
             vec![]
         } else {
-            // 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![]
-            }
+            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()
         };
         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/src/tools/rust-analyzer/crates/hir-ty/src/tests/coercion.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/coercion.rs
index ef94814d587..7e7c1f835c7 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/coercion.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/coercion.rs
@@ -535,7 +535,7 @@ fn test() {
 
 #[test]
 fn coerce_unsize_generic() {
-    check_no_mismatches(
+    check(
         r#"
 //- minicore: coerce_unsized
 struct Foo<T> { t: T };
@@ -543,7 +543,9 @@ 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]>
 }
 "#,
     );
@@ -955,24 +957,3 @@ 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/src/tools/rust-analyzer/crates/hir-ty/src/tests/traits.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/traits.rs
index f0eb41b1ce7..dda7bfb2baf 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/traits.rs
+++ b/src/tools/rust-analyzer/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;
-  //^^^^^^^^^^^^^^^^^^^^{unknown}
+  //^^^^^^^^^^^^^^^^^^^^Yes
     Struct::<*const T>::IS_SEND;
-  //^^^^^^^^^^^^^^^^^^^^^^^^^^^{unknown}
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^^Yes
     Enum::<T>::IS_SEND;
   //^^^^^^^^^^^^^^^^^^Yes
     Enum::<U>::IS_SEND;
-  //^^^^^^^^^^^^^^^^^^{unknown}
+  //^^^^^^^^^^^^^^^^^^Yes
     Enum::<*const T>::IS_SEND;
-  //^^^^^^^^^^^^^^^^^^^^^^^^^{unknown}
+  //^^^^^^^^^^^^^^^^^^^^^^^^^Yes
     Union::<T>::IS_SEND;
   //^^^^^^^^^^^^^^^^^^^Yes
     Union::<U>::IS_SEND;
-  //^^^^^^^^^^^^^^^^^^^{unknown}
+  //^^^^^^^^^^^^^^^^^^^Yes
     Union::<*const T>::IS_SEND;
-  //^^^^^^^^^^^^^^^^^^^^^^^^^^{unknown}
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^Yes
     PhantomData::<T>::IS_SEND;
   //^^^^^^^^^^^^^^^^^^^^^^^^^Yes
     PhantomData::<U>::IS_SEND;