From 8e9837df21942ca12a5aece0a868ea46eb405742 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sat, 7 Dec 2019 11:50:36 +0100 Subject: Remove idx and parent generics from generics This makes `hir_def::GenericParams` flatter. The logic for re-numbering the params is moved to hir instead. --- crates/ra_hir_def/src/generics.rs | 90 +++++++++------------------------------ crates/ra_hir_def/src/resolver.rs | 38 ++++++++++------- 2 files changed, 42 insertions(+), 86 deletions(-) (limited to 'crates/ra_hir_def/src') diff --git a/crates/ra_hir_def/src/generics.rs b/crates/ra_hir_def/src/generics.rs index abe749a40..94ce83564 100644 --- a/crates/ra_hir_def/src/generics.rs +++ b/crates/ra_hir_def/src/generics.rs @@ -12,14 +12,12 @@ use crate::{ db::DefDatabase, src::HasSource, type_ref::{TypeBound, TypeRef}, - AdtId, AstItemDef, ContainerId, GenericDefId, LocalGenericParamId, Lookup, + AdtId, AstItemDef, GenericDefId, LocalGenericParamId, Lookup, }; /// Data about a generic parameter (to a function, struct, impl, ...). #[derive(Clone, PartialEq, Eq, Debug)] pub struct GenericParamData { - // FIXME: give generic params proper IDs - pub idx: u32, pub name: Name, pub default: Option, } @@ -27,7 +25,6 @@ pub struct GenericParamData { /// Data about the generic parameters of a function, struct, impl, etc. #[derive(Clone, PartialEq, Eq, Debug)] pub struct GenericParams { - pub parent_params: Option>, pub params: Arena, pub where_predicates: Vec, } @@ -47,51 +44,40 @@ impl GenericParams { db: &impl DefDatabase, def: GenericDefId, ) -> Arc { - let parent_generics = parent_generic_def(db, def).map(|it| db.generic_params(it)); - Arc::new(GenericParams::new(db, def.into(), parent_generics)) + Arc::new(GenericParams::new(db, def.into())) } - fn new( - db: &impl DefDatabase, - def: GenericDefId, - parent_params: Option>, - ) -> GenericParams { - let mut generics = - GenericParams { params: Arena::default(), parent_params, where_predicates: Vec::new() }; - let start = generics.parent_params.as_ref().map(|p| p.params.len()).unwrap_or(0) as u32; + fn new(db: &impl DefDatabase, def: GenericDefId) -> GenericParams { + let mut generics = GenericParams { params: Arena::default(), where_predicates: Vec::new() }; // FIXME: add `: Sized` bound for everything except for `Self` in traits match def { - GenericDefId::FunctionId(it) => generics.fill(&it.lookup(db).source(db).value, start), - GenericDefId::AdtId(AdtId::StructId(it)) => generics.fill(&it.source(db).value, start), - GenericDefId::AdtId(AdtId::UnionId(it)) => generics.fill(&it.source(db).value, start), - GenericDefId::AdtId(AdtId::EnumId(it)) => generics.fill(&it.source(db).value, start), + GenericDefId::FunctionId(it) => generics.fill(&it.lookup(db).source(db).value), + GenericDefId::AdtId(AdtId::StructId(it)) => generics.fill(&it.source(db).value), + GenericDefId::AdtId(AdtId::UnionId(it)) => generics.fill(&it.source(db).value), + GenericDefId::AdtId(AdtId::EnumId(it)) => generics.fill(&it.source(db).value), GenericDefId::TraitId(it) => { // traits get the Self type as an implicit first type parameter - generics.params.alloc(GenericParamData { - idx: start, - name: name::SELF_TYPE, - default: None, - }); - generics.fill(&it.source(db).value, start + 1); + generics.params.alloc(GenericParamData { name: name::SELF_TYPE, default: None }); + generics.fill(&it.source(db).value); // add super traits as bounds on Self // i.e., trait Foo: Bar is equivalent to trait Foo where Self: Bar let self_param = TypeRef::Path(name::SELF_TYPE.into()); generics.fill_bounds(&it.source(db).value, self_param); } - GenericDefId::TypeAliasId(it) => generics.fill(&it.lookup(db).source(db).value, start), + GenericDefId::TypeAliasId(it) => generics.fill(&it.lookup(db).source(db).value), // Note that we don't add `Self` here: in `impl`s, `Self` is not a // type-parameter, but rather is a type-alias for impl's target // type, so this is handled by the resolver. - GenericDefId::ImplId(it) => generics.fill(&it.source(db).value, start), + GenericDefId::ImplId(it) => generics.fill(&it.source(db).value), GenericDefId::EnumVariantId(_) | GenericDefId::ConstId(_) => {} } generics } - fn fill(&mut self, node: &impl TypeParamsOwner, start: u32) { + fn fill(&mut self, node: &impl TypeParamsOwner) { if let Some(params) = node.type_param_list() { - self.fill_params(params, start) + self.fill_params(params) } if let Some(where_clause) = node.where_clause() { self.fill_where_predicates(where_clause); @@ -106,12 +92,12 @@ impl GenericParams { } } - fn fill_params(&mut self, params: ast::TypeParamList, start: u32) { - for (idx, type_param) in params.type_params().enumerate() { + fn fill_params(&mut self, params: ast::TypeParamList) { + for type_param in params.type_params() { let name = type_param.name().map_or_else(Name::missing, |it| it.as_name()); // FIXME: Use `Path::from_src` let default = type_param.default_type().map(TypeRef::from_ast); - let param = GenericParamData { idx: idx as u32 + start, name: name.clone(), default }; + let param = GenericParamData { name: name.clone(), default }; self.params.alloc(param); let type_ref = TypeRef::Path(name.into()); @@ -141,45 +127,7 @@ impl GenericParams { self.where_predicates.push(WherePredicate { type_ref, bound }); } - pub fn find_by_name(&self, name: &Name) -> Option<&GenericParamData> { - self.params.iter().map(|(_id, data)| data).find(|p| &p.name == name) - } - - pub fn count_parent_params(&self) -> usize { - self.parent_params.as_ref().map(|p| p.count_params_including_parent()).unwrap_or(0) - } - - pub fn count_params_including_parent(&self) -> usize { - let parent_count = self.count_parent_params(); - parent_count + self.params.len() - } - - fn for_each_param<'a>(&'a self, f: &mut impl FnMut(&'a GenericParamData)) { - if let Some(parent) = &self.parent_params { - parent.for_each_param(f); - } - self.params.iter().map(|(_id, data)| data).for_each(f); - } - - pub fn params_including_parent(&self) -> Vec<&GenericParamData> { - let mut vec = Vec::with_capacity(self.count_params_including_parent()); - self.for_each_param(&mut |p| vec.push(p)); - vec - } -} - -fn parent_generic_def(db: &impl DefDatabase, def: GenericDefId) -> Option { - let container = match def { - GenericDefId::FunctionId(it) => it.lookup(db).container, - GenericDefId::TypeAliasId(it) => it.lookup(db).container, - GenericDefId::ConstId(it) => it.lookup(db).container, - GenericDefId::EnumVariantId(it) => return Some(it.parent.into()), - GenericDefId::AdtId(_) | GenericDefId::TraitId(_) | GenericDefId::ImplId(_) => return None, - }; - - match container { - ContainerId::ImplId(it) => Some(it.into()), - ContainerId::TraitId(it) => Some(it.into()), - ContainerId::ModuleId(_) => None, + pub fn find_by_name(&self, name: &Name) -> Option { + self.params.iter().find_map(|(id, p)| if &p.name == name { Some(id) } else { None }) } } diff --git a/crates/ra_hir_def/src/resolver.rs b/crates/ra_hir_def/src/resolver.rs index ee19d79a7..e00bd03d5 100644 --- a/crates/ra_hir_def/src/resolver.rs +++ b/crates/ra_hir_def/src/resolver.rs @@ -18,12 +18,13 @@ use crate::{ path::{Path, PathKind}, per_ns::PerNs, AdtId, AstItemDef, ConstId, ContainerId, DefWithBodyId, EnumId, EnumVariantId, FunctionId, - GenericDefId, HasModule, ImplId, LocalModuleId, Lookup, ModuleDefId, ModuleId, StaticId, - StructId, TraitId, TypeAliasId, + GenericDefId, GenericParamId, HasModule, ImplId, LocalModuleId, Lookup, ModuleDefId, ModuleId, + StaticId, StructId, TraitId, TypeAliasId, }; #[derive(Debug, Clone, Default)] pub struct Resolver { + // FIXME: all usages generally call `.rev`, so maybe reverse once in consturciton? scopes: Vec, } @@ -58,7 +59,7 @@ enum Scope { #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum TypeNs { SelfType(ImplId), - GenericParam(u32), + GenericParam(GenericParamId), AdtId(AdtId), AdtSelfType(AdtId), // Yup, enum variants are added to the types ns, but any usage of variant as @@ -152,10 +153,13 @@ impl Resolver { Scope::ExprScope(_) => continue, Scope::GenericParams { .. } | Scope::ImplBlockScope(_) if skip_to_mod => continue, - Scope::GenericParams { params, .. } => { - if let Some(param) = params.find_by_name(first_name) { + Scope::GenericParams { params, def } => { + if let Some(local_id) = params.find_by_name(first_name) { let idx = if path.segments.len() == 1 { None } else { Some(1) }; - return Some((TypeNs::GenericParam(param.idx), idx)); + return Some(( + TypeNs::GenericParam(GenericParamId { local_id, parent: *def }), + idx, + )); } } Scope::ImplBlockScope(impl_) => { @@ -246,9 +250,9 @@ impl Resolver { } Scope::ExprScope(_) => continue, - Scope::GenericParams { params, .. } if n_segments > 1 => { - if let Some(param) = params.find_by_name(first_name) { - let ty = TypeNs::GenericParam(param.idx); + Scope::GenericParams { params, def } if n_segments > 1 => { + if let Some(local_id) = params.find_by_name(first_name) { + let ty = TypeNs::GenericParam(GenericParamId { local_id, parent: *def }); return Some(ResolveValueResult::Partial(ty, 1)); } } @@ -368,6 +372,7 @@ impl Resolver { ) -> impl Iterator + 'a { self.scopes .iter() + .rev() .filter_map(|scope| match scope { Scope::GenericParams { params, .. } => Some(params), _ => None, @@ -376,14 +381,14 @@ impl Resolver { } pub fn generic_def(&self) -> Option { - self.scopes.iter().find_map(|scope| match scope { + self.scopes.iter().rev().find_map(|scope| match scope { Scope::GenericParams { def, .. } => Some(*def), _ => None, }) } pub fn body_owner(&self) -> Option { - self.scopes.iter().find_map(|scope| match scope { + self.scopes.iter().rev().find_map(|scope| match scope { Scope::ExprScope(it) => Some(it.owner), _ => None, }) @@ -394,7 +399,7 @@ pub enum ScopeDef { PerNs(PerNs), ImplSelfType(ImplId), AdtSelfType(AdtId), - GenericParam(u32), + GenericParam(GenericParamId), Local(PatId), } @@ -425,9 +430,12 @@ impl Scope { }); } } - Scope::GenericParams { params, .. } => { - for (_id, param) in params.params.iter() { - f(param.name.clone(), ScopeDef::GenericParam(param.idx)) + Scope::GenericParams { params, def } => { + for (local_id, param) in params.params.iter() { + f( + param.name.clone(), + ScopeDef::GenericParam(GenericParamId { local_id, parent: *def }), + ) } } Scope::ImplBlockScope(i) => { -- cgit v1.2.3