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/src/code_model.rs | 38 +++++++++++++++++++++----- crates/hir/src/from_id.rs | 1 + crates/hir/src/has_source.rs | 12 +++++++-- crates/hir/src/lib.rs | 6 ++--- crates/hir/src/semantics.rs | 12 ++++++--- crates/hir/src/semantics/source_to_def.rs | 18 ++++++++++--- crates/hir/src/source_analyzer.rs | 1 + 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 ++++++++---- crates/hir_ty/src/db.rs | 7 +++-- crates/hir_ty/src/infer/path.rs | 1 + crates/hir_ty/src/lower.rs | 15 ++++++++--- crates/hir_ty/src/tests/simple.rs | 17 ++++++++++++ 16 files changed, 173 insertions(+), 37 deletions(-) (limited to 'crates') diff --git a/crates/hir/src/code_model.rs b/crates/hir/src/code_model.rs index b7ded3478..97b7a8b5f 100644 --- a/crates/hir/src/code_model.rs +++ b/crates/hir/src/code_model.rs @@ -18,10 +18,10 @@ use hir_def::{ resolver::{HasResolver, Resolver}, src::HasSource as _, type_ref::{Mutability, TypeRef}, - AdtId, AssocContainerId, AssocItemId, AssocItemLoc, AttrDefId, ConstId, DefWithBodyId, EnumId, - FunctionId, GenericDefId, HasModule, ImplId, LifetimeParamId, LocalEnumVariantId, LocalFieldId, - LocalModuleId, Lookup, ModuleId, StaticId, StructId, TraitId, TypeAliasId, TypeParamId, - UnionId, + AdtId, AssocContainerId, AssocItemId, AssocItemLoc, AttrDefId, ConstId, ConstParamId, + DefWithBodyId, EnumId, FunctionId, GenericDefId, HasModule, ImplId, LifetimeParamId, + LocalEnumVariantId, LocalFieldId, LocalModuleId, Lookup, ModuleId, StaticId, StructId, TraitId, + TypeAliasId, TypeParamId, UnionId, }; use hir_def::{find_path::PrefixKind, item_scope::ItemInNs, visibility::Visibility}; use hir_expand::{ @@ -1125,7 +1125,12 @@ impl GenericDef { id: LifetimeParamId { parent: self.into(), local_id }, }) .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 { @@ -1237,8 +1242,9 @@ impl Label { pub enum GenericParam { TypeParam(TypeParam), LifetimeParam(LifetimeParam), + ConstParam(ConstParam), } -impl_from!(TypeParam, LifetimeParam for GenericParam); +impl_from!(TypeParam, LifetimeParam, ConstParam for GenericParam); #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] 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)] pub struct Impl { pub(crate) id: ImplId, diff --git a/crates/hir/src/from_id.rs b/crates/hir/src/from_id.rs index a0792b9a6..2422887e3 100644 --- a/crates/hir/src/from_id.rs +++ b/crates/hir/src/from_id.rs @@ -44,6 +44,7 @@ from_id![ (hir_def::ImplId, crate::Impl), (hir_def::TypeParamId, crate::TypeParam), (hir_def::LifetimeParamId, crate::LifetimeParam), + (hir_def::ConstParamId, crate::ConstParam), (hir_expand::MacroDefId, crate::MacroDef) ]; diff --git a/crates/hir/src/has_source.rs b/crates/hir/src/has_source.rs index 0dc07c33e..dd7c0c570 100644 --- a/crates/hir/src/has_source.rs +++ b/crates/hir/src/has_source.rs @@ -10,8 +10,8 @@ use hir_expand::InFile; use syntax::ast; use crate::{ - db::HirDatabase, Const, Enum, Field, FieldSource, Function, Impl, LifetimeParam, MacroDef, - Module, Static, Struct, Trait, TypeAlias, TypeParam, Union, Variant, + db::HirDatabase, Const, ConstParam, Enum, Field, FieldSource, Function, Impl, LifetimeParam, + MacroDef, Module, Static, Struct, Trait, TypeAlias, TypeParam, Union, Variant, }; pub trait HasSource { @@ -140,3 +140,11 @@ impl HasSource for LifetimeParam { 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 { + let child_source = self.id.parent.child_source(db.upcast()); + child_source.map(|it| it[self.id.local_id].clone()) + } +} diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index 7ac9fd507..8ac27e2dd 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -34,9 +34,9 @@ pub use crate::{ attrs::{HasAttrs, Namespace}, code_model::{ Access, Adt, AsAssocItem, AssocItem, AssocItemContainer, Callable, CallableKind, Const, - Crate, CrateDependency, DefWithBody, Enum, Field, FieldSource, Function, GenericDef, - HasVisibility, Impl, Label, LifetimeParam, Local, MacroDef, Module, ModuleDef, ScopeDef, - Static, Struct, Trait, Type, TypeAlias, TypeParam, Union, Variant, VariantDef, + ConstParam, Crate, CrateDependency, DefWithBody, Enum, Field, FieldSource, Function, + GenericDef, HasVisibility, Impl, Label, LifetimeParam, Local, MacroDef, Module, ModuleDef, + ScopeDef, Static, Struct, Trait, Type, TypeAlias, TypeParam, Union, Variant, VariantDef, }, has_source::HasSource, semantics::{PathResolution, Semantics, SemanticsScope}, diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs index 67cd16e31..cd689c869 100644 --- a/crates/hir/src/semantics.rs +++ b/crates/hir/src/semantics.rs @@ -25,9 +25,9 @@ use crate::{ diagnostics::Diagnostic, semantics::source_to_def::{ChildContainer, SourceToDefCache, SourceToDefCtx}, source_analyzer::{resolve_hir_path, SourceAnalyzer}, - AssocItem, Callable, Crate, Field, Function, HirFileId, Impl, InFile, Label, LifetimeParam, - Local, MacroDef, Module, ModuleDef, Name, Path, ScopeDef, Trait, Type, TypeAlias, TypeParam, - VariantDef, + AssocItem, Callable, ConstParam, Crate, Field, Function, HirFileId, Impl, InFile, Label, + LifetimeParam, Local, MacroDef, Module, ModuleDef, Name, Path, ScopeDef, Trait, Type, + TypeAlias, TypeParam, VariantDef, }; #[derive(Debug, Clone, PartialEq, Eq)] @@ -38,6 +38,7 @@ pub enum PathResolution { Local(Local), /// A generic parameter TypeParam(TypeParam), + ConstParam(ConstParam), SelfType(Impl), Macro(MacroDef), AssocItem(AssocItem), @@ -59,7 +60,9 @@ impl PathResolution { PathResolution::Def(ModuleDef::TypeAlias(alias)) => { 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::SelfType(impl_def) => Some(TypeNs::SelfType((*impl_def).into())), PathResolution::AssocItem(AssocItem::Const(_)) @@ -744,6 +747,7 @@ to_def_impls![ (crate::Variant, ast::Variant, enum_variant_to_def), (crate::TypeParam, ast::TypeParam, type_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::Local, ast::IdentPat, bind_pat_to_def), (crate::Label, ast::Label, label_to_def), diff --git a/crates/hir/src/semantics/source_to_def.rs b/crates/hir/src/semantics/source_to_def.rs index 424e6e8a9..4b9ebff72 100644 --- a/crates/hir/src/semantics/source_to_def.rs +++ b/crates/hir/src/semantics/source_to_def.rs @@ -6,9 +6,9 @@ use hir_def::{ dyn_map::DynMap, expr::{LabelId, PatId}, keys::{self, Key}, - ConstId, DefWithBodyId, EnumId, EnumVariantId, FieldId, FunctionId, GenericDefId, ImplId, - LifetimeParamId, ModuleId, StaticId, StructId, TraitId, TypeAliasId, TypeParamId, UnionId, - VariantId, + ConstId, ConstParamId, DefWithBodyId, EnumId, EnumVariantId, FieldId, FunctionId, GenericDefId, + ImplId, LifetimeParamId, ModuleId, StaticId, StructId, TraitId, TypeAliasId, TypeParamId, + UnionId, VariantId, }; use hir_expand::{name::AsName, AstId, MacroDefKind}; use rustc_hash::FxHashMap; @@ -157,6 +157,18 @@ impl SourceToDefCtx<'_, '_> { dyn_map[keys::LIFETIME_PARAM].get(&src).copied() } + pub(super) fn const_param_to_def( + &mut self, + src: InFile, + ) -> Option { + 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? pub(super) fn macro_rules_to_def( &mut self, diff --git a/crates/hir/src/source_analyzer.rs b/crates/hir/src/source_analyzer.rs index bddc49c05..30a8e513d 100644 --- a/crates/hir/src/source_analyzer.rs +++ b/crates/hir/src/source_analyzer.rs @@ -479,6 +479,7 @@ pub(crate) fn resolve_hir_path( ValueNs::StructId(it) => PathResolution::Def(Struct::from(it).into()), ValueNs::EnumVariantId(it) => PathResolution::Def(Variant::from(it).into()), ValueNs::ImplSelf(impl_id) => PathResolution::SelfType(impl_id.into()), + ValueNs::GenericParam(it) => PathResolution::ConstParam(it.into()), }; Some(res) }); 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_) => { diff --git a/crates/hir_ty/src/db.rs b/crates/hir_ty/src/db.rs index 66bdb8e88..f3567c49e 100644 --- a/crates/hir_ty/src/db.rs +++ b/crates/hir_ty/src/db.rs @@ -5,8 +5,8 @@ use std::sync::Arc; use arena::map::ArenaMap; use base_db::{impl_intern_key, salsa, CrateId, Upcast}; use hir_def::{ - db::DefDatabase, expr::ExprId, DefWithBodyId, FunctionId, GenericDefId, ImplId, LocalFieldId, - TypeParamId, VariantId, + db::DefDatabase, expr::ExprId, ConstParamId, DefWithBodyId, FunctionId, GenericDefId, ImplId, + LocalFieldId, TypeParamId, VariantId, }; use crate::{ @@ -37,6 +37,9 @@ pub trait HirDatabase: DefDatabase + Upcast { #[salsa::cycle(crate::lower::impl_self_ty_recover)] fn impl_self_ty(&self, def: ImplId) -> Binders; + #[salsa::invoke(crate::lower::const_param_ty_query)] + fn const_param_ty(&self, def: ConstParamId) -> Ty; + #[salsa::invoke(crate::lower::impl_trait_query)] fn impl_trait(&self, def: ImplId) -> Option>; diff --git a/crates/hir_ty/src/infer/path.rs b/crates/hir_ty/src/infer/path.rs index 80d7ed10e..5d541104e 100644 --- a/crates/hir_ty/src/infer/path.rs +++ b/crates/hir_ty/src/infer/path.rs @@ -89,6 +89,7 @@ impl<'a> InferenceContext<'a> { return None; } } + ValueNs::GenericParam(it) => return Some(self.db.const_param_ty(it)), }; let ty = self.db.value_ty(typable); diff --git a/crates/hir_ty/src/lower.rs b/crates/hir_ty/src/lower.rs index 8da56cd11..222f61a11 100644 --- a/crates/hir_ty/src/lower.rs +++ b/crates/hir_ty/src/lower.rs @@ -16,9 +16,9 @@ use hir_def::{ path::{GenericArg, Path, PathSegment, PathSegments}, resolver::{HasResolver, Resolver, TypeNs}, type_ref::{TypeBound, TypeRef}, - AdtId, AssocContainerId, AssocItemId, ConstId, EnumId, EnumVariantId, FunctionId, GenericDefId, - HasModule, ImplId, LocalFieldId, Lookup, StaticId, StructId, TraitId, TypeAliasId, TypeParamId, - UnionId, VariantId, + AdtId, AssocContainerId, AssocItemId, ConstId, ConstParamId, EnumId, EnumVariantId, FunctionId, + GenericDefId, HasModule, ImplId, LocalFieldId, Lookup, StaticId, StructId, TraitId, + TypeAliasId, TypeParamId, UnionId, VariantId, }; use hir_expand::name::Name; 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)) } +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( db: &dyn HirDatabase, _cycle: &[String], diff --git a/crates/hir_ty/src/tests/simple.rs b/crates/hir_ty/src/tests/simple.rs index a61282d5a..bd6beea99 100644 --- a/crates/hir_ty/src/tests/simple.rs +++ b/crates/hir_ty/src/tests/simple.rs @@ -2375,3 +2375,20 @@ fn infer_operator_overload() { "#]], ); } + + +#[test] +fn infer_const_params() { + check_infer( + r#" + fn foo() { + let bar = FOO; + } + "#, + expect![[r#" + 27..49 '{ ...FOO; }': () + 37..40 'bar': usize + 43..46 'FOO': usize + "#]], + ); +} -- cgit v1.2.3 From 18bf2e5af5875f036b321bcf9e07e9904c02510e Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Fri, 1 Jan 2021 10:07:01 +0100 Subject: Add ConstParams to the ide layer --- crates/assists/src/ast_transform.rs | 3 ++- crates/hir_ty/src/tests/simple.rs | 1 - crates/ide/src/display/navigation_target.rs | 19 +++++++++++++++++++ crates/ide/src/doc_links.rs | 1 + crates/ide/src/hover.rs | 5 ++++- crates/ide/src/references.rs | 16 ++++++++++++++++ crates/ide/src/syntax_highlighting.rs | 1 + crates/ide/src/syntax_highlighting/tags.rs | 1 + .../syntax_highlighting/test_data/highlighting.html | 4 ++++ crates/ide/src/syntax_highlighting/tests.rs | 4 ++++ crates/ide_db/src/defs.rs | 13 +++++++++++-- crates/rust-analyzer/src/semantic_tokens.rs | 1 + crates/rust-analyzer/src/to_proto.rs | 2 ++ 13 files changed, 66 insertions(+), 5 deletions(-) (limited to 'crates') diff --git a/crates/assists/src/ast_transform.rs b/crates/assists/src/ast_transform.rs index da94e9987..4a3ed7783 100644 --- a/crates/assists/src/ast_transform.rs +++ b/crates/assists/src/ast_transform.rs @@ -204,7 +204,8 @@ impl<'a> AstTransform<'a> for QualifyPaths<'a> { } PathResolution::Local(_) | PathResolution::TypeParam(_) - | PathResolution::SelfType(_) => None, + | PathResolution::SelfType(_) + | PathResolution::ConstParam(_) => None, PathResolution::Macro(_) => None, PathResolution::AssocItem(_) => None, } diff --git a/crates/hir_ty/src/tests/simple.rs b/crates/hir_ty/src/tests/simple.rs index bd6beea99..8d431b920 100644 --- a/crates/hir_ty/src/tests/simple.rs +++ b/crates/hir_ty/src/tests/simple.rs @@ -2376,7 +2376,6 @@ fn infer_operator_overload() { ); } - #[test] fn infer_const_params() { check_infer( diff --git a/crates/ide/src/display/navigation_target.rs b/crates/ide/src/display/navigation_target.rs index 6431e7d6d..bcde2b6f1 100644 --- a/crates/ide/src/display/navigation_target.rs +++ b/crates/ide/src/display/navigation_target.rs @@ -24,6 +24,7 @@ pub enum SymbolKind { Impl, Field, TypeParam, + ConstParam, LifetimeParam, ValueParam, SelfParam, @@ -225,6 +226,7 @@ impl TryToNav for Definition { Definition::TypeParam(it) => Some(it.to_nav(db)), Definition::LifetimeParam(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. /// /// e.g. `struct Name`, `enum Name`, `fn Name` diff --git a/crates/ide/src/doc_links.rs b/crates/ide/src/doc_links.rs index e10516f43..367fac05e 100644 --- a/crates/ide/src/doc_links.rs +++ b/crates/ide/src/doc_links.rs @@ -193,6 +193,7 @@ fn rewrite_intra_doc_link( Definition::SelfType(_) | Definition::Local(_) | Definition::TypeParam(_) + | Definition::ConstParam(_) | Definition::LifetimeParam(_) | Definition::Label(_) => return None, }?; diff --git a/crates/ide/src/hover.rs b/crates/ide/src/hover.rs index 73245fbe7..49eb8caae 100644 --- a/crates/ide/src/hover.rs +++ b/crates/ide/src/hover.rs @@ -370,7 +370,10 @@ fn hover_for_definition(db: &RootDatabase, def: Definition) -> Option { 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 None } diff --git a/crates/ide/src/references.rs b/crates/ide/src/references.rs index 21b2d7ca1..fa58fc319 100644 --- a/crates/ide/src/references.rs +++ b/crates/ide/src/references.rs @@ -1144,4 +1144,20 @@ fn foo<'a>() -> &'a () { "#]], ); } + + #[test] + fn test_find_const_param() { + check( + r#" +fn foo: usize>() -> usize { + FOO +} +"#, + expect![[r#" + FOO ConstParam FileId(0) 7..23 13..16 Other + + FileId(0) 42..45 Other + "#]], + ); + } } diff --git a/crates/ide/src/syntax_highlighting.rs b/crates/ide/src/syntax_highlighting.rs index 5ad96581b..ba0085244 100644 --- a/crates/ide/src/syntax_highlighting.rs +++ b/crates/ide/src/syntax_highlighting.rs @@ -819,6 +819,7 @@ fn highlight_def(db: &RootDatabase, def: Definition) -> Highlight { }, Definition::SelfType(_) => HighlightTag::Symbol(SymbolKind::Impl), Definition::TypeParam(_) => HighlightTag::Symbol(SymbolKind::TypeParam), + Definition::ConstParam(_) => HighlightTag::Symbol(SymbolKind::ConstParam), Definition::Local(local) => { let tag = if local.is_param(db) { HighlightTag::Symbol(SymbolKind::ValueParam) diff --git a/crates/ide/src/syntax_highlighting/tags.rs b/crates/ide/src/syntax_highlighting/tags.rs index 2a6cc0cab..8b8867079 100644 --- a/crates/ide/src/syntax_highlighting/tags.rs +++ b/crates/ide/src/syntax_highlighting/tags.rs @@ -77,6 +77,7 @@ impl HighlightTag { SymbolKind::Function => "function", SymbolKind::TypeAlias => "type_alias", SymbolKind::TypeParam => "type_param", + SymbolKind::ConstParam => "const_param", SymbolKind::LifetimeParam => "lifetime", SymbolKind::Macro => "macro", SymbolKind::Local => "variable", diff --git a/crates/ide/src/syntax_highlighting/test_data/highlighting.html b/crates/ide/src/syntax_highlighting/test_data/highlighting.html index 72ff9dd40..02270b077 100644 --- a/crates/ide/src/syntax_highlighting/test_data/highlighting.html +++ b/crates/ide/src/syntax_highlighting/test_data/highlighting.html @@ -118,6 +118,10 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd loop {} } +fn const_param<const FOO: usize>() -> usize { + FOO +} + use ops::Fn; fn baz<F: Fn() -> ()>(f: F) { f() diff --git a/crates/ide/src/syntax_highlighting/tests.rs b/crates/ide/src/syntax_highlighting/tests.rs index e0df0d2b5..30b5b648e 100644 --- a/crates/ide/src/syntax_highlighting/tests.rs +++ b/crates/ide/src/syntax_highlighting/tests.rs @@ -91,6 +91,10 @@ fn never() -> ! { loop {} } +fn const_param() -> usize { + FOO +} + use ops::Fn; fn baz ()>(f: F) { f() diff --git a/crates/ide_db/src/defs.rs b/crates/ide_db/src/defs.rs index d33a6cb86..cc5078bf0 100644 --- a/crates/ide_db/src/defs.rs +++ b/crates/ide_db/src/defs.rs @@ -6,8 +6,8 @@ // FIXME: this badly needs rename/rewrite (matklad, 2020-02-06). use hir::{ - db::HirDatabase, Crate, Field, HasVisibility, Impl, Label, LifetimeParam, Local, MacroDef, - Module, ModuleDef, Name, PathResolution, Semantics, TypeParam, Visibility, + db::HirDatabase, ConstParam, Crate, Field, HasVisibility, Impl, Label, LifetimeParam, Local, + MacroDef, Module, ModuleDef, Name, PathResolution, Semantics, TypeParam, Visibility, }; use syntax::{ ast::{self, AstNode}, @@ -26,6 +26,7 @@ pub enum Definition { Local(Local), TypeParam(TypeParam), LifetimeParam(LifetimeParam), + ConstParam(ConstParam), Label(Label), } @@ -39,6 +40,7 @@ impl Definition { Definition::Local(it) => Some(it.module(db)), Definition::TypeParam(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)), } } @@ -52,6 +54,7 @@ impl Definition { Definition::Local(_) => None, Definition::TypeParam(_) => None, Definition::LifetimeParam(_) => None, + Definition::ConstParam(_) => None, Definition::Label(_) => None, } } @@ -79,6 +82,7 @@ impl Definition { Definition::Local(it) => it.name(db)?, Definition::TypeParam(it) => it.name(db), Definition::LifetimeParam(it) => it.name(db), + Definition::ConstParam(it) => it.name(db), Definition::Label(it) => it.name(db), }; Some(name) @@ -233,6 +237,10 @@ impl NameClass { let def = sema.to_def(&it)?; Some(NameClass::Definition(Definition::TypeParam(def))) }, + ast::ConstParam(it) => { + let def = sema.to_def(&it)?; + Some(NameClass::Definition(Definition::ConstParam(def))) + }, _ => None, } } @@ -417,6 +425,7 @@ impl From for Definition { PathResolution::TypeParam(par) => Definition::TypeParam(par), PathResolution::Macro(def) => Definition::Macro(def), PathResolution::SelfType(impl_def) => Definition::SelfType(impl_def), + PathResolution::ConstParam(par) => Definition::ConstParam(par), } } } diff --git a/crates/rust-analyzer/src/semantic_tokens.rs b/crates/rust-analyzer/src/semantic_tokens.rs index c2f6a655d..5c4366f16 100644 --- a/crates/rust-analyzer/src/semantic_tokens.rs +++ b/crates/rust-analyzer/src/semantic_tokens.rs @@ -44,6 +44,7 @@ define_semantic_token_types![ (ESCAPE_SEQUENCE, "escapeSequence"), (FORMAT_SPECIFIER, "formatSpecifier"), (GENERIC, "generic"), + (CONST_PARAMETER, "constParameter"), (LIFETIME, "lifetime"), (LABEL, "label"), (PUNCTUATION, "punctuation"), diff --git a/crates/rust-analyzer/src/to_proto.rs b/crates/rust-analyzer/src/to_proto.rs index 1a38e79f0..999b18351 100644 --- a/crates/rust-analyzer/src/to_proto.rs +++ b/crates/rust-analyzer/src/to_proto.rs @@ -42,6 +42,7 @@ pub(crate) fn symbol_kind(symbol_kind: SymbolKind) -> lsp_types::SymbolKind { SymbolKind::Field => lsp_types::SymbolKind::Field, SymbolKind::Static => lsp_types::SymbolKind::Constant, SymbolKind::Const => lsp_types::SymbolKind::Constant, + SymbolKind::ConstParam => lsp_types::SymbolKind::Constant, SymbolKind::Impl => lsp_types::SymbolKind::Object, SymbolKind::Local | SymbolKind::SelfParam @@ -378,6 +379,7 @@ fn semantic_token_type_and_modifiers( SymbolKind::Impl => lsp_types::SemanticTokenType::TYPE, SymbolKind::Field => lsp_types::SemanticTokenType::PROPERTY, SymbolKind::TypeParam => lsp_types::SemanticTokenType::TYPE_PARAMETER, + SymbolKind::ConstParam => semantic_tokens::CONST_PARAMETER, SymbolKind::LifetimeParam => semantic_tokens::LIFETIME, SymbolKind::Label => semantic_tokens::LABEL, SymbolKind::ValueParam => lsp_types::SemanticTokenType::PARAMETER, -- cgit v1.2.3