diff options
author | bors[bot] <bors[bot]@users.noreply.github.com> | 2019-02-24 06:45:08 +0000 |
---|---|---|
committer | bors[bot] <bors[bot]@users.noreply.github.com> | 2019-02-24 06:45:08 +0000 |
commit | c5e74cebdcbade069c0e1e81e298ab7d729e4cd5 (patch) | |
tree | 574d01f1f7532574ed22610341b3ac79da59d93f /crates/ra_hir/src/ty/infer.rs | |
parent | 1eef9fbefe44e919f6ddc7ce1c44625ffde6be1c (diff) | |
parent | 82fe7b77a3b4f49540ae1fc319bdd38afd73c877 (diff) |
Merge #886
886: Associated method generics r=matklad a=flodiebold
Refactor associated method resolution a bit and make it work with generics.
Co-authored-by: Florian Diebold <[email protected]>
Diffstat (limited to 'crates/ra_hir/src/ty/infer.rs')
-rw-r--r-- | crates/ra_hir/src/ty/infer.rs | 86 |
1 files changed, 53 insertions, 33 deletions
diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs index 6ee9080d3..13080b5aa 100644 --- a/crates/ra_hir/src/ty/infer.rs +++ b/crates/ra_hir/src/ty/infer.rs | |||
@@ -360,46 +360,66 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
360 | // we might have resolved into a type for which | 360 | // we might have resolved into a type for which |
361 | // we may find some associated item starting at the | 361 | // we may find some associated item starting at the |
362 | // path.segment pointed to by `remaining_index´ | 362 | // path.segment pointed to by `remaining_index´ |
363 | let resolved = | 363 | let mut resolved = |
364 | if remaining_index.is_none() { def.take_values()? } else { def.take_types()? }; | 364 | if remaining_index.is_none() { def.take_values()? } else { def.take_types()? }; |
365 | 365 | ||
366 | let remaining_index = remaining_index.unwrap_or(path.segments.len()); | ||
367 | |||
368 | // resolve intermediate segments | ||
369 | for segment in &path.segments[remaining_index..] { | ||
370 | let ty = match resolved { | ||
371 | Resolution::Def(def) => { | ||
372 | let typable: Option<TypableDef> = def.into(); | ||
373 | let typable = typable?; | ||
374 | |||
375 | let substs = | ||
376 | Ty::substs_from_path_segment(self.db, &self.resolver, segment, typable); | ||
377 | self.db.type_for_def(typable, Namespace::Types).apply_substs(substs) | ||
378 | } | ||
379 | Resolution::LocalBinding(_) => { | ||
380 | // can't have a local binding in an associated item path | ||
381 | return None; | ||
382 | } | ||
383 | Resolution::GenericParam(..) => { | ||
384 | // TODO associated item of generic param | ||
385 | return None; | ||
386 | } | ||
387 | Resolution::SelfType(_) => { | ||
388 | // TODO associated item of self type | ||
389 | return None; | ||
390 | } | ||
391 | }; | ||
392 | |||
393 | // Attempt to find an impl_item for the type which has a name matching | ||
394 | // the current segment | ||
395 | log::debug!("looking for path segment: {:?}", segment); | ||
396 | let item = ty.iterate_impl_items(self.db, |item| match item { | ||
397 | crate::ImplItem::Method(func) => { | ||
398 | let sig = func.signature(self.db); | ||
399 | if segment.name == *sig.name() { | ||
400 | return Some(func); | ||
401 | } | ||
402 | None | ||
403 | } | ||
404 | |||
405 | // TODO: Resolve associated const | ||
406 | crate::ImplItem::Const(_) => None, | ||
407 | |||
408 | // TODO: Resolve associated types | ||
409 | crate::ImplItem::Type(_) => None, | ||
410 | })?; | ||
411 | resolved = Resolution::Def(item.into()); | ||
412 | } | ||
413 | |||
366 | match resolved { | 414 | match resolved { |
367 | Resolution::Def(def) => { | 415 | Resolution::Def(def) => { |
368 | let typable: Option<TypableDef> = def.into(); | 416 | let typable: Option<TypableDef> = def.into(); |
369 | let typable = typable?; | 417 | let typable = typable?; |
370 | 418 | ||
371 | if let Some(remaining_index) = remaining_index { | 419 | let substs = Ty::substs_from_path(self.db, &self.resolver, path, typable); |
372 | let ty = self.db.type_for_def(typable, Namespace::Types); | 420 | let ty = self.db.type_for_def(typable, Namespace::Values).apply_substs(substs); |
373 | // TODO: Keep resolving the segments | 421 | let ty = self.insert_type_vars(ty); |
374 | // if we have more segments to process | 422 | Some(ty) |
375 | let segment = &path.segments[remaining_index]; | ||
376 | |||
377 | log::debug!("looking for path segment: {:?}", segment); | ||
378 | |||
379 | // Attempt to find an impl_item for the type which has a name matching | ||
380 | // the current segment | ||
381 | let ty = ty.iterate_impl_items(self.db, |item| match item { | ||
382 | crate::ImplItem::Method(func) => { | ||
383 | let sig = func.signature(self.db); | ||
384 | if segment.name == *sig.name() { | ||
385 | return Some(func.ty(self.db)); | ||
386 | } | ||
387 | None | ||
388 | } | ||
389 | |||
390 | // TODO: Resolve associated const | ||
391 | crate::ImplItem::Const(_) => None, | ||
392 | |||
393 | // TODO: Resolve associated types | ||
394 | crate::ImplItem::Type(_) => None, | ||
395 | }); | ||
396 | ty | ||
397 | } else { | ||
398 | let substs = Ty::substs_from_path(self.db, &self.resolver, path, typable); | ||
399 | let ty = self.db.type_for_def(typable, Namespace::Values).apply_substs(substs); | ||
400 | let ty = self.insert_type_vars(ty); | ||
401 | Some(ty) | ||
402 | } | ||
403 | } | 423 | } |
404 | Resolution::LocalBinding(pat) => { | 424 | Resolution::LocalBinding(pat) => { |
405 | let ty = self.type_of_pat.get(pat)?; | 425 | let ty = self.type_of_pat.get(pat)?; |