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

@ -204,7 +204,8 @@ impl<'a> AstTransform<'a> for QualifyPaths<'a> {
} }
PathResolution::Local(_) PathResolution::Local(_)
| PathResolution::TypeParam(_) | PathResolution::TypeParam(_)
| PathResolution::SelfType(_) => None, | PathResolution::SelfType(_)
| PathResolution::ConstParam(_) => None,
PathResolution::Macro(_) => None, PathResolution::Macro(_) => None,
PathResolution::AssocItem(_) => None, PathResolution::AssocItem(_) => None,
} }

View file

@ -18,10 +18,10 @@ use hir_def::{
resolver::{HasResolver, Resolver}, resolver::{HasResolver, Resolver},
src::HasSource as _, src::HasSource as _,
type_ref::{Mutability, TypeRef}, type_ref::{Mutability, TypeRef},
AdtId, AssocContainerId, AssocItemId, AssocItemLoc, AttrDefId, ConstId, DefWithBodyId, EnumId, AdtId, AssocContainerId, AssocItemId, AssocItemLoc, AttrDefId, ConstId, ConstParamId,
FunctionId, GenericDefId, HasModule, ImplId, LifetimeParamId, LocalEnumVariantId, LocalFieldId, DefWithBodyId, EnumId, FunctionId, GenericDefId, HasModule, ImplId, LifetimeParamId,
LocalModuleId, Lookup, ModuleId, StaticId, StructId, TraitId, TypeAliasId, TypeParamId, LocalEnumVariantId, LocalFieldId, LocalModuleId, Lookup, ModuleId, StaticId, StructId, TraitId,
UnionId, TypeAliasId, TypeParamId, UnionId,
}; };
use hir_def::{find_path::PrefixKind, item_scope::ItemInNs, visibility::Visibility}; use hir_def::{find_path::PrefixKind, item_scope::ItemInNs, visibility::Visibility};
use hir_expand::{ use hir_expand::{
@ -1125,7 +1125,12 @@ impl GenericDef {
id: LifetimeParamId { parent: self.into(), local_id }, id: LifetimeParamId { parent: self.into(), local_id },
}) })
.map(GenericParam::LifetimeParam); .map(GenericParam::LifetimeParam);
ty_params.chain(lt_params).collect() let const_params = generics
.consts
.iter()
.map(|(local_id, _)| ConstParam { id: ConstParamId { parent: self.into(), local_id } })
.map(GenericParam::ConstParam);
ty_params.chain(lt_params).chain(const_params).collect()
} }
pub fn type_params(self, db: &dyn HirDatabase) -> Vec<TypeParam> { pub fn type_params(self, db: &dyn HirDatabase) -> Vec<TypeParam> {
@ -1237,8 +1242,9 @@ impl Label {
pub enum GenericParam { pub enum GenericParam {
TypeParam(TypeParam), TypeParam(TypeParam),
LifetimeParam(LifetimeParam), LifetimeParam(LifetimeParam),
ConstParam(ConstParam),
} }
impl_from!(TypeParam, LifetimeParam for GenericParam); impl_from!(TypeParam, LifetimeParam, ConstParam for GenericParam);
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct TypeParam { pub struct TypeParam {
@ -1300,6 +1306,26 @@ impl LifetimeParam {
} }
} }
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct ConstParam {
pub(crate) id: ConstParamId,
}
impl ConstParam {
pub fn name(self, db: &dyn HirDatabase) -> Name {
let params = db.generic_params(self.id.parent);
params.consts[self.id.local_id].name.clone()
}
pub fn module(self, db: &dyn HirDatabase) -> Module {
self.id.parent.module(db.upcast()).into()
}
pub fn parent(self, _db: &dyn HirDatabase) -> GenericDef {
self.id.parent.into()
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Impl { pub struct Impl {
pub(crate) id: ImplId, pub(crate) id: ImplId,

View file

@ -44,6 +44,7 @@ from_id![
(hir_def::ImplId, crate::Impl), (hir_def::ImplId, crate::Impl),
(hir_def::TypeParamId, crate::TypeParam), (hir_def::TypeParamId, crate::TypeParam),
(hir_def::LifetimeParamId, crate::LifetimeParam), (hir_def::LifetimeParamId, crate::LifetimeParam),
(hir_def::ConstParamId, crate::ConstParam),
(hir_expand::MacroDefId, crate::MacroDef) (hir_expand::MacroDefId, crate::MacroDef)
]; ];

View file

@ -10,8 +10,8 @@ use hir_expand::InFile;
use syntax::ast; use syntax::ast;
use crate::{ use crate::{
db::HirDatabase, Const, Enum, Field, FieldSource, Function, Impl, LifetimeParam, MacroDef, db::HirDatabase, Const, ConstParam, Enum, Field, FieldSource, Function, Impl, LifetimeParam,
Module, Static, Struct, Trait, TypeAlias, TypeParam, Union, Variant, MacroDef, Module, Static, Struct, Trait, TypeAlias, TypeParam, Union, Variant,
}; };
pub trait HasSource { pub trait HasSource {
@ -140,3 +140,11 @@ impl HasSource for LifetimeParam {
child_source.map(|it| it[self.id.local_id].clone()) child_source.map(|it| it[self.id.local_id].clone())
} }
} }
impl HasSource for ConstParam {
type Ast = ast::ConstParam;
fn source(self, db: &dyn HirDatabase) -> InFile<Self::Ast> {
let child_source = self.id.parent.child_source(db.upcast());
child_source.map(|it| it[self.id.local_id].clone())
}
}

View file

@ -34,9 +34,9 @@ pub use crate::{
attrs::{HasAttrs, Namespace}, attrs::{HasAttrs, Namespace},
code_model::{ code_model::{
Access, Adt, AsAssocItem, AssocItem, AssocItemContainer, Callable, CallableKind, Const, Access, Adt, AsAssocItem, AssocItem, AssocItemContainer, Callable, CallableKind, Const,
Crate, CrateDependency, DefWithBody, Enum, Field, FieldSource, Function, GenericDef, ConstParam, Crate, CrateDependency, DefWithBody, Enum, Field, FieldSource, Function,
HasVisibility, Impl, Label, LifetimeParam, Local, MacroDef, Module, ModuleDef, ScopeDef, GenericDef, HasVisibility, Impl, Label, LifetimeParam, Local, MacroDef, Module, ModuleDef,
Static, Struct, Trait, Type, TypeAlias, TypeParam, Union, Variant, VariantDef, ScopeDef, Static, Struct, Trait, Type, TypeAlias, TypeParam, Union, Variant, VariantDef,
}, },
has_source::HasSource, has_source::HasSource,
semantics::{PathResolution, Semantics, SemanticsScope}, semantics::{PathResolution, Semantics, SemanticsScope},

View file

@ -25,9 +25,9 @@ use crate::{
diagnostics::Diagnostic, diagnostics::Diagnostic,
semantics::source_to_def::{ChildContainer, SourceToDefCache, SourceToDefCtx}, semantics::source_to_def::{ChildContainer, SourceToDefCache, SourceToDefCtx},
source_analyzer::{resolve_hir_path, SourceAnalyzer}, source_analyzer::{resolve_hir_path, SourceAnalyzer},
AssocItem, Callable, Crate, Field, Function, HirFileId, Impl, InFile, Label, LifetimeParam, AssocItem, Callable, ConstParam, Crate, Field, Function, HirFileId, Impl, InFile, Label,
Local, MacroDef, Module, ModuleDef, Name, Path, ScopeDef, Trait, Type, TypeAlias, TypeParam, LifetimeParam, Local, MacroDef, Module, ModuleDef, Name, Path, ScopeDef, Trait, Type,
VariantDef, TypeAlias, TypeParam, VariantDef,
}; };
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq)]
@ -38,6 +38,7 @@ pub enum PathResolution {
Local(Local), Local(Local),
/// A generic parameter /// A generic parameter
TypeParam(TypeParam), TypeParam(TypeParam),
ConstParam(ConstParam),
SelfType(Impl), SelfType(Impl),
Macro(MacroDef), Macro(MacroDef),
AssocItem(AssocItem), AssocItem(AssocItem),
@ -59,7 +60,9 @@ impl PathResolution {
PathResolution::Def(ModuleDef::TypeAlias(alias)) => { PathResolution::Def(ModuleDef::TypeAlias(alias)) => {
Some(TypeNs::TypeAliasId((*alias).into())) Some(TypeNs::TypeAliasId((*alias).into()))
} }
PathResolution::Local(_) | PathResolution::Macro(_) => None, PathResolution::Local(_) | PathResolution::Macro(_) | PathResolution::ConstParam(_) => {
None
}
PathResolution::TypeParam(param) => Some(TypeNs::GenericParam((*param).into())), PathResolution::TypeParam(param) => Some(TypeNs::GenericParam((*param).into())),
PathResolution::SelfType(impl_def) => Some(TypeNs::SelfType((*impl_def).into())), PathResolution::SelfType(impl_def) => Some(TypeNs::SelfType((*impl_def).into())),
PathResolution::AssocItem(AssocItem::Const(_)) PathResolution::AssocItem(AssocItem::Const(_))
@ -744,6 +747,7 @@ to_def_impls![
(crate::Variant, ast::Variant, enum_variant_to_def), (crate::Variant, ast::Variant, enum_variant_to_def),
(crate::TypeParam, ast::TypeParam, type_param_to_def), (crate::TypeParam, ast::TypeParam, type_param_to_def),
(crate::LifetimeParam, ast::LifetimeParam, lifetime_param_to_def), (crate::LifetimeParam, ast::LifetimeParam, lifetime_param_to_def),
(crate::ConstParam, ast::ConstParam, const_param_to_def),
(crate::MacroDef, ast::MacroRules, macro_rules_to_def), (crate::MacroDef, ast::MacroRules, macro_rules_to_def),
(crate::Local, ast::IdentPat, bind_pat_to_def), (crate::Local, ast::IdentPat, bind_pat_to_def),
(crate::Label, ast::Label, label_to_def), (crate::Label, ast::Label, label_to_def),

View file

@ -6,9 +6,9 @@ use hir_def::{
dyn_map::DynMap, dyn_map::DynMap,
expr::{LabelId, PatId}, expr::{LabelId, PatId},
keys::{self, Key}, keys::{self, Key},
ConstId, DefWithBodyId, EnumId, EnumVariantId, FieldId, FunctionId, GenericDefId, ImplId, ConstId, ConstParamId, DefWithBodyId, EnumId, EnumVariantId, FieldId, FunctionId, GenericDefId,
LifetimeParamId, ModuleId, StaticId, StructId, TraitId, TypeAliasId, TypeParamId, UnionId, ImplId, LifetimeParamId, ModuleId, StaticId, StructId, TraitId, TypeAliasId, TypeParamId,
VariantId, UnionId, VariantId,
}; };
use hir_expand::{name::AsName, AstId, MacroDefKind}; use hir_expand::{name::AsName, AstId, MacroDefKind};
use rustc_hash::FxHashMap; use rustc_hash::FxHashMap;
@ -157,6 +157,18 @@ impl SourceToDefCtx<'_, '_> {
dyn_map[keys::LIFETIME_PARAM].get(&src).copied() dyn_map[keys::LIFETIME_PARAM].get(&src).copied()
} }
pub(super) fn const_param_to_def(
&mut self,
src: InFile<ast::ConstParam>,
) -> Option<ConstParamId> {
let container: ChildContainer =
self.find_generic_param_container(src.as_ref().map(|it| it.syntax()))?.into();
let db = self.db;
let dyn_map =
&*self.cache.entry(container).or_insert_with(|| container.child_by_source(db));
dyn_map[keys::CONST_PARAM].get(&src).copied()
}
// FIXME: use DynMap as well? // FIXME: use DynMap as well?
pub(super) fn macro_rules_to_def( pub(super) fn macro_rules_to_def(
&mut self, &mut self,

View file

@ -479,6 +479,7 @@ pub(crate) fn resolve_hir_path(
ValueNs::StructId(it) => PathResolution::Def(Struct::from(it).into()), ValueNs::StructId(it) => PathResolution::Def(Struct::from(it).into()),
ValueNs::EnumVariantId(it) => PathResolution::Def(Variant::from(it).into()), ValueNs::EnumVariantId(it) => PathResolution::Def(Variant::from(it).into()),
ValueNs::ImplSelf(impl_id) => PathResolution::SelfType(impl_id.into()), ValueNs::ImplSelf(impl_id) => PathResolution::SelfType(impl_id.into()),
ValueNs::GenericParam(it) => PathResolution::ConstParam(it.into()),
}; };
Some(res) Some(res)
}); });

View file

@ -21,11 +21,11 @@ use crate::{
keys, keys,
src::{HasChildSource, HasSource}, src::{HasChildSource, HasSource},
type_ref::{LifetimeRef, TypeBound, TypeRef}, type_ref::{LifetimeRef, TypeBound, TypeRef},
AdtId, GenericDefId, LifetimeParamId, LocalLifetimeParamId, LocalTypeParamId, Lookup, AdtId, ConstParamId, GenericDefId, LifetimeParamId, LocalConstParamId, LocalLifetimeParamId,
TypeParamId, 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)] #[derive(Clone, PartialEq, Eq, Debug)]
pub struct TypeParamData { pub struct TypeParamData {
pub name: Option<Name>, pub name: Option<Name>,
@ -33,12 +33,19 @@ pub struct TypeParamData {
pub provenance: TypeParamProvenance, 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)] #[derive(Clone, PartialEq, Eq, Debug)]
pub struct LifetimeParamData { pub struct LifetimeParamData {
pub name: Name, 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)] #[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub enum TypeParamProvenance { pub enum TypeParamProvenance {
TypeParamList, TypeParamList,
@ -51,6 +58,7 @@ pub enum TypeParamProvenance {
pub struct GenericParams { pub struct GenericParams {
pub types: Arena<TypeParamData>, pub types: Arena<TypeParamData>,
pub lifetimes: Arena<LifetimeParamData>, pub lifetimes: Arena<LifetimeParamData>,
pub consts: Arena<ConstParamData>,
pub where_predicates: Vec<WherePredicate>, pub where_predicates: Vec<WherePredicate>,
} }
@ -76,6 +84,7 @@ pub enum WherePredicateTypeTarget {
pub(crate) struct SourceMap { pub(crate) struct SourceMap {
pub(crate) type_params: ArenaMap<LocalTypeParamId, Either<ast::Trait, ast::TypeParam>>, pub(crate) type_params: ArenaMap<LocalTypeParamId, Either<ast::Trait, ast::TypeParam>>,
lifetime_params: ArenaMap<LocalLifetimeParamId, ast::LifetimeParam>, lifetime_params: ArenaMap<LocalLifetimeParamId, ast::LifetimeParam>,
const_params: ArenaMap<LocalConstParamId, ast::ConstParam>,
} }
impl GenericParams { impl GenericParams {
@ -268,6 +277,13 @@ impl GenericParams {
let lifetime_ref = LifetimeRef::new_name(name); let lifetime_ref = LifetimeRef::new_name(name);
self.fill_bounds(&lower_ctx, &lifetime_param, Either::Right(lifetime_ref)); 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) { 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 self.types
.iter() .iter()
.find_map(|(id, p)| if p.name.as_ref() == Some(name) { Some(id) } else { None }) .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> { pub fn find_trait_self_param(&self) -> Option<LocalTypeParamId> {
self.types.iter().find_map(|(id, p)| { self.types.iter().find_map(|(id, p)| {
if p.provenance == TypeParamProvenance::TraitSelf { 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 { impl ChildBySource for GenericDefId {
fn child_by_source(&self, db: &dyn DefDatabase) -> DynMap { fn child_by_source(&self, db: &dyn DefDatabase) -> DynMap {
let mut res = DynMap::default(); let mut res = DynMap::default();
@ -406,6 +436,10 @@ impl ChildBySource for GenericDefId {
let id = LifetimeParamId { parent: *self, local_id }; let id = LifetimeParamId { parent: *self, local_id };
res[keys::LIFETIME_PARAM].insert(sm.with_value(src.clone()), 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 res
} }
} }

View file

@ -260,6 +260,7 @@ impl GenericParamsStorage {
fn alloc(&mut self, params: GenericParams) -> GenericParamsId { fn alloc(&mut self, params: GenericParams) -> GenericParamsId {
if params.types.is_empty() if params.types.is_empty()
&& params.lifetimes.is_empty() && params.lifetimes.is_empty()
&& params.consts.is_empty()
&& params.where_predicates.is_empty() && params.where_predicates.is_empty()
{ {
return GenericParamsId::EMPTY; return GenericParamsId::EMPTY;
@ -269,8 +270,12 @@ impl GenericParamsStorage {
} }
} }
static EMPTY_GENERICS: GenericParams = static EMPTY_GENERICS: GenericParams = GenericParams {
GenericParams { types: Arena::new(), lifetimes: Arena::new(), where_predicates: Vec::new() }; types: Arena::new(),
lifetimes: Arena::new(),
consts: Arena::new(),
where_predicates: Vec::new(),
};
#[derive(Default, Debug, Eq, PartialEq)] #[derive(Default, Debug, Eq, PartialEq)]
struct ItemTreeData { struct ItemTreeData {

View file

@ -8,8 +8,8 @@ use syntax::{ast, AstNode, AstPtr};
use crate::{ use crate::{
dyn_map::{DynMap, Policy}, dyn_map::{DynMap, Policy},
ConstId, EnumId, EnumVariantId, FieldId, FunctionId, ImplId, LifetimeParamId, StaticId, ConstId, ConstParamId, EnumId, EnumVariantId, FieldId, FunctionId, ImplId, LifetimeParamId,
StructId, TraitId, TypeAliasId, TypeParamId, UnionId, StaticId, StructId, TraitId, TypeAliasId, TypeParamId, UnionId,
}; };
pub type Key<K, V> = crate::dyn_map::Key<InFile<K>, V, AstPtrPolicy<K, V>>; 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 RECORD_FIELD: Key<ast::RecordField, FieldId> = Key::new();
pub const TYPE_PARAM: Key<ast::TypeParam, TypeParamId> = Key::new(); pub const TYPE_PARAM: Key<ast::TypeParam, TypeParamId> = Key::new();
pub const LIFETIME_PARAM: Key<ast::LifetimeParam, LifetimeParamId> = 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(); pub const MACRO: Key<ast::MacroCall, MacroDefId> = Key::new();

View file

@ -231,6 +231,13 @@ pub struct LifetimeParamId {
} }
pub type LocalLifetimeParamId = Idx<generics::LifetimeParamData>; 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)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum ContainerId { pub enum ContainerId {
ModuleId(ModuleId), ModuleId(ModuleId),

View file

@ -20,9 +20,9 @@ use crate::{
path::{ModPath, PathKind}, path::{ModPath, PathKind},
per_ns::PerNs, per_ns::PerNs,
visibility::{RawVisibility, Visibility}, visibility::{RawVisibility, Visibility},
AdtId, AssocContainerId, ConstId, ContainerId, DefWithBodyId, EnumId, EnumVariantId, AdtId, AssocContainerId, ConstId, ConstParamId, ContainerId, DefWithBodyId, EnumId,
FunctionId, GenericDefId, HasModule, ImplId, LocalModuleId, Lookup, ModuleDefId, ModuleId, EnumVariantId, FunctionId, GenericDefId, HasModule, ImplId, LocalModuleId, Lookup, ModuleDefId,
StaticId, StructId, TraitId, TypeAliasId, TypeParamId, VariantId, ModuleId, StaticId, StructId, TraitId, TypeAliasId, TypeParamId, VariantId,
}; };
#[derive(Debug, Clone, Default)] #[derive(Debug, Clone, Default)]
@ -93,6 +93,7 @@ pub enum ValueNs {
StaticId(StaticId), StaticId(StaticId),
StructId(StructId), StructId(StructId),
EnumVariantId(EnumVariantId), EnumVariantId(EnumVariantId),
GenericParam(ConstParamId),
} }
impl Resolver { impl Resolver {
@ -163,7 +164,7 @@ impl Resolver {
} }
Scope::GenericParams { params, def } => { 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) }; let idx = if path.segments.len() == 1 { None } else { Some(1) };
return Some(( return Some((
TypeNs::GenericParam(TypeParamId { local_id, parent: *def }), TypeNs::GenericParam(TypeParamId { local_id, parent: *def }),
@ -285,11 +286,17 @@ impl Resolver {
Scope::ExprScope(_) => continue, Scope::ExprScope(_) => continue,
Scope::GenericParams { params, def } if n_segments > 1 => { 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 }); let ty = TypeNs::GenericParam(TypeParamId { local_id, parent: *def });
return Some(ResolveValueResult::Partial(ty, 1)); 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::GenericParams { .. } => continue,
Scope::ImplDefScope(impl_) => { Scope::ImplDefScope(impl_) => {

View file

@ -5,8 +5,8 @@ use std::sync::Arc;
use arena::map::ArenaMap; use arena::map::ArenaMap;
use base_db::{impl_intern_key, salsa, CrateId, Upcast}; use base_db::{impl_intern_key, salsa, CrateId, Upcast};
use hir_def::{ use hir_def::{
db::DefDatabase, expr::ExprId, DefWithBodyId, FunctionId, GenericDefId, ImplId, LocalFieldId, db::DefDatabase, expr::ExprId, ConstParamId, DefWithBodyId, FunctionId, GenericDefId, ImplId,
TypeParamId, VariantId, LocalFieldId, TypeParamId, VariantId,
}; };
use crate::{ use crate::{
@ -37,6 +37,9 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
#[salsa::cycle(crate::lower::impl_self_ty_recover)] #[salsa::cycle(crate::lower::impl_self_ty_recover)]
fn impl_self_ty(&self, def: ImplId) -> Binders<Ty>; fn impl_self_ty(&self, def: ImplId) -> Binders<Ty>;
#[salsa::invoke(crate::lower::const_param_ty_query)]
fn const_param_ty(&self, def: ConstParamId) -> Ty;
#[salsa::invoke(crate::lower::impl_trait_query)] #[salsa::invoke(crate::lower::impl_trait_query)]
fn impl_trait(&self, def: ImplId) -> Option<Binders<TraitRef>>; fn impl_trait(&self, def: ImplId) -> Option<Binders<TraitRef>>;

View file

@ -89,6 +89,7 @@ impl<'a> InferenceContext<'a> {
return None; return None;
} }
} }
ValueNs::GenericParam(it) => return Some(self.db.const_param_ty(it)),
}; };
let ty = self.db.value_ty(typable); let ty = self.db.value_ty(typable);

View file

@ -16,9 +16,9 @@ use hir_def::{
path::{GenericArg, Path, PathSegment, PathSegments}, path::{GenericArg, Path, PathSegment, PathSegments},
resolver::{HasResolver, Resolver, TypeNs}, resolver::{HasResolver, Resolver, TypeNs},
type_ref::{TypeBound, TypeRef}, type_ref::{TypeBound, TypeRef},
AdtId, AssocContainerId, AssocItemId, ConstId, EnumId, EnumVariantId, FunctionId, GenericDefId, AdtId, AssocContainerId, AssocItemId, ConstId, ConstParamId, EnumId, EnumVariantId, FunctionId,
HasModule, ImplId, LocalFieldId, Lookup, StaticId, StructId, TraitId, TypeAliasId, TypeParamId, GenericDefId, HasModule, ImplId, LocalFieldId, Lookup, StaticId, StructId, TraitId,
UnionId, VariantId, TypeAliasId, TypeParamId, UnionId, VariantId,
}; };
use hir_expand::name::Name; use hir_expand::name::Name;
use smallvec::SmallVec; use smallvec::SmallVec;
@ -1221,6 +1221,15 @@ pub(crate) fn impl_self_ty_query(db: &dyn HirDatabase, impl_id: ImplId) -> Binde
Binders::new(generics.len(), Ty::from_hir(&ctx, &impl_data.target_type)) Binders::new(generics.len(), Ty::from_hir(&ctx, &impl_data.target_type))
} }
pub(crate) fn const_param_ty_query(db: &dyn HirDatabase, def: ConstParamId) -> Ty {
let parent_data = db.generic_params(def.parent);
let data = &parent_data.consts[def.local_id];
let resolver = def.parent.resolver(db.upcast());
let ctx = TyLoweringContext::new(db, &resolver);
Ty::from_hir(&ctx, &data.ty)
}
pub(crate) fn impl_self_ty_recover( pub(crate) fn impl_self_ty_recover(
db: &dyn HirDatabase, db: &dyn HirDatabase,
_cycle: &[String], _cycle: &[String],

View file

@ -2375,3 +2375,19 @@ fn infer_operator_overload() {
"#]], "#]],
); );
} }
#[test]
fn infer_const_params() {
check_infer(
r#"
fn foo<const FOO: usize>() {
let bar = FOO;
}
"#,
expect![[r#"
27..49 '{ ...FOO; }': ()
37..40 'bar': usize
43..46 'FOO': usize
"#]],
);
}

View file

@ -24,6 +24,7 @@ pub enum SymbolKind {
Impl, Impl,
Field, Field,
TypeParam, TypeParam,
ConstParam,
LifetimeParam, LifetimeParam,
ValueParam, ValueParam,
SelfParam, SelfParam,
@ -225,6 +226,7 @@ impl TryToNav for Definition {
Definition::TypeParam(it) => Some(it.to_nav(db)), Definition::TypeParam(it) => Some(it.to_nav(db)),
Definition::LifetimeParam(it) => Some(it.to_nav(db)), Definition::LifetimeParam(it) => Some(it.to_nav(db)),
Definition::Label(it) => Some(it.to_nav(db)), Definition::Label(it) => Some(it.to_nav(db)),
Definition::ConstParam(it) => Some(it.to_nav(db)),
} }
} }
} }
@ -485,6 +487,23 @@ impl ToNav for hir::LifetimeParam {
} }
} }
impl ToNav for hir::ConstParam {
fn to_nav(&self, db: &RootDatabase) -> NavigationTarget {
let src = self.source(db);
let full_range = src.value.syntax().text_range();
NavigationTarget {
file_id: src.file_id.original_file(db),
name: self.name(db).to_string().into(),
kind: Some(SymbolKind::ConstParam),
full_range,
focus_range: src.value.name().map(|n| n.syntax().text_range()),
container_name: None,
description: None,
docs: None,
}
}
}
/// Get a description of a symbol. /// Get a description of a symbol.
/// ///
/// e.g. `struct Name`, `enum Name`, `fn Name` /// e.g. `struct Name`, `enum Name`, `fn Name`

View file

@ -193,6 +193,7 @@ fn rewrite_intra_doc_link(
Definition::SelfType(_) Definition::SelfType(_)
| Definition::Local(_) | Definition::Local(_)
| Definition::TypeParam(_) | Definition::TypeParam(_)
| Definition::ConstParam(_)
| Definition::LifetimeParam(_) | Definition::LifetimeParam(_)
| Definition::Label(_) => return None, | Definition::Label(_) => return None,
}?; }?;

View file

@ -370,7 +370,10 @@ fn hover_for_definition(db: &RootDatabase, def: Definition) -> Option<Markup> {
Adt::Enum(it) => from_def_source(db, it, mod_path), Adt::Enum(it) => from_def_source(db, it, mod_path),
}) })
} }
Definition::TypeParam(_) | Definition::LifetimeParam(_) | Definition::Label(_) => { Definition::TypeParam(_)
| Definition::LifetimeParam(_)
| Definition::ConstParam(_)
| Definition::Label(_) => {
// FIXME: Hover for generic param // FIXME: Hover for generic param
None None
} }

View file

@ -1144,4 +1144,20 @@ fn foo<'a>() -> &'a () {
"#]], "#]],
); );
} }
#[test]
fn test_find_const_param() {
check(
r#"
fn foo<const FOO<|>: usize>() -> usize {
FOO
}
"#,
expect![[r#"
FOO ConstParam FileId(0) 7..23 13..16 Other
FileId(0) 42..45 Other
"#]],
);
}
} }

View file

@ -819,6 +819,7 @@ fn highlight_def(db: &RootDatabase, def: Definition) -> Highlight {
}, },
Definition::SelfType(_) => HighlightTag::Symbol(SymbolKind::Impl), Definition::SelfType(_) => HighlightTag::Symbol(SymbolKind::Impl),
Definition::TypeParam(_) => HighlightTag::Symbol(SymbolKind::TypeParam), Definition::TypeParam(_) => HighlightTag::Symbol(SymbolKind::TypeParam),
Definition::ConstParam(_) => HighlightTag::Symbol(SymbolKind::ConstParam),
Definition::Local(local) => { Definition::Local(local) => {
let tag = if local.is_param(db) { let tag = if local.is_param(db) {
HighlightTag::Symbol(SymbolKind::ValueParam) HighlightTag::Symbol(SymbolKind::ValueParam)

View file

@ -77,6 +77,7 @@ impl HighlightTag {
SymbolKind::Function => "function", SymbolKind::Function => "function",
SymbolKind::TypeAlias => "type_alias", SymbolKind::TypeAlias => "type_alias",
SymbolKind::TypeParam => "type_param", SymbolKind::TypeParam => "type_param",
SymbolKind::ConstParam => "const_param",
SymbolKind::LifetimeParam => "lifetime", SymbolKind::LifetimeParam => "lifetime",
SymbolKind::Macro => "macro", SymbolKind::Macro => "macro",
SymbolKind::Local => "variable", SymbolKind::Local => "variable",

View file

@ -118,6 +118,10 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
<span class="keyword control">loop</span> <span class="punctuation">{</span><span class="punctuation">}</span> <span class="keyword control">loop</span> <span class="punctuation">{</span><span class="punctuation">}</span>
<span class="punctuation">}</span> <span class="punctuation">}</span>
<span class="keyword">fn</span> <span class="function declaration">const_param</span><span class="punctuation">&lt;</span><span class="keyword">const</span> <span class="const_param declaration">FOO</span><span class="punctuation">:</span> <span class="builtin_type">usize</span><span class="punctuation">&gt;</span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="operator">-&gt;</span> <span class="builtin_type">usize</span> <span class="punctuation">{</span>
<span class="const_param">FOO</span>
<span class="punctuation">}</span>
<span class="keyword">use</span> <span class="module">ops</span><span class="operator">::</span><span class="trait">Fn</span><span class="punctuation">;</span> <span class="keyword">use</span> <span class="module">ops</span><span class="operator">::</span><span class="trait">Fn</span><span class="punctuation">;</span>
<span class="keyword">fn</span> <span class="function declaration">baz</span><span class="punctuation">&lt;</span><span class="type_param declaration">F</span><span class="punctuation">:</span> <span class="trait">Fn</span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="operator">-&gt;</span> <span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">&gt;</span><span class="punctuation">(</span><span class="value_param declaration callable">f</span><span class="punctuation">:</span> <span class="type_param">F</span><span class="punctuation">)</span> <span class="punctuation">{</span> <span class="keyword">fn</span> <span class="function declaration">baz</span><span class="punctuation">&lt;</span><span class="type_param declaration">F</span><span class="punctuation">:</span> <span class="trait">Fn</span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="operator">-&gt;</span> <span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">&gt;</span><span class="punctuation">(</span><span class="value_param declaration callable">f</span><span class="punctuation">:</span> <span class="type_param">F</span><span class="punctuation">)</span> <span class="punctuation">{</span>
<span class="value_param callable">f</span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="value_param callable">f</span><span class="punctuation">(</span><span class="punctuation">)</span>

View file

@ -91,6 +91,10 @@ fn never() -> ! {
loop {} loop {}
} }
fn const_param<const FOO: usize>() -> usize {
FOO
}
use ops::Fn; use ops::Fn;
fn baz<F: Fn() -> ()>(f: F) { fn baz<F: Fn() -> ()>(f: F) {
f() f()

View file

@ -6,8 +6,8 @@
// FIXME: this badly needs rename/rewrite (matklad, 2020-02-06). // FIXME: this badly needs rename/rewrite (matklad, 2020-02-06).
use hir::{ use hir::{
db::HirDatabase, Crate, Field, HasVisibility, Impl, Label, LifetimeParam, Local, MacroDef, db::HirDatabase, ConstParam, Crate, Field, HasVisibility, Impl, Label, LifetimeParam, Local,
Module, ModuleDef, Name, PathResolution, Semantics, TypeParam, Visibility, MacroDef, Module, ModuleDef, Name, PathResolution, Semantics, TypeParam, Visibility,
}; };
use syntax::{ use syntax::{
ast::{self, AstNode}, ast::{self, AstNode},
@ -26,6 +26,7 @@ pub enum Definition {
Local(Local), Local(Local),
TypeParam(TypeParam), TypeParam(TypeParam),
LifetimeParam(LifetimeParam), LifetimeParam(LifetimeParam),
ConstParam(ConstParam),
Label(Label), Label(Label),
} }
@ -39,6 +40,7 @@ impl Definition {
Definition::Local(it) => Some(it.module(db)), Definition::Local(it) => Some(it.module(db)),
Definition::TypeParam(it) => Some(it.module(db)), Definition::TypeParam(it) => Some(it.module(db)),
Definition::LifetimeParam(it) => Some(it.module(db)), Definition::LifetimeParam(it) => Some(it.module(db)),
Definition::ConstParam(it) => Some(it.module(db)),
Definition::Label(it) => Some(it.module(db)), Definition::Label(it) => Some(it.module(db)),
} }
} }
@ -52,6 +54,7 @@ impl Definition {
Definition::Local(_) => None, Definition::Local(_) => None,
Definition::TypeParam(_) => None, Definition::TypeParam(_) => None,
Definition::LifetimeParam(_) => None, Definition::LifetimeParam(_) => None,
Definition::ConstParam(_) => None,
Definition::Label(_) => None, Definition::Label(_) => None,
} }
} }
@ -79,6 +82,7 @@ impl Definition {
Definition::Local(it) => it.name(db)?, Definition::Local(it) => it.name(db)?,
Definition::TypeParam(it) => it.name(db), Definition::TypeParam(it) => it.name(db),
Definition::LifetimeParam(it) => it.name(db), Definition::LifetimeParam(it) => it.name(db),
Definition::ConstParam(it) => it.name(db),
Definition::Label(it) => it.name(db), Definition::Label(it) => it.name(db),
}; };
Some(name) Some(name)
@ -233,6 +237,10 @@ impl NameClass {
let def = sema.to_def(&it)?; let def = sema.to_def(&it)?;
Some(NameClass::Definition(Definition::TypeParam(def))) Some(NameClass::Definition(Definition::TypeParam(def)))
}, },
ast::ConstParam(it) => {
let def = sema.to_def(&it)?;
Some(NameClass::Definition(Definition::ConstParam(def)))
},
_ => None, _ => None,
} }
} }
@ -417,6 +425,7 @@ impl From<PathResolution> for Definition {
PathResolution::TypeParam(par) => Definition::TypeParam(par), PathResolution::TypeParam(par) => Definition::TypeParam(par),
PathResolution::Macro(def) => Definition::Macro(def), PathResolution::Macro(def) => Definition::Macro(def),
PathResolution::SelfType(impl_def) => Definition::SelfType(impl_def), PathResolution::SelfType(impl_def) => Definition::SelfType(impl_def),
PathResolution::ConstParam(par) => Definition::ConstParam(par),
} }
} }
} }

View file

@ -44,6 +44,7 @@ define_semantic_token_types![
(ESCAPE_SEQUENCE, "escapeSequence"), (ESCAPE_SEQUENCE, "escapeSequence"),
(FORMAT_SPECIFIER, "formatSpecifier"), (FORMAT_SPECIFIER, "formatSpecifier"),
(GENERIC, "generic"), (GENERIC, "generic"),
(CONST_PARAMETER, "constParameter"),
(LIFETIME, "lifetime"), (LIFETIME, "lifetime"),
(LABEL, "label"), (LABEL, "label"),
(PUNCTUATION, "punctuation"), (PUNCTUATION, "punctuation"),

View file

@ -42,6 +42,7 @@ pub(crate) fn symbol_kind(symbol_kind: SymbolKind) -> lsp_types::SymbolKind {
SymbolKind::Field => lsp_types::SymbolKind::Field, SymbolKind::Field => lsp_types::SymbolKind::Field,
SymbolKind::Static => lsp_types::SymbolKind::Constant, SymbolKind::Static => lsp_types::SymbolKind::Constant,
SymbolKind::Const => lsp_types::SymbolKind::Constant, SymbolKind::Const => lsp_types::SymbolKind::Constant,
SymbolKind::ConstParam => lsp_types::SymbolKind::Constant,
SymbolKind::Impl => lsp_types::SymbolKind::Object, SymbolKind::Impl => lsp_types::SymbolKind::Object,
SymbolKind::Local SymbolKind::Local
| SymbolKind::SelfParam | SymbolKind::SelfParam
@ -378,6 +379,7 @@ fn semantic_token_type_and_modifiers(
SymbolKind::Impl => lsp_types::SemanticTokenType::TYPE, SymbolKind::Impl => lsp_types::SemanticTokenType::TYPE,
SymbolKind::Field => lsp_types::SemanticTokenType::PROPERTY, SymbolKind::Field => lsp_types::SemanticTokenType::PROPERTY,
SymbolKind::TypeParam => lsp_types::SemanticTokenType::TYPE_PARAMETER, SymbolKind::TypeParam => lsp_types::SemanticTokenType::TYPE_PARAMETER,
SymbolKind::ConstParam => semantic_tokens::CONST_PARAMETER,
SymbolKind::LifetimeParam => semantic_tokens::LIFETIME, SymbolKind::LifetimeParam => semantic_tokens::LIFETIME,
SymbolKind::Label => semantic_tokens::LABEL, SymbolKind::Label => semantic_tokens::LABEL,
SymbolKind::ValueParam => lsp_types::SemanticTokenType::PARAMETER, SymbolKind::ValueParam => lsp_types::SemanticTokenType::PARAMETER,