aboutsummaryrefslogtreecommitdiff
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
parent9dec65d3b1aa703ceef993e46136f8949d7e0e48 (diff)
wip lower impl trait to type args
-rw-r--r--crates/ra_hir/src/code_model.rs2
-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
-rw-r--r--crates/ra_hir_ty/src/infer/expr.rs4
-rw-r--r--crates/ra_hir_ty/src/lib.rs2
-rw-r--r--crates/ra_hir_ty/src/lower.rs1
-rw-r--r--crates/ra_hir_ty/src/utils.rs3
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 {
755impl TypeParam { 755impl 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)]
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> {
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};
13use hir_expand::name::{name, Name}; 13use hir_expand::name::Name;
14use ra_syntax::ast::RangeOp; 14use ra_syntax::ast::RangeOp;
15 15
16use crate::{ 16use 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 {