From c14a9b0d7c42bce277b1d08be08ada93c6373a3d Mon Sep 17 00:00:00 2001 From: Yotam Ofek Date: Tue, 24 Aug 2021 19:16:18 +0300 Subject: [PATCH 1/2] Register inherent impls for builtin array type. --- crates/hir_ty/src/method_resolution.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/hir_ty/src/method_resolution.rs b/crates/hir_ty/src/method_resolution.rs index 3d233b1e20ab..eaeab33fc551 100644 --- a/crates/hir_ty/src/method_resolution.rs +++ b/crates/hir_ty/src/method_resolution.rs @@ -348,6 +348,7 @@ pub fn def_crates( } TyKind::Str => lang_item_crate!("str_alloc", "str"), TyKind::Slice(_) => lang_item_crate!("slice_alloc", "slice"), + TyKind::Array(..) => lang_item_crate!("array"), TyKind::Raw(Mutability::Not, _) => lang_item_crate!("const_ptr"), TyKind::Raw(Mutability::Mut, _) => lang_item_crate!("mut_ptr"), TyKind::Dyn(_) => { From 3077ef9d44669e32ee446ea89adf9dbddf86c4a2 Mon Sep 17 00:00:00 2001 From: Yotam Ofek Date: Tue, 24 Aug 2021 19:17:34 +0300 Subject: [PATCH 2/2] Auto-deref arrays as arrays with unknown length. --- crates/hir_ty/src/method_resolution.rs | 20 ++++++++++---- crates/hir_ty/src/tests/method_resolution.rs | 29 ++++++++++++++++++++ 2 files changed, 44 insertions(+), 5 deletions(-) diff --git a/crates/hir_ty/src/method_resolution.rs b/crates/hir_ty/src/method_resolution.rs index eaeab33fc551..b3ab03927e50 100644 --- a/crates/hir_ty/src/method_resolution.rs +++ b/crates/hir_ty/src/method_resolution.rs @@ -16,6 +16,7 @@ use rustc_hash::{FxHashMap, FxHashSet}; use crate::{ autoderef, + consteval::{self, ConstExt}, db::HirDatabase, from_foreign_def_id, primitive::{self, FloatTy, IntTy, UintTy}, @@ -955,12 +956,21 @@ fn autoderef_method_receiver( ) -> Vec> { let mut deref_chain: Vec<_> = autoderef::autoderef(db, Some(krate), ty).collect(); // As a last step, we can do array unsizing (that's the only unsizing that rustc does for method receivers!) - if let Some(TyKind::Array(parameters, _)) = - deref_chain.last().map(|ty| ty.value.kind(&Interner)) + if let Some((TyKind::Array(parameters, array_len), binders)) = + deref_chain.last().map(|ty| (ty.value.kind(&Interner), &ty.binders)) { - let kinds = deref_chain.last().unwrap().binders.clone(); - let unsized_ty = TyKind::Slice(parameters.clone()).intern(&Interner); - deref_chain.push(Canonical { value: unsized_ty, binders: kinds }) + let kinds = binders.clone(); + let parameters = parameters.clone(); + + if !array_len.is_unknown() { + let unknown_array_len_ty = + TyKind::Array(parameters.clone(), consteval::usize_const(None)).intern(&Interner); + let kinds = kinds.clone(); + deref_chain.push(Canonical { value: unknown_array_len_ty, binders: kinds }); + } + + let unsized_ty = TyKind::Slice(parameters).intern(&Interner); + deref_chain.push(Canonical { value: unsized_ty, binders: kinds }); } deref_chain } diff --git a/crates/hir_ty/src/tests/method_resolution.rs b/crates/hir_ty/src/tests/method_resolution.rs index 0c5022730998..5f138b8f979a 100644 --- a/crates/hir_ty/src/tests/method_resolution.rs +++ b/crates/hir_ty/src/tests/method_resolution.rs @@ -1265,6 +1265,35 @@ fn f() { ); } +#[test] +fn resolve_const_generic_array_methods() { + check_types( + r#" +#[lang = "array"] +impl [T; N] { + pub fn map(self, f: F) -> [U; N] + where + F: FnMut(T) -> U, + { loop {} } +} + +#[lang = "slice"] +impl [T] { + pub fn map(self, f: F) -> &[U] + where + F: FnMut(T) -> U, + { loop {} } +} + +fn f() { + let v = [1, 2].map::<_, usize>(|x| -> x * 2); + v; + //^ [usize; _] +} + "#, + ); +} + #[test] fn skip_array_during_method_dispatch() { check_types(