diff options
-rw-r--r-- | crates/ra_hir/src/ty/method_resolution.rs | 63 |
1 files changed, 38 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..e023ff25a 100644 --- a/crates/ra_hir/src/ty/method_resolution.rs +++ b/crates/ra_hir/src/ty/method_resolution.rs | |||
@@ -4,6 +4,7 @@ | |||
4 | //! and the corresponding code mostly in librustc_typeck/check/method/probe.rs. | 4 | //! and the corresponding code mostly in librustc_typeck/check/method/probe.rs. |
5 | use std::sync::Arc; | 5 | use std::sync::Arc; |
6 | 6 | ||
7 | use arrayvec::ArrayVec; | ||
7 | use rustc_hash::FxHashMap; | 8 | use rustc_hash::FxHashMap; |
8 | 9 | ||
9 | use crate::{ | 10 | use crate::{ |
@@ -113,19 +114,32 @@ impl CrateImplBlocks { | |||
113 | } | 114 | } |
114 | } | 115 | } |
115 | 116 | ||
116 | fn def_crate(db: &impl HirDatabase, cur_crate: Crate, ty: &Ty) -> Option<Crate> { | 117 | fn def_crates(db: &impl HirDatabase, cur_crate: Crate, ty: &Ty) -> Option<ArrayVec<[Crate; 2]>> { |
118 | // Types like slice can have inherent impls in several crates, (core and alloc). | ||
119 | // The correspoinding impls are marked with lang items, so we can use them to find the required crates. | ||
120 | macro_rules! lang_item_crate { | ||
121 | ($db:expr, $cur_crate:expr, $($name:expr),+ $(,)?) => {{ | ||
122 | let mut v = ArrayVec::<[Crate; 2]>::new(); | ||
123 | $( | ||
124 | v.push($db.lang_item($cur_crate, $name.into())?.krate($db)?); | ||
125 | )+ | ||
126 | Some(v) | ||
127 | }}; | ||
128 | } | ||
129 | |||
117 | match ty { | 130 | match ty { |
118 | Ty::Apply(a_ty) => match a_ty.ctor { | 131 | Ty::Apply(a_ty) => match a_ty.ctor { |
119 | TypeCtor::Adt(def_id) => def_id.krate(db), | 132 | TypeCtor::Adt(def_id) => Some(std::iter::once(def_id.krate(db)?).collect()), |
120 | TypeCtor::Bool => db.lang_item(cur_crate, "bool".into())?.krate(db), | 133 | TypeCtor::Bool => lang_item_crate!(db, cur_crate, "bool"), |
121 | TypeCtor::Char => db.lang_item(cur_crate, "char".into())?.krate(db), | 134 | TypeCtor::Char => lang_item_crate!(db, cur_crate, "char"), |
122 | TypeCtor::Float(UncertainFloatTy::Known(f)) => { | 135 | TypeCtor::Float(UncertainFloatTy::Known(f)) => { |
123 | db.lang_item(cur_crate, f.ty_to_string().into())?.krate(db) | 136 | lang_item_crate!(db, cur_crate, f.ty_to_string()) |
124 | } | 137 | } |
125 | TypeCtor::Int(UncertainIntTy::Known(i)) => { | 138 | TypeCtor::Int(UncertainIntTy::Known(i)) => { |
126 | db.lang_item(cur_crate, i.ty_to_string().into())?.krate(db) | 139 | lang_item_crate!(db, cur_crate, i.ty_to_string()) |
127 | } | 140 | } |
128 | TypeCtor::Str => db.lang_item(cur_crate, "str".into())?.krate(db), | 141 | TypeCtor::Str => lang_item_crate!(db, cur_crate, "str"), |
142 | TypeCtor::Slice => lang_item_crate!(db, cur_crate, "slice_alloc", "slice"), | ||
129 | _ => None, | 143 | _ => None, |
130 | }, | 144 | }, |
131 | _ => None, | 145 | _ => None, |
@@ -218,19 +232,17 @@ fn iterate_inherent_methods<T>( | |||
218 | krate: Crate, | 232 | krate: Crate, |
219 | mut callback: impl FnMut(&Ty, Function) -> Option<T>, | 233 | mut callback: impl FnMut(&Ty, Function) -> Option<T>, |
220 | ) -> Option<T> { | 234 | ) -> Option<T> { |
221 | let krate = match def_crate(db, krate, &ty.value) { | 235 | for krate in def_crates(db, krate, &ty.value)? { |
222 | Some(krate) => krate, | 236 | let impls = db.impls_in_crate(krate); |
223 | None => return None, | ||
224 | }; | ||
225 | let impls = db.impls_in_crate(krate); | ||
226 | 237 | ||
227 | for impl_block in impls.lookup_impl_blocks(&ty.value) { | 238 | for impl_block in impls.lookup_impl_blocks(&ty.value) { |
228 | for item in impl_block.items(db) { | 239 | for item in impl_block.items(db) { |
229 | if let ImplItem::Method(f) = item { | 240 | if let ImplItem::Method(f) = item { |
230 | let data = f.data(db); | 241 | let data = f.data(db); |
231 | if name.map_or(true, |name| data.name() == name) && data.has_self_param() { | 242 | if name.map_or(true, |name| data.name() == name) && data.has_self_param() { |
232 | if let Some(result) = callback(&ty.value, f) { | 243 | if let Some(result) = callback(&ty.value, f) { |
233 | return Some(result); | 244 | return Some(result); |
245 | } | ||
234 | } | 246 | } |
235 | } | 247 | } |
236 | } | 248 | } |
@@ -248,13 +260,14 @@ impl Ty { | |||
248 | krate: Crate, | 260 | krate: Crate, |
249 | mut callback: impl FnMut(ImplItem) -> Option<T>, | 261 | mut callback: impl FnMut(ImplItem) -> Option<T>, |
250 | ) -> Option<T> { | 262 | ) -> Option<T> { |
251 | let krate = def_crate(db, krate, &self)?; | 263 | for krate in def_crates(db, krate, &self)? { |
252 | let impls = db.impls_in_crate(krate); | 264 | let impls = db.impls_in_crate(krate); |
253 | 265 | ||
254 | for impl_block in impls.lookup_impl_blocks(&self) { | 266 | for impl_block in impls.lookup_impl_blocks(&self) { |
255 | for item in impl_block.items(db) { | 267 | for item in impl_block.items(db) { |
256 | if let Some(result) = callback(item) { | 268 | if let Some(result) = callback(item) { |
257 | return Some(result); | 269 | return Some(result); |
270 | } | ||
258 | } | 271 | } |
259 | } | 272 | } |
260 | } | 273 | } |