diff options
author | Lukas Wirth <[email protected]> | 2021-01-01 09:06:42 +0000 |
---|---|---|
committer | Lukas Wirth <[email protected]> | 2021-01-01 09:06:42 +0000 |
commit | 0acdb730769cfb040ffc5e2c87f83b19fd3ce291 (patch) | |
tree | 5e416c64e2bf0cfb8dee2c212ae9f301dd974416 /crates | |
parent | 77ad203a719be074e81485af7a4fb02fac6cbf61 (diff) |
Add ConstParams to the HIR
Diffstat (limited to 'crates')
-rw-r--r-- | crates/hir/src/code_model.rs | 38 | ||||
-rw-r--r-- | crates/hir/src/from_id.rs | 1 | ||||
-rw-r--r-- | crates/hir/src/has_source.rs | 12 | ||||
-rw-r--r-- | crates/hir/src/lib.rs | 6 | ||||
-rw-r--r-- | crates/hir/src/semantics.rs | 12 | ||||
-rw-r--r-- | crates/hir/src/semantics/source_to_def.rs | 18 | ||||
-rw-r--r-- | crates/hir/src/source_analyzer.rs | 1 | ||||
-rw-r--r-- | crates/hir_def/src/generics.rs | 44 | ||||
-rw-r--r-- | crates/hir_def/src/item_tree.rs | 9 | ||||
-rw-r--r-- | crates/hir_def/src/keys.rs | 5 | ||||
-rw-r--r-- | crates/hir_def/src/lib.rs | 7 | ||||
-rw-r--r-- | crates/hir_def/src/resolver.rs | 17 | ||||
-rw-r--r-- | crates/hir_ty/src/db.rs | 7 | ||||
-rw-r--r-- | crates/hir_ty/src/infer/path.rs | 1 | ||||
-rw-r--r-- | crates/hir_ty/src/lower.rs | 15 | ||||
-rw-r--r-- | crates/hir_ty/src/tests/simple.rs | 17 |
16 files changed, 173 insertions, 37 deletions
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::{ | |||
18 | resolver::{HasResolver, Resolver}, | 18 | resolver::{HasResolver, Resolver}, |
19 | src::HasSource as _, | 19 | src::HasSource as _, |
20 | type_ref::{Mutability, TypeRef}, | 20 | type_ref::{Mutability, TypeRef}, |
21 | AdtId, AssocContainerId, AssocItemId, AssocItemLoc, AttrDefId, ConstId, DefWithBodyId, EnumId, | 21 | AdtId, AssocContainerId, AssocItemId, AssocItemLoc, AttrDefId, ConstId, ConstParamId, |
22 | FunctionId, GenericDefId, HasModule, ImplId, LifetimeParamId, LocalEnumVariantId, LocalFieldId, | 22 | DefWithBodyId, EnumId, FunctionId, GenericDefId, HasModule, ImplId, LifetimeParamId, |
23 | LocalModuleId, Lookup, ModuleId, StaticId, StructId, TraitId, TypeAliasId, TypeParamId, | 23 | LocalEnumVariantId, LocalFieldId, LocalModuleId, Lookup, ModuleId, StaticId, StructId, TraitId, |
24 | UnionId, | 24 | TypeAliasId, TypeParamId, UnionId, |
25 | }; | 25 | }; |
26 | use hir_def::{find_path::PrefixKind, item_scope::ItemInNs, visibility::Visibility}; | 26 | use hir_def::{find_path::PrefixKind, item_scope::ItemInNs, visibility::Visibility}; |
27 | use hir_expand::{ | 27 | use hir_expand::{ |
@@ -1125,7 +1125,12 @@ impl GenericDef { | |||
1125 | id: LifetimeParamId { parent: self.into(), local_id }, | 1125 | id: LifetimeParamId { parent: self.into(), local_id }, |
1126 | }) | 1126 | }) |
1127 | .map(GenericParam::LifetimeParam); | 1127 | .map(GenericParam::LifetimeParam); |
1128 | ty_params.chain(lt_params).collect() | 1128 | let const_params = generics |
1129 | .consts | ||
1130 | .iter() | ||
1131 | .map(|(local_id, _)| ConstParam { id: ConstParamId { parent: self.into(), local_id } }) | ||
1132 | .map(GenericParam::ConstParam); | ||
1133 | ty_params.chain(lt_params).chain(const_params).collect() | ||
1129 | } | 1134 | } |
1130 | 1135 | ||
1131 | pub fn type_params(self, db: &dyn HirDatabase) -> Vec<TypeParam> { | 1136 | pub fn type_params(self, db: &dyn HirDatabase) -> Vec<TypeParam> { |
@@ -1237,8 +1242,9 @@ impl Label { | |||
1237 | pub enum GenericParam { | 1242 | pub enum GenericParam { |
1238 | TypeParam(TypeParam), | 1243 | TypeParam(TypeParam), |
1239 | LifetimeParam(LifetimeParam), | 1244 | LifetimeParam(LifetimeParam), |
1245 | ConstParam(ConstParam), | ||
1240 | } | 1246 | } |
1241 | impl_from!(TypeParam, LifetimeParam for GenericParam); | 1247 | impl_from!(TypeParam, LifetimeParam, ConstParam for GenericParam); |
1242 | 1248 | ||
1243 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] | 1249 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] |
1244 | pub struct TypeParam { | 1250 | pub struct TypeParam { |
@@ -1300,6 +1306,26 @@ impl LifetimeParam { | |||
1300 | } | 1306 | } |
1301 | } | 1307 | } |
1302 | 1308 | ||
1309 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] | ||
1310 | pub struct ConstParam { | ||
1311 | pub(crate) id: ConstParamId, | ||
1312 | } | ||
1313 | |||
1314 | impl ConstParam { | ||
1315 | pub fn name(self, db: &dyn HirDatabase) -> Name { | ||
1316 | let params = db.generic_params(self.id.parent); | ||
1317 | params.consts[self.id.local_id].name.clone() | ||
1318 | } | ||
1319 | |||
1320 | pub fn module(self, db: &dyn HirDatabase) -> Module { | ||
1321 | self.id.parent.module(db.upcast()).into() | ||
1322 | } | ||
1323 | |||
1324 | pub fn parent(self, _db: &dyn HirDatabase) -> GenericDef { | ||
1325 | self.id.parent.into() | ||
1326 | } | ||
1327 | } | ||
1328 | |||
1303 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 1329 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
1304 | pub struct Impl { | 1330 | pub struct Impl { |
1305 | pub(crate) id: ImplId, | 1331 | 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![ | |||
44 | (hir_def::ImplId, crate::Impl), | 44 | (hir_def::ImplId, crate::Impl), |
45 | (hir_def::TypeParamId, crate::TypeParam), | 45 | (hir_def::TypeParamId, crate::TypeParam), |
46 | (hir_def::LifetimeParamId, crate::LifetimeParam), | 46 | (hir_def::LifetimeParamId, crate::LifetimeParam), |
47 | (hir_def::ConstParamId, crate::ConstParam), | ||
47 | (hir_expand::MacroDefId, crate::MacroDef) | 48 | (hir_expand::MacroDefId, crate::MacroDef) |
48 | ]; | 49 | ]; |
49 | 50 | ||
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; | |||
10 | use syntax::ast; | 10 | use syntax::ast; |
11 | 11 | ||
12 | use crate::{ | 12 | use crate::{ |
13 | db::HirDatabase, Const, Enum, Field, FieldSource, Function, Impl, LifetimeParam, MacroDef, | 13 | db::HirDatabase, Const, ConstParam, Enum, Field, FieldSource, Function, Impl, LifetimeParam, |
14 | Module, Static, Struct, Trait, TypeAlias, TypeParam, Union, Variant, | 14 | MacroDef, Module, Static, Struct, Trait, TypeAlias, TypeParam, Union, Variant, |
15 | }; | 15 | }; |
16 | 16 | ||
17 | pub trait HasSource { | 17 | pub trait HasSource { |
@@ -140,3 +140,11 @@ impl HasSource for LifetimeParam { | |||
140 | child_source.map(|it| it[self.id.local_id].clone()) | 140 | child_source.map(|it| it[self.id.local_id].clone()) |
141 | } | 141 | } |
142 | } | 142 | } |
143 | |||
144 | impl HasSource for ConstParam { | ||
145 | type Ast = ast::ConstParam; | ||
146 | fn source(self, db: &dyn HirDatabase) -> InFile<Self::Ast> { | ||
147 | let child_source = self.id.parent.child_source(db.upcast()); | ||
148 | child_source.map(|it| it[self.id.local_id].clone()) | ||
149 | } | ||
150 | } | ||
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::{ | |||
34 | attrs::{HasAttrs, Namespace}, | 34 | attrs::{HasAttrs, Namespace}, |
35 | code_model::{ | 35 | code_model::{ |
36 | Access, Adt, AsAssocItem, AssocItem, AssocItemContainer, Callable, CallableKind, Const, | 36 | Access, Adt, AsAssocItem, AssocItem, AssocItemContainer, Callable, CallableKind, Const, |
37 | Crate, CrateDependency, DefWithBody, Enum, Field, FieldSource, Function, GenericDef, | 37 | ConstParam, Crate, CrateDependency, DefWithBody, Enum, Field, FieldSource, Function, |
38 | HasVisibility, Impl, Label, LifetimeParam, Local, MacroDef, Module, ModuleDef, ScopeDef, | 38 | GenericDef, HasVisibility, Impl, Label, LifetimeParam, Local, MacroDef, Module, ModuleDef, |
39 | Static, Struct, Trait, Type, TypeAlias, TypeParam, Union, Variant, VariantDef, | 39 | ScopeDef, Static, Struct, Trait, Type, TypeAlias, TypeParam, Union, Variant, VariantDef, |
40 | }, | 40 | }, |
41 | has_source::HasSource, | 41 | has_source::HasSource, |
42 | semantics::{PathResolution, Semantics, SemanticsScope}, | 42 | 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::{ | |||
25 | diagnostics::Diagnostic, | 25 | diagnostics::Diagnostic, |
26 | semantics::source_to_def::{ChildContainer, SourceToDefCache, SourceToDefCtx}, | 26 | semantics::source_to_def::{ChildContainer, SourceToDefCache, SourceToDefCtx}, |
27 | source_analyzer::{resolve_hir_path, SourceAnalyzer}, | 27 | source_analyzer::{resolve_hir_path, SourceAnalyzer}, |
28 | AssocItem, Callable, Crate, Field, Function, HirFileId, Impl, InFile, Label, LifetimeParam, | 28 | AssocItem, Callable, ConstParam, Crate, Field, Function, HirFileId, Impl, InFile, Label, |
29 | Local, MacroDef, Module, ModuleDef, Name, Path, ScopeDef, Trait, Type, TypeAlias, TypeParam, | 29 | LifetimeParam, Local, MacroDef, Module, ModuleDef, Name, Path, ScopeDef, Trait, Type, |
30 | VariantDef, | 30 | TypeAlias, TypeParam, VariantDef, |
31 | }; | 31 | }; |
32 | 32 | ||
33 | #[derive(Debug, Clone, PartialEq, Eq)] | 33 | #[derive(Debug, Clone, PartialEq, Eq)] |
@@ -38,6 +38,7 @@ pub enum PathResolution { | |||
38 | Local(Local), | 38 | Local(Local), |
39 | /// A generic parameter | 39 | /// A generic parameter |
40 | TypeParam(TypeParam), | 40 | TypeParam(TypeParam), |
41 | ConstParam(ConstParam), | ||
41 | SelfType(Impl), | 42 | SelfType(Impl), |
42 | Macro(MacroDef), | 43 | Macro(MacroDef), |
43 | AssocItem(AssocItem), | 44 | AssocItem(AssocItem), |
@@ -59,7 +60,9 @@ impl PathResolution { | |||
59 | PathResolution::Def(ModuleDef::TypeAlias(alias)) => { | 60 | PathResolution::Def(ModuleDef::TypeAlias(alias)) => { |
60 | Some(TypeNs::TypeAliasId((*alias).into())) | 61 | Some(TypeNs::TypeAliasId((*alias).into())) |
61 | } | 62 | } |
62 | PathResolution::Local(_) | PathResolution::Macro(_) => None, | 63 | PathResolution::Local(_) | PathResolution::Macro(_) | PathResolution::ConstParam(_) => { |
64 | None | ||
65 | } | ||
63 | PathResolution::TypeParam(param) => Some(TypeNs::GenericParam((*param).into())), | 66 | PathResolution::TypeParam(param) => Some(TypeNs::GenericParam((*param).into())), |
64 | PathResolution::SelfType(impl_def) => Some(TypeNs::SelfType((*impl_def).into())), | 67 | PathResolution::SelfType(impl_def) => Some(TypeNs::SelfType((*impl_def).into())), |
65 | PathResolution::AssocItem(AssocItem::Const(_)) | 68 | PathResolution::AssocItem(AssocItem::Const(_)) |
@@ -744,6 +747,7 @@ to_def_impls![ | |||
744 | (crate::Variant, ast::Variant, enum_variant_to_def), | 747 | (crate::Variant, ast::Variant, enum_variant_to_def), |
745 | (crate::TypeParam, ast::TypeParam, type_param_to_def), | 748 | (crate::TypeParam, ast::TypeParam, type_param_to_def), |
746 | (crate::LifetimeParam, ast::LifetimeParam, lifetime_param_to_def), | 749 | (crate::LifetimeParam, ast::LifetimeParam, lifetime_param_to_def), |
750 | (crate::ConstParam, ast::ConstParam, const_param_to_def), | ||
747 | (crate::MacroDef, ast::MacroRules, macro_rules_to_def), | 751 | (crate::MacroDef, ast::MacroRules, macro_rules_to_def), |
748 | (crate::Local, ast::IdentPat, bind_pat_to_def), | 752 | (crate::Local, ast::IdentPat, bind_pat_to_def), |
749 | (crate::Label, ast::Label, label_to_def), | 753 | (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::{ | |||
6 | dyn_map::DynMap, | 6 | dyn_map::DynMap, |
7 | expr::{LabelId, PatId}, | 7 | expr::{LabelId, PatId}, |
8 | keys::{self, Key}, | 8 | keys::{self, Key}, |
9 | ConstId, DefWithBodyId, EnumId, EnumVariantId, FieldId, FunctionId, GenericDefId, ImplId, | 9 | ConstId, ConstParamId, DefWithBodyId, EnumId, EnumVariantId, FieldId, FunctionId, GenericDefId, |
10 | LifetimeParamId, ModuleId, StaticId, StructId, TraitId, TypeAliasId, TypeParamId, UnionId, | 10 | ImplId, LifetimeParamId, ModuleId, StaticId, StructId, TraitId, TypeAliasId, TypeParamId, |
11 | VariantId, | 11 | UnionId, VariantId, |
12 | }; | 12 | }; |
13 | use hir_expand::{name::AsName, AstId, MacroDefKind}; | 13 | use hir_expand::{name::AsName, AstId, MacroDefKind}; |
14 | use rustc_hash::FxHashMap; | 14 | use rustc_hash::FxHashMap; |
@@ -157,6 +157,18 @@ impl SourceToDefCtx<'_, '_> { | |||
157 | dyn_map[keys::LIFETIME_PARAM].get(&src).copied() | 157 | dyn_map[keys::LIFETIME_PARAM].get(&src).copied() |
158 | } | 158 | } |
159 | 159 | ||
160 | pub(super) fn const_param_to_def( | ||
161 | &mut self, | ||
162 | src: InFile<ast::ConstParam>, | ||
163 | ) -> Option<ConstParamId> { | ||
164 | let container: ChildContainer = | ||
165 | self.find_generic_param_container(src.as_ref().map(|it| it.syntax()))?.into(); | ||
166 | let db = self.db; | ||
167 | let dyn_map = | ||
168 | &*self.cache.entry(container).or_insert_with(|| container.child_by_source(db)); | ||
169 | dyn_map[keys::CONST_PARAM].get(&src).copied() | ||
170 | } | ||
171 | |||
160 | // FIXME: use DynMap as well? | 172 | // FIXME: use DynMap as well? |
161 | pub(super) fn macro_rules_to_def( | 173 | pub(super) fn macro_rules_to_def( |
162 | &mut self, | 174 | &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( | |||
479 | ValueNs::StructId(it) => PathResolution::Def(Struct::from(it).into()), | 479 | ValueNs::StructId(it) => PathResolution::Def(Struct::from(it).into()), |
480 | ValueNs::EnumVariantId(it) => PathResolution::Def(Variant::from(it).into()), | 480 | ValueNs::EnumVariantId(it) => PathResolution::Def(Variant::from(it).into()), |
481 | ValueNs::ImplSelf(impl_id) => PathResolution::SelfType(impl_id.into()), | 481 | ValueNs::ImplSelf(impl_id) => PathResolution::SelfType(impl_id.into()), |
482 | ValueNs::GenericParam(it) => PathResolution::ConstParam(it.into()), | ||
482 | }; | 483 | }; |
483 | Some(res) | 484 | Some(res) |
484 | }); | 485 | }); |
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::{ | |||
21 | keys, | 21 | keys, |
22 | src::{HasChildSource, HasSource}, | 22 | src::{HasChildSource, HasSource}, |
23 | type_ref::{LifetimeRef, TypeBound, TypeRef}, | 23 | type_ref::{LifetimeRef, TypeBound, TypeRef}, |
24 | AdtId, GenericDefId, LifetimeParamId, LocalLifetimeParamId, LocalTypeParamId, Lookup, | 24 | AdtId, ConstParamId, GenericDefId, LifetimeParamId, LocalConstParamId, LocalLifetimeParamId, |
25 | TypeParamId, | 25 | LocalTypeParamId, Lookup, TypeParamId, |
26 | }; | 26 | }; |
27 | 27 | ||
28 | /// Data about a generic parameter (to a function, struct, impl, ...). | 28 | /// Data about a generic type parameter (to a function, struct, impl, ...). |
29 | #[derive(Clone, PartialEq, Eq, Debug)] | 29 | #[derive(Clone, PartialEq, Eq, Debug)] |
30 | pub struct TypeParamData { | 30 | pub struct TypeParamData { |
31 | pub name: Option<Name>, | 31 | pub name: Option<Name>, |
@@ -33,12 +33,19 @@ pub struct TypeParamData { | |||
33 | pub provenance: TypeParamProvenance, | 33 | pub provenance: TypeParamProvenance, |
34 | } | 34 | } |
35 | 35 | ||
36 | /// Data about a generic parameter (to a function, struct, impl, ...). | 36 | /// Data about a generic lifetime parameter (to a function, struct, impl, ...). |
37 | #[derive(Clone, PartialEq, Eq, Debug)] | 37 | #[derive(Clone, PartialEq, Eq, Debug)] |
38 | pub struct LifetimeParamData { | 38 | pub struct LifetimeParamData { |
39 | pub name: Name, | 39 | pub name: Name, |
40 | } | 40 | } |
41 | 41 | ||
42 | /// Data about a generic const parameter (to a function, struct, impl, ...). | ||
43 | #[derive(Clone, PartialEq, Eq, Debug)] | ||
44 | pub struct ConstParamData { | ||
45 | pub name: Name, | ||
46 | pub ty: TypeRef, | ||
47 | } | ||
48 | |||
42 | #[derive(Copy, Clone, PartialEq, Eq, Debug)] | 49 | #[derive(Copy, Clone, PartialEq, Eq, Debug)] |
43 | pub enum TypeParamProvenance { | 50 | pub enum TypeParamProvenance { |
44 | TypeParamList, | 51 | TypeParamList, |
@@ -51,6 +58,7 @@ pub enum TypeParamProvenance { | |||
51 | pub struct GenericParams { | 58 | pub struct GenericParams { |
52 | pub types: Arena<TypeParamData>, | 59 | pub types: Arena<TypeParamData>, |
53 | pub lifetimes: Arena<LifetimeParamData>, | 60 | pub lifetimes: Arena<LifetimeParamData>, |
61 | pub consts: Arena<ConstParamData>, | ||
54 | pub where_predicates: Vec<WherePredicate>, | 62 | pub where_predicates: Vec<WherePredicate>, |
55 | } | 63 | } |
56 | 64 | ||
@@ -76,6 +84,7 @@ pub enum WherePredicateTypeTarget { | |||
76 | pub(crate) struct SourceMap { | 84 | pub(crate) struct SourceMap { |
77 | pub(crate) type_params: ArenaMap<LocalTypeParamId, Either<ast::Trait, ast::TypeParam>>, | 85 | pub(crate) type_params: ArenaMap<LocalTypeParamId, Either<ast::Trait, ast::TypeParam>>, |
78 | lifetime_params: ArenaMap<LocalLifetimeParamId, ast::LifetimeParam>, | 86 | lifetime_params: ArenaMap<LocalLifetimeParamId, ast::LifetimeParam>, |
87 | const_params: ArenaMap<LocalConstParamId, ast::ConstParam>, | ||
79 | } | 88 | } |
80 | 89 | ||
81 | impl GenericParams { | 90 | impl GenericParams { |
@@ -268,6 +277,13 @@ impl GenericParams { | |||
268 | let lifetime_ref = LifetimeRef::new_name(name); | 277 | let lifetime_ref = LifetimeRef::new_name(name); |
269 | self.fill_bounds(&lower_ctx, &lifetime_param, Either::Right(lifetime_ref)); | 278 | self.fill_bounds(&lower_ctx, &lifetime_param, Either::Right(lifetime_ref)); |
270 | } | 279 | } |
280 | for const_param in params.const_params() { | ||
281 | let name = const_param.name().map_or_else(Name::missing, |it| it.as_name()); | ||
282 | let ty = const_param.ty().map_or(TypeRef::Error, |it| TypeRef::from_ast(lower_ctx, it)); | ||
283 | let param = ConstParamData { name, ty }; | ||
284 | let param_id = self.consts.alloc(param); | ||
285 | sm.const_params.insert(param_id, const_param.clone()); | ||
286 | } | ||
271 | } | 287 | } |
272 | 288 | ||
273 | fn fill_where_predicates(&mut self, lower_ctx: &LowerCtx, where_clause: ast::WhereClause) { | 289 | fn fill_where_predicates(&mut self, lower_ctx: &LowerCtx, where_clause: ast::WhereClause) { |
@@ -353,12 +369,16 @@ impl GenericParams { | |||
353 | }); | 369 | }); |
354 | } | 370 | } |
355 | 371 | ||
356 | pub fn find_by_name(&self, name: &Name) -> Option<LocalTypeParamId> { | 372 | pub fn find_type_by_name(&self, name: &Name) -> Option<LocalTypeParamId> { |
357 | self.types | 373 | self.types |
358 | .iter() | 374 | .iter() |
359 | .find_map(|(id, p)| if p.name.as_ref() == Some(name) { Some(id) } else { None }) | 375 | .find_map(|(id, p)| if p.name.as_ref() == Some(name) { Some(id) } else { None }) |
360 | } | 376 | } |
361 | 377 | ||
378 | pub fn find_const_by_name(&self, name: &Name) -> Option<LocalConstParamId> { | ||
379 | self.consts.iter().find_map(|(id, p)| if p.name == *name { Some(id) } else { None }) | ||
380 | } | ||
381 | |||
362 | pub fn find_trait_self_param(&self) -> Option<LocalTypeParamId> { | 382 | pub fn find_trait_self_param(&self) -> Option<LocalTypeParamId> { |
363 | self.types.iter().find_map(|(id, p)| { | 383 | self.types.iter().find_map(|(id, p)| { |
364 | if p.provenance == TypeParamProvenance::TraitSelf { | 384 | if p.provenance == TypeParamProvenance::TraitSelf { |
@@ -390,6 +410,16 @@ impl HasChildSource<LocalLifetimeParamId> for GenericDefId { | |||
390 | } | 410 | } |
391 | } | 411 | } |
392 | 412 | ||
413 | impl HasChildSource<LocalConstParamId> for GenericDefId { | ||
414 | type Value = ast::ConstParam; | ||
415 | fn child_source( | ||
416 | &self, | ||
417 | db: &dyn DefDatabase, | ||
418 | ) -> InFile<ArenaMap<LocalConstParamId, Self::Value>> { | ||
419 | GenericParams::new(db, *self).1.map(|source_maps| source_maps.const_params) | ||
420 | } | ||
421 | } | ||
422 | |||
393 | impl ChildBySource for GenericDefId { | 423 | impl ChildBySource for GenericDefId { |
394 | fn child_by_source(&self, db: &dyn DefDatabase) -> DynMap { | 424 | fn child_by_source(&self, db: &dyn DefDatabase) -> DynMap { |
395 | let mut res = DynMap::default(); | 425 | let mut res = DynMap::default(); |
@@ -406,6 +436,10 @@ impl ChildBySource for GenericDefId { | |||
406 | let id = LifetimeParamId { parent: *self, local_id }; | 436 | let id = LifetimeParamId { parent: *self, local_id }; |
407 | res[keys::LIFETIME_PARAM].insert(sm.with_value(src.clone()), id); | 437 | res[keys::LIFETIME_PARAM].insert(sm.with_value(src.clone()), id); |
408 | } | 438 | } |
439 | for (local_id, src) in sm.value.const_params.iter() { | ||
440 | let id = ConstParamId { parent: *self, local_id }; | ||
441 | res[keys::CONST_PARAM].insert(sm.with_value(src.clone()), id); | ||
442 | } | ||
409 | res | 443 | res |
410 | } | 444 | } |
411 | } | 445 | } |
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 { | |||
260 | fn alloc(&mut self, params: GenericParams) -> GenericParamsId { | 260 | fn alloc(&mut self, params: GenericParams) -> GenericParamsId { |
261 | if params.types.is_empty() | 261 | if params.types.is_empty() |
262 | && params.lifetimes.is_empty() | 262 | && params.lifetimes.is_empty() |
263 | && params.consts.is_empty() | ||
263 | && params.where_predicates.is_empty() | 264 | && params.where_predicates.is_empty() |
264 | { | 265 | { |
265 | return GenericParamsId::EMPTY; | 266 | return GenericParamsId::EMPTY; |
@@ -269,8 +270,12 @@ impl GenericParamsStorage { | |||
269 | } | 270 | } |
270 | } | 271 | } |
271 | 272 | ||
272 | static EMPTY_GENERICS: GenericParams = | 273 | static EMPTY_GENERICS: GenericParams = GenericParams { |
273 | GenericParams { types: Arena::new(), lifetimes: Arena::new(), where_predicates: Vec::new() }; | 274 | types: Arena::new(), |
275 | lifetimes: Arena::new(), | ||
276 | consts: Arena::new(), | ||
277 | where_predicates: Vec::new(), | ||
278 | }; | ||
274 | 279 | ||
275 | #[derive(Default, Debug, Eq, PartialEq)] | 280 | #[derive(Default, Debug, Eq, PartialEq)] |
276 | struct ItemTreeData { | 281 | 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}; | |||
8 | 8 | ||
9 | use crate::{ | 9 | use crate::{ |
10 | dyn_map::{DynMap, Policy}, | 10 | dyn_map::{DynMap, Policy}, |
11 | ConstId, EnumId, EnumVariantId, FieldId, FunctionId, ImplId, LifetimeParamId, StaticId, | 11 | ConstId, ConstParamId, EnumId, EnumVariantId, FieldId, FunctionId, ImplId, LifetimeParamId, |
12 | StructId, TraitId, TypeAliasId, TypeParamId, UnionId, | 12 | StaticId, StructId, TraitId, TypeAliasId, TypeParamId, UnionId, |
13 | }; | 13 | }; |
14 | 14 | ||
15 | pub type Key<K, V> = crate::dyn_map::Key<InFile<K>, V, AstPtrPolicy<K, V>>; | 15 | 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(); | |||
29 | pub const RECORD_FIELD: Key<ast::RecordField, FieldId> = Key::new(); | 29 | pub const RECORD_FIELD: Key<ast::RecordField, FieldId> = Key::new(); |
30 | pub const TYPE_PARAM: Key<ast::TypeParam, TypeParamId> = Key::new(); | 30 | pub const TYPE_PARAM: Key<ast::TypeParam, TypeParamId> = Key::new(); |
31 | pub const LIFETIME_PARAM: Key<ast::LifetimeParam, LifetimeParamId> = Key::new(); | 31 | pub const LIFETIME_PARAM: Key<ast::LifetimeParam, LifetimeParamId> = Key::new(); |
32 | pub const CONST_PARAM: Key<ast::ConstParam, ConstParamId> = Key::new(); | ||
32 | 33 | ||
33 | pub const MACRO: Key<ast::MacroCall, MacroDefId> = Key::new(); | 34 | pub const MACRO: Key<ast::MacroCall, MacroDefId> = Key::new(); |
34 | 35 | ||
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 | |||
@@ -232,6 +232,13 @@ pub struct LifetimeParamId { | |||
232 | pub type LocalLifetimeParamId = Idx<generics::LifetimeParamData>; | 232 | pub type LocalLifetimeParamId = Idx<generics::LifetimeParamData>; |
233 | 233 | ||
234 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 234 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
235 | pub struct ConstParamId { | ||
236 | pub parent: GenericDefId, | ||
237 | pub local_id: LocalConstParamId, | ||
238 | } | ||
239 | pub type LocalConstParamId = Idx<generics::ConstParamData>; | ||
240 | |||
241 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||
235 | pub enum ContainerId { | 242 | pub enum ContainerId { |
236 | ModuleId(ModuleId), | 243 | ModuleId(ModuleId), |
237 | DefWithBodyId(DefWithBodyId), | 244 | DefWithBodyId(DefWithBodyId), |
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::{ | |||
20 | path::{ModPath, PathKind}, | 20 | path::{ModPath, PathKind}, |
21 | per_ns::PerNs, | 21 | per_ns::PerNs, |
22 | visibility::{RawVisibility, Visibility}, | 22 | visibility::{RawVisibility, Visibility}, |
23 | AdtId, AssocContainerId, ConstId, ContainerId, DefWithBodyId, EnumId, EnumVariantId, | 23 | AdtId, AssocContainerId, ConstId, ConstParamId, ContainerId, DefWithBodyId, EnumId, |
24 | FunctionId, GenericDefId, HasModule, ImplId, LocalModuleId, Lookup, ModuleDefId, ModuleId, | 24 | EnumVariantId, FunctionId, GenericDefId, HasModule, ImplId, LocalModuleId, Lookup, ModuleDefId, |
25 | StaticId, StructId, TraitId, TypeAliasId, TypeParamId, VariantId, | 25 | ModuleId, StaticId, StructId, TraitId, TypeAliasId, TypeParamId, VariantId, |
26 | }; | 26 | }; |
27 | 27 | ||
28 | #[derive(Debug, Clone, Default)] | 28 | #[derive(Debug, Clone, Default)] |
@@ -93,6 +93,7 @@ pub enum ValueNs { | |||
93 | StaticId(StaticId), | 93 | StaticId(StaticId), |
94 | StructId(StructId), | 94 | StructId(StructId), |
95 | EnumVariantId(EnumVariantId), | 95 | EnumVariantId(EnumVariantId), |
96 | GenericParam(ConstParamId), | ||
96 | } | 97 | } |
97 | 98 | ||
98 | impl Resolver { | 99 | impl Resolver { |
@@ -163,7 +164,7 @@ impl Resolver { | |||
163 | } | 164 | } |
164 | 165 | ||
165 | Scope::GenericParams { params, def } => { | 166 | Scope::GenericParams { params, def } => { |
166 | if let Some(local_id) = params.find_by_name(first_name) { | 167 | if let Some(local_id) = params.find_type_by_name(first_name) { |
167 | let idx = if path.segments.len() == 1 { None } else { Some(1) }; | 168 | let idx = if path.segments.len() == 1 { None } else { Some(1) }; |
168 | return Some(( | 169 | return Some(( |
169 | TypeNs::GenericParam(TypeParamId { local_id, parent: *def }), | 170 | TypeNs::GenericParam(TypeParamId { local_id, parent: *def }), |
@@ -285,11 +286,17 @@ impl Resolver { | |||
285 | Scope::ExprScope(_) => continue, | 286 | Scope::ExprScope(_) => continue, |
286 | 287 | ||
287 | Scope::GenericParams { params, def } if n_segments > 1 => { | 288 | Scope::GenericParams { params, def } if n_segments > 1 => { |
288 | if let Some(local_id) = params.find_by_name(first_name) { | 289 | if let Some(local_id) = params.find_type_by_name(first_name) { |
289 | let ty = TypeNs::GenericParam(TypeParamId { local_id, parent: *def }); | 290 | let ty = TypeNs::GenericParam(TypeParamId { local_id, parent: *def }); |
290 | return Some(ResolveValueResult::Partial(ty, 1)); | 291 | return Some(ResolveValueResult::Partial(ty, 1)); |
291 | } | 292 | } |
292 | } | 293 | } |
294 | Scope::GenericParams { params, def } if n_segments == 1 => { | ||
295 | if let Some(local_id) = params.find_const_by_name(first_name) { | ||
296 | let val = ValueNs::GenericParam(ConstParamId { local_id, parent: *def }); | ||
297 | return Some(ResolveValueResult::ValueNs(val)); | ||
298 | } | ||
299 | } | ||
293 | Scope::GenericParams { .. } => continue, | 300 | Scope::GenericParams { .. } => continue, |
294 | 301 | ||
295 | Scope::ImplDefScope(impl_) => { | 302 | 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; | |||
5 | use arena::map::ArenaMap; | 5 | use arena::map::ArenaMap; |
6 | use base_db::{impl_intern_key, salsa, CrateId, Upcast}; | 6 | use base_db::{impl_intern_key, salsa, CrateId, Upcast}; |
7 | use hir_def::{ | 7 | use hir_def::{ |
8 | db::DefDatabase, expr::ExprId, DefWithBodyId, FunctionId, GenericDefId, ImplId, LocalFieldId, | 8 | db::DefDatabase, expr::ExprId, ConstParamId, DefWithBodyId, FunctionId, GenericDefId, ImplId, |
9 | TypeParamId, VariantId, | 9 | LocalFieldId, TypeParamId, VariantId, |
10 | }; | 10 | }; |
11 | 11 | ||
12 | use crate::{ | 12 | use crate::{ |
@@ -37,6 +37,9 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> { | |||
37 | #[salsa::cycle(crate::lower::impl_self_ty_recover)] | 37 | #[salsa::cycle(crate::lower::impl_self_ty_recover)] |
38 | fn impl_self_ty(&self, def: ImplId) -> Binders<Ty>; | 38 | fn impl_self_ty(&self, def: ImplId) -> Binders<Ty>; |
39 | 39 | ||
40 | #[salsa::invoke(crate::lower::const_param_ty_query)] | ||
41 | fn const_param_ty(&self, def: ConstParamId) -> Ty; | ||
42 | |||
40 | #[salsa::invoke(crate::lower::impl_trait_query)] | 43 | #[salsa::invoke(crate::lower::impl_trait_query)] |
41 | fn impl_trait(&self, def: ImplId) -> Option<Binders<TraitRef>>; | 44 | fn impl_trait(&self, def: ImplId) -> Option<Binders<TraitRef>>; |
42 | 45 | ||
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> { | |||
89 | return None; | 89 | return None; |
90 | } | 90 | } |
91 | } | 91 | } |
92 | ValueNs::GenericParam(it) => return Some(self.db.const_param_ty(it)), | ||
92 | }; | 93 | }; |
93 | 94 | ||
94 | let ty = self.db.value_ty(typable); | 95 | 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::{ | |||
16 | path::{GenericArg, Path, PathSegment, PathSegments}, | 16 | path::{GenericArg, Path, PathSegment, PathSegments}, |
17 | resolver::{HasResolver, Resolver, TypeNs}, | 17 | resolver::{HasResolver, Resolver, TypeNs}, |
18 | type_ref::{TypeBound, TypeRef}, | 18 | type_ref::{TypeBound, TypeRef}, |
19 | AdtId, AssocContainerId, AssocItemId, ConstId, EnumId, EnumVariantId, FunctionId, GenericDefId, | 19 | AdtId, AssocContainerId, AssocItemId, ConstId, ConstParamId, EnumId, EnumVariantId, FunctionId, |
20 | HasModule, ImplId, LocalFieldId, Lookup, StaticId, StructId, TraitId, TypeAliasId, TypeParamId, | 20 | GenericDefId, HasModule, ImplId, LocalFieldId, Lookup, StaticId, StructId, TraitId, |
21 | UnionId, VariantId, | 21 | TypeAliasId, TypeParamId, UnionId, VariantId, |
22 | }; | 22 | }; |
23 | use hir_expand::name::Name; | 23 | use hir_expand::name::Name; |
24 | use smallvec::SmallVec; | 24 | use smallvec::SmallVec; |
@@ -1221,6 +1221,15 @@ pub(crate) fn impl_self_ty_query(db: &dyn HirDatabase, impl_id: ImplId) -> Binde | |||
1221 | Binders::new(generics.len(), Ty::from_hir(&ctx, &impl_data.target_type)) | 1221 | Binders::new(generics.len(), Ty::from_hir(&ctx, &impl_data.target_type)) |
1222 | } | 1222 | } |
1223 | 1223 | ||
1224 | pub(crate) fn const_param_ty_query(db: &dyn HirDatabase, def: ConstParamId) -> Ty { | ||
1225 | let parent_data = db.generic_params(def.parent); | ||
1226 | let data = &parent_data.consts[def.local_id]; | ||
1227 | let resolver = def.parent.resolver(db.upcast()); | ||
1228 | let ctx = TyLoweringContext::new(db, &resolver); | ||
1229 | |||
1230 | Ty::from_hir(&ctx, &data.ty) | ||
1231 | } | ||
1232 | |||
1224 | pub(crate) fn impl_self_ty_recover( | 1233 | pub(crate) fn impl_self_ty_recover( |
1225 | db: &dyn HirDatabase, | 1234 | db: &dyn HirDatabase, |
1226 | _cycle: &[String], | 1235 | _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() { | |||
2375 | "#]], | 2375 | "#]], |
2376 | ); | 2376 | ); |
2377 | } | 2377 | } |
2378 | |||
2379 | |||
2380 | #[test] | ||
2381 | fn infer_const_params() { | ||
2382 | check_infer( | ||
2383 | r#" | ||
2384 | fn foo<const FOO: usize>() { | ||
2385 | let bar = FOO; | ||
2386 | } | ||
2387 | "#, | ||
2388 | expect![[r#" | ||
2389 | 27..49 '{ ...FOO; }': () | ||
2390 | 37..40 'bar': usize | ||
2391 | 43..46 'FOO': usize | ||
2392 | "#]], | ||
2393 | ); | ||
2394 | } | ||