diff options
author | Florian Diebold <[email protected]> | 2020-01-24 18:35:09 +0000 |
---|---|---|
committer | Florian Diebold <[email protected]> | 2020-02-07 17:28:10 +0000 |
commit | 93aa166748eef9560df2435391dc3f3b53f8262d (patch) | |
tree | e91083af566a07b9324548cc87f04776124906cf | |
parent | 9dec65d3b1aa703ceef993e46136f8949d7e0e48 (diff) |
wip lower impl trait to type args
-rw-r--r-- | crates/ra_hir/src/code_model.rs | 2 | ||||
-rw-r--r-- | crates/ra_hir_def/src/generics.rs | 45 | ||||
-rw-r--r-- | crates/ra_hir_def/src/resolver.rs | 10 | ||||
-rw-r--r-- | crates/ra_hir_def/src/type_ref.rs | 44 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/infer/expr.rs | 4 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/lib.rs | 2 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/lower.rs | 1 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/utils.rs | 3 |
8 files changed, 97 insertions, 14 deletions
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index fda31d517..817c27410 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs | |||
@@ -755,7 +755,7 @@ pub struct TypeParam { | |||
755 | impl TypeParam { | 755 | impl TypeParam { |
756 | pub fn name(self, db: &impl HirDatabase) -> Name { | 756 | pub fn name(self, db: &impl HirDatabase) -> Name { |
757 | let params = db.generic_params(self.id.parent); | 757 | let params = db.generic_params(self.id.parent); |
758 | params.types[self.id.local_id].name.clone() | 758 | params.types[self.id.local_id].name.clone().unwrap_or_else(Name::missing) |
759 | } | 759 | } |
760 | 760 | ||
761 | pub fn module(self, db: &impl HirDatabase) -> Module { | 761 | pub fn module(self, db: &impl HirDatabase) -> Module { |
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)] |
29 | pub struct TypeParamData { | 29 | pub 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)] | ||
36 | pub 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) = ¶m.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 | ||
129 | pub(crate) fn type_bounds_from_ast(type_bounds_opt: Option<ast::TypeBoundList>) -> Vec<TypeBound> { | 173 | pub(crate) fn type_bounds_from_ast(type_bounds_opt: Option<ast::TypeBoundList>) -> Vec<TypeBound> { |
diff --git a/crates/ra_hir_ty/src/infer/expr.rs b/crates/ra_hir_ty/src/infer/expr.rs index 31259a01d..97cb20cea 100644 --- a/crates/ra_hir_ty/src/infer/expr.rs +++ b/crates/ra_hir_ty/src/infer/expr.rs | |||
@@ -10,7 +10,7 @@ use hir_def::{ | |||
10 | resolver::resolver_for_expr, | 10 | resolver::resolver_for_expr, |
11 | AdtId, AssocContainerId, Lookup, StructFieldId, | 11 | AdtId, AssocContainerId, Lookup, StructFieldId, |
12 | }; | 12 | }; |
13 | use hir_expand::name::{name, Name}; | 13 | use hir_expand::name::Name; |
14 | use ra_syntax::ast::RangeOp; | 14 | use ra_syntax::ast::RangeOp; |
15 | 15 | ||
16 | use crate::{ | 16 | use crate::{ |
@@ -654,7 +654,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
654 | // Parent arguments are unknown, except for the receiver type | 654 | // Parent arguments are unknown, except for the receiver type |
655 | if let Some(parent_generics) = def_generics.as_ref().map(|p| p.iter_parent()) { | 655 | if let Some(parent_generics) = def_generics.as_ref().map(|p| p.iter_parent()) { |
656 | for (_id, param) in parent_generics { | 656 | for (_id, param) in parent_generics { |
657 | if param.name == name![Self] { | 657 | if param.provenance == hir_def::generics::TypeParamProvenance::TraitSelf { |
658 | substs.push(receiver_ty.clone()); | 658 | substs.push(receiver_ty.clone()); |
659 | } else { | 659 | } else { |
660 | substs.push(Ty::Unknown); | 660 | substs.push(Ty::Unknown); |
diff --git a/crates/ra_hir_ty/src/lib.rs b/crates/ra_hir_ty/src/lib.rs index c64b81f98..cb7a60352 100644 --- a/crates/ra_hir_ty/src/lib.rs +++ b/crates/ra_hir_ty/src/lib.rs | |||
@@ -368,7 +368,7 @@ impl Substs { | |||
368 | /// Return Substs that replace each parameter by itself (i.e. `Ty::Param`). | 368 | /// Return Substs that replace each parameter by itself (i.e. `Ty::Param`). |
369 | pub(crate) fn identity(generic_params: &Generics) -> Substs { | 369 | pub(crate) fn identity(generic_params: &Generics) -> Substs { |
370 | Substs( | 370 | Substs( |
371 | generic_params.iter().map(|(idx, p)| Ty::Param { idx, name: p.name.clone() }).collect(), | 371 | generic_params.iter().map(|(idx, p)| Ty::Param { idx, name: p.name.clone().unwrap_or_else(Name::missing) }).collect(), |
372 | ) | 372 | ) |
373 | } | 373 | } |
374 | 374 | ||
diff --git a/crates/ra_hir_ty/src/lower.rs b/crates/ra_hir_ty/src/lower.rs index 39406d8ce..6f7681475 100644 --- a/crates/ra_hir_ty/src/lower.rs +++ b/crates/ra_hir_ty/src/lower.rs | |||
@@ -341,6 +341,7 @@ pub(super) fn substs_from_path_segment( | |||
341 | // Self type as an implicit first type parameter, but it can't be | 341 | // Self type as an implicit first type parameter, but it can't be |
342 | // actually provided in the type arguments | 342 | // actually provided in the type arguments |
343 | // (well, actually sometimes it can, in the form of type-relative paths: `<Foo as Default>::default()`) | 343 | // (well, actually sometimes it can, in the form of type-relative paths: `<Foo as Default>::default()`) |
344 | // TODO handle this using type param provenance | ||
344 | substs.push(Ty::Unknown); | 345 | substs.push(Ty::Unknown); |
345 | } | 346 | } |
346 | if let Some(generic_args) = &segment.args_and_bindings { | 347 | if let Some(generic_args) = &segment.args_and_bindings { |
diff --git a/crates/ra_hir_ty/src/utils.rs b/crates/ra_hir_ty/src/utils.rs index 0b1806a84..314a3241f 100644 --- a/crates/ra_hir_ty/src/utils.rs +++ b/crates/ra_hir_ty/src/utils.rs | |||
@@ -127,7 +127,8 @@ impl Generics { | |||
127 | self.find_param(param).0 | 127 | self.find_param(param).0 |
128 | } | 128 | } |
129 | pub(crate) fn param_name(&self, param: TypeParamId) -> Name { | 129 | pub(crate) fn param_name(&self, param: TypeParamId) -> Name { |
130 | self.find_param(param).1.name.clone() | 130 | // FIXME make this return Option |
131 | self.find_param(param).1.name.clone().unwrap_or_else(Name::missing) | ||
131 | } | 132 | } |
132 | fn find_param(&self, param: TypeParamId) -> (u32, &TypeParamData) { | 133 | fn find_param(&self, param: TypeParamId) -> (u32, &TypeParamData) { |
133 | if param.parent == self.def { | 134 | if param.parent == self.def { |