aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2019-12-07 12:33:08 +0000
committerGitHub <[email protected]>2019-12-07 12:33:08 +0000
commit7aac5f2b427247120025f63c4864a1b937ed20c7 (patch)
tree51a841eaac9c7416e379b23887ee97ddc541ab5c
parent35fc983dd9e904ad4961b9c10be3397bad33da0c (diff)
parent29b5e1ec2a4bc25daddfe5137503b156b3cd283f (diff)
Merge #2492
2492: Refactor generic parameteres lowering r=flodiebold a=matklad indices and parent params seem to be concerns, specific to `hir_ty`, so move them there. Co-authored-by: Aleksey Kladov <[email protected]>
-rw-r--r--crates/ra_hir/src/code_model.rs5
-rw-r--r--crates/ra_hir/src/source_binder.rs10
-rw-r--r--crates/ra_hir_def/src/generics.rs97
-rw-r--r--crates/ra_hir_def/src/lib.rs10
-rw-r--r--crates/ra_hir_def/src/resolver.rs38
-rw-r--r--crates/ra_hir_ty/src/autoderef.rs10
-rw-r--r--crates/ra_hir_ty/src/infer/expr.rs34
-rw-r--r--crates/ra_hir_ty/src/lib.rs44
-rw-r--r--crates/ra_hir_ty/src/lower.rs46
-rw-r--r--crates/ra_hir_ty/src/traits/chalk.rs16
-rw-r--r--crates/ra_hir_ty/src/utils.rs83
11 files changed, 213 insertions, 180 deletions
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs
index 7706399ae..29ace8479 100644
--- a/crates/ra_hir/src/code_model.rs
+++ b/crates/ra_hir/src/code_model.rs
@@ -15,7 +15,7 @@ use hir_def::{
15 per_ns::PerNs, 15 per_ns::PerNs,
16 resolver::HasResolver, 16 resolver::HasResolver,
17 type_ref::{Mutability, TypeRef}, 17 type_ref::{Mutability, TypeRef},
18 AdtId, AstItemDef, ConstId, ContainerId, DefWithBodyId, EnumId, FunctionId, GenericDefId, 18 AdtId, AstItemDef, ConstId, ContainerId, DefWithBodyId, EnumId, FunctionId, GenericParamId,
19 HasModule, ImplId, LocalEnumVariantId, LocalImportId, LocalModuleId, LocalStructFieldId, 19 HasModule, ImplId, LocalEnumVariantId, LocalImportId, LocalModuleId, LocalStructFieldId,
20 Lookup, ModuleId, StaticId, StructId, TraitId, TypeAliasId, UnionId, 20 Lookup, ModuleId, StaticId, StructId, TraitId, TypeAliasId, UnionId,
21}; 21};
@@ -857,8 +857,7 @@ impl Local {
857 857
858#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] 858#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
859pub struct GenericParam { 859pub struct GenericParam {
860 pub(crate) parent: GenericDefId, 860 pub(crate) id: GenericParamId,
861 pub(crate) idx: u32,
862} 861}
863 862
864#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 863#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs
index 0e136b904..8c4b635d2 100644
--- a/crates/ra_hir/src/source_binder.rs
+++ b/crates/ra_hir/src/source_binder.rs
@@ -262,10 +262,7 @@ impl SourceAnalyzer {
262 ) -> Option<PathResolution> { 262 ) -> Option<PathResolution> {
263 let types = self.resolver.resolve_path_in_type_ns_fully(db, &path).map(|ty| match ty { 263 let types = self.resolver.resolve_path_in_type_ns_fully(db, &path).map(|ty| match ty {
264 TypeNs::SelfType(it) => PathResolution::SelfType(it.into()), 264 TypeNs::SelfType(it) => PathResolution::SelfType(it.into()),
265 TypeNs::GenericParam(idx) => PathResolution::GenericParam(GenericParam { 265 TypeNs::GenericParam(id) => PathResolution::GenericParam(GenericParam { id }),
266 parent: self.resolver.generic_def().unwrap(),
267 idx,
268 }),
269 TypeNs::AdtSelfType(it) | TypeNs::AdtId(it) => { 266 TypeNs::AdtSelfType(it) | TypeNs::AdtId(it) => {
270 PathResolution::Def(Adt::from(it).into()) 267 PathResolution::Def(Adt::from(it).into())
271 } 268 }
@@ -337,10 +334,7 @@ impl SourceAnalyzer {
337 resolver::ScopeDef::PerNs(it) => it.into(), 334 resolver::ScopeDef::PerNs(it) => it.into(),
338 resolver::ScopeDef::ImplSelfType(it) => ScopeDef::ImplSelfType(it.into()), 335 resolver::ScopeDef::ImplSelfType(it) => ScopeDef::ImplSelfType(it.into()),
339 resolver::ScopeDef::AdtSelfType(it) => ScopeDef::AdtSelfType(it.into()), 336 resolver::ScopeDef::AdtSelfType(it) => ScopeDef::AdtSelfType(it.into()),
340 resolver::ScopeDef::GenericParam(idx) => { 337 resolver::ScopeDef::GenericParam(id) => ScopeDef::GenericParam(GenericParam { id }),
341 let parent = self.resolver.generic_def().unwrap();
342 ScopeDef::GenericParam(GenericParam { parent, idx })
343 }
344 resolver::ScopeDef::Local(pat_id) => { 338 resolver::ScopeDef::Local(pat_id) => {
345 let parent = self.resolver.body_owner().unwrap().into(); 339 let parent = self.resolver.body_owner().unwrap().into();
346 ScopeDef::Local(Local { parent, pat_id }) 340 ScopeDef::Local(Local { parent, pat_id })
diff --git a/crates/ra_hir_def/src/generics.rs b/crates/ra_hir_def/src/generics.rs
index 5f648ffc3..94ce83564 100644
--- a/crates/ra_hir_def/src/generics.rs
+++ b/crates/ra_hir_def/src/generics.rs
@@ -5,20 +5,19 @@
5use std::sync::Arc; 5use std::sync::Arc;
6 6
7use hir_expand::name::{self, AsName, Name}; 7use hir_expand::name::{self, AsName, Name};
8use ra_arena::Arena;
8use ra_syntax::ast::{self, NameOwner, TypeBoundsOwner, TypeParamsOwner}; 9use ra_syntax::ast::{self, NameOwner, TypeBoundsOwner, TypeParamsOwner};
9 10
10use crate::{ 11use crate::{
11 db::DefDatabase, 12 db::DefDatabase,
12 src::HasSource, 13 src::HasSource,
13 type_ref::{TypeBound, TypeRef}, 14 type_ref::{TypeBound, TypeRef},
14 AdtId, AstItemDef, ContainerId, GenericDefId, Lookup, 15 AdtId, AstItemDef, GenericDefId, LocalGenericParamId, Lookup,
15}; 16};
16 17
17/// Data about a generic parameter (to a function, struct, impl, ...). 18/// Data about a generic parameter (to a function, struct, impl, ...).
18#[derive(Clone, PartialEq, Eq, Debug)] 19#[derive(Clone, PartialEq, Eq, Debug)]
19pub struct GenericParam { 20pub struct GenericParamData {
20 // FIXME: give generic params proper IDs
21 pub idx: u32,
22 pub name: Name, 21 pub name: Name,
23 pub default: Option<TypeRef>, 22 pub default: Option<TypeRef>,
24} 23}
@@ -26,8 +25,7 @@ pub struct GenericParam {
26/// Data about the generic parameters of a function, struct, impl, etc. 25/// Data about the generic parameters of a function, struct, impl, etc.
27#[derive(Clone, PartialEq, Eq, Debug)] 26#[derive(Clone, PartialEq, Eq, Debug)]
28pub struct GenericParams { 27pub struct GenericParams {
29 pub parent_params: Option<Arc<GenericParams>>, 28 pub params: Arena<LocalGenericParamId, GenericParamData>,
30 pub params: Vec<GenericParam>,
31 pub where_predicates: Vec<WherePredicate>, 29 pub where_predicates: Vec<WherePredicate>,
32} 30}
33 31
@@ -46,51 +44,40 @@ impl GenericParams {
46 db: &impl DefDatabase, 44 db: &impl DefDatabase,
47 def: GenericDefId, 45 def: GenericDefId,
48 ) -> Arc<GenericParams> { 46 ) -> Arc<GenericParams> {
49 let parent_generics = parent_generic_def(db, def).map(|it| db.generic_params(it)); 47 Arc::new(GenericParams::new(db, def.into()))
50 Arc::new(GenericParams::new(db, def.into(), parent_generics))
51 } 48 }
52 49
53 fn new( 50 fn new(db: &impl DefDatabase, def: GenericDefId) -> GenericParams {
54 db: &impl DefDatabase, 51 let mut generics = GenericParams { params: Arena::default(), where_predicates: Vec::new() };
55 def: GenericDefId,
56 parent_params: Option<Arc<GenericParams>>,
57 ) -> GenericParams {
58 let mut generics =
59 GenericParams { params: Vec::new(), parent_params, where_predicates: Vec::new() };
60 let start = generics.parent_params.as_ref().map(|p| p.params.len()).unwrap_or(0) as u32;
61 // FIXME: add `: Sized` bound for everything except for `Self` in traits 52 // FIXME: add `: Sized` bound for everything except for `Self` in traits
62 match def { 53 match def {
63 GenericDefId::FunctionId(it) => generics.fill(&it.lookup(db).source(db).value, start), 54 GenericDefId::FunctionId(it) => generics.fill(&it.lookup(db).source(db).value),
64 GenericDefId::AdtId(AdtId::StructId(it)) => generics.fill(&it.source(db).value, start), 55 GenericDefId::AdtId(AdtId::StructId(it)) => generics.fill(&it.source(db).value),
65 GenericDefId::AdtId(AdtId::UnionId(it)) => generics.fill(&it.source(db).value, start), 56 GenericDefId::AdtId(AdtId::UnionId(it)) => generics.fill(&it.source(db).value),
66 GenericDefId::AdtId(AdtId::EnumId(it)) => generics.fill(&it.source(db).value, start), 57 GenericDefId::AdtId(AdtId::EnumId(it)) => generics.fill(&it.source(db).value),
67 GenericDefId::TraitId(it) => { 58 GenericDefId::TraitId(it) => {
68 // traits get the Self type as an implicit first type parameter 59 // traits get the Self type as an implicit first type parameter
69 generics.params.push(GenericParam { 60 generics.params.alloc(GenericParamData { name: name::SELF_TYPE, default: None });
70 idx: start, 61 generics.fill(&it.source(db).value);
71 name: name::SELF_TYPE,
72 default: None,
73 });
74 generics.fill(&it.source(db).value, start + 1);
75 // add super traits as bounds on Self 62 // add super traits as bounds on Self
76 // i.e., trait Foo: Bar is equivalent to trait Foo where Self: Bar 63 // i.e., trait Foo: Bar is equivalent to trait Foo where Self: Bar
77 let self_param = TypeRef::Path(name::SELF_TYPE.into()); 64 let self_param = TypeRef::Path(name::SELF_TYPE.into());
78 generics.fill_bounds(&it.source(db).value, self_param); 65 generics.fill_bounds(&it.source(db).value, self_param);
79 } 66 }
80 GenericDefId::TypeAliasId(it) => generics.fill(&it.lookup(db).source(db).value, start), 67 GenericDefId::TypeAliasId(it) => generics.fill(&it.lookup(db).source(db).value),
81 // Note that we don't add `Self` here: in `impl`s, `Self` is not a 68 // Note that we don't add `Self` here: in `impl`s, `Self` is not a
82 // type-parameter, but rather is a type-alias for impl's target 69 // type-parameter, but rather is a type-alias for impl's target
83 // type, so this is handled by the resolver. 70 // type, so this is handled by the resolver.
84 GenericDefId::ImplId(it) => generics.fill(&it.source(db).value, start), 71 GenericDefId::ImplId(it) => generics.fill(&it.source(db).value),
85 GenericDefId::EnumVariantId(_) | GenericDefId::ConstId(_) => {} 72 GenericDefId::EnumVariantId(_) | GenericDefId::ConstId(_) => {}
86 } 73 }
87 74
88 generics 75 generics
89 } 76 }
90 77
91 fn fill(&mut self, node: &impl TypeParamsOwner, start: u32) { 78 fn fill(&mut self, node: &impl TypeParamsOwner) {
92 if let Some(params) = node.type_param_list() { 79 if let Some(params) = node.type_param_list() {
93 self.fill_params(params, start) 80 self.fill_params(params)
94 } 81 }
95 if let Some(where_clause) = node.where_clause() { 82 if let Some(where_clause) = node.where_clause() {
96 self.fill_where_predicates(where_clause); 83 self.fill_where_predicates(where_clause);
@@ -105,13 +92,13 @@ impl GenericParams {
105 } 92 }
106 } 93 }
107 94
108 fn fill_params(&mut self, params: ast::TypeParamList, start: u32) { 95 fn fill_params(&mut self, params: ast::TypeParamList) {
109 for (idx, type_param) in params.type_params().enumerate() { 96 for type_param in params.type_params() {
110 let name = type_param.name().map_or_else(Name::missing, |it| it.as_name()); 97 let name = type_param.name().map_or_else(Name::missing, |it| it.as_name());
111 // FIXME: Use `Path::from_src` 98 // FIXME: Use `Path::from_src`
112 let default = type_param.default_type().map(TypeRef::from_ast); 99 let default = type_param.default_type().map(TypeRef::from_ast);
113 let param = GenericParam { idx: idx as u32 + start, name: name.clone(), default }; 100 let param = GenericParamData { name: name.clone(), default };
114 self.params.push(param); 101 self.params.alloc(param);
115 102
116 let type_ref = TypeRef::Path(name.into()); 103 let type_ref = TypeRef::Path(name.into());
117 self.fill_bounds(&type_param, type_ref); 104 self.fill_bounds(&type_param, type_ref);
@@ -140,45 +127,7 @@ impl GenericParams {
140 self.where_predicates.push(WherePredicate { type_ref, bound }); 127 self.where_predicates.push(WherePredicate { type_ref, bound });
141 } 128 }
142 129
143 pub fn find_by_name(&self, name: &Name) -> Option<&GenericParam> { 130 pub fn find_by_name(&self, name: &Name) -> Option<LocalGenericParamId> {
144 self.params.iter().find(|p| &p.name == name) 131 self.params.iter().find_map(|(id, p)| if &p.name == name { Some(id) } else { None })
145 }
146
147 pub fn count_parent_params(&self) -> usize {
148 self.parent_params.as_ref().map(|p| p.count_params_including_parent()).unwrap_or(0)
149 }
150
151 pub fn count_params_including_parent(&self) -> usize {
152 let parent_count = self.count_parent_params();
153 parent_count + self.params.len()
154 }
155
156 fn for_each_param<'a>(&'a self, f: &mut impl FnMut(&'a GenericParam)) {
157 if let Some(parent) = &self.parent_params {
158 parent.for_each_param(f);
159 }
160 self.params.iter().for_each(f);
161 }
162
163 pub fn params_including_parent(&self) -> Vec<&GenericParam> {
164 let mut vec = Vec::with_capacity(self.count_params_including_parent());
165 self.for_each_param(&mut |p| vec.push(p));
166 vec
167 }
168}
169
170fn parent_generic_def(db: &impl DefDatabase, def: GenericDefId) -> Option<GenericDefId> {
171 let container = match def {
172 GenericDefId::FunctionId(it) => it.lookup(db).container,
173 GenericDefId::TypeAliasId(it) => it.lookup(db).container,
174 GenericDefId::ConstId(it) => it.lookup(db).container,
175 GenericDefId::EnumVariantId(it) => return Some(it.parent.into()),
176 GenericDefId::AdtId(_) | GenericDefId::TraitId(_) | GenericDefId::ImplId(_) => return None,
177 };
178
179 match container {
180 ContainerId::ImplId(it) => Some(it.into()),
181 ContainerId::TraitId(it) => Some(it.into()),
182 ContainerId::ModuleId(_) => None,
183 } 132 }
184} 133}
diff --git a/crates/ra_hir_def/src/lib.rs b/crates/ra_hir_def/src/lib.rs
index 68e66d276..b8dfc0ab1 100644
--- a/crates/ra_hir_def/src/lib.rs
+++ b/crates/ra_hir_def/src/lib.rs
@@ -318,6 +318,16 @@ macro_rules! impl_froms {
318} 318}
319 319
320#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 320#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
321pub struct GenericParamId {
322 pub parent: GenericDefId,
323 pub local_id: LocalGenericParamId,
324}
325
326#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
327pub struct LocalGenericParamId(RawId);
328impl_arena_id!(LocalGenericParamId);
329
330#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
321pub enum ContainerId { 331pub enum ContainerId {
322 ModuleId(ModuleId), 332 ModuleId(ModuleId),
323 ImplId(ImplId), 333 ImplId(ImplId),
diff --git a/crates/ra_hir_def/src/resolver.rs b/crates/ra_hir_def/src/resolver.rs
index 7d4df222e..e00bd03d5 100644
--- a/crates/ra_hir_def/src/resolver.rs
+++ b/crates/ra_hir_def/src/resolver.rs
@@ -18,12 +18,13 @@ use crate::{
18 path::{Path, PathKind}, 18 path::{Path, PathKind},
19 per_ns::PerNs, 19 per_ns::PerNs,
20 AdtId, AstItemDef, ConstId, ContainerId, DefWithBodyId, EnumId, EnumVariantId, FunctionId, 20 AdtId, AstItemDef, ConstId, ContainerId, DefWithBodyId, EnumId, EnumVariantId, FunctionId,
21 GenericDefId, HasModule, ImplId, LocalModuleId, Lookup, ModuleDefId, ModuleId, StaticId, 21 GenericDefId, GenericParamId, HasModule, ImplId, LocalModuleId, Lookup, ModuleDefId, ModuleId,
22 StructId, TraitId, TypeAliasId, 22 StaticId, StructId, TraitId, TypeAliasId,
23}; 23};
24 24
25#[derive(Debug, Clone, Default)] 25#[derive(Debug, Clone, Default)]
26pub struct Resolver { 26pub struct Resolver {
27 // FIXME: all usages generally call `.rev`, so maybe reverse once in consturciton?
27 scopes: Vec<Scope>, 28 scopes: Vec<Scope>,
28} 29}
29 30
@@ -58,7 +59,7 @@ enum Scope {
58#[derive(Debug, Clone, PartialEq, Eq, Hash)] 59#[derive(Debug, Clone, PartialEq, Eq, Hash)]
59pub enum TypeNs { 60pub enum TypeNs {
60 SelfType(ImplId), 61 SelfType(ImplId),
61 GenericParam(u32), 62 GenericParam(GenericParamId),
62 AdtId(AdtId), 63 AdtId(AdtId),
63 AdtSelfType(AdtId), 64 AdtSelfType(AdtId),
64 // Yup, enum variants are added to the types ns, but any usage of variant as 65 // Yup, enum variants are added to the types ns, but any usage of variant as
@@ -152,10 +153,13 @@ impl Resolver {
152 Scope::ExprScope(_) => continue, 153 Scope::ExprScope(_) => continue,
153 Scope::GenericParams { .. } | Scope::ImplBlockScope(_) if skip_to_mod => continue, 154 Scope::GenericParams { .. } | Scope::ImplBlockScope(_) if skip_to_mod => continue,
154 155
155 Scope::GenericParams { params, .. } => { 156 Scope::GenericParams { params, def } => {
156 if let Some(param) = params.find_by_name(first_name) { 157 if let Some(local_id) = params.find_by_name(first_name) {
157 let idx = if path.segments.len() == 1 { None } else { Some(1) }; 158 let idx = if path.segments.len() == 1 { None } else { Some(1) };
158 return Some((TypeNs::GenericParam(param.idx), idx)); 159 return Some((
160 TypeNs::GenericParam(GenericParamId { local_id, parent: *def }),
161 idx,
162 ));
159 } 163 }
160 } 164 }
161 Scope::ImplBlockScope(impl_) => { 165 Scope::ImplBlockScope(impl_) => {
@@ -246,9 +250,9 @@ impl Resolver {
246 } 250 }
247 Scope::ExprScope(_) => continue, 251 Scope::ExprScope(_) => continue,
248 252
249 Scope::GenericParams { params, .. } if n_segments > 1 => { 253 Scope::GenericParams { params, def } if n_segments > 1 => {
250 if let Some(param) = params.find_by_name(first_name) { 254 if let Some(local_id) = params.find_by_name(first_name) {
251 let ty = TypeNs::GenericParam(param.idx); 255 let ty = TypeNs::GenericParam(GenericParamId { local_id, parent: *def });
252 return Some(ResolveValueResult::Partial(ty, 1)); 256 return Some(ResolveValueResult::Partial(ty, 1));
253 } 257 }
254 } 258 }
@@ -368,6 +372,7 @@ impl Resolver {
368 ) -> impl Iterator<Item = &'a crate::generics::WherePredicate> + 'a { 372 ) -> impl Iterator<Item = &'a crate::generics::WherePredicate> + 'a {
369 self.scopes 373 self.scopes
370 .iter() 374 .iter()
375 .rev()
371 .filter_map(|scope| match scope { 376 .filter_map(|scope| match scope {
372 Scope::GenericParams { params, .. } => Some(params), 377 Scope::GenericParams { params, .. } => Some(params),
373 _ => None, 378 _ => None,
@@ -376,14 +381,14 @@ impl Resolver {
376 } 381 }
377 382
378 pub fn generic_def(&self) -> Option<GenericDefId> { 383 pub fn generic_def(&self) -> Option<GenericDefId> {
379 self.scopes.iter().find_map(|scope| match scope { 384 self.scopes.iter().rev().find_map(|scope| match scope {
380 Scope::GenericParams { def, .. } => Some(*def), 385 Scope::GenericParams { def, .. } => Some(*def),
381 _ => None, 386 _ => None,
382 }) 387 })
383 } 388 }
384 389
385 pub fn body_owner(&self) -> Option<DefWithBodyId> { 390 pub fn body_owner(&self) -> Option<DefWithBodyId> {
386 self.scopes.iter().find_map(|scope| match scope { 391 self.scopes.iter().rev().find_map(|scope| match scope {
387 Scope::ExprScope(it) => Some(it.owner), 392 Scope::ExprScope(it) => Some(it.owner),
388 _ => None, 393 _ => None,
389 }) 394 })
@@ -394,7 +399,7 @@ pub enum ScopeDef {
394 PerNs(PerNs), 399 PerNs(PerNs),
395 ImplSelfType(ImplId), 400 ImplSelfType(ImplId),
396 AdtSelfType(AdtId), 401 AdtSelfType(AdtId),
397 GenericParam(u32), 402 GenericParam(GenericParamId),
398 Local(PatId), 403 Local(PatId),
399} 404}
400 405
@@ -425,9 +430,12 @@ impl Scope {
425 }); 430 });
426 } 431 }
427 } 432 }
428 Scope::GenericParams { params, .. } => { 433 Scope::GenericParams { params, def } => {
429 for param in params.params.iter() { 434 for (local_id, param) in params.params.iter() {
430 f(param.name.clone(), ScopeDef::GenericParam(param.idx)) 435 f(
436 param.name.clone(),
437 ScopeDef::GenericParam(GenericParamId { local_id, parent: *def }),
438 )
431 } 439 }
432 } 440 }
433 Scope::ImplBlockScope(i) => { 441 Scope::ImplBlockScope(i) => {
diff --git a/crates/ra_hir_ty/src/autoderef.rs b/crates/ra_hir_ty/src/autoderef.rs
index 9d1d4e48c..d557962b4 100644
--- a/crates/ra_hir_ty/src/autoderef.rs
+++ b/crates/ra_hir_ty/src/autoderef.rs
@@ -10,10 +10,10 @@ use hir_expand::name;
10use log::{info, warn}; 10use log::{info, warn};
11use ra_db::CrateId; 11use ra_db::CrateId;
12 12
13use crate::db::HirDatabase; 13use crate::{
14 14 db::HirDatabase,
15use super::{
16 traits::{InEnvironment, Solution}, 15 traits::{InEnvironment, Solution},
16 utils::generics,
17 Canonical, Substs, Ty, TypeWalk, 17 Canonical, Substs, Ty, TypeWalk,
18}; 18};
19 19
@@ -54,8 +54,8 @@ fn deref_by_trait(
54 }; 54 };
55 let target = db.trait_data(deref_trait).associated_type_by_name(&name::TARGET_TYPE)?; 55 let target = db.trait_data(deref_trait).associated_type_by_name(&name::TARGET_TYPE)?;
56 56
57 let generic_params = db.generic_params(target.into()); 57 let generic_params = generics(db, target.into());
58 if generic_params.count_params_including_parent() != 1 { 58 if generic_params.len() != 1 {
59 // the Target type + Deref trait should only have one generic parameter, 59 // the Target type + Deref trait should only have one generic parameter,
60 // namely Deref's Self type 60 // namely Deref's Self type
61 return None; 61 return None;
diff --git a/crates/ra_hir_ty/src/infer/expr.rs b/crates/ra_hir_ty/src/infer/expr.rs
index b8df27706..2c296987c 100644
--- a/crates/ra_hir_ty/src/infer/expr.rs
+++ b/crates/ra_hir_ty/src/infer/expr.rs
@@ -6,7 +6,6 @@ use std::sync::Arc;
6use hir_def::{ 6use hir_def::{
7 builtin_type::Signedness, 7 builtin_type::Signedness,
8 expr::{Array, BinaryOp, Expr, ExprId, Literal, Statement, UnaryOp}, 8 expr::{Array, BinaryOp, Expr, ExprId, Literal, Statement, UnaryOp},
9 generics::GenericParams,
10 path::{GenericArg, GenericArgs}, 9 path::{GenericArg, GenericArgs},
11 resolver::resolver_for_expr, 10 resolver::resolver_for_expr,
12 AdtId, ContainerId, Lookup, StructFieldId, 11 AdtId, ContainerId, Lookup, StructFieldId,
@@ -15,7 +14,11 @@ use hir_expand::name::{self, Name};
15use ra_syntax::ast::RangeOp; 14use ra_syntax::ast::RangeOp;
16 15
17use crate::{ 16use crate::{
18 autoderef, db::HirDatabase, method_resolution, op, traits::InEnvironment, utils::variant_data, 17 autoderef,
18 db::HirDatabase,
19 method_resolution, op,
20 traits::InEnvironment,
21 utils::{generics, variant_data, Generics},
19 CallableDef, InferTy, IntTy, Mutability, Obligation, ProjectionPredicate, ProjectionTy, Substs, 22 CallableDef, InferTy, IntTy, Mutability, Obligation, ProjectionPredicate, ProjectionTy, Substs,
20 TraitRef, Ty, TypeCtor, TypeWalk, Uncertain, 23 TraitRef, Ty, TypeCtor, TypeWalk, Uncertain,
21}; 24};
@@ -596,7 +599,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
596 Some((ty, func)) => { 599 Some((ty, func)) => {
597 let ty = canonicalized_receiver.decanonicalize_ty(ty); 600 let ty = canonicalized_receiver.decanonicalize_ty(ty);
598 self.write_method_resolution(tgt_expr, func); 601 self.write_method_resolution(tgt_expr, func);
599 (ty, self.db.value_ty(func.into()), Some(self.db.generic_params(func.into()))) 602 (ty, self.db.value_ty(func.into()), Some(generics(self.db, func.into())))
600 } 603 }
601 None => (receiver_ty, Ty::Unknown, None), 604 None => (receiver_ty, Ty::Unknown, None),
602 }; 605 };
@@ -653,16 +656,16 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
653 656
654 fn substs_for_method_call( 657 fn substs_for_method_call(
655 &mut self, 658 &mut self,
656 def_generics: Option<Arc<GenericParams>>, 659 def_generics: Option<Generics>,
657 generic_args: Option<&GenericArgs>, 660 generic_args: Option<&GenericArgs>,
658 receiver_ty: &Ty, 661 receiver_ty: &Ty,
659 ) -> Substs { 662 ) -> Substs {
660 let (parent_param_count, param_count) = 663 let (total_len, _parent_len, child_len) =
661 def_generics.as_ref().map_or((0, 0), |g| (g.count_parent_params(), g.params.len())); 664 def_generics.as_ref().map_or((0, 0, 0), |g| g.len_split());
662 let mut substs = Vec::with_capacity(parent_param_count + param_count); 665 let mut substs = Vec::with_capacity(total_len);
663 // Parent arguments are unknown, except for the receiver type 666 // Parent arguments are unknown, except for the receiver type
664 if let Some(parent_generics) = def_generics.and_then(|p| p.parent_params.clone()) { 667 if let Some(parent_generics) = def_generics.as_ref().map(|p| p.iter_parent()) {
665 for param in &parent_generics.params { 668 for (_id, param) in parent_generics {
666 if param.name == name::SELF_TYPE { 669 if param.name == name::SELF_TYPE {
667 substs.push(receiver_ty.clone()); 670 substs.push(receiver_ty.clone());
668 } else { 671 } else {
@@ -673,7 +676,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
673 // handle provided type arguments 676 // handle provided type arguments
674 if let Some(generic_args) = generic_args { 677 if let Some(generic_args) = generic_args {
675 // if args are provided, it should be all of them, but we can't rely on that 678 // if args are provided, it should be all of them, but we can't rely on that
676 for arg in generic_args.args.iter().take(param_count) { 679 for arg in generic_args.args.iter().take(child_len) {
677 match arg { 680 match arg {
678 GenericArg::Type(type_ref) => { 681 GenericArg::Type(type_ref) => {
679 let ty = self.make_ty(type_ref); 682 let ty = self.make_ty(type_ref);
@@ -683,10 +686,10 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
683 } 686 }
684 }; 687 };
685 let supplied_params = substs.len(); 688 let supplied_params = substs.len();
686 for _ in supplied_params..parent_param_count + param_count { 689 for _ in supplied_params..total_len {
687 substs.push(Ty::Unknown); 690 substs.push(Ty::Unknown);
688 } 691 }
689 assert_eq!(substs.len(), parent_param_count + param_count); 692 assert_eq!(substs.len(), total_len);
690 Substs(substs.into()) 693 Substs(substs.into())
691 } 694 }
692 695
@@ -705,11 +708,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
705 CallableDef::FunctionId(f) => { 708 CallableDef::FunctionId(f) => {
706 if let ContainerId::TraitId(trait_) = f.lookup(self.db).container { 709 if let ContainerId::TraitId(trait_) = f.lookup(self.db).container {
707 // construct a TraitDef 710 // construct a TraitDef
708 let substs = a_ty.parameters.prefix( 711 let substs =
709 self.db 712 a_ty.parameters.prefix(generics(self.db, trait_.into()).len());
710 .generic_params(trait_.into())
711 .count_params_including_parent(),
712 );
713 self.obligations.push(Obligation::Trait(TraitRef { 713 self.obligations.push(Obligation::Trait(TraitRef {
714 trait_: trait_.into(), 714 trait_: trait_.into(),
715 substs, 715 substs,
diff --git a/crates/ra_hir_ty/src/lib.rs b/crates/ra_hir_ty/src/lib.rs
index 3c1f738df..3ad913e55 100644
--- a/crates/ra_hir_ty/src/lib.rs
+++ b/crates/ra_hir_ty/src/lib.rs
@@ -44,8 +44,8 @@ use std::sync::Arc;
44use std::{fmt, iter, mem}; 44use std::{fmt, iter, mem};
45 45
46use hir_def::{ 46use hir_def::{
47 expr::ExprId, generics::GenericParams, type_ref::Mutability, AdtId, ContainerId, DefWithBodyId, 47 expr::ExprId, type_ref::Mutability, AdtId, ContainerId, DefWithBodyId, GenericDefId, HasModule,
48 GenericDefId, HasModule, Lookup, TraitId, TypeAliasId, 48 Lookup, TraitId, TypeAliasId,
49}; 49};
50use hir_expand::name::Name; 50use hir_expand::name::Name;
51use ra_db::{impl_intern_key, salsa, CrateId}; 51use ra_db::{impl_intern_key, salsa, CrateId};
@@ -53,7 +53,7 @@ use ra_db::{impl_intern_key, salsa, CrateId};
53use crate::{ 53use crate::{
54 db::HirDatabase, 54 db::HirDatabase,
55 primitive::{FloatTy, IntTy, Uncertain}, 55 primitive::{FloatTy, IntTy, Uncertain},
56 utils::make_mut_slice, 56 utils::{generics, make_mut_slice, Generics},
57}; 57};
58use display::{HirDisplay, HirFormatter}; 58use display::{HirDisplay, HirFormatter};
59 59
@@ -166,16 +166,16 @@ impl TypeCtor {
166 | TypeCtor::Closure { .. } // 1 param representing the signature of the closure 166 | TypeCtor::Closure { .. } // 1 param representing the signature of the closure
167 => 1, 167 => 1,
168 TypeCtor::Adt(adt) => { 168 TypeCtor::Adt(adt) => {
169 let generic_params = db.generic_params(AdtId::from(adt).into()); 169 let generic_params = generics(db, AdtId::from(adt).into());
170 generic_params.count_params_including_parent() 170 generic_params.len()
171 } 171 }
172 TypeCtor::FnDef(callable) => { 172 TypeCtor::FnDef(callable) => {
173 let generic_params = db.generic_params(callable.into()); 173 let generic_params = generics(db, callable.into());
174 generic_params.count_params_including_parent() 174 generic_params.len()
175 } 175 }
176 TypeCtor::AssociatedType(type_alias) => { 176 TypeCtor::AssociatedType(type_alias) => {
177 let generic_params = db.generic_params(type_alias.into()); 177 let generic_params = generics(db, type_alias.into());
178 generic_params.count_params_including_parent() 178 generic_params.len()
179 } 179 }
180 TypeCtor::FnPtr { num_args } => num_args as usize + 1, 180 TypeCtor::FnPtr { num_args } => num_args as usize + 1,
181 TypeCtor::Tuple { cardinality } => cardinality as usize, 181 TypeCtor::Tuple { cardinality } => cardinality as usize,
@@ -364,36 +364,26 @@ impl Substs {
364 } 364 }
365 365
366 /// Return Substs that replace each parameter by itself (i.e. `Ty::Param`). 366 /// Return Substs that replace each parameter by itself (i.e. `Ty::Param`).
367 pub fn identity(generic_params: &GenericParams) -> Substs { 367 pub(crate) fn identity(generic_params: &Generics) -> Substs {
368 Substs( 368 Substs(
369 generic_params 369 generic_params.iter().map(|(idx, p)| Ty::Param { idx, name: p.name.clone() }).collect(),
370 .params_including_parent()
371 .into_iter()
372 .map(|p| Ty::Param { idx: p.idx, name: p.name.clone() })
373 .collect(),
374 ) 370 )
375 } 371 }
376 372
377 /// Return Substs that replace each parameter by a bound variable. 373 /// Return Substs that replace each parameter by a bound variable.
378 pub fn bound_vars(generic_params: &GenericParams) -> Substs { 374 pub(crate) fn bound_vars(generic_params: &Generics) -> Substs {
379 Substs( 375 Substs(generic_params.iter().map(|(idx, _p)| Ty::Bound(idx)).collect())
380 generic_params
381 .params_including_parent()
382 .into_iter()
383 .map(|p| Ty::Bound(p.idx))
384 .collect(),
385 )
386 } 376 }
387 377
388 pub fn build_for_def(db: &impl HirDatabase, def: impl Into<GenericDefId>) -> SubstsBuilder { 378 pub fn build_for_def(db: &impl HirDatabase, def: impl Into<GenericDefId>) -> SubstsBuilder {
389 let def = def.into(); 379 let def = def.into();
390 let params = db.generic_params(def); 380 let params = generics(db, def);
391 let param_count = params.count_params_including_parent(); 381 let param_count = params.len();
392 Substs::builder(param_count) 382 Substs::builder(param_count)
393 } 383 }
394 384
395 pub fn build_for_generics(generic_params: &GenericParams) -> SubstsBuilder { 385 pub(crate) fn build_for_generics(generic_params: &Generics) -> SubstsBuilder {
396 Substs::builder(generic_params.count_params_including_parent()) 386 Substs::builder(generic_params.len())
397 } 387 }
398 388
399 pub fn build_for_type_ctor(db: &impl HirDatabase, type_ctor: TypeCtor) -> SubstsBuilder { 389 pub fn build_for_type_ctor(db: &impl HirDatabase, type_ctor: TypeCtor) -> SubstsBuilder {
diff --git a/crates/ra_hir_ty/src/lower.rs b/crates/ra_hir_ty/src/lower.rs
index 32569ac66..eab91229e 100644
--- a/crates/ra_hir_ty/src/lower.rs
+++ b/crates/ra_hir_ty/src/lower.rs
@@ -24,7 +24,7 @@ use crate::{
24 db::HirDatabase, 24 db::HirDatabase,
25 primitive::{FloatTy, IntTy}, 25 primitive::{FloatTy, IntTy},
26 utils::{ 26 utils::{
27 all_super_traits, associated_type_by_name_including_super_traits, make_mut_slice, 27 all_super_traits, associated_type_by_name_including_super_traits, generics, make_mut_slice,
28 variant_data, 28 variant_data,
29 }, 29 },
30 FnSig, GenericPredicate, ProjectionPredicate, ProjectionTy, Substs, TraitEnvironment, TraitRef, 30 FnSig, GenericPredicate, ProjectionPredicate, ProjectionTy, Substs, TraitEnvironment, TraitRef,
@@ -111,7 +111,9 @@ impl Ty {
111 Some((it, None)) => it, 111 Some((it, None)) => it,
112 _ => return None, 112 _ => return None,
113 }; 113 };
114 if let TypeNs::GenericParam(idx) = resolution { 114 if let TypeNs::GenericParam(param_id) = resolution {
115 let generics = generics(db, resolver.generic_def().expect("generics in scope"));
116 let idx = generics.param_idx(param_id);
115 Some(idx) 117 Some(idx)
116 } else { 118 } else {
117 None 119 None
@@ -174,9 +176,11 @@ impl Ty {
174 Ty::Dyn(Arc::new([GenericPredicate::Implemented(trait_ref)])) 176 Ty::Dyn(Arc::new([GenericPredicate::Implemented(trait_ref)]))
175 }; 177 };
176 } 178 }
177 TypeNs::GenericParam(idx) => { 179 TypeNs::GenericParam(param_id) => {
180 let generics = generics(db, resolver.generic_def().expect("generics in scope"));
181 let idx = generics.param_idx(param_id);
178 // FIXME: maybe return name in resolution? 182 // FIXME: maybe return name in resolution?
179 let name = resolved_segment.name.clone(); 183 let name = generics.param_name(param_id);
180 Ty::Param { idx, name } 184 Ty::Param { idx, name }
181 } 185 }
182 TypeNs::SelfType(impl_id) => db.impl_self_ty(impl_id).clone(), 186 TypeNs::SelfType(impl_id) => db.impl_self_ty(impl_id).clone(),
@@ -315,11 +319,10 @@ pub(super) fn substs_from_path_segment(
315 add_self_param: bool, 319 add_self_param: bool,
316) -> Substs { 320) -> Substs {
317 let mut substs = Vec::new(); 321 let mut substs = Vec::new();
318 let def_generics = def_generic.map(|def| db.generic_params(def.into())); 322 let def_generics = def_generic.map(|def| generics(db, def.into()));
319 323
320 let (parent_param_count, param_count) = 324 let (total_len, parent_len, child_len) = def_generics.map_or((0, 0, 0), |g| g.len_split());
321 def_generics.map_or((0, 0), |g| (g.count_parent_params(), g.params.len())); 325 substs.extend(iter::repeat(Ty::Unknown).take(parent_len));
322 substs.extend(iter::repeat(Ty::Unknown).take(parent_param_count));
323 if add_self_param { 326 if add_self_param {
324 // FIXME this add_self_param argument is kind of a hack: Traits have the 327 // FIXME this add_self_param argument is kind of a hack: Traits have the
325 // Self type as an implicit first type parameter, but it can't be 328 // Self type as an implicit first type parameter, but it can't be
@@ -330,8 +333,8 @@ pub(super) fn substs_from_path_segment(
330 if let Some(generic_args) = &segment.args_and_bindings { 333 if let Some(generic_args) = &segment.args_and_bindings {
331 // if args are provided, it should be all of them, but we can't rely on that 334 // if args are provided, it should be all of them, but we can't rely on that
332 let self_param_correction = if add_self_param { 1 } else { 0 }; 335 let self_param_correction = if add_self_param { 1 } else { 0 };
333 let param_count = param_count - self_param_correction; 336 let child_len = child_len + self_param_correction;
334 for arg in generic_args.args.iter().take(param_count) { 337 for arg in generic_args.args.iter().take(child_len) {
335 match arg { 338 match arg {
336 GenericArg::Type(type_ref) => { 339 GenericArg::Type(type_ref) => {
337 let ty = Ty::from_hir(db, resolver, type_ref); 340 let ty = Ty::from_hir(db, resolver, type_ref);
@@ -342,10 +345,10 @@ pub(super) fn substs_from_path_segment(
342 } 345 }
343 // add placeholders for args that were not provided 346 // add placeholders for args that were not provided
344 let supplied_params = substs.len(); 347 let supplied_params = substs.len();
345 for _ in supplied_params..parent_param_count + param_count { 348 for _ in supplied_params..total_len {
346 substs.push(Ty::Unknown); 349 substs.push(Ty::Unknown);
347 } 350 }
348 assert_eq!(substs.len(), parent_param_count + param_count); 351 assert_eq!(substs.len(), total_len);
349 352
350 // handle defaults 353 // handle defaults
351 if let Some(def_generic) = def_generic { 354 if let Some(def_generic) = def_generic {
@@ -567,12 +570,11 @@ pub(crate) fn generic_predicates_query(
567/// Resolve the default type params from generics 570/// Resolve the default type params from generics
568pub(crate) fn generic_defaults_query(db: &impl HirDatabase, def: GenericDefId) -> Substs { 571pub(crate) fn generic_defaults_query(db: &impl HirDatabase, def: GenericDefId) -> Substs {
569 let resolver = def.resolver(db); 572 let resolver = def.resolver(db);
570 let generic_params = db.generic_params(def.into()); 573 let generic_params = generics(db, def.into());
571 574
572 let defaults = generic_params 575 let defaults = generic_params
573 .params_including_parent() 576 .iter()
574 .into_iter() 577 .map(|(_idx, p)| p.default.as_ref().map_or(Ty::Unknown, |t| Ty::from_hir(db, &resolver, t)))
575 .map(|p| p.default.as_ref().map_or(Ty::Unknown, |t| Ty::from_hir(db, &resolver, t)))
576 .collect(); 578 .collect();
577 579
578 Substs(defaults) 580 Substs(defaults)
@@ -589,7 +591,7 @@ fn fn_sig_for_fn(db: &impl HirDatabase, def: FunctionId) -> FnSig {
589/// Build the declared type of a function. This should not need to look at the 591/// Build the declared type of a function. This should not need to look at the
590/// function body. 592/// function body.
591fn type_for_fn(db: &impl HirDatabase, def: FunctionId) -> Ty { 593fn type_for_fn(db: &impl HirDatabase, def: FunctionId) -> Ty {
592 let generics = db.generic_params(def.into()); 594 let generics = generics(db, def.into());
593 let substs = Substs::identity(&generics); 595 let substs = Substs::identity(&generics);
594 Ty::apply(TypeCtor::FnDef(def.into()), substs) 596 Ty::apply(TypeCtor::FnDef(def.into()), substs)
595} 597}
@@ -639,7 +641,7 @@ fn type_for_struct_constructor(db: &impl HirDatabase, def: StructId) -> Ty {
639 if struct_data.variant_data.is_unit() { 641 if struct_data.variant_data.is_unit() {
640 return type_for_adt(db, def.into()); // Unit struct 642 return type_for_adt(db, def.into()); // Unit struct
641 } 643 }
642 let generics = db.generic_params(def.into()); 644 let generics = generics(db, def.into());
643 let substs = Substs::identity(&generics); 645 let substs = Substs::identity(&generics);
644 Ty::apply(TypeCtor::FnDef(def.into()), substs) 646 Ty::apply(TypeCtor::FnDef(def.into()), substs)
645} 647}
@@ -653,7 +655,7 @@ fn fn_sig_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariantId
653 .iter() 655 .iter()
654 .map(|(_, field)| Ty::from_hir(db, &resolver, &field.type_ref)) 656 .map(|(_, field)| Ty::from_hir(db, &resolver, &field.type_ref))
655 .collect::<Vec<_>>(); 657 .collect::<Vec<_>>();
656 let generics = db.generic_params(def.parent.into()); 658 let generics = generics(db, def.parent.into());
657 let substs = Substs::identity(&generics); 659 let substs = Substs::identity(&generics);
658 let ret = type_for_adt(db, def.parent.into()).subst(&substs); 660 let ret = type_for_adt(db, def.parent.into()).subst(&substs);
659 FnSig::from_params_and_return(params, ret) 661 FnSig::from_params_and_return(params, ret)
@@ -666,18 +668,18 @@ fn type_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariantId)
666 if var_data.is_unit() { 668 if var_data.is_unit() {
667 return type_for_adt(db, def.parent.into()); // Unit variant 669 return type_for_adt(db, def.parent.into()); // Unit variant
668 } 670 }
669 let generics = db.generic_params(def.parent.into()); 671 let generics = generics(db, def.parent.into());
670 let substs = Substs::identity(&generics); 672 let substs = Substs::identity(&generics);
671 Ty::apply(TypeCtor::FnDef(EnumVariantId::from(def).into()), substs) 673 Ty::apply(TypeCtor::FnDef(EnumVariantId::from(def).into()), substs)
672} 674}
673 675
674fn type_for_adt(db: &impl HirDatabase, adt: AdtId) -> Ty { 676fn type_for_adt(db: &impl HirDatabase, adt: AdtId) -> Ty {
675 let generics = db.generic_params(adt.into()); 677 let generics = generics(db, adt.into());
676 Ty::apply(TypeCtor::Adt(adt), Substs::identity(&generics)) 678 Ty::apply(TypeCtor::Adt(adt), Substs::identity(&generics))
677} 679}
678 680
679fn type_for_type_alias(db: &impl HirDatabase, t: TypeAliasId) -> Ty { 681fn type_for_type_alias(db: &impl HirDatabase, t: TypeAliasId) -> Ty {
680 let generics = db.generic_params(t.into()); 682 let generics = generics(db, t.into());
681 let resolver = t.resolver(db); 683 let resolver = t.resolver(db);
682 let type_ref = &db.type_alias_data(t).type_ref; 684 let type_ref = &db.type_alias_data(t).type_ref;
683 let substs = Substs::identity(&generics); 685 let substs = Substs::identity(&generics);
diff --git a/crates/ra_hir_ty/src/traits/chalk.rs b/crates/ra_hir_ty/src/traits/chalk.rs
index e3f02fa15..1e7ff93d5 100644
--- a/crates/ra_hir_ty/src/traits/chalk.rs
+++ b/crates/ra_hir_ty/src/traits/chalk.rs
@@ -19,8 +19,8 @@ use ra_db::{
19 19
20use super::{builtin, AssocTyValue, Canonical, ChalkContext, Impl, Obligation}; 20use super::{builtin, AssocTyValue, Canonical, ChalkContext, Impl, Obligation};
21use crate::{ 21use crate::{
22 db::HirDatabase, display::HirDisplay, ApplicationTy, GenericPredicate, ProjectionTy, Substs, 22 db::HirDatabase, display::HirDisplay, utils::generics, ApplicationTy, GenericPredicate,
23 TraitRef, Ty, TypeCtor, TypeWalk, 23 ProjectionTy, Substs, TraitRef, Ty, TypeCtor, TypeWalk,
24}; 24};
25 25
26/// This represents a trait whose name we could not resolve. 26/// This represents a trait whose name we could not resolve.
@@ -547,7 +547,7 @@ pub(crate) fn associated_ty_data_query(
547 ContainerId::TraitId(t) => t, 547 ContainerId::TraitId(t) => t,
548 _ => panic!("associated type not in trait"), 548 _ => panic!("associated type not in trait"),
549 }; 549 };
550 let generic_params = db.generic_params(type_alias.into()); 550 let generic_params = generics(db, type_alias.into());
551 let bound_data = chalk_rust_ir::AssociatedTyDatumBound { 551 let bound_data = chalk_rust_ir::AssociatedTyDatumBound {
552 // FIXME add bounds and where clauses 552 // FIXME add bounds and where clauses
553 bounds: vec![], 553 bounds: vec![],
@@ -557,7 +557,7 @@ pub(crate) fn associated_ty_data_query(
557 trait_id: trait_.to_chalk(db), 557 trait_id: trait_.to_chalk(db),
558 id, 558 id,
559 name: lalrpop_intern::intern(&db.type_alias_data(type_alias).name.to_string()), 559 name: lalrpop_intern::intern(&db.type_alias_data(type_alias).name.to_string()),
560 binders: make_binders(bound_data, generic_params.count_params_including_parent()), 560 binders: make_binders(bound_data, generic_params.len()),
561 }; 561 };
562 Arc::new(datum) 562 Arc::new(datum)
563} 563}
@@ -589,7 +589,7 @@ pub(crate) fn trait_datum_query(
589 let trait_: TraitId = from_chalk(db, trait_id); 589 let trait_: TraitId = from_chalk(db, trait_id);
590 let trait_data = db.trait_data(trait_); 590 let trait_data = db.trait_data(trait_);
591 debug!("trait {:?} = {:?}", trait_id, trait_data.name); 591 debug!("trait {:?} = {:?}", trait_id, trait_data.name);
592 let generic_params = db.generic_params(trait_.into()); 592 let generic_params = generics(db, trait_.into());
593 let bound_vars = Substs::bound_vars(&generic_params); 593 let bound_vars = Substs::bound_vars(&generic_params);
594 let flags = chalk_rust_ir::TraitFlags { 594 let flags = chalk_rust_ir::TraitFlags {
595 auto: trait_data.auto, 595 auto: trait_data.auto,
@@ -626,7 +626,7 @@ pub(crate) fn struct_datum_query(
626 let where_clauses = type_ctor 626 let where_clauses = type_ctor
627 .as_generic_def() 627 .as_generic_def()
628 .map(|generic_def| { 628 .map(|generic_def| {
629 let generic_params = db.generic_params(generic_def.into()); 629 let generic_params = generics(db, generic_def.into());
630 let bound_vars = Substs::bound_vars(&generic_params); 630 let bound_vars = Substs::bound_vars(&generic_params);
631 convert_where_clauses(db, generic_def, &bound_vars) 631 convert_where_clauses(db, generic_def, &bound_vars)
632 }) 632 })
@@ -669,7 +669,7 @@ fn impl_block_datum(
669 let trait_ref = db.impl_trait(impl_id)?; 669 let trait_ref = db.impl_trait(impl_id)?;
670 let impl_data = db.impl_data(impl_id); 670 let impl_data = db.impl_data(impl_id);
671 671
672 let generic_params = db.generic_params(impl_id.into()); 672 let generic_params = generics(db, impl_id.into());
673 let bound_vars = Substs::bound_vars(&generic_params); 673 let bound_vars = Substs::bound_vars(&generic_params);
674 let trait_ref = trait_ref.subst(&bound_vars); 674 let trait_ref = trait_ref.subst(&bound_vars);
675 let trait_ = trait_ref.trait_; 675 let trait_ = trait_ref.trait_;
@@ -767,7 +767,7 @@ fn type_alias_associated_ty_value(
767 .trait_data(trait_ref.trait_) 767 .trait_data(trait_ref.trait_)
768 .associated_type_by_name(&type_alias_data.name) 768 .associated_type_by_name(&type_alias_data.name)
769 .expect("assoc ty value should not exist"); // validated when building the impl data as well 769 .expect("assoc ty value should not exist"); // validated when building the impl data as well
770 let generic_params = db.generic_params(impl_id.into()); 770 let generic_params = generics(db, impl_id.into());
771 let bound_vars = Substs::bound_vars(&generic_params); 771 let bound_vars = Substs::bound_vars(&generic_params);
772 let ty = db.ty(type_alias.into()).subst(&bound_vars); 772 let ty = db.ty(type_alias.into()).subst(&bound_vars);
773 let value_bound = chalk_rust_ir::AssociatedTyValueBound { ty: ty.to_chalk(db) }; 773 let value_bound = chalk_rust_ir::AssociatedTyValueBound { ty: ty.to_chalk(db) };
diff --git a/crates/ra_hir_ty/src/utils.rs b/crates/ra_hir_ty/src/utils.rs
index e4ba890ef..936cfe25e 100644
--- a/crates/ra_hir_ty/src/utils.rs
+++ b/crates/ra_hir_ty/src/utils.rs
@@ -5,9 +5,10 @@ use std::sync::Arc;
5use hir_def::{ 5use hir_def::{
6 adt::VariantData, 6 adt::VariantData,
7 db::DefDatabase, 7 db::DefDatabase,
8 generics::{GenericParamData, GenericParams},
8 resolver::{HasResolver, TypeNs}, 9 resolver::{HasResolver, TypeNs},
9 type_ref::TypeRef, 10 type_ref::TypeRef,
10 TraitId, TypeAliasId, VariantId, 11 ContainerId, GenericDefId, GenericParamId, Lookup, TraitId, TypeAliasId, VariantId,
11}; 12};
12use hir_expand::name::{self, Name}; 13use hir_expand::name::{self, Name};
13 14
@@ -82,3 +83,83 @@ pub(crate) fn make_mut_slice<T: Clone>(a: &mut Arc<[T]>) -> &mut [T] {
82 } 83 }
83 Arc::get_mut(a).unwrap() 84 Arc::get_mut(a).unwrap()
84} 85}
86
87pub(crate) fn generics(db: &impl DefDatabase, def: GenericDefId) -> Generics {
88 let parent_generics = parent_generic_def(db, def).map(|def| Box::new(generics(db, def)));
89 Generics { def, params: db.generic_params(def), parent_generics }
90}
91
92pub(crate) struct Generics {
93 def: GenericDefId,
94 pub(crate) params: Arc<GenericParams>,
95 parent_generics: Option<Box<Generics>>,
96}
97
98impl Generics {
99 pub(crate) fn iter<'a>(&'a self) -> impl Iterator<Item = (u32, &'a GenericParamData)> + 'a {
100 self.parent_generics
101 .as_ref()
102 .into_iter()
103 .flat_map(|it| it.params.params.iter())
104 .chain(self.params.params.iter())
105 .enumerate()
106 .map(|(i, (_local_id, p))| (i as u32, p))
107 }
108
109 pub(crate) fn iter_parent<'a>(
110 &'a self,
111 ) -> impl Iterator<Item = (u32, &'a GenericParamData)> + 'a {
112 self.parent_generics
113 .as_ref()
114 .into_iter()
115 .flat_map(|it| it.params.params.iter())
116 .enumerate()
117 .map(|(i, (_local_id, p))| (i as u32, p))
118 }
119
120 pub(crate) fn len(&self) -> usize {
121 self.len_split().0
122 }
123 /// (total, parents, child)
124 pub(crate) fn len_split(&self) -> (usize, usize, usize) {
125 let parent = self.parent_generics.as_ref().map_or(0, |p| p.len());
126 let child = self.params.params.len();
127 (parent + child, parent, child)
128 }
129 pub(crate) fn param_idx(&self, param: GenericParamId) -> u32 {
130 self.find_param(param).0
131 }
132 pub(crate) fn param_name(&self, param: GenericParamId) -> Name {
133 self.find_param(param).1.name.clone()
134 }
135 fn find_param(&self, param: GenericParamId) -> (u32, &GenericParamData) {
136 if param.parent == self.def {
137 let (idx, (_local_id, data)) = self
138 .params
139 .params
140 .iter()
141 .enumerate()
142 .find(|(_, (idx, _))| *idx == param.local_id)
143 .unwrap();
144 let (_total, parent_len, _child) = self.len_split();
145 return ((parent_len + idx) as u32, data);
146 }
147 self.parent_generics.as_ref().unwrap().find_param(param)
148 }
149}
150
151fn parent_generic_def(db: &impl DefDatabase, def: GenericDefId) -> Option<GenericDefId> {
152 let container = match def {
153 GenericDefId::FunctionId(it) => it.lookup(db).container,
154 GenericDefId::TypeAliasId(it) => it.lookup(db).container,
155 GenericDefId::ConstId(it) => it.lookup(db).container,
156 GenericDefId::EnumVariantId(it) => return Some(it.parent.into()),
157 GenericDefId::AdtId(_) | GenericDefId::TraitId(_) | GenericDefId::ImplId(_) => return None,
158 };
159
160 match container {
161 ContainerId::ImplId(it) => Some(it.into()),
162 ContainerId::TraitId(it) => Some(it.into()),
163 ContainerId::ModuleId(_) => None,
164 }
165}