diff options
Diffstat (limited to 'crates/ra_hir/src/ty/infer')
-rw-r--r-- | crates/ra_hir/src/ty/infer/path.rs | 86 |
1 files changed, 49 insertions, 37 deletions
diff --git a/crates/ra_hir/src/ty/infer/path.rs b/crates/ra_hir/src/ty/infer/path.rs index 8d8b56d2d..09ff79728 100644 --- a/crates/ra_hir/src/ty/infer/path.rs +++ b/crates/ra_hir/src/ty/infer/path.rs | |||
@@ -2,14 +2,14 @@ | |||
2 | 2 | ||
3 | use hir_def::{ | 3 | use hir_def::{ |
4 | path::{Path, PathSegment}, | 4 | path::{Path, PathSegment}, |
5 | resolver::{ResolveValueResult, Resolver, TypeNs, ValueNs}, | 5 | resolver::{HasResolver, ResolveValueResult, Resolver, TypeNs, ValueNs}, |
6 | AssocItemId, ContainerId, Lookup, | ||
6 | }; | 7 | }; |
7 | use hir_expand::name::Name; | 8 | use hir_expand::name::Name; |
8 | 9 | ||
9 | use crate::{ | 10 | use crate::{ |
10 | db::HirDatabase, | 11 | db::HirDatabase, |
11 | ty::{method_resolution, Substs, Ty, TypeWalk, ValueTyDefId}, | 12 | ty::{method_resolution, Substs, Ty, TypeWalk, ValueTyDefId}, |
12 | AssocItem, Container, Function, | ||
13 | }; | 13 | }; |
14 | 14 | ||
15 | use super::{ExprOrPatId, InferenceContext, TraitRef}; | 15 | use super::{ExprOrPatId, InferenceContext, TraitRef}; |
@@ -143,31 +143,35 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
143 | id: ExprOrPatId, | 143 | id: ExprOrPatId, |
144 | ) -> Option<(ValueNs, Option<Substs>)> { | 144 | ) -> Option<(ValueNs, Option<Substs>)> { |
145 | let trait_ = trait_ref.trait_; | 145 | let trait_ = trait_ref.trait_; |
146 | let item = | 146 | let item = self |
147 | self.db.trait_data(trait_).items.iter().map(|(_name, id)| (*id).into()).find_map( | 147 | .db |
148 | |item| match item { | 148 | .trait_data(trait_) |
149 | AssocItem::Function(func) => { | 149 | .items |
150 | if segment.name == func.name(self.db) { | 150 | .iter() |
151 | Some(AssocItem::Function(func)) | 151 | .map(|(_name, id)| (*id).into()) |
152 | } else { | 152 | .find_map(|item| match item { |
153 | None | 153 | AssocItemId::FunctionId(func) => { |
154 | } | 154 | if segment.name == self.db.function_data(func).name { |
155 | Some(AssocItemId::FunctionId(func)) | ||
156 | } else { | ||
157 | None | ||
155 | } | 158 | } |
159 | } | ||
156 | 160 | ||
157 | AssocItem::Const(konst) => { | 161 | AssocItemId::ConstId(konst) => { |
158 | if konst.name(self.db).map_or(false, |n| n == segment.name) { | 162 | if self.db.const_data(konst).name.as_ref().map_or(false, |n| n == &segment.name) |
159 | Some(AssocItem::Const(konst)) | 163 | { |
160 | } else { | 164 | Some(AssocItemId::ConstId(konst)) |
161 | None | 165 | } else { |
162 | } | 166 | None |
163 | } | 167 | } |
164 | AssocItem::TypeAlias(_) => None, | 168 | } |
165 | }, | 169 | AssocItemId::TypeAliasId(_) => None, |
166 | )?; | 170 | })?; |
167 | let def = match item { | 171 | let def = match item { |
168 | AssocItem::Function(f) => ValueNs::FunctionId(f.id), | 172 | AssocItemId::FunctionId(f) => ValueNs::FunctionId(f), |
169 | AssocItem::Const(c) => ValueNs::ConstId(c.id), | 173 | AssocItemId::ConstId(c) => ValueNs::ConstId(c), |
170 | AssocItem::TypeAlias(_) => unreachable!(), | 174 | AssocItemId::TypeAliasId(_) => unreachable!(), |
171 | }; | 175 | }; |
172 | let substs = Substs::build_for_def(self.db, item) | 176 | let substs = Substs::build_for_def(self.db, item) |
173 | .use_parent_substs(&trait_ref.substs) | 177 | .use_parent_substs(&trait_ref.substs) |
@@ -197,16 +201,18 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
197 | Some(name), | 201 | Some(name), |
198 | method_resolution::LookupMode::Path, | 202 | method_resolution::LookupMode::Path, |
199 | move |_ty, item| { | 203 | move |_ty, item| { |
200 | let def = match item { | 204 | let (def, container) = match item { |
201 | AssocItem::Function(f) => ValueNs::FunctionId(f.id), | 205 | AssocItemId::FunctionId(f) => { |
202 | AssocItem::Const(c) => ValueNs::ConstId(c.id), | 206 | (ValueNs::FunctionId(f), f.lookup(self.db).container) |
203 | AssocItem::TypeAlias(_) => unreachable!(), | 207 | } |
208 | AssocItemId::ConstId(c) => (ValueNs::ConstId(c), c.lookup(self.db).container), | ||
209 | AssocItemId::TypeAliasId(_) => unreachable!(), | ||
204 | }; | 210 | }; |
205 | let substs = match item.container(self.db) { | 211 | let substs = match container { |
206 | Container::ImplBlock(_) => self.find_self_types(&def, ty.clone()), | 212 | ContainerId::ImplId(_) => self.find_self_types(&def, ty.clone()), |
207 | Container::Trait(t) => { | 213 | ContainerId::TraitId(trait_) => { |
208 | // we're picking this method | 214 | // we're picking this method |
209 | let trait_substs = Substs::build_for_def(self.db, t.id) | 215 | let trait_substs = Substs::build_for_def(self.db, trait_) |
210 | .push(ty.clone()) | 216 | .push(ty.clone()) |
211 | .fill(std::iter::repeat_with(|| self.new_type_var())) | 217 | .fill(std::iter::repeat_with(|| self.new_type_var())) |
212 | .build(); | 218 | .build(); |
@@ -215,29 +221,35 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
215 | .fill_with_params() | 221 | .fill_with_params() |
216 | .build(); | 222 | .build(); |
217 | self.obligations.push(super::Obligation::Trait(TraitRef { | 223 | self.obligations.push(super::Obligation::Trait(TraitRef { |
218 | trait_: t.id, | 224 | trait_, |
219 | substs: trait_substs, | 225 | substs: trait_substs, |
220 | })); | 226 | })); |
221 | Some(substs) | 227 | Some(substs) |
222 | } | 228 | } |
229 | ContainerId::ModuleId(_) => None, | ||
223 | }; | 230 | }; |
224 | 231 | ||
225 | self.write_assoc_resolution(id, item); | 232 | self.write_assoc_resolution(id, item.into()); |
226 | Some((def, substs)) | 233 | Some((def, substs)) |
227 | }, | 234 | }, |
228 | ) | 235 | ) |
229 | } | 236 | } |
230 | 237 | ||
231 | fn find_self_types(&self, def: &ValueNs, actual_def_ty: Ty) -> Option<Substs> { | 238 | fn find_self_types(&self, def: &ValueNs, actual_def_ty: Ty) -> Option<Substs> { |
232 | if let ValueNs::FunctionId(func) = def { | 239 | if let ValueNs::FunctionId(func) = *def { |
233 | let func = Function::from(*func); | ||
234 | // We only do the infer if parent has generic params | 240 | // We only do the infer if parent has generic params |
235 | let gen = self.db.generic_params(func.id.into()); | 241 | let gen = self.db.generic_params(func.into()); |
236 | if gen.count_parent_params() == 0 { | 242 | if gen.count_parent_params() == 0 { |
237 | return None; | 243 | return None; |
238 | } | 244 | } |
239 | 245 | ||
240 | let impl_block = func.impl_block(self.db)?.target_ty(self.db); | 246 | let impl_id = match func.lookup(self.db).container { |
247 | ContainerId::ImplId(it) => it, | ||
248 | _ => return None, | ||
249 | }; | ||
250 | let resolver = impl_id.resolver(self.db); | ||
251 | let impl_data = self.db.impl_data(impl_id); | ||
252 | let impl_block = Ty::from_hir(self.db, &resolver, &impl_data.target_type); | ||
241 | let impl_block_substs = impl_block.substs()?; | 253 | let impl_block_substs = impl_block.substs()?; |
242 | let actual_substs = actual_def_ty.substs()?; | 254 | let actual_substs = actual_def_ty.substs()?; |
243 | 255 | ||