7080: Implement ConstParams for HIR r=Veykril a=Veykril

r? @flodiebold 

Co-authored-by: Lukas Wirth <lukastw97@gmail.com>
This commit is contained in:
bors[bot] 2021-01-01 13:45:10 +00:00 committed by GitHub
commit 0e5fe47153
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
28 changed files with 238 additions and 41 deletions

View file

@ -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<Name>,
@ -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<TypeParamData>,
pub lifetimes: Arena<LifetimeParamData>,
pub consts: Arena<ConstParamData>,
pub where_predicates: Vec<WherePredicate>,
}
@ -76,6 +84,7 @@ pub enum WherePredicateTypeTarget {
pub(crate) struct SourceMap {
pub(crate) type_params: ArenaMap<LocalTypeParamId, Either<ast::Trait, ast::TypeParam>>,
lifetime_params: ArenaMap<LocalLifetimeParamId, ast::LifetimeParam>,
const_params: ArenaMap<LocalConstParamId, ast::ConstParam>,
}
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<LocalTypeParamId> {
pub fn find_type_by_name(&self, name: &Name) -> Option<LocalTypeParamId> {
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<LocalConstParamId> {
self.consts.iter().find_map(|(id, p)| if p.name == *name { Some(id) } else { None })
}
pub fn find_trait_self_param(&self) -> Option<LocalTypeParamId> {
self.types.iter().find_map(|(id, p)| {
if p.provenance == TypeParamProvenance::TraitSelf {
@ -390,6 +410,16 @@ impl HasChildSource<LocalLifetimeParamId> for GenericDefId {
}
}
impl HasChildSource<LocalConstParamId> for GenericDefId {
type Value = ast::ConstParam;
fn child_source(
&self,
db: &dyn DefDatabase,
) -> InFile<ArenaMap<LocalConstParamId, Self::Value>> {
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
}
}

View file

@ -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 {

View file

@ -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<K, V> = crate::dyn_map::Key<InFile<K>, V, AstPtrPolicy<K, V>>;
@ -29,6 +29,7 @@ pub const TUPLE_FIELD: Key<ast::TupleField, FieldId> = Key::new();
pub const RECORD_FIELD: Key<ast::RecordField, FieldId> = Key::new();
pub const TYPE_PARAM: Key<ast::TypeParam, TypeParamId> = Key::new();
pub const LIFETIME_PARAM: Key<ast::LifetimeParam, LifetimeParamId> = Key::new();
pub const CONST_PARAM: Key<ast::ConstParam, ConstParamId> = Key::new();
pub const MACRO: Key<ast::MacroCall, MacroDefId> = Key::new();

View file

@ -231,6 +231,13 @@ pub struct LifetimeParamId {
}
pub type LocalLifetimeParamId = Idx<generics::LifetimeParamData>;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct ConstParamId {
pub parent: GenericDefId,
pub local_id: LocalConstParamId,
}
pub type LocalConstParamId = Idx<generics::ConstParamData>;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum ContainerId {
ModuleId(ModuleId),

View file

@ -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_) => {