diff --git a/crates/hir-ty/src/autoderef.rs b/crates/hir-ty/src/autoderef.rs index caddca6d91..58744dd0c0 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 858de00059..8c7714b9a6 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 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 - } - }; - // 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() }); } + if self.unsize_array { + 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 + }; + adjust.push(Adjustment { + kind: Adjust::Pointer(PointerCast::Unsize), + 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 616ca8058e..42fb685abf 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 dff6091440..5634bafd06 100644 --- a/crates/test-utils/src/minicore.rs +++ b/crates/test-utils/src/minicore.rs @@ -273,6 +273,24 @@ pub mod ops { } } + impl Index for [T; N] + where + I: SliceIndex<[T]>, + { + type Output = I::Output; + fn index(&self, index: I) -> &I::Output { + loop {} + } + } + impl IndexMut for [T; N] + where + I: SliceIndex<[T]>, + { + fn index_mut(&mut self, index: I) -> &mut I::Output { + loop {} + } + } + pub unsafe trait SliceIndex { type Output: ?Sized; }