diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2019-09-25 21:23:09 +0100 |
---|---|---|
committer | GitHub <[email protected]> | 2019-09-25 21:23:09 +0100 |
commit | 0d277faf6c4052dcc80037fc43b4986980d0814b (patch) | |
tree | 807f32992732a74c591f6a8c85aff354ebea09c6 /crates/ra_hir/src/ty | |
parent | 5704485063bad82e651c8e68f4fa2d333bfdf152 (diff) | |
parent | c35ef5013c3223986ae5111a3720ef8e85c80efc (diff) |
Merge #1914
1914: Resolve trait associated items r=matklad a=flodiebold
E.g. `Default::default` or `<Foo as Default>::default`.
Co-authored-by: Florian Diebold <[email protected]>
Diffstat (limited to 'crates/ra_hir/src/ty')
-rw-r--r-- | crates/ra_hir/src/ty/infer/path.rs | 55 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/lower.rs | 2 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/tests.rs | 15 |
3 files changed, 59 insertions, 13 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 | ||
3 | use super::{ExprOrPatId, InferenceContext}; | 3 | use super::{ExprOrPatId, InferenceContext, TraitRef}; |
4 | use crate::{ | 4 | use 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, |
diff --git a/crates/ra_hir/src/ty/lower.rs b/crates/ra_hir/src/ty/lower.rs index 8d71abc95..dd503d771 100644 --- a/crates/ra_hir/src/ty/lower.rs +++ b/crates/ra_hir/src/ty/lower.rs | |||
@@ -386,7 +386,7 @@ impl TraitRef { | |||
386 | Some(TraitRef::from_resolved_path(db, resolver, resolved, segment, explicit_self_ty)) | 386 | Some(TraitRef::from_resolved_path(db, resolver, resolved, segment, explicit_self_ty)) |
387 | } | 387 | } |
388 | 388 | ||
389 | fn from_resolved_path( | 389 | pub(super) fn from_resolved_path( |
390 | db: &impl HirDatabase, | 390 | db: &impl HirDatabase, |
391 | resolver: &Resolver, | 391 | resolver: &Resolver, |
392 | resolved: Trait, | 392 | resolved: Trait, |
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs index 2872cd27b..f4f63ca93 100644 --- a/crates/ra_hir/src/ty/tests.rs +++ b/crates/ra_hir/src/ty/tests.rs | |||
@@ -2535,17 +2535,16 @@ fn test() { | |||
2535 | } | 2535 | } |
2536 | "#), | 2536 | "#), |
2537 | @r###" | 2537 | @r###" |
2538 | |||
2539 | [87; 193) '{ ...t(); }': () | 2538 | [87; 193) '{ ...t(); }': () |
2540 | [97; 99) 's1': S | 2539 | [97; 99) 's1': S |
2541 | [105; 121) 'Defaul...efault': {unknown} | 2540 | [105; 121) 'Defaul...efault': fn default<S>() -> Self |
2542 | [105; 123) 'Defaul...ault()': S | 2541 | [105; 123) 'Defaul...ault()': S |
2543 | [133; 135) 's2': {unknown} | 2542 | [133; 135) 's2': {unknown} |
2544 | [138; 148) 'S::default': {unknown} | 2543 | [138; 148) 'S::default': {unknown} |
2545 | [138; 150) 'S::default()': {unknown} | 2544 | [138; 150) 'S::default()': {unknown} |
2546 | [160; 162) 's3': {unknown} | 2545 | [160; 162) 's3': S |
2547 | [165; 188) '<S as ...efault': {unknown} | 2546 | [165; 188) '<S as ...efault': fn default<S>() -> Self |
2548 | [165; 190) '<S as ...ault()': {unknown} | 2547 | [165; 190) '<S as ...ault()': S |
2549 | "### | 2548 | "### |
2550 | ); | 2549 | ); |
2551 | } | 2550 | } |
@@ -2674,9 +2673,9 @@ fn test() { | |||
2674 | [148; 149) 'y': u64 | 2673 | [148; 149) 'y': u64 |
2675 | [157; 158) 'S': S | 2674 | [157; 158) 'S': S |
2676 | [157; 165) 'S.into()': u64 | 2675 | [157; 165) 'S.into()': u64 |
2677 | [175; 176) 'z': {unknown} | 2676 | [175; 176) 'z': u64 |
2678 | [179; 196) 'Into::...::into': {unknown} | 2677 | [179; 196) 'Into::...::into': fn into<S, u64>(Self) -> T |
2679 | [179; 199) 'Into::...nto(S)': {unknown} | 2678 | [179; 199) 'Into::...nto(S)': u64 |
2680 | [197; 198) 'S': S | 2679 | [197; 198) 'S': S |
2681 | "### | 2680 | "### |
2682 | ); | 2681 | ); |