about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--crates/hir-ty/src/autoderef.rs2
-rw-r--r--crates/hir-ty/src/method_resolution.rs32
-rw-r--r--crates/hir-ty/src/tests/method_resolution.rs3
-rw-r--r--crates/test-utils/src/minicore.rs18
4 files changed, 40 insertions, 15 deletions
diff --git a/crates/hir-ty/src/autoderef.rs b/crates/hir-ty/src/autoderef.rs
index caddca6d915..58744dd0c0f 100644
--- a/crates/hir-ty/src/autoderef.rs
+++ b/crates/hir-ty/src/autoderef.rs
@@ -17,11 +17,13 @@ use crate::{
 
 static AUTODEREF_RECURSION_LIMIT: Limit = Limit::new(10);
 
+#[derive(Debug)]
 pub(crate) enum AutoderefKind {
     Builtin,
     Overloaded,
 }
 
+#[derive(Debug)]
 pub(crate) struct Autoderef<'a, 'db> {
     pub(crate) table: &'a mut InferenceTable<'db>,
     ty: Ty,
diff --git a/crates/hir-ty/src/method_resolution.rs b/crates/hir-ty/src/method_resolution.rs
index 858de000596..8c7714b9a69 100644
--- a/crates/hir-ty/src/method_resolution.rs
+++ b/crates/hir-ty/src/method_resolution.rs
@@ -5,7 +5,7 @@
 use std::{ops::ControlFlow, sync::Arc};
 
 use base_db::{CrateId, Edition};
-use chalk_ir::{cast::Cast, Mutability, UniverseIndex};
+use chalk_ir::{cast::Cast, Mutability, TyKind, UniverseIndex};
 use hir_def::{
     data::ImplData, item_scope::ItemScope, lang_item::LangItem, nameres::DefMap, AssocItemId,
     BlockId, ConstId, FunctionId, HasModule, ImplId, ItemContainerId, Lookup, ModuleDefId,
@@ -25,7 +25,7 @@ use crate::{
     static_lifetime, to_chalk_trait_id,
     utils::all_super_traits,
     AdtId, Canonical, CanonicalVarKinds, DebruijnIndex, ForeignDefId, InEnvironment, Interner,
-    Scalar, Substitution, TraitEnvironment, TraitRef, TraitRefExt, Ty, TyBuilder, TyExt, TyKind,
+    Scalar, Substitution, TraitEnvironment, TraitRef, TraitRefExt, Ty, TyBuilder, TyExt,
 };
 
 /// This is used as a key for indexing impls.
@@ -588,25 +588,31 @@ impl ReceiverAdjustments {
                 }
             }
         }
+        if let Some(m) = self.autoref {
+            ty = TyKind::Ref(m, static_lifetime(), ty).intern(Interner);
+            adjust
+                .push(Adjustment { kind: Adjust::Borrow(AutoBorrow::Ref(m)), target: ty.clone() });
+        }
         if self.unsize_array {
-            ty = match ty.kind(Interner) {
-                TyKind::Array(inner, _) => TyKind::Slice(inner.clone()).intern(Interner),
-                _ => {
-                    never!("unsize_array with non-array {:?}", ty);
-                    ty
+            ty = 'x: {
+                if let TyKind::Ref(m, l, inner) = ty.kind(Interner) {
+                    if let TyKind::Array(inner, _) = inner.kind(Interner) {
+                        break 'x TyKind::Ref(
+                            m.clone(),
+                            l.clone(),
+                            TyKind::Slice(inner.clone()).intern(Interner),
+                        )
+                        .intern(Interner);
+                    }
                 }
+                never!("unsize_array with non-reference-to-array {:?}", ty);
+                ty
             };
-            // FIXME this is kind of wrong since the unsize needs to happen to a pointer/reference
             adjust.push(Adjustment {
                 kind: Adjust::Pointer(PointerCast::Unsize),
                 target: ty.clone(),
             });
         }
-        if let Some(m) = self.autoref {
-            ty = TyKind::Ref(m, static_lifetime(), ty).intern(Interner);
-            adjust
-                .push(Adjustment { kind: Adjust::Borrow(AutoBorrow::Ref(m)), target: ty.clone() });
-        }
         (ty, adjust)
     }
 
diff --git a/crates/hir-ty/src/tests/method_resolution.rs b/crates/hir-ty/src/tests/method_resolution.rs
index 616ca8058e9..42fb685abf9 100644
--- a/crates/hir-ty/src/tests/method_resolution.rs
+++ b/crates/hir-ty/src/tests/method_resolution.rs
@@ -1725,14 +1725,13 @@ fn test() {
 
 #[test]
 fn receiver_adjustment_unsize_array() {
-    // FIXME not quite correct
     check(
         r#"
 //- minicore: slice
 fn test() {
     let a = [1, 2, 3];
     a.len();
-} //^ adjustments: Pointer(Unsize), Borrow(Ref(Not))
+} //^ adjustments: Borrow(Ref(Not)), Pointer(Unsize)
 "#,
     );
 }
diff --git a/crates/test-utils/src/minicore.rs b/crates/test-utils/src/minicore.rs
index dff60914409..5634bafd062 100644
--- a/crates/test-utils/src/minicore.rs
+++ b/crates/test-utils/src/minicore.rs
@@ -273,6 +273,24 @@ pub mod ops {
             }
         }
 
+        impl<T, I, const N: usize> Index<I> for [T; N]
+        where
+            I: SliceIndex<[T]>,
+        {
+            type Output = I::Output;
+            fn index(&self, index: I) -> &I::Output {
+                loop {}
+            }
+        }
+        impl<T, I, const N: usize> IndexMut<I> for [T; N]
+        where
+            I: SliceIndex<[T]>,
+        {
+            fn index_mut(&mut self, index: I) -> &mut I::Output {
+                loop {}
+            }
+        }
+
         pub unsafe trait SliceIndex<T: ?Sized> {
             type Output: ?Sized;
         }