Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-def/src/lib.rs')
-rw-r--r--crates/hir-def/src/lib.rs76
1 files changed, 60 insertions, 16 deletions
diff --git a/crates/hir-def/src/lib.rs b/crates/hir-def/src/lib.rs
index 98cff54cc2..44dd0a7b38 100644
--- a/crates/hir-def/src/lib.rs
+++ b/crates/hir-def/src/lib.rs
@@ -89,8 +89,8 @@ use crate::{
builtin_type::BuiltinType,
data::adt::VariantData,
item_tree::{
- Const, Enum, Function, Impl, ItemTreeId, ItemTreeNode, MacroDef, MacroRules, ModItem,
- Static, Struct, Trait, TraitAlias, TypeAlias, Union,
+ Const, Enum, Function, Impl, ItemTreeId, ItemTreeNode, MacroDef, MacroRules, Static,
+ Struct, Trait, TraitAlias, TypeAlias, Union,
},
};
@@ -476,20 +476,55 @@ impl_from!(
for ModuleDefId
);
-// FIXME: make this a DefWithBodyId
+/// Id of the anonymous const block expression and patterns. This is very similar to `ClosureId` and
+/// shouldn't be a `DefWithBodyId` since its type inference is dependent on its parent.
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
pub struct AnonymousConstId(InternId);
impl_intern_key!(AnonymousConstId);
+#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
+pub enum TypeOwnerId {
+ ModuleId(ModuleId),
+ DefWithBodyId(DefWithBodyId),
+ GenericDefId(GenericDefId),
+}
+
+impl TypeOwnerId {
+ fn as_generic_def_id(self) -> Option<GenericDefId> {
+ match self {
+ TypeOwnerId::ModuleId(_) => None,
+ TypeOwnerId::DefWithBodyId(x) => x.as_generic_def_id(),
+ TypeOwnerId::GenericDefId(x) => Some(x),
+ }
+ }
+}
+
+impl_from!(ModuleId, DefWithBodyId(FunctionId, ConstId, StaticId), GenericDefId(AdtId, TypeAliasId, ImplId) for TypeOwnerId);
+
+#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
+pub struct InTypeConstId(InternId);
+type InTypeConstLoc = (AstId<ast::Expr>, TypeOwnerId);
+impl_intern!(InTypeConstId, InTypeConstLoc, intern_in_type_const, lookup_intern_in_type_const);
+
+impl InTypeConstId {
+ pub fn source(&self, db: &dyn db::DefDatabase) -> ast::Expr {
+ let src = self.lookup(db).0;
+ let file_id = src.file_id;
+ let root = &db.parse_or_expand(file_id);
+ db.ast_id_map(file_id).get(src.value).to_node(root)
+ }
+}
+
/// A constant, which might appears as a const item, an annonymous const block in expressions
/// or patterns, or as a constant in types with const generics.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum GeneralConstId {
ConstId(ConstId),
AnonymousConstId(AnonymousConstId),
+ InTypeConstId(InTypeConstId),
}
-impl_from!(ConstId, AnonymousConstId for GeneralConstId);
+impl_from!(ConstId, AnonymousConstId, InTypeConstId for GeneralConstId);
impl GeneralConstId {
pub fn generic_def(self, db: &dyn db::DefDatabase) -> Option<GenericDefId> {
@@ -499,6 +534,10 @@ impl GeneralConstId {
let (parent, _) = db.lookup_intern_anonymous_const(x);
parent.as_generic_def_id()
}
+ GeneralConstId::InTypeConstId(x) => {
+ let (_, parent) = x.lookup(db);
+ parent.as_generic_def_id()
+ }
}
}
@@ -512,6 +551,7 @@ impl GeneralConstId {
.unwrap_or("_")
.to_owned(),
GeneralConstId::AnonymousConstId(id) => format!("{{anonymous const {id:?}}}"),
+ GeneralConstId::InTypeConstId(id) => format!("{{in type const {id:?}}}"),
}
}
}
@@ -522,10 +562,11 @@ pub enum DefWithBodyId {
FunctionId(FunctionId),
StaticId(StaticId),
ConstId(ConstId),
+ InTypeConstId(InTypeConstId),
VariantId(EnumVariantId),
}
-impl_from!(FunctionId, ConstId, StaticId for DefWithBodyId);
+impl_from!(FunctionId, ConstId, StaticId, InTypeConstId for DefWithBodyId);
impl From<EnumVariantId> for DefWithBodyId {
fn from(id: EnumVariantId) -> Self {
@@ -540,6 +581,9 @@ impl DefWithBodyId {
DefWithBodyId::StaticId(_) => None,
DefWithBodyId::ConstId(c) => Some(c.into()),
DefWithBodyId::VariantId(c) => Some(c.into()),
+ // FIXME: stable rust doesn't allow generics in constants, but we should
+ // use `TypeOwnerId::as_generic_def_id` when it does.
+ DefWithBodyId::InTypeConstId(_) => None,
}
}
}
@@ -734,24 +778,24 @@ impl HasModule for MacroId {
}
}
-impl HasModule for DefWithBodyId {
+impl HasModule for TypeOwnerId {
fn module(&self, db: &dyn db::DefDatabase) -> ModuleId {
match self {
- DefWithBodyId::FunctionId(it) => it.lookup(db).module(db),
- DefWithBodyId::StaticId(it) => it.lookup(db).module(db),
- DefWithBodyId::ConstId(it) => it.lookup(db).module(db),
- DefWithBodyId::VariantId(it) => it.parent.lookup(db).container,
+ TypeOwnerId::ModuleId(x) => *x,
+ TypeOwnerId::DefWithBodyId(x) => x.module(db),
+ TypeOwnerId::GenericDefId(x) => x.module(db),
}
}
}
-impl DefWithBodyId {
- pub fn as_mod_item(self, db: &dyn db::DefDatabase) -> ModItem {
+impl HasModule for DefWithBodyId {
+ fn module(&self, db: &dyn db::DefDatabase) -> ModuleId {
match self {
- DefWithBodyId::FunctionId(it) => it.lookup(db).id.value.into(),
- DefWithBodyId::StaticId(it) => it.lookup(db).id.value.into(),
- DefWithBodyId::ConstId(it) => it.lookup(db).id.value.into(),
- DefWithBodyId::VariantId(it) => it.parent.lookup(db).id.value.into(),
+ DefWithBodyId::FunctionId(it) => it.lookup(db).module(db),
+ DefWithBodyId::StaticId(it) => it.lookup(db).module(db),
+ DefWithBodyId::ConstId(it) => it.lookup(db).module(db),
+ DefWithBodyId::VariantId(it) => it.parent.lookup(db).container,
+ DefWithBodyId::InTypeConstId(it) => it.lookup(db).1.module(db),
}
}
}