Unnamed repository; edit this file 'description' to name the repository.
-rw-r--r--crates/hir-def/src/body.rs9
-rw-r--r--crates/hir-def/src/lib.rs11
-rw-r--r--crates/hir-def/src/resolver.rs1
-rw-r--r--crates/hir-ty/src/consteval.rs31
-rw-r--r--crates/hir-ty/src/db.rs16
-rw-r--r--crates/hir-ty/src/diagnostics/unsafe_check.rs4
-rw-r--r--crates/hir-ty/src/infer.rs8
-rw-r--r--crates/hir-ty/src/tests.rs10
-rw-r--r--crates/hir/src/from_id.rs10
-rw-r--r--crates/hir/src/lib.rs16
-rw-r--r--crates/hir/src/symbols.rs5
-rw-r--r--crates/ide-db/src/search.rs1
-rw-r--r--crates/ide/src/hover/render.rs13
-rw-r--r--crates/ide/src/hover/tests.rs109
14 files changed, 227 insertions, 17 deletions
diff --git a/crates/hir-def/src/body.rs b/crates/hir-def/src/body.rs
index 22f5fb9926..484e2d7d7d 100644
--- a/crates/hir-def/src/body.rs
+++ b/crates/hir-def/src/body.rs
@@ -27,7 +27,7 @@ use crate::{
macro_id_to_def_id,
nameres::DefMap,
path::{ModPath, Path},
- src::HasSource,
+ src::{HasChildSource, HasSource},
AsMacroCall, BlockId, DefWithBodyId, HasModule, LocalModuleId, Lookup, MacroId, ModuleId,
UnresolvedMacro,
};
@@ -324,6 +324,13 @@ impl Body {
let src = s.source(db);
(src.file_id, s.module(db), src.value.body())
}
+ DefWithBodyId::VariantId(v) => {
+ let e = v.parent.lookup(db);
+ let src = v.parent.child_source(db);
+ let variant = &src.value[v.local_id];
+ // TODO(ole): Handle missing exprs (+1 to the prev)
+ (src.file_id, e.container, variant.expr())
+ }
};
let expander = Expander::new(db, file_id, module);
let (mut body, source_map) = Body::new(db, expander, params, body);
diff --git a/crates/hir-def/src/lib.rs b/crates/hir-def/src/lib.rs
index 32ebfda4fd..4c44840e86 100644
--- a/crates/hir-def/src/lib.rs
+++ b/crates/hir-def/src/lib.rs
@@ -474,16 +474,25 @@ pub enum DefWithBodyId {
FunctionId(FunctionId),
StaticId(StaticId),
ConstId(ConstId),
+ VariantId(EnumVariantId),
}
impl_from!(FunctionId, ConstId, StaticId for DefWithBodyId);
+// FIXME: Rename EnumVariantId to VariantId so that the macro above can be used
+impl From<EnumVariantId> for DefWithBodyId {
+ fn from(id: EnumVariantId) -> Self {
+ DefWithBodyId::VariantId(id)
+ }
+}
+
impl DefWithBodyId {
pub fn as_generic_def_id(self) -> Option<GenericDefId> {
match self {
DefWithBodyId::FunctionId(f) => Some(f.into()),
DefWithBodyId::StaticId(_) => None,
DefWithBodyId::ConstId(c) => Some(c.into()),
+ DefWithBodyId::VariantId(c) => Some(c.into()),
}
}
}
@@ -681,6 +690,7 @@ impl HasModule for DefWithBodyId {
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,
}
}
}
@@ -691,6 +701,7 @@ impl DefWithBodyId {
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(),
}
}
}
diff --git a/crates/hir-def/src/resolver.rs b/crates/hir-def/src/resolver.rs
index 8aa5973cac..070f683713 100644
--- a/crates/hir-def/src/resolver.rs
+++ b/crates/hir-def/src/resolver.rs
@@ -839,6 +839,7 @@ impl HasResolver for DefWithBodyId {
DefWithBodyId::ConstId(c) => c.resolver(db),
DefWithBodyId::FunctionId(f) => f.resolver(db),
DefWithBodyId::StaticId(s) => s.resolver(db),
+ DefWithBodyId::VariantId(v) => v.parent.resolver(db),
}
}
}
diff --git a/crates/hir-ty/src/consteval.rs b/crates/hir-ty/src/consteval.rs
index 6ecb6e6fd1..e934fe1c32 100644
--- a/crates/hir-ty/src/consteval.rs
+++ b/crates/hir-ty/src/consteval.rs
@@ -11,7 +11,7 @@ use hir_def::{
path::ModPath,
resolver::{resolver_for_expr, ResolveValueResult, Resolver, ValueNs},
type_ref::ConstScalar,
- ConstId, DefWithBodyId,
+ ConstId, DefWithBodyId, EnumVariantId,
};
use la_arena::{Arena, Idx};
use stdx::never;
@@ -339,6 +339,7 @@ pub fn eval_const(
ValueNs::GenericParam(_) => {
Err(ConstEvalError::NotSupported("const generic without substitution"))
}
+ ValueNs::EnumVariantId(id) => ctx.db.const_eval_variant(id), // TODO(ole): Assuming this is all that has to happen?
_ => Err(ConstEvalError::NotSupported("path that are not const or local")),
}
}
@@ -412,6 +413,14 @@ pub(crate) fn const_eval_recover(
Err(ConstEvalError::Loop)
}
+pub(crate) fn const_eval_recover_variant(
+ _: &dyn HirDatabase,
+ _: &[String],
+ _: &EnumVariantId,
+) -> Result<ComputedExpr, ConstEvalError> {
+ Err(ConstEvalError::Loop)
+}
+
pub(crate) fn const_eval_query(
db: &dyn HirDatabase,
const_id: ConstId,
@@ -433,6 +442,26 @@ pub(crate) fn const_eval_query(
result
}
+pub(crate) fn const_eval_query_variant(
+ db: &dyn HirDatabase,
+ variant_id: EnumVariantId,
+) -> Result<ComputedExpr, ConstEvalError> {
+ let def = variant_id.into();
+ let body = db.body(def);
+ let infer = &db.infer(def);
+ eval_const(
+ body.body_expr,
+ &mut ConstEvalCtx {
+ db,
+ owner: def,
+ exprs: &body.exprs,
+ pats: &body.pats,
+ local_data: HashMap::default(),
+ infer,
+ },
+ )
+}
+
pub(crate) fn eval_to_const<'a>(
expr: Idx<Expr>,
mode: ParamLoweringMode,
diff --git a/crates/hir-ty/src/db.rs b/crates/hir-ty/src/db.rs
index dd5639f00d..79c5c01ec6 100644
--- a/crates/hir-ty/src/db.rs
+++ b/crates/hir-ty/src/db.rs
@@ -6,8 +6,9 @@ use std::sync::Arc;
use arrayvec::ArrayVec;
use base_db::{impl_intern_key, salsa, CrateId, Upcast};
use hir_def::{
- db::DefDatabase, expr::ExprId, BlockId, ConstId, ConstParamId, DefWithBodyId, FunctionId,
- GenericDefId, ImplId, LifetimeParamId, LocalFieldId, TypeOrConstParamId, VariantId,
+ db::DefDatabase, expr::ExprId, BlockId, ConstId, ConstParamId, DefWithBodyId, EnumVariantId,
+ FunctionId, GenericDefId, ImplId, LifetimeParamId, LocalFieldId, Lookup, TypeOrConstParamId,
+ VariantId,
};
use la_arena::ArenaMap;
@@ -47,6 +48,10 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
#[salsa::cycle(crate::consteval::const_eval_recover)]
fn const_eval(&self, def: ConstId) -> Result<ComputedExpr, ConstEvalError>;
+ #[salsa::invoke(crate::consteval::const_eval_query_variant)]
+ #[salsa::cycle(crate::consteval::const_eval_recover_variant)]
+ fn const_eval_variant(&self, def: EnumVariantId) -> Result<ComputedExpr, ConstEvalError>;
+
#[salsa::invoke(crate::lower::impl_trait_query)]
fn impl_trait(&self, def: ImplId) -> Option<Binders<TraitRef>>;
@@ -188,6 +193,13 @@ fn infer_wait(db: &dyn HirDatabase, def: DefWithBodyId) -> Arc<InferenceResult>
DefWithBodyId::ConstId(it) => {
db.const_data(it).name.clone().unwrap_or_else(Name::missing).to_string()
}
+ DefWithBodyId::VariantId(it) => {
+ let up_db: &dyn DefDatabase = db.upcast();
+ let loc = it.parent.lookup(up_db);
+ let item_tree = loc.id.item_tree(up_db);
+ let konst = &item_tree[loc.id.value];
+ konst.name.to_string()
+ }
});
db.infer_query(def)
}
diff --git a/crates/hir-ty/src/diagnostics/unsafe_check.rs b/crates/hir-ty/src/diagnostics/unsafe_check.rs
index 161b19a739..431ab949b4 100644
--- a/crates/hir-ty/src/diagnostics/unsafe_check.rs
+++ b/crates/hir-ty/src/diagnostics/unsafe_check.rs
@@ -18,7 +18,9 @@ pub fn missing_unsafe(db: &dyn HirDatabase, def: DefWithBodyId) -> Vec<ExprId> {
let is_unsafe = match def {
DefWithBodyId::FunctionId(it) => db.function_data(it).has_unsafe_kw(),
- DefWithBodyId::StaticId(_) | DefWithBodyId::ConstId(_) => false,
+ DefWithBodyId::StaticId(_) | DefWithBodyId::ConstId(_) | DefWithBodyId::VariantId(_) => {
+ false
+ }
};
if is_unsafe {
return res;
diff --git a/crates/hir-ty/src/infer.rs b/crates/hir-ty/src/infer.rs
index e37763e8ea..63d0f1b01c 100644
--- a/crates/hir-ty/src/infer.rs
+++ b/crates/hir-ty/src/infer.rs
@@ -67,6 +67,14 @@ pub(crate) fn infer_query(db: &dyn HirDatabase, def: DefWithBodyId) -> Arc<Infer
DefWithBodyId::ConstId(c) => ctx.collect_const(&db.const_data(c)),
DefWithBodyId::FunctionId(f) => ctx.collect_fn(f),
DefWithBodyId::StaticId(s) => ctx.collect_static(&db.static_data(s)),
+ DefWithBodyId::VariantId(v) => {
+ //let def = AttrDefId::EnumVariantId(v);
+ //let attrs = db.attrs(def);
+ //let repr = attrs.by_key("repr").attrs().next().unwrap();
+ //let ident = repr.single_ident_value().unwrap().text;
+ // TODO(ole): Get the real type
+ ctx.return_ty = TyBuilder::def_ty(db, v.parent.into()).fill_with_unknown().build()
+ }
}
ctx.infer_body();
diff --git a/crates/hir-ty/src/tests.rs b/crates/hir-ty/src/tests.rs
index d2f13e4351..be5ece9c5c 100644
--- a/crates/hir-ty/src/tests.rs
+++ b/crates/hir-ty/src/tests.rs
@@ -16,7 +16,7 @@ use base_db::{fixture::WithFixture, FileRange, SourceDatabaseExt};
use expect_test::Expect;
use hir_def::{
body::{Body, BodySourceMap, SyntheticSyntax},
- db::DefDatabase,
+ db::{DefDatabase, InternDatabase},
expr::{ExprId, PatId},
item_scope::ItemScope,
nameres::DefMap,
@@ -135,6 +135,10 @@ fn check_impl(ra_fixture: &str, allow_none: bool, only_types: bool, display_sour
let loc = it.lookup(&db);
loc.source(&db).value.syntax().text_range().start()
}
+ DefWithBodyId::VariantId(it) => {
+ let loc = db.lookup_intern_enum(it.parent);
+ loc.source(&db).value.syntax().text_range().start()
+ }
});
let mut unexpected_type_mismatches = String::new();
for def in defs {
@@ -388,6 +392,10 @@ fn infer_with_mismatches(content: &str, include_mismatches: bool) -> String {
let loc = it.lookup(&db);
loc.source(&db).value.syntax().text_range().start()
}
+ DefWithBodyId::VariantId(it) => {
+ let loc = db.lookup_intern_enum(it.parent);
+ loc.source(&db).value.syntax().text_range().start()
+ }
});
for def in defs {
let (_body, source_map) = db.body_with_source_map(def);
diff --git a/crates/hir/src/from_id.rs b/crates/hir/src/from_id.rs
index 9c7558d191..f825a72c0f 100644
--- a/crates/hir/src/from_id.rs
+++ b/crates/hir/src/from_id.rs
@@ -140,6 +140,7 @@ impl From<DefWithBody> for DefWithBodyId {
DefWithBody::Function(it) => DefWithBodyId::FunctionId(it.id),
DefWithBody::Static(it) => DefWithBodyId::StaticId(it.id),
DefWithBody::Const(it) => DefWithBodyId::ConstId(it.id),
+ DefWithBody::Variant(it) => DefWithBodyId::VariantId(it.into()),
}
}
}
@@ -150,6 +151,7 @@ impl From<DefWithBodyId> for DefWithBody {
DefWithBodyId::FunctionId(it) => DefWithBody::Function(it.into()),
DefWithBodyId::StaticId(it) => DefWithBody::Static(it.into()),
DefWithBodyId::ConstId(it) => DefWithBody::Const(it.into()),
+ DefWithBodyId::VariantId(it) => DefWithBody::Variant(it.into()),
}
}
}
@@ -172,9 +174,7 @@ impl From<GenericDef> for GenericDefId {
GenericDef::Trait(it) => GenericDefId::TraitId(it.id),
GenericDef::TypeAlias(it) => GenericDefId::TypeAliasId(it.id),
GenericDef::Impl(it) => GenericDefId::ImplId(it.id),
- GenericDef::Variant(it) => {
- GenericDefId::EnumVariantId(EnumVariantId { parent: it.parent.id, local_id: it.id })
- }
+ GenericDef::Variant(it) => GenericDefId::EnumVariantId(it.into()),
GenericDef::Const(it) => GenericDefId::ConstId(it.id),
}
}
@@ -188,9 +188,7 @@ impl From<GenericDefId> for GenericDef {
GenericDefId::TraitId(it) => GenericDef::Trait(it.into()),
GenericDefId::TypeAliasId(it) => GenericDef::TypeAlias(it.into()),
GenericDefId::ImplId(it) => GenericDef::Impl(it.into()),
- GenericDefId::EnumVariantId(it) => {
- GenericDef::Variant(Variant { parent: it.parent.into(), id: it.local_id })
- }
+ GenericDefId::EnumVariantId(it) => GenericDef::Variant(it.into()),
GenericDefId::ConstId(it) => GenericDef::Const(it.into()),
}
}
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index 7dd891c86e..258224a758 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -73,7 +73,7 @@ use once_cell::unsync::Lazy;
use rustc_hash::FxHashSet;
use stdx::{impl_from, never};
use syntax::{
- ast::{self, HasAttrs as _, HasDocComments, HasName},
+ ast::{self, Expr, HasAttrs as _, HasDocComments, HasName},
AstNode, AstPtr, SmolStr, SyntaxNodePtr, TextRange, T,
};
@@ -962,11 +962,16 @@ impl HasVisibility for Enum {
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Variant {
- pub(crate) parent: Enum,
- pub(crate) id: LocalEnumVariantId,
+ pub parent: Enum,
+ pub id: LocalEnumVariantId,
}
impl Variant {
+ pub fn value(self, db: &dyn HirDatabase) -> Option<Expr> {
+ // TODO(ole): Handle missing exprs (+1 to the prev)
+ self.source(db)?.value.expr()
+ }
+
pub fn module(self, db: &dyn HirDatabase) -> Module {
self.parent.module(db)
}
@@ -1129,6 +1134,7 @@ pub enum DefWithBody {
Function(Function),
Static(Static),
Const(Const),
+ Variant(Variant),
}
impl_from!(Function, Const, Static for DefWithBody);
@@ -1138,6 +1144,7 @@ impl DefWithBody {
DefWithBody::Const(c) => c.module(db),
DefWithBody::Function(f) => f.module(db),
DefWithBody::Static(s) => s.module(db),
+ DefWithBody::Variant(v) => v.module(db),
}
}
@@ -1146,6 +1153,7 @@ impl DefWithBody {
DefWithBody::Function(f) => Some(f.name(db)),
DefWithBody::Static(s) => Some(s.name(db)),
DefWithBody::Const(c) => c.name(db),
+ DefWithBody::Variant(v) => Some(v.name(db)),
}
}
@@ -1155,6 +1163,7 @@ impl DefWithBody {
DefWithBody::Function(it) => it.ret_type(db),
DefWithBody::Static(it) => it.ty(db),
DefWithBody::Const(it) => it.ty(db),
+ DefWithBody::Variant(it) => it.parent.ty(db),
}
}
@@ -1379,6 +1388,7 @@ impl DefWithBody {
DefWithBody::Function(it) => it.into(),
DefWithBody::Static(it) => it.into(),
DefWithBody::Const(it) => it.into(),
+ DefWithBody::Variant(it) => it.into(),
};
for diag in hir_ty::diagnostics::incorrect_case(db, krate, def.into()) {
acc.push(diag.into())
diff --git a/crates/hir/src/symbols.rs b/crates/hir/src/symbols.rs
index 616a406c72..8432f0e7e0 100644
--- a/crates/hir/src/symbols.rs
+++ b/crates/hir/src/symbols.rs
@@ -1,6 +1,7 @@
//! File symbol extraction.
use base_db::FileRange;
+use hir_def::db::DefDatabase;
use hir_def::{
item_tree::ItemTreeNode, src::HasSource, AdtId, AssocItemId, AssocItemLoc, DefWithBodyId,
HasModule, ImplId, ItemContainerId, Lookup, MacroId, ModuleDefId, ModuleId, TraitId,
@@ -244,6 +245,10 @@ impl<'a> SymbolCollector<'a> {
DefWithBodyId::ConstId(id) => Some(
id.lookup(self.db.upcast()).source(self.db.upcast()).value.name()?.text().into(),
),
+ DefWithBodyId::VariantId(id) => Some({
+ let up_db: &dyn DefDatabase = self.db.upcast();
+ up_db.lookup_intern_enum(id.parent).source(up_db).value.name()?.text().into()
+ }),
}
}
diff --git a/crates/ide-db/src/search.rs b/crates/ide-db/src/search.rs
index 7deffe8e0f..20ab474e80 100644
--- a/crates/ide-db/src/search.rs
+++ b/crates/ide-db/src/search.rs
@@ -236,6 +236,7 @@ impl Definition {
DefWithBody::Function(f) => f.source(db).map(|src| src.syntax().cloned()),
DefWithBody::Const(c) => c.source(db).map(|src| src.syntax().cloned()),
DefWithBody::Static(s) => s.source(db).map(|src| src.syntax().cloned()),
+ DefWithBody::Variant(v) => v.source(db).map(|src| src.syntax().cloned()),
};
return match def {
Some(def) => SearchScope::file_range(def.as_ref().original_file_range(db)),
diff --git a/crates/ide/src/hover/render.rs b/crates/ide/src/hover/render.rs
index c5c50d88dd..cd63131e7a 100644
--- a/crates/ide/src/hover/render.rs
+++ b/crates/ide/src/hover/render.rs
@@ -2,7 +2,9 @@
use std::fmt::Display;
use either::Either;
-use hir::{AsAssocItem, AttributeTemplate, HasAttrs, HasSource, HirDisplay, Semantics, TypeInfo};
+use hir::{
+ db::HirDatabase, AsAssocItem, AttributeTemplate, HasAttrs, HasSource, HirDisplay, Semantics, TypeInfo,
+};
use ide_db::{
base_db::SourceDatabase,
defs::Definition,
@@ -346,7 +348,14 @@ pub(super) fn definition(
Definition::Module(it) => label_and_docs(db, it),
Definition::Function(it) => label_and_docs(db, it),
Definition::Adt(it) => label_and_docs(db, it),
- Definition::Variant(it) => label_and_docs(db, it),
+ Definition::Variant(it) => label_value_and_docs(db, it, |&it| {
+ let hir_db: &dyn HirDatabase = db;
+ let body = hir_db.const_eval_variant(it.into());
+ match body {
+ Ok(x) => Some(format!("{}", x)),
+ Err(_) => it.value(db).map(|s| format!("{}", s)),
+ }
+ }),
Definition::Const(it) => label_value_and_docs(db, it, |it| {
let body = it.eval(db);
match body {
diff --git a/crates/ide/src/hover/tests.rs b/crates/ide/src/hover/tests.rs
index 4b8b47783d..f24dec25b6 100644
--- a/crates/ide/src/hover/tests.rs
+++ b/crates/ide/src/hover/tests.rs
@@ -3528,6 +3528,86 @@ impl<const LEN: usize> Foo<LEN$0> {}
}
#[test]
+fn hover_const_eval_variant() {
+ // show hex for <10
+ check(
+ r#"
+#[repr(u8)]
+enum E {
+ /// This is a doc
+ A$0 = 1 << 3,
+}
+"#,
+ expect![[r#"
+ *A*
+
+ ```rust
+ test::E
+ ```
+
+ ```rust
+ A = 8
+ ```
+
+ ---
+
+ This is a doc
+ "#]],
+ );
+ // show hex for >10
+ check(
+ r#"
+#[repr(u8)]
+enum E {
+ /// This is a doc
+ A$0 = (1 << 3) + (1 << 2),
+}
+"#,
+ expect![[r#"
+ *A*
+
+ ```rust
+ test::E
+ ```
+
+ ```rust
+ A = 12 (0xC)
+ ```
+
+ ---
+
+ This is a doc
+ "#]],
+ );
+ // enums in const eval
+ check(
+ r#"
+#[repr(u8)]
+enum E {
+ A = 1,
+ /// This is a doc
+ B$0 = E::A + 1,
+}
+"#,
+ expect![[r#"
+ *B*
+
+ ```rust
+ test::E
+ ```
+
+ ```rust
+ B = 2
+ ```
+
+ ---
+
+ This is a doc
+ "#]],
+ );
+}
+
+#[test]
fn hover_const_eval() {
// show hex for <10
check(
@@ -3823,6 +3903,35 @@ fn foo() {
This is a doc
"#]],
);
+ check(
+ r#"
+enum E {
+ /// This is a doc
+ A = 3,
+}
+fn foo(e: E) {
+ match e {
+ E::A$0 => (),
+ _ => ()
+ }
+}
+"#,
+ expect![[r#"
+ *A*
+
+ ```rust
+ test::E
+ ```
+
+ ```rust
+ A = 3
+ ```
+
+ ---
+
+ This is a doc
+ "#]],
+ );
}
#[test]