aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_def/src
diff options
context:
space:
mode:
authorFlorian Diebold <[email protected]>2020-01-24 18:35:09 +0000
committerFlorian Diebold <[email protected]>2020-02-07 17:28:10 +0000
commit93aa166748eef9560df2435391dc3f3b53f8262d (patch)
treee91083af566a07b9324548cc87f04776124906cf /crates/ra_hir_def/src
parent9dec65d3b1aa703ceef993e46136f8949d7e0e48 (diff)
wip lower impl trait to type args
Diffstat (limited to 'crates/ra_hir_def/src')
-rw-r--r--crates/ra_hir_def/src/generics.rs45
-rw-r--r--crates/ra_hir_def/src/resolver.rs10
-rw-r--r--crates/ra_hir_def/src/type_ref.rs44
3 files changed, 90 insertions, 9 deletions
diff --git a/crates/ra_hir_def/src/generics.rs b/crates/ra_hir_def/src/generics.rs
index e9c28c730..7553d8a87 100644
--- a/crates/ra_hir_def/src/generics.rs
+++ b/crates/ra_hir_def/src/generics.rs
@@ -27,8 +27,16 @@ use crate::{
27/// Data about a generic parameter (to a function, struct, impl, ...). 27/// Data about a generic parameter (to a function, struct, impl, ...).
28#[derive(Clone, PartialEq, Eq, Debug)] 28#[derive(Clone, PartialEq, Eq, Debug)]
29pub struct TypeParamData { 29pub struct TypeParamData {
30 pub name: Name, 30 pub name: Option<Name>,
31 pub default: Option<TypeRef>, 31 pub default: Option<TypeRef>,
32 pub provenance: TypeParamProvenance,
33}
34
35#[derive(Copy, Clone, PartialEq, Eq, Debug)]
36pub enum TypeParamProvenance {
37 TypeParamList,
38 TraitSelf,
39 ArgumentImplTrait,
32} 40}
33 41
34/// Data about the generic parameters of a function, struct, impl, etc. 42/// Data about the generic parameters of a function, struct, impl, etc.
@@ -68,6 +76,11 @@ impl GenericParams {
68 GenericDefId::FunctionId(it) => { 76 GenericDefId::FunctionId(it) => {
69 let src = it.lookup(db).source(db); 77 let src = it.lookup(db).source(db);
70 generics.fill(&mut sm, &src.value); 78 generics.fill(&mut sm, &src.value);
79 // lower `impl Trait` in arguments
80 let data = db.function_data(it);
81 for param in &data.params {
82 generics.fill_implicit_impl_trait_args(param);
83 }
71 src.file_id 84 src.file_id
72 } 85 }
73 GenericDefId::AdtId(AdtId::StructId(it)) => { 86 GenericDefId::AdtId(AdtId::StructId(it)) => {
@@ -89,8 +102,11 @@ impl GenericParams {
89 let src = it.lookup(db).source(db); 102 let src = it.lookup(db).source(db);
90 103
91 // traits get the Self type as an implicit first type parameter 104 // traits get the Self type as an implicit first type parameter
92 let self_param_id = 105 let self_param_id = generics.types.alloc(TypeParamData {
93 generics.types.alloc(TypeParamData { name: name![Self], default: None }); 106 name: Some(name![Self]),
107 default: None,
108 provenance: TypeParamProvenance::TraitSelf,
109 });
94 sm.insert(self_param_id, Either::Left(src.value.clone())); 110 sm.insert(self_param_id, Either::Left(src.value.clone()));
95 // add super traits as bounds on Self 111 // add super traits as bounds on Self
96 // i.e., trait Foo: Bar is equivalent to trait Foo where Self: Bar 112 // i.e., trait Foo: Bar is equivalent to trait Foo where Self: Bar
@@ -142,7 +158,11 @@ impl GenericParams {
142 let name = type_param.name().map_or_else(Name::missing, |it| it.as_name()); 158 let name = type_param.name().map_or_else(Name::missing, |it| it.as_name());
143 // FIXME: Use `Path::from_src` 159 // FIXME: Use `Path::from_src`
144 let default = type_param.default_type().map(TypeRef::from_ast); 160 let default = type_param.default_type().map(TypeRef::from_ast);
145 let param = TypeParamData { name: name.clone(), default }; 161 let param = TypeParamData {
162 name: Some(name.clone()),
163 default,
164 provenance: TypeParamProvenance::TypeParamList,
165 };
146 let param_id = self.types.alloc(param); 166 let param_id = self.types.alloc(param);
147 sm.insert(param_id, Either::Right(type_param.clone())); 167 sm.insert(param_id, Either::Right(type_param.clone()));
148 168
@@ -173,8 +193,23 @@ impl GenericParams {
173 self.where_predicates.push(WherePredicate { type_ref, bound }); 193 self.where_predicates.push(WherePredicate { type_ref, bound });
174 } 194 }
175 195
196 fn fill_implicit_impl_trait_args(&mut self, type_ref: &TypeRef) {
197 type_ref.walk(&mut |type_ref| {
198 if let TypeRef::ImplTrait(_) = type_ref {
199 let param = TypeParamData {
200 name: None,
201 default: None,
202 provenance: TypeParamProvenance::ArgumentImplTrait,
203 };
204 let _param_id = self.types.alloc(param);
205 }
206 });
207 }
208
176 pub fn find_by_name(&self, name: &Name) -> Option<LocalTypeParamId> { 209 pub fn find_by_name(&self, name: &Name) -> Option<LocalTypeParamId> {
177 self.types.iter().find_map(|(id, p)| if &p.name == name { Some(id) } else { None }) 210 self.types
211 .iter()
212 .find_map(|(id, p)| if p.name.as_ref() == Some(name) { Some(id) } else { None })
178 } 213 }
179} 214}
180 215
diff --git a/crates/ra_hir_def/src/resolver.rs b/crates/ra_hir_def/src/resolver.rs
index f7bac5801..05cf4646a 100644
--- a/crates/ra_hir_def/src/resolver.rs
+++ b/crates/ra_hir_def/src/resolver.rs
@@ -490,10 +490,12 @@ impl Scope {
490 } 490 }
491 Scope::GenericParams { params, def } => { 491 Scope::GenericParams { params, def } => {
492 for (local_id, param) in params.types.iter() { 492 for (local_id, param) in params.types.iter() {
493 f( 493 if let Some(name) = &param.name {
494 param.name.clone(), 494 f(
495 ScopeDef::GenericParam(TypeParamId { local_id, parent: *def }), 495 name.clone(),
496 ) 496 ScopeDef::GenericParam(TypeParamId { local_id, parent: *def }),
497 )
498 }
497 } 499 }
498 } 500 }
499 Scope::ImplBlockScope(i) => { 501 Scope::ImplBlockScope(i) => {
diff --git a/crates/ra_hir_def/src/type_ref.rs b/crates/ra_hir_def/src/type_ref.rs
index 5f10e9a88..109414770 100644
--- a/crates/ra_hir_def/src/type_ref.rs
+++ b/crates/ra_hir_def/src/type_ref.rs
@@ -124,6 +124,50 @@ impl TypeRef {
124 pub(crate) fn unit() -> TypeRef { 124 pub(crate) fn unit() -> TypeRef {
125 TypeRef::Tuple(Vec::new()) 125 TypeRef::Tuple(Vec::new())
126 } 126 }
127
128 pub fn walk(&self, f: &mut impl FnMut(&TypeRef)) {
129 go(self, f);
130
131 fn go(type_ref: &TypeRef, f: &mut impl FnMut(&TypeRef)) {
132 f(type_ref);
133 match type_ref {
134 TypeRef::Fn(types) | TypeRef::Tuple(types) => {
135 types.iter().for_each(|t| go(t, f))
136 }
137 TypeRef::RawPtr(type_ref, _)
138 | TypeRef::Reference(type_ref, _)
139 | TypeRef::Array(type_ref)
140 | TypeRef::Slice(type_ref) => go(&type_ref, f),
141 TypeRef::ImplTrait(bounds) | TypeRef::DynTrait(bounds) => {
142 for bound in bounds {
143 match bound {
144 TypeBound::Path(path) => go_path(path, f),
145 TypeBound::Error => (),
146 }
147 }
148 }
149 TypeRef::Path(path) => go_path(path, f),
150 TypeRef::Never | TypeRef::Placeholder | TypeRef::Error => {}
151 };
152 }
153
154 fn go_path(path: &Path, f: &mut impl FnMut(&TypeRef)) {
155 if let Some(type_ref) = path.type_anchor() {
156 go(type_ref, f);
157 }
158 for segment in path.segments().iter() {
159 if let Some(args_and_bindings) = segment.args_and_bindings {
160 for arg in &args_and_bindings.args {
161 let crate::path::GenericArg::Type(type_ref) = arg;
162 go(type_ref, f);
163 }
164 for (_, type_ref) in &args_and_bindings.bindings {
165 go(type_ref, f);
166 }
167 }
168 }
169 }
170 }
127} 171}
128 172
129pub(crate) fn type_bounds_from_ast(type_bounds_opt: Option<ast::TypeBoundList>) -> Vec<TypeBound> { 173pub(crate) fn type_bounds_from_ast(type_bounds_opt: Option<ast::TypeBoundList>) -> Vec<TypeBound> {