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 c8ff6cba3dd..6d4753ea389 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,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/src/tools/rust-analyzer/crates/hir-ty/src/tests/coercion.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/coercion.rs index 7e7c1f835c7..ef94814d587 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( + check_no_mismatches( r#" //- minicore: coerce_unsized struct Foo { t: T }; @@ -543,9 +543,7 @@ struct Bar(Foo); 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); + +fn need(_: &Foo 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 dda7bfb2baf..f0eb41b1ce7 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() { Struct::::IS_SEND; //^^^^^^^^^^^^^^^^^^^^Yes Struct::::IS_SEND; - //^^^^^^^^^^^^^^^^^^^^Yes + //^^^^^^^^^^^^^^^^^^^^{unknown} Struct::<*const T>::IS_SEND; - //^^^^^^^^^^^^^^^^^^^^^^^^^^^Yes + //^^^^^^^^^^^^^^^^^^^^^^^^^^^{unknown} Enum::::IS_SEND; //^^^^^^^^^^^^^^^^^^Yes Enum::::IS_SEND; - //^^^^^^^^^^^^^^^^^^Yes + //^^^^^^^^^^^^^^^^^^{unknown} Enum::<*const T>::IS_SEND; - //^^^^^^^^^^^^^^^^^^^^^^^^^Yes + //^^^^^^^^^^^^^^^^^^^^^^^^^{unknown} Union::::IS_SEND; //^^^^^^^^^^^^^^^^^^^Yes Union::::IS_SEND; - //^^^^^^^^^^^^^^^^^^^Yes + //^^^^^^^^^^^^^^^^^^^{unknown} Union::<*const T>::IS_SEND; - //^^^^^^^^^^^^^^^^^^^^^^^^^^Yes + //^^^^^^^^^^^^^^^^^^^^^^^^^^{unknown} PhantomData::::IS_SEND; //^^^^^^^^^^^^^^^^^^^^^^^^^Yes PhantomData::::IS_SEND;