diff options
Diffstat (limited to 'crates/ra_hir/src/ty/method_resolution.rs')
-rw-r--r-- | crates/ra_hir/src/ty/method_resolution.rs | 68 |
1 files changed, 39 insertions, 29 deletions
diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir/src/ty/method_resolution.rs index 64adb814d..c5ab690eb 100644 --- a/crates/ra_hir/src/ty/method_resolution.rs +++ b/crates/ra_hir/src/ty/method_resolution.rs | |||
@@ -5,7 +5,7 @@ | |||
5 | use std::sync::Arc; | 5 | use std::sync::Arc; |
6 | 6 | ||
7 | use arrayvec::ArrayVec; | 7 | use arrayvec::ArrayVec; |
8 | use hir_def::resolver::Resolver; | 8 | use hir_def::{lang_item::LangItemTarget, resolver::Resolver, AstItemDef}; |
9 | use rustc_hash::FxHashMap; | 9 | use rustc_hash::FxHashMap; |
10 | 10 | ||
11 | use crate::{ | 11 | use crate::{ |
@@ -15,7 +15,7 @@ use crate::{ | |||
15 | AssocItem, Crate, Function, ImplBlock, Module, Mutability, Name, Trait, | 15 | AssocItem, Crate, Function, ImplBlock, Module, Mutability, Name, Trait, |
16 | }; | 16 | }; |
17 | 17 | ||
18 | use super::{autoderef, lower, Canonical, InEnvironment, TraitEnvironment, TraitRef}; | 18 | use super::{autoderef, Canonical, InEnvironment, TraitEnvironment, TraitRef}; |
19 | 19 | ||
20 | /// This is used as a key for indexing impls. | 20 | /// This is used as a key for indexing impls. |
21 | #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] | 21 | #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] |
@@ -91,34 +91,43 @@ fn def_crates(db: &impl HirDatabase, cur_crate: Crate, ty: &Ty) -> Option<ArrayV | |||
91 | // Types like slice can have inherent impls in several crates, (core and alloc). | 91 | // Types like slice can have inherent impls in several crates, (core and alloc). |
92 | // The corresponding impls are marked with lang items, so we can use them to find the required crates. | 92 | // The corresponding impls are marked with lang items, so we can use them to find the required crates. |
93 | macro_rules! lang_item_crate { | 93 | macro_rules! lang_item_crate { |
94 | ($db:expr, $cur_crate:expr, $($name:expr),+ $(,)?) => {{ | 94 | ($($name:expr),+ $(,)?) => {{ |
95 | let mut v = ArrayVec::<[Crate; 2]>::new(); | 95 | let mut v = ArrayVec::<[LangItemTarget; 2]>::new(); |
96 | $( | 96 | $( |
97 | v.extend($db.lang_item($cur_crate, $name.into()).and_then(|item| item.krate($db))); | 97 | v.extend(db.lang_item(cur_crate.crate_id, $name.into())); |
98 | )+ | 98 | )+ |
99 | Some(v) | 99 | v |
100 | }}; | 100 | }}; |
101 | } | 101 | } |
102 | 102 | ||
103 | match ty { | 103 | let lang_item_targets = match ty { |
104 | Ty::Apply(a_ty) => match a_ty.ctor { | 104 | Ty::Apply(a_ty) => match a_ty.ctor { |
105 | TypeCtor::Adt(def_id) => Some(std::iter::once(def_id.krate(db)?).collect()), | 105 | TypeCtor::Adt(def_id) => return Some(std::iter::once(def_id.krate(db)?).collect()), |
106 | TypeCtor::Bool => lang_item_crate!(db, cur_crate, "bool"), | 106 | TypeCtor::Bool => lang_item_crate!("bool"), |
107 | TypeCtor::Char => lang_item_crate!(db, cur_crate, "char"), | 107 | TypeCtor::Char => lang_item_crate!("char"), |
108 | TypeCtor::Float(Uncertain::Known(f)) => match f.bitness { | 108 | TypeCtor::Float(Uncertain::Known(f)) => match f.bitness { |
109 | // There are two lang items: one in libcore (fXX) and one in libstd (fXX_runtime) | 109 | // There are two lang items: one in libcore (fXX) and one in libstd (fXX_runtime) |
110 | FloatBitness::X32 => lang_item_crate!(db, cur_crate, "f32", "f32_runtime"), | 110 | FloatBitness::X32 => lang_item_crate!("f32", "f32_runtime"), |
111 | FloatBitness::X64 => lang_item_crate!(db, cur_crate, "f64", "f64_runtime"), | 111 | FloatBitness::X64 => lang_item_crate!("f64", "f64_runtime"), |
112 | }, | 112 | }, |
113 | TypeCtor::Int(Uncertain::Known(i)) => lang_item_crate!(db, cur_crate, i.ty_to_string()), | 113 | TypeCtor::Int(Uncertain::Known(i)) => lang_item_crate!(i.ty_to_string()), |
114 | TypeCtor::Str => lang_item_crate!(db, cur_crate, "str_alloc", "str"), | 114 | TypeCtor::Str => lang_item_crate!("str_alloc", "str"), |
115 | TypeCtor::Slice => lang_item_crate!(db, cur_crate, "slice_alloc", "slice"), | 115 | TypeCtor::Slice => lang_item_crate!("slice_alloc", "slice"), |
116 | TypeCtor::RawPtr(Mutability::Shared) => lang_item_crate!(db, cur_crate, "const_ptr"), | 116 | TypeCtor::RawPtr(Mutability::Shared) => lang_item_crate!("const_ptr"), |
117 | TypeCtor::RawPtr(Mutability::Mut) => lang_item_crate!(db, cur_crate, "mut_ptr"), | 117 | TypeCtor::RawPtr(Mutability::Mut) => lang_item_crate!("mut_ptr"), |
118 | _ => None, | 118 | _ => return None, |
119 | }, | 119 | }, |
120 | _ => None, | 120 | _ => return None, |
121 | } | 121 | }; |
122 | let res = lang_item_targets | ||
123 | .into_iter() | ||
124 | .filter_map(|it| match it { | ||
125 | LangItemTarget::ImplBlockId(it) => Some(it), | ||
126 | _ => None, | ||
127 | }) | ||
128 | .map(|it| it.module(db).krate.into()) | ||
129 | .collect(); | ||
130 | Some(res) | ||
122 | } | 131 | } |
123 | 132 | ||
124 | /// Look up the method with the given name, returning the actual autoderefed | 133 | /// Look up the method with the given name, returning the actual autoderefed |
@@ -170,8 +179,9 @@ pub(crate) fn iterate_method_candidates<T>( | |||
170 | // Also note that when we've got a receiver like &S, even if the method we | 179 | // Also note that when we've got a receiver like &S, even if the method we |
171 | // find in the end takes &self, we still do the autoderef step (just as | 180 | // find in the end takes &self, we still do the autoderef step (just as |
172 | // rustc does an autoderef and then autoref again). | 181 | // rustc does an autoderef and then autoref again). |
173 | 182 | let environment = TraitEnvironment::lower(db, resolver); | |
174 | for derefed_ty in autoderef::autoderef(db, resolver, ty.clone()) { | 183 | let ty = InEnvironment { value: ty.clone(), environment }; |
184 | for derefed_ty in autoderef::autoderef(db, resolver.krate(), ty) { | ||
175 | if let Some(result) = iterate_inherent_methods( | 185 | if let Some(result) = iterate_inherent_methods( |
176 | &derefed_ty, | 186 | &derefed_ty, |
177 | db, | 187 | db, |
@@ -221,7 +231,7 @@ fn iterate_trait_method_candidates<T>( | |||
221 | ) -> Option<T> { | 231 | ) -> Option<T> { |
222 | let krate = resolver.krate()?; | 232 | let krate = resolver.krate()?; |
223 | // FIXME: maybe put the trait_env behind a query (need to figure out good input parameters for that) | 233 | // FIXME: maybe put the trait_env behind a query (need to figure out good input parameters for that) |
224 | let env = lower::trait_env(db, resolver); | 234 | let env = TraitEnvironment::lower(db, resolver); |
225 | // if ty is `impl Trait` or `dyn Trait`, the trait doesn't need to be in scope | 235 | // if ty is `impl Trait` or `dyn Trait`, the trait doesn't need to be in scope |
226 | let inherent_trait = ty.value.inherent_trait().into_iter(); | 236 | let inherent_trait = ty.value.inherent_trait().into_iter(); |
227 | // if we have `T: Trait` in the param env, the trait doesn't need to be in scope | 237 | // if we have `T: Trait` in the param env, the trait doesn't need to be in scope |
@@ -233,7 +243,7 @@ fn iterate_trait_method_candidates<T>( | |||
233 | .chain(traits_from_env) | 243 | .chain(traits_from_env) |
234 | .chain(resolver.traits_in_scope(db).into_iter().map(Trait::from)); | 244 | .chain(resolver.traits_in_scope(db).into_iter().map(Trait::from)); |
235 | 'traits: for t in traits { | 245 | 'traits: for t in traits { |
236 | let data = t.trait_data(db); | 246 | let data = db.trait_data(t.id); |
237 | 247 | ||
238 | // we'll be lazy about checking whether the type implements the | 248 | // we'll be lazy about checking whether the type implements the |
239 | // trait, but if we find out it doesn't, we'll skip the rest of the | 249 | // trait, but if we find out it doesn't, we'll skip the rest of the |
@@ -291,9 +301,9 @@ fn is_valid_candidate( | |||
291 | ) -> bool { | 301 | ) -> bool { |
292 | match item { | 302 | match item { |
293 | AssocItem::Function(m) => { | 303 | AssocItem::Function(m) => { |
294 | let data = m.data(db); | 304 | let data = db.function_data(m.id); |
295 | name.map_or(true, |name| data.name() == name) | 305 | name.map_or(true, |name| data.name == *name) |
296 | && (data.has_self_param() || mode == LookupMode::Path) | 306 | && (data.has_self_param || mode == LookupMode::Path) |
297 | } | 307 | } |
298 | AssocItem::Const(c) => { | 308 | AssocItem::Const(c) => { |
299 | name.map_or(true, |name| Some(name) == c.name(db).as_ref()) | 309 | name.map_or(true, |name| Some(name) == c.name(db).as_ref()) |
@@ -315,7 +325,7 @@ pub(crate) fn implements_trait( | |||
315 | // anyway, but currently Chalk doesn't implement `dyn/impl Trait` yet | 325 | // anyway, but currently Chalk doesn't implement `dyn/impl Trait` yet |
316 | return true; | 326 | return true; |
317 | } | 327 | } |
318 | let env = lower::trait_env(db, resolver); | 328 | let env = TraitEnvironment::lower(db, resolver); |
319 | let goal = generic_implements_goal(db, env, trait_, ty.clone()); | 329 | let goal = generic_implements_goal(db, env, trait_, ty.clone()); |
320 | let solution = db.trait_solve(krate, goal); | 330 | let solution = db.trait_solve(krate, goal); |
321 | 331 | ||
@@ -355,7 +365,7 @@ fn generic_implements_goal( | |||
355 | self_ty: Canonical<Ty>, | 365 | self_ty: Canonical<Ty>, |
356 | ) -> Canonical<InEnvironment<super::Obligation>> { | 366 | ) -> Canonical<InEnvironment<super::Obligation>> { |
357 | let num_vars = self_ty.num_vars; | 367 | let num_vars = self_ty.num_vars; |
358 | let substs = super::Substs::build_for_def(db, trait_) | 368 | let substs = super::Substs::build_for_def(db, trait_.id) |
359 | .push(self_ty.value) | 369 | .push(self_ty.value) |
360 | .fill_with_bound_vars(num_vars as u32) | 370 | .fill_with_bound_vars(num_vars as u32) |
361 | .build(); | 371 | .build(); |