From 0acdb730769cfb040ffc5e2c87f83b19fd3ce291 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Fri, 1 Jan 2021 10:06:42 +0100 Subject: Add ConstParams to the HIR --- crates/hir_def/src/generics.rs | 44 ++++++++++++++++++++++++++++++++++++----- crates/hir_def/src/item_tree.rs | 9 +++++++-- crates/hir_def/src/keys.rs | 5 +++-- crates/hir_def/src/lib.rs | 7 +++++++ crates/hir_def/src/resolver.rs | 17 +++++++++++----- 5 files changed, 68 insertions(+), 14 deletions(-) (limited to 'crates/hir_def/src') diff --git a/crates/hir_def/src/generics.rs b/crates/hir_def/src/generics.rs index bb8fca009..9b5b886c2 100644 --- a/crates/hir_def/src/generics.rs +++ b/crates/hir_def/src/generics.rs @@ -21,11 +21,11 @@ use crate::{ keys, src::{HasChildSource, HasSource}, type_ref::{LifetimeRef, TypeBound, TypeRef}, - AdtId, GenericDefId, LifetimeParamId, LocalLifetimeParamId, LocalTypeParamId, Lookup, - TypeParamId, + AdtId, ConstParamId, GenericDefId, LifetimeParamId, LocalConstParamId, LocalLifetimeParamId, + LocalTypeParamId, Lookup, TypeParamId, }; -/// Data about a generic parameter (to a function, struct, impl, ...). +/// Data about a generic type parameter (to a function, struct, impl, ...). #[derive(Clone, PartialEq, Eq, Debug)] pub struct TypeParamData { pub name: Option, @@ -33,12 +33,19 @@ pub struct TypeParamData { pub provenance: TypeParamProvenance, } -/// Data about a generic parameter (to a function, struct, impl, ...). +/// Data about a generic lifetime parameter (to a function, struct, impl, ...). #[derive(Clone, PartialEq, Eq, Debug)] pub struct LifetimeParamData { pub name: Name, } +/// Data about a generic const parameter (to a function, struct, impl, ...). +#[derive(Clone, PartialEq, Eq, Debug)] +pub struct ConstParamData { + pub name: Name, + pub ty: TypeRef, +} + #[derive(Copy, Clone, PartialEq, Eq, Debug)] pub enum TypeParamProvenance { TypeParamList, @@ -51,6 +58,7 @@ pub enum TypeParamProvenance { pub struct GenericParams { pub types: Arena, pub lifetimes: Arena, + pub consts: Arena, pub where_predicates: Vec, } @@ -76,6 +84,7 @@ pub enum WherePredicateTypeTarget { pub(crate) struct SourceMap { pub(crate) type_params: ArenaMap>, lifetime_params: ArenaMap, + const_params: ArenaMap, } impl GenericParams { @@ -268,6 +277,13 @@ impl GenericParams { let lifetime_ref = LifetimeRef::new_name(name); self.fill_bounds(&lower_ctx, &lifetime_param, Either::Right(lifetime_ref)); } + for const_param in params.const_params() { + let name = const_param.name().map_or_else(Name::missing, |it| it.as_name()); + let ty = const_param.ty().map_or(TypeRef::Error, |it| TypeRef::from_ast(lower_ctx, it)); + let param = ConstParamData { name, ty }; + let param_id = self.consts.alloc(param); + sm.const_params.insert(param_id, const_param.clone()); + } } fn fill_where_predicates(&mut self, lower_ctx: &LowerCtx, where_clause: ast::WhereClause) { @@ -353,12 +369,16 @@ impl GenericParams { }); } - pub fn find_by_name(&self, name: &Name) -> Option { + pub fn find_type_by_name(&self, name: &Name) -> Option { self.types .iter() .find_map(|(id, p)| if p.name.as_ref() == Some(name) { Some(id) } else { None }) } + pub fn find_const_by_name(&self, name: &Name) -> Option { + self.consts.iter().find_map(|(id, p)| if p.name == *name { Some(id) } else { None }) + } + pub fn find_trait_self_param(&self) -> Option { self.types.iter().find_map(|(id, p)| { if p.provenance == TypeParamProvenance::TraitSelf { @@ -390,6 +410,16 @@ impl HasChildSource for GenericDefId { } } +impl HasChildSource for GenericDefId { + type Value = ast::ConstParam; + fn child_source( + &self, + db: &dyn DefDatabase, + ) -> InFile> { + GenericParams::new(db, *self).1.map(|source_maps| source_maps.const_params) + } +} + impl ChildBySource for GenericDefId { fn child_by_source(&self, db: &dyn DefDatabase) -> DynMap { let mut res = DynMap::default(); @@ -406,6 +436,10 @@ impl ChildBySource for GenericDefId { let id = LifetimeParamId { parent: *self, local_id }; res[keys::LIFETIME_PARAM].insert(sm.with_value(src.clone()), id); } + for (local_id, src) in sm.value.const_params.iter() { + let id = ConstParamId { parent: *self, local_id }; + res[keys::CONST_PARAM].insert(sm.with_value(src.clone()), id); + } res } } diff --git a/crates/hir_def/src/item_tree.rs b/crates/hir_def/src/item_tree.rs index 100dbf5d6..b6f510731 100644 --- a/crates/hir_def/src/item_tree.rs +++ b/crates/hir_def/src/item_tree.rs @@ -260,6 +260,7 @@ impl GenericParamsStorage { fn alloc(&mut self, params: GenericParams) -> GenericParamsId { if params.types.is_empty() && params.lifetimes.is_empty() + && params.consts.is_empty() && params.where_predicates.is_empty() { return GenericParamsId::EMPTY; @@ -269,8 +270,12 @@ impl GenericParamsStorage { } } -static EMPTY_GENERICS: GenericParams = - GenericParams { types: Arena::new(), lifetimes: Arena::new(), where_predicates: Vec::new() }; +static EMPTY_GENERICS: GenericParams = GenericParams { + types: Arena::new(), + lifetimes: Arena::new(), + consts: Arena::new(), + where_predicates: Vec::new(), +}; #[derive(Default, Debug, Eq, PartialEq)] struct ItemTreeData { diff --git a/crates/hir_def/src/keys.rs b/crates/hir_def/src/keys.rs index 9c585de2c..89b3ed868 100644 --- a/crates/hir_def/src/keys.rs +++ b/crates/hir_def/src/keys.rs @@ -8,8 +8,8 @@ use syntax::{ast, AstNode, AstPtr}; use crate::{ dyn_map::{DynMap, Policy}, - ConstId, EnumId, EnumVariantId, FieldId, FunctionId, ImplId, LifetimeParamId, StaticId, - StructId, TraitId, TypeAliasId, TypeParamId, UnionId, + ConstId, ConstParamId, EnumId, EnumVariantId, FieldId, FunctionId, ImplId, LifetimeParamId, + StaticId, StructId, TraitId, TypeAliasId, TypeParamId, UnionId, }; pub type Key = crate::dyn_map::Key, V, AstPtrPolicy>; @@ -29,6 +29,7 @@ pub const TUPLE_FIELD: Key = Key::new(); pub const RECORD_FIELD: Key = Key::new(); pub const TYPE_PARAM: Key = Key::new(); pub const LIFETIME_PARAM: Key = Key::new(); +pub const CONST_PARAM: Key = Key::new(); pub const MACRO: Key = Key::new(); diff --git a/crates/hir_def/src/lib.rs b/crates/hir_def/src/lib.rs index ba09a9126..25f460504 100644 --- a/crates/hir_def/src/lib.rs +++ b/crates/hir_def/src/lib.rs @@ -231,6 +231,13 @@ pub struct LifetimeParamId { } pub type LocalLifetimeParamId = Idx; +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct ConstParamId { + pub parent: GenericDefId, + pub local_id: LocalConstParamId, +} +pub type LocalConstParamId = Idx; + #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub enum ContainerId { ModuleId(ModuleId), diff --git a/crates/hir_def/src/resolver.rs b/crates/hir_def/src/resolver.rs index f8cc5e075..129f1dbac 100644 --- a/crates/hir_def/src/resolver.rs +++ b/crates/hir_def/src/resolver.rs @@ -20,9 +20,9 @@ use crate::{ path::{ModPath, PathKind}, per_ns::PerNs, visibility::{RawVisibility, Visibility}, - AdtId, AssocContainerId, ConstId, ContainerId, DefWithBodyId, EnumId, EnumVariantId, - FunctionId, GenericDefId, HasModule, ImplId, LocalModuleId, Lookup, ModuleDefId, ModuleId, - StaticId, StructId, TraitId, TypeAliasId, TypeParamId, VariantId, + AdtId, AssocContainerId, ConstId, ConstParamId, ContainerId, DefWithBodyId, EnumId, + EnumVariantId, FunctionId, GenericDefId, HasModule, ImplId, LocalModuleId, Lookup, ModuleDefId, + ModuleId, StaticId, StructId, TraitId, TypeAliasId, TypeParamId, VariantId, }; #[derive(Debug, Clone, Default)] @@ -93,6 +93,7 @@ pub enum ValueNs { StaticId(StaticId), StructId(StructId), EnumVariantId(EnumVariantId), + GenericParam(ConstParamId), } impl Resolver { @@ -163,7 +164,7 @@ impl Resolver { } Scope::GenericParams { params, def } => { - if let Some(local_id) = params.find_by_name(first_name) { + if let Some(local_id) = params.find_type_by_name(first_name) { let idx = if path.segments.len() == 1 { None } else { Some(1) }; return Some(( TypeNs::GenericParam(TypeParamId { local_id, parent: *def }), @@ -285,11 +286,17 @@ impl Resolver { Scope::ExprScope(_) => continue, Scope::GenericParams { params, def } if n_segments > 1 => { - if let Some(local_id) = params.find_by_name(first_name) { + if let Some(local_id) = params.find_type_by_name(first_name) { let ty = TypeNs::GenericParam(TypeParamId { local_id, parent: *def }); return Some(ResolveValueResult::Partial(ty, 1)); } } + Scope::GenericParams { params, def } if n_segments == 1 => { + if let Some(local_id) = params.find_const_by_name(first_name) { + let val = ValueNs::GenericParam(ConstParamId { local_id, parent: *def }); + return Some(ResolveValueResult::ValueNs(val)); + } + } Scope::GenericParams { .. } => continue, Scope::ImplDefScope(impl_) => { -- cgit v1.2.3