aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/ty/infer/path.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir/src/ty/infer/path.rs')
-rw-r--r--crates/ra_hir/src/ty/infer/path.rs55
1 files changed, 51 insertions, 4 deletions
diff --git a/crates/ra_hir/src/ty/infer/path.rs b/crates/ra_hir/src/ty/infer/path.rs
index 54aae4f0c..feb7481b2 100644
--- a/crates/ra_hir/src/ty/infer/path.rs
+++ b/crates/ra_hir/src/ty/infer/path.rs
@@ -1,6 +1,6 @@
1//! Path expression resolution. 1//! Path expression resolution.
2 2
3use super::{ExprOrPatId, InferenceContext}; 3use super::{ExprOrPatId, InferenceContext, TraitRef};
4use crate::{ 4use crate::{
5 db::HirDatabase, 5 db::HirDatabase,
6 resolve::{ResolveValueResult, Resolver, TypeNs, ValueNs}, 6 resolve::{ResolveValueResult, Resolver, TypeNs, ValueNs},
@@ -91,9 +91,17 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
91 let is_before_last = remaining_segments.len() == 1; 91 let is_before_last = remaining_segments.len() == 1;
92 92
93 match (def, is_before_last) { 93 match (def, is_before_last) {
94 (TypeNs::Trait(_trait), true) => { 94 (TypeNs::Trait(trait_), true) => {
95 // FIXME Associated item of trait, e.g. `Default::default` 95 let segment =
96 None 96 remaining_segments.last().expect("there should be at least one segment here");
97 let trait_ref = TraitRef::from_resolved_path(
98 self.db,
99 &self.resolver,
100 trait_,
101 resolved_segment,
102 None,
103 );
104 self.resolve_trait_assoc_item(trait_ref, segment, id)
97 } 105 }
98 (def, _) => { 106 (def, _) => {
99 // Either we already have a type (e.g. `Vec::new`), or we have a 107 // Either we already have a type (e.g. `Vec::new`), or we have a
@@ -120,6 +128,45 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
120 } 128 }
121 } 129 }
122 130
131 fn resolve_trait_assoc_item(
132 &mut self,
133 trait_ref: TraitRef,
134 segment: &crate::path::PathSegment,
135 id: ExprOrPatId,
136 ) -> Option<(ValueNs, Option<Substs>)> {
137 let trait_ = trait_ref.trait_;
138 let item = trait_.items(self.db).iter().copied().find_map(|item| match item {
139 AssocItem::Function(func) => {
140 if segment.name == func.name(self.db) {
141 Some(AssocItem::Function(func))
142 } else {
143 None
144 }
145 }
146
147 AssocItem::Const(konst) => {
148 if konst.name(self.db).map_or(false, |n| n == segment.name) {
149 Some(AssocItem::Const(konst))
150 } else {
151 None
152 }
153 }
154 AssocItem::TypeAlias(_) => None,
155 })?;
156 let def = match item {
157 AssocItem::Function(f) => ValueNs::Function(f),
158 AssocItem::Const(c) => ValueNs::Const(c),
159 AssocItem::TypeAlias(_) => unreachable!(),
160 };
161 let generics = item.generic_params(self.db);
162 let mut substs = Vec::with_capacity(generics.count_params_including_parent());
163 substs.extend(trait_ref.substs.iter().cloned());
164 substs.extend(std::iter::repeat(Ty::Unknown).take(generics.params.len()));
165
166 self.write_assoc_resolution(id, item);
167 Some((def, Some(substs.into())))
168 }
169
123 fn resolve_ty_assoc_item( 170 fn resolve_ty_assoc_item(
124 &mut self, 171 &mut self,
125 ty: Ty, 172 ty: Ty,