aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/ty
diff options
context:
space:
mode:
authorFlorian Diebold <[email protected]>2019-03-26 22:07:26 +0000
committerFlorian Diebold <[email protected]>2019-04-14 10:28:53 +0100
commit413c87f155ab6b389b1cc122b5739716acccb476 (patch)
treeece00ee4bb46d32ec2a3c4124a43e3634eacd007 /crates/ra_hir/src/ty
parent23b876bc3b00c53ce24b8a99b4f4bf190fc6300e (diff)
Get substs for trait refs in impl blocks
Diffstat (limited to 'crates/ra_hir/src/ty')
-rw-r--r--crates/ra_hir/src/ty/lower.rs95
-rw-r--r--crates/ra_hir/src/ty/method_resolution.rs6
2 files changed, 74 insertions, 27 deletions
diff --git a/crates/ra_hir/src/ty/lower.rs b/crates/ra_hir/src/ty/lower.rs
index 003a89f0d..4523b3954 100644
--- a/crates/ra_hir/src/ty/lower.rs
+++ b/crates/ra_hir/src/ty/lower.rs
@@ -17,9 +17,9 @@ use crate::{
17 resolve::{Resolver, Resolution}, 17 resolve::{Resolver, Resolution},
18 path::{ PathSegment, GenericArg}, 18 path::{ PathSegment, GenericArg},
19 generics::GenericParams, 19 generics::GenericParams,
20 adt::VariantDef, 20 adt::VariantDef, Trait
21}; 21};
22use super::{Ty, primitive, FnSig, Substs, TypeCtor}; 22use super::{Ty, primitive, FnSig, Substs, TypeCtor, TraitRef};
23 23
24impl Ty { 24impl Ty {
25 pub(crate) fn from_hir(db: &impl HirDatabase, resolver: &Resolver, type_ref: &TypeRef) -> Self { 25 pub(crate) fn from_hir(db: &impl HirDatabase, resolver: &Resolver, type_ref: &TypeRef) -> Self {
@@ -115,7 +115,6 @@ impl Ty {
115 segment: &PathSegment, 115 segment: &PathSegment,
116 resolved: TypableDef, 116 resolved: TypableDef,
117 ) -> Substs { 117 ) -> Substs {
118 let mut substs = Vec::new();
119 let def_generics = match resolved { 118 let def_generics = match resolved {
120 TypableDef::Function(func) => func.generic_params(db), 119 TypableDef::Function(func) => func.generic_params(db),
121 TypableDef::Struct(s) => s.generic_params(db), 120 TypableDef::Struct(s) => s.generic_params(db),
@@ -124,28 +123,7 @@ impl Ty {
124 TypableDef::TypeAlias(t) => t.generic_params(db), 123 TypableDef::TypeAlias(t) => t.generic_params(db),
125 TypableDef::Const(_) | TypableDef::Static(_) => GenericParams::default().into(), 124 TypableDef::Const(_) | TypableDef::Static(_) => GenericParams::default().into(),
126 }; 125 };
127 let parent_param_count = def_generics.count_parent_params(); 126 substs_from_path_segment(db, resolver, segment, &def_generics, false)
128 substs.extend((0..parent_param_count).map(|_| Ty::Unknown));
129 if let Some(generic_args) = &segment.args_and_bindings {
130 // if args are provided, it should be all of them, but we can't rely on that
131 let param_count = def_generics.params.len();
132 for arg in generic_args.args.iter().take(param_count) {
133 match arg {
134 GenericArg::Type(type_ref) => {
135 let ty = Ty::from_hir(db, resolver, type_ref);
136 substs.push(ty);
137 }
138 }
139 }
140 }
141 // add placeholders for args that were not provided
142 // FIXME: handle defaults
143 let supplied_params = substs.len();
144 for _ in supplied_params..def_generics.count_params_including_parent() {
145 substs.push(Ty::Unknown);
146 }
147 assert_eq!(substs.len(), def_generics.count_params_including_parent());
148 Substs(substs.into())
149 } 127 }
150 128
151 /// Collect generic arguments from a path into a `Substs`. See also 129 /// Collect generic arguments from a path into a `Substs`. See also
@@ -185,6 +163,73 @@ impl Ty {
185 } 163 }
186} 164}
187 165
166pub(super) fn substs_from_path_segment(
167 db: &impl HirDatabase,
168 resolver: &Resolver,
169 segment: &PathSegment,
170 def_generics: &GenericParams,
171 add_self_param: bool,
172) -> Substs {
173 let mut substs = Vec::new();
174 let parent_param_count = def_generics.count_parent_params();
175 substs.extend((0..parent_param_count).map(|_| Ty::Unknown));
176 if add_self_param {
177 // FIXME this add_self_param argument is kind of a hack: Traits have the
178 // Self type as an implicit first type parameter, but it can't be
179 // actually provided in the type arguments
180 substs.push(Ty::Unknown);
181 }
182 if let Some(generic_args) = &segment.args_and_bindings {
183 // if args are provided, it should be all of them, but we can't rely on that
184 let param_count = def_generics.params.len();
185 for arg in generic_args.args.iter().take(param_count) {
186 match arg {
187 GenericArg::Type(type_ref) => {
188 let ty = Ty::from_hir(db, resolver, type_ref);
189 substs.push(ty);
190 }
191 }
192 }
193 }
194 // add placeholders for args that were not provided
195 // FIXME: handle defaults
196 let supplied_params = substs.len();
197 for _ in supplied_params..def_generics.count_params_including_parent() {
198 substs.push(Ty::Unknown);
199 }
200 assert_eq!(substs.len(), def_generics.count_params_including_parent());
201 Substs(substs.into())
202}
203
204impl TraitRef {
205 pub(crate) fn from_hir(
206 db: &impl HirDatabase,
207 resolver: &Resolver,
208 type_ref: &TypeRef,
209 ) -> Option<Self> {
210 let path = match type_ref {
211 TypeRef::Path(path) => path,
212 _ => return None,
213 };
214 let resolved = match resolver.resolve_path(db, &path).take_types()? {
215 Resolution::Def(ModuleDef::Trait(tr)) => tr,
216 _ => return None,
217 };
218 let substs = Self::substs_from_path(db, resolver, path, resolved);
219 Some(TraitRef { trait_: resolved, substs })
220 }
221
222 fn substs_from_path(
223 db: &impl HirDatabase,
224 resolver: &Resolver,
225 path: &Path,
226 resolved: Trait,
227 ) -> Substs {
228 let segment = path.segments.last().expect("path should have at least one segment");
229 substs_from_path_segment(db, resolver, segment, &resolved.generic_params(db), true)
230 }
231}
232
188/// Build the declared type of an item. This depends on the namespace; e.g. for 233/// Build the declared type of an item. This depends on the namespace; e.g. for
189/// `struct Foo(usize)`, we have two types: The type of the struct itself, and 234/// `struct Foo(usize)`, we have two types: The type of the struct itself, and
190/// the constructor function `(usize) -> Foo` which lives in the values 235/// the constructor function `(usize) -> Foo` which lives in the values
diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir/src/ty/method_resolution.rs
index bb23246a6..aac7d6384 100644
--- a/crates/ra_hir/src/ty/method_resolution.rs
+++ b/crates/ra_hir/src/ty/method_resolution.rs
@@ -72,9 +72,9 @@ impl CrateImplBlocks {
72 72
73 let target_ty = impl_block.target_ty(db); 73 let target_ty = impl_block.target_ty(db);
74 74
75 if let Some(tr) = impl_block.target_trait(db) { 75 if let Some(tr) = impl_block.target_trait_ref(db) {
76 self.impls_by_trait 76 self.impls_by_trait
77 .entry(tr) 77 .entry(tr.trait_)
78 .or_insert_with(Vec::new) 78 .or_insert_with(Vec::new)
79 .push((module.module_id, impl_id)); 79 .push((module.module_id, impl_id));
80 } else { 80 } else {
@@ -185,6 +185,8 @@ impl Ty {
185 // well (in fact, the 'implements' condition could just be considered a 185 // well (in fact, the 'implements' condition could just be considered a
186 // 'where Self: Trait' clause) 186 // 'where Self: Trait' clause)
187 candidates.retain(|(t, _m)| { 187 candidates.retain(|(t, _m)| {
188 // FIXME construct substs of the correct length for the trait
189 // - check in rustc whether it does anything smarter than putting variables for everything
188 let trait_ref = TraitRef { trait_: *t, substs: Substs::single(self.clone()) }; 190 let trait_ref = TraitRef { trait_: *t, substs: Substs::single(self.clone()) };
189 db.implements(trait_ref) 191 db.implements(trait_ref)
190 }); 192 });