aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_hir/src/ty/method_resolution.rs63
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.
5use std::sync::Arc; 5use std::sync::Arc;
6 6
7use arrayvec::ArrayVec;
7use rustc_hash::FxHashMap; 8use rustc_hash::FxHashMap;
8 9
9use crate::{ 10use crate::{
@@ -113,19 +114,32 @@ impl CrateImplBlocks {
113 } 114 }
114} 115}
115 116
116fn def_crate(db: &impl HirDatabase, cur_crate: Crate, ty: &Ty) -> Option<Crate> { 117fn 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 }