From 9e7a6bd66e308da6856d7f7f1eae51c45f786d86 Mon Sep 17 00:00:00 2001 From: Shotaro Yamada Date: Tue, 25 Jun 2019 02:17:44 +0900 Subject: Method resolution for slices --- crates/ra_hir/src/ty/method_resolution.rs | 61 ++++++++++++++++++------------- 1 file changed, 36 insertions(+), 25 deletions(-) diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir/src/ty/method_resolution.rs index 46ec136bd..080ba1ef6 100644 --- a/crates/ra_hir/src/ty/method_resolution.rs +++ b/crates/ra_hir/src/ty/method_resolution.rs @@ -4,6 +4,7 @@ //! and the corresponding code mostly in librustc_typeck/check/method/probe.rs. use std::sync::Arc; +use arrayvec::ArrayVec; use rustc_hash::FxHashMap; use crate::{ @@ -113,19 +114,30 @@ impl CrateImplBlocks { } } -fn def_crate(db: &impl HirDatabase, cur_crate: Crate, ty: &Ty) -> Option { +fn def_crates(db: &impl HirDatabase, cur_crate: Crate, ty: &Ty) -> Option> { + macro_rules! lang_item_crate { + ($db:expr, $cur_crate:expr, $($name:expr),+ $(,)?) => {{ + let mut v = ArrayVec::<[Crate; 2]>::new(); + $( + v.push($db.lang_item($cur_crate, $name.into())?.krate($db)?); + )+ + Some(v) + }}; + } + match ty { Ty::Apply(a_ty) => match a_ty.ctor { - TypeCtor::Adt(def_id) => def_id.krate(db), - TypeCtor::Bool => db.lang_item(cur_crate, "bool".into())?.krate(db), - TypeCtor::Char => db.lang_item(cur_crate, "char".into())?.krate(db), + TypeCtor::Adt(def_id) => Some(std::iter::once(def_id.krate(db)?).collect()), + TypeCtor::Bool => lang_item_crate![db, cur_crate, "bool"], + TypeCtor::Char => lang_item_crate![db, cur_crate, "char"], TypeCtor::Float(UncertainFloatTy::Known(f)) => { - db.lang_item(cur_crate, f.ty_to_string().into())?.krate(db) + lang_item_crate![db, cur_crate, f.ty_to_string()] } TypeCtor::Int(UncertainIntTy::Known(i)) => { - db.lang_item(cur_crate, i.ty_to_string().into())?.krate(db) + lang_item_crate![db, cur_crate, i.ty_to_string()] } - TypeCtor::Str => db.lang_item(cur_crate, "str".into())?.krate(db), + TypeCtor::Str => lang_item_crate![db, cur_crate, "str"], + TypeCtor::Slice => lang_item_crate![db, cur_crate, "slice_alloc", "slice"], _ => None, }, _ => None, @@ -218,19 +230,17 @@ fn iterate_inherent_methods( krate: Crate, mut callback: impl FnMut(&Ty, Function) -> Option, ) -> Option { - let krate = match def_crate(db, krate, &ty.value) { - Some(krate) => krate, - None => return None, - }; - let impls = db.impls_in_crate(krate); + for krate in def_crates(db, krate, &ty.value)? { + let impls = db.impls_in_crate(krate); - for impl_block in impls.lookup_impl_blocks(&ty.value) { - for item in impl_block.items(db) { - if let ImplItem::Method(f) = item { - let data = f.data(db); - if name.map_or(true, |name| data.name() == name) && data.has_self_param() { - if let Some(result) = callback(&ty.value, f) { - return Some(result); + for impl_block in impls.lookup_impl_blocks(&ty.value) { + for item in impl_block.items(db) { + if let ImplItem::Method(f) = item { + let data = f.data(db); + if name.map_or(true, |name| data.name() == name) && data.has_self_param() { + if let Some(result) = callback(&ty.value, f) { + return Some(result); + } } } } @@ -248,13 +258,14 @@ impl Ty { krate: Crate, mut callback: impl FnMut(ImplItem) -> Option, ) -> Option { - let krate = def_crate(db, krate, &self)?; - let impls = db.impls_in_crate(krate); + for krate in def_crates(db, krate, &self)? { + let impls = db.impls_in_crate(krate); - for impl_block in impls.lookup_impl_blocks(&self) { - for item in impl_block.items(db) { - if let Some(result) = callback(item) { - return Some(result); + for impl_block in impls.lookup_impl_blocks(&self) { + for item in impl_block.items(db) { + if let Some(result) = callback(item) { + return Some(result); + } } } } -- cgit v1.2.3 From 9668737d0595874c9cf287c81f8026d320290c35 Mon Sep 17 00:00:00 2001 From: Shotaro Yamada Date: Tue, 25 Jun 2019 20:57:42 +0900 Subject: Add comment --- crates/ra_hir/src/ty/method_resolution.rs | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir/src/ty/method_resolution.rs index 080ba1ef6..e023ff25a 100644 --- a/crates/ra_hir/src/ty/method_resolution.rs +++ b/crates/ra_hir/src/ty/method_resolution.rs @@ -115,6 +115,8 @@ impl CrateImplBlocks { } fn def_crates(db: &impl HirDatabase, cur_crate: Crate, ty: &Ty) -> Option> { + // Types like slice can have inherent impls in several crates, (core and alloc). + // The correspoinding impls are marked with lang items, so we can use them to find the required crates. macro_rules! lang_item_crate { ($db:expr, $cur_crate:expr, $($name:expr),+ $(,)?) => {{ let mut v = ArrayVec::<[Crate; 2]>::new(); @@ -128,16 +130,16 @@ fn def_crates(db: &impl HirDatabase, cur_crate: Crate, ty: &Ty) -> Option match a_ty.ctor { TypeCtor::Adt(def_id) => Some(std::iter::once(def_id.krate(db)?).collect()), - TypeCtor::Bool => lang_item_crate![db, cur_crate, "bool"], - TypeCtor::Char => lang_item_crate![db, cur_crate, "char"], + TypeCtor::Bool => lang_item_crate!(db, cur_crate, "bool"), + TypeCtor::Char => lang_item_crate!(db, cur_crate, "char"), TypeCtor::Float(UncertainFloatTy::Known(f)) => { - lang_item_crate![db, cur_crate, f.ty_to_string()] + lang_item_crate!(db, cur_crate, f.ty_to_string()) } TypeCtor::Int(UncertainIntTy::Known(i)) => { - lang_item_crate![db, cur_crate, i.ty_to_string()] + lang_item_crate!(db, cur_crate, i.ty_to_string()) } - TypeCtor::Str => lang_item_crate![db, cur_crate, "str"], - TypeCtor::Slice => lang_item_crate![db, cur_crate, "slice_alloc", "slice"], + TypeCtor::Str => lang_item_crate!(db, cur_crate, "str"), + TypeCtor::Slice => lang_item_crate!(db, cur_crate, "slice_alloc", "slice"), _ => None, }, _ => None, -- cgit v1.2.3