Skip to content

Commit 997fc46

Browse files
committed
Implemented basic enum const eval
1 parent f64c956 commit 997fc46

File tree

14 files changed

+227
-17
lines changed

14 files changed

+227
-17
lines changed

crates/hir-def/src/body.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ use crate::{
2727
macro_id_to_def_id,
2828
nameres::DefMap,
2929
path::{ModPath, Path},
30-
src::HasSource,
30+
src::{HasChildSource, HasSource},
3131
AsMacroCall, BlockId, DefWithBodyId, HasModule, LocalModuleId, Lookup, MacroId, ModuleId,
3232
UnresolvedMacro,
3333
};
@@ -324,6 +324,13 @@ impl Body {
324324
let src = s.source(db);
325325
(src.file_id, s.module(db), src.value.body())
326326
}
327+
DefWithBodyId::VariantId(v) => {
328+
let e = v.parent.lookup(db);
329+
let src = v.parent.child_source(db);
330+
let variant = &src.value[v.local_id];
331+
// TODO(ole): Handle missing exprs (+1 to the prev)
332+
(src.file_id, e.container, variant.expr())
333+
}
327334
};
328335
let expander = Expander::new(db, file_id, module);
329336
let (mut body, source_map) = Body::new(db, expander, params, body);

crates/hir-def/src/lib.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -474,16 +474,25 @@ pub enum DefWithBodyId {
474474
FunctionId(FunctionId),
475475
StaticId(StaticId),
476476
ConstId(ConstId),
477+
VariantId(EnumVariantId),
477478
}
478479

479480
impl_from!(FunctionId, ConstId, StaticId for DefWithBodyId);
480481

482+
// FIXME: Rename EnumVariantId to VariantId so that the macro above can be used
483+
impl From<EnumVariantId> for DefWithBodyId {
484+
fn from(id: EnumVariantId) -> Self {
485+
DefWithBodyId::VariantId(id)
486+
}
487+
}
488+
481489
impl DefWithBodyId {
482490
pub fn as_generic_def_id(self) -> Option<GenericDefId> {
483491
match self {
484492
DefWithBodyId::FunctionId(f) => Some(f.into()),
485493
DefWithBodyId::StaticId(_) => None,
486494
DefWithBodyId::ConstId(c) => Some(c.into()),
495+
DefWithBodyId::VariantId(c) => Some(c.into()),
487496
}
488497
}
489498
}
@@ -681,6 +690,7 @@ impl HasModule for DefWithBodyId {
681690
DefWithBodyId::FunctionId(it) => it.lookup(db).module(db),
682691
DefWithBodyId::StaticId(it) => it.lookup(db).module(db),
683692
DefWithBodyId::ConstId(it) => it.lookup(db).module(db),
693+
DefWithBodyId::VariantId(it) => it.parent.lookup(db).container,
684694
}
685695
}
686696
}
@@ -691,6 +701,7 @@ impl DefWithBodyId {
691701
DefWithBodyId::FunctionId(it) => it.lookup(db).id.value.into(),
692702
DefWithBodyId::StaticId(it) => it.lookup(db).id.value.into(),
693703
DefWithBodyId::ConstId(it) => it.lookup(db).id.value.into(),
704+
DefWithBodyId::VariantId(it) => it.parent.lookup(db).id.value.into(),
694705
}
695706
}
696707
}

crates/hir-def/src/resolver.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -839,6 +839,7 @@ impl HasResolver for DefWithBodyId {
839839
DefWithBodyId::ConstId(c) => c.resolver(db),
840840
DefWithBodyId::FunctionId(f) => f.resolver(db),
841841
DefWithBodyId::StaticId(s) => s.resolver(db),
842+
DefWithBodyId::VariantId(v) => v.parent.resolver(db),
842843
}
843844
}
844845
}

crates/hir-ty/src/consteval.rs

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use hir_def::{
1111
path::ModPath,
1212
resolver::{resolver_for_expr, ResolveValueResult, Resolver, ValueNs},
1313
type_ref::ConstScalar,
14-
ConstId, DefWithBodyId,
14+
ConstId, DefWithBodyId, EnumVariantId,
1515
};
1616
use la_arena::{Arena, Idx};
1717
use stdx::never;
@@ -339,6 +339,7 @@ pub fn eval_const(
339339
ValueNs::GenericParam(_) => {
340340
Err(ConstEvalError::NotSupported("const generic without substitution"))
341341
}
342+
ValueNs::EnumVariantId(id) => ctx.db.const_eval_variant(id), // TODO(ole): Assuming this is all that has to happen?
342343
_ => Err(ConstEvalError::NotSupported("path that are not const or local")),
343344
}
344345
}
@@ -412,6 +413,14 @@ pub(crate) fn const_eval_recover(
412413
Err(ConstEvalError::Loop)
413414
}
414415

416+
pub(crate) fn const_eval_recover_variant(
417+
_: &dyn HirDatabase,
418+
_: &[String],
419+
_: &EnumVariantId,
420+
) -> Result<ComputedExpr, ConstEvalError> {
421+
Err(ConstEvalError::Loop)
422+
}
423+
415424
pub(crate) fn const_eval_query(
416425
db: &dyn HirDatabase,
417426
const_id: ConstId,
@@ -433,6 +442,26 @@ pub(crate) fn const_eval_query(
433442
result
434443
}
435444

445+
pub(crate) fn const_eval_query_variant(
446+
db: &dyn HirDatabase,
447+
variant_id: EnumVariantId,
448+
) -> Result<ComputedExpr, ConstEvalError> {
449+
let def = variant_id.into();
450+
let body = db.body(def);
451+
let infer = &db.infer(def);
452+
eval_const(
453+
body.body_expr,
454+
&mut ConstEvalCtx {
455+
db,
456+
owner: def,
457+
exprs: &body.exprs,
458+
pats: &body.pats,
459+
local_data: HashMap::default(),
460+
infer,
461+
},
462+
)
463+
}
464+
436465
pub(crate) fn eval_to_const<'a>(
437466
expr: Idx<Expr>,
438467
mode: ParamLoweringMode,

crates/hir-ty/src/db.rs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,9 @@ use std::sync::Arc;
66
use arrayvec::ArrayVec;
77
use base_db::{impl_intern_key, salsa, CrateId, Upcast};
88
use hir_def::{
9-
db::DefDatabase, expr::ExprId, BlockId, ConstId, ConstParamId, DefWithBodyId, FunctionId,
10-
GenericDefId, ImplId, LifetimeParamId, LocalFieldId, TypeOrConstParamId, VariantId,
9+
db::DefDatabase, expr::ExprId, BlockId, ConstId, ConstParamId, DefWithBodyId, EnumVariantId,
10+
FunctionId, GenericDefId, ImplId, LifetimeParamId, LocalFieldId, Lookup, TypeOrConstParamId,
11+
VariantId,
1112
};
1213
use la_arena::ArenaMap;
1314

@@ -47,6 +48,10 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
4748
#[salsa::cycle(crate::consteval::const_eval_recover)]
4849
fn const_eval(&self, def: ConstId) -> Result<ComputedExpr, ConstEvalError>;
4950

51+
#[salsa::invoke(crate::consteval::const_eval_query_variant)]
52+
#[salsa::cycle(crate::consteval::const_eval_recover_variant)]
53+
fn const_eval_variant(&self, def: EnumVariantId) -> Result<ComputedExpr, ConstEvalError>;
54+
5055
#[salsa::invoke(crate::lower::impl_trait_query)]
5156
fn impl_trait(&self, def: ImplId) -> Option<Binders<TraitRef>>;
5257

@@ -188,6 +193,13 @@ fn infer_wait(db: &dyn HirDatabase, def: DefWithBodyId) -> Arc<InferenceResult>
188193
DefWithBodyId::ConstId(it) => {
189194
db.const_data(it).name.clone().unwrap_or_else(Name::missing).to_string()
190195
}
196+
DefWithBodyId::VariantId(it) => {
197+
let up_db: &dyn DefDatabase = db.upcast();
198+
let loc = it.parent.lookup(up_db);
199+
let item_tree = loc.id.item_tree(up_db);
200+
let konst = &item_tree[loc.id.value];
201+
konst.name.to_string()
202+
}
191203
});
192204
db.infer_query(def)
193205
}

crates/hir-ty/src/diagnostics/unsafe_check.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,9 @@ pub fn missing_unsafe(db: &dyn HirDatabase, def: DefWithBodyId) -> Vec<ExprId> {
1818

1919
let is_unsafe = match def {
2020
DefWithBodyId::FunctionId(it) => db.function_data(it).has_unsafe_kw(),
21-
DefWithBodyId::StaticId(_) | DefWithBodyId::ConstId(_) => false,
21+
DefWithBodyId::StaticId(_) | DefWithBodyId::ConstId(_) | DefWithBodyId::VariantId(_) => {
22+
false
23+
}
2224
};
2325
if is_unsafe {
2426
return res;

crates/hir-ty/src/infer.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,14 @@ pub(crate) fn infer_query(db: &dyn HirDatabase, def: DefWithBodyId) -> Arc<Infer
6767
DefWithBodyId::ConstId(c) => ctx.collect_const(&db.const_data(c)),
6868
DefWithBodyId::FunctionId(f) => ctx.collect_fn(f),
6969
DefWithBodyId::StaticId(s) => ctx.collect_static(&db.static_data(s)),
70+
DefWithBodyId::VariantId(v) => {
71+
//let def = AttrDefId::EnumVariantId(v);
72+
//let attrs = db.attrs(def);
73+
//let repr = attrs.by_key("repr").attrs().next().unwrap();
74+
//let ident = repr.single_ident_value().unwrap().text;
75+
// TODO(ole): Get the real type
76+
ctx.return_ty = TyBuilder::def_ty(db, v.parent.into()).fill_with_unknown().build()
77+
}
7078
}
7179

7280
ctx.infer_body();

crates/hir-ty/src/tests.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use base_db::{fixture::WithFixture, FileRange, SourceDatabaseExt};
1616
use expect_test::Expect;
1717
use hir_def::{
1818
body::{Body, BodySourceMap, SyntheticSyntax},
19-
db::DefDatabase,
19+
db::{DefDatabase, InternDatabase},
2020
expr::{ExprId, PatId},
2121
item_scope::ItemScope,
2222
nameres::DefMap,
@@ -135,6 +135,10 @@ fn check_impl(ra_fixture: &str, allow_none: bool, only_types: bool, display_sour
135135
let loc = it.lookup(&db);
136136
loc.source(&db).value.syntax().text_range().start()
137137
}
138+
DefWithBodyId::VariantId(it) => {
139+
let loc = db.lookup_intern_enum(it.parent);
140+
loc.source(&db).value.syntax().text_range().start()
141+
}
138142
});
139143
let mut unexpected_type_mismatches = String::new();
140144
for def in defs {
@@ -388,6 +392,10 @@ fn infer_with_mismatches(content: &str, include_mismatches: bool) -> String {
388392
let loc = it.lookup(&db);
389393
loc.source(&db).value.syntax().text_range().start()
390394
}
395+
DefWithBodyId::VariantId(it) => {
396+
let loc = db.lookup_intern_enum(it.parent);
397+
loc.source(&db).value.syntax().text_range().start()
398+
}
391399
});
392400
for def in defs {
393401
let (_body, source_map) = db.body_with_source_map(def);

crates/hir/src/from_id.rs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@ impl From<DefWithBody> for DefWithBodyId {
140140
DefWithBody::Function(it) => DefWithBodyId::FunctionId(it.id),
141141
DefWithBody::Static(it) => DefWithBodyId::StaticId(it.id),
142142
DefWithBody::Const(it) => DefWithBodyId::ConstId(it.id),
143+
DefWithBody::Variant(it) => DefWithBodyId::VariantId(it.into()),
143144
}
144145
}
145146
}
@@ -150,6 +151,7 @@ impl From<DefWithBodyId> for DefWithBody {
150151
DefWithBodyId::FunctionId(it) => DefWithBody::Function(it.into()),
151152
DefWithBodyId::StaticId(it) => DefWithBody::Static(it.into()),
152153
DefWithBodyId::ConstId(it) => DefWithBody::Const(it.into()),
154+
DefWithBodyId::VariantId(it) => DefWithBody::Variant(it.into()),
153155
}
154156
}
155157
}
@@ -172,9 +174,7 @@ impl From<GenericDef> for GenericDefId {
172174
GenericDef::Trait(it) => GenericDefId::TraitId(it.id),
173175
GenericDef::TypeAlias(it) => GenericDefId::TypeAliasId(it.id),
174176
GenericDef::Impl(it) => GenericDefId::ImplId(it.id),
175-
GenericDef::Variant(it) => {
176-
GenericDefId::EnumVariantId(EnumVariantId { parent: it.parent.id, local_id: it.id })
177-
}
177+
GenericDef::Variant(it) => GenericDefId::EnumVariantId(it.into()),
178178
GenericDef::Const(it) => GenericDefId::ConstId(it.id),
179179
}
180180
}
@@ -188,9 +188,7 @@ impl From<GenericDefId> for GenericDef {
188188
GenericDefId::TraitId(it) => GenericDef::Trait(it.into()),
189189
GenericDefId::TypeAliasId(it) => GenericDef::TypeAlias(it.into()),
190190
GenericDefId::ImplId(it) => GenericDef::Impl(it.into()),
191-
GenericDefId::EnumVariantId(it) => {
192-
GenericDef::Variant(Variant { parent: it.parent.into(), id: it.local_id })
193-
}
191+
GenericDefId::EnumVariantId(it) => GenericDef::Variant(it.into()),
194192
GenericDefId::ConstId(it) => GenericDef::Const(it.into()),
195193
}
196194
}

crates/hir/src/lib.rs

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ use once_cell::unsync::Lazy;
7373
use rustc_hash::FxHashSet;
7474
use stdx::{impl_from, never};
7575
use syntax::{
76-
ast::{self, HasAttrs as _, HasDocComments, HasName},
76+
ast::{self, Expr, HasAttrs as _, HasDocComments, HasName},
7777
AstNode, AstPtr, SmolStr, SyntaxNodePtr, TextRange, T,
7878
};
7979

@@ -962,11 +962,16 @@ impl HasVisibility for Enum {
962962

963963
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
964964
pub struct Variant {
965-
pub(crate) parent: Enum,
966-
pub(crate) id: LocalEnumVariantId,
965+
pub parent: Enum,
966+
pub id: LocalEnumVariantId,
967967
}
968968

969969
impl Variant {
970+
pub fn value(self, db: &dyn HirDatabase) -> Option<Expr> {
971+
// TODO(ole): Handle missing exprs (+1 to the prev)
972+
self.source(db)?.value.expr()
973+
}
974+
970975
pub fn module(self, db: &dyn HirDatabase) -> Module {
971976
self.parent.module(db)
972977
}
@@ -1129,6 +1134,7 @@ pub enum DefWithBody {
11291134
Function(Function),
11301135
Static(Static),
11311136
Const(Const),
1137+
Variant(Variant),
11321138
}
11331139
impl_from!(Function, Const, Static for DefWithBody);
11341140

@@ -1138,6 +1144,7 @@ impl DefWithBody {
11381144
DefWithBody::Const(c) => c.module(db),
11391145
DefWithBody::Function(f) => f.module(db),
11401146
DefWithBody::Static(s) => s.module(db),
1147+
DefWithBody::Variant(v) => v.module(db),
11411148
}
11421149
}
11431150

@@ -1146,6 +1153,7 @@ impl DefWithBody {
11461153
DefWithBody::Function(f) => Some(f.name(db)),
11471154
DefWithBody::Static(s) => Some(s.name(db)),
11481155
DefWithBody::Const(c) => c.name(db),
1156+
DefWithBody::Variant(v) => Some(v.name(db)),
11491157
}
11501158
}
11511159

@@ -1155,6 +1163,7 @@ impl DefWithBody {
11551163
DefWithBody::Function(it) => it.ret_type(db),
11561164
DefWithBody::Static(it) => it.ty(db),
11571165
DefWithBody::Const(it) => it.ty(db),
1166+
DefWithBody::Variant(it) => it.parent.ty(db),
11581167
}
11591168
}
11601169

@@ -1379,6 +1388,7 @@ impl DefWithBody {
13791388
DefWithBody::Function(it) => it.into(),
13801389
DefWithBody::Static(it) => it.into(),
13811390
DefWithBody::Const(it) => it.into(),
1391+
DefWithBody::Variant(it) => it.into(),
13821392
};
13831393
for diag in hir_ty::diagnostics::incorrect_case(db, krate, def.into()) {
13841394
acc.push(diag.into())

crates/hir/src/symbols.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
//! File symbol extraction.
22
33
use base_db::FileRange;
4+
use hir_def::db::DefDatabase;
45
use hir_def::{
56
item_tree::ItemTreeNode, src::HasSource, AdtId, AssocItemId, AssocItemLoc, DefWithBodyId,
67
HasModule, ImplId, ItemContainerId, Lookup, MacroId, ModuleDefId, ModuleId, TraitId,
@@ -244,6 +245,10 @@ impl<'a> SymbolCollector<'a> {
244245
DefWithBodyId::ConstId(id) => Some(
245246
id.lookup(self.db.upcast()).source(self.db.upcast()).value.name()?.text().into(),
246247
),
248+
DefWithBodyId::VariantId(id) => Some({
249+
let up_db: &dyn DefDatabase = self.db.upcast();
250+
up_db.lookup_intern_enum(id.parent).source(up_db).value.name()?.text().into()
251+
}),
247252
}
248253
}
249254

crates/ide-db/src/search.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,7 @@ impl Definition {
236236
DefWithBody::Function(f) => f.source(db).map(|src| src.syntax().cloned()),
237237
DefWithBody::Const(c) => c.source(db).map(|src| src.syntax().cloned()),
238238
DefWithBody::Static(s) => s.source(db).map(|src| src.syntax().cloned()),
239+
DefWithBody::Variant(v) => v.source(db).map(|src| src.syntax().cloned()),
239240
};
240241
return match def {
241242
Some(def) => SearchScope::file_range(def.as_ref().original_file_range(db)),

crates/ide/src/hover/render.rs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22
use std::fmt::Display;
33

44
use either::Either;
5-
use hir::{AsAssocItem, AttributeTemplate, HasAttrs, HasSource, HirDisplay, Semantics, TypeInfo};
5+
use hir::{
6+
db::HirDatabase, AsAssocItem, AttributeTemplate, HasAttrs, HasSource, HirDisplay, Semantics, TypeInfo,
7+
};
68
use ide_db::{
79
base_db::SourceDatabase,
810
defs::Definition,
@@ -346,7 +348,14 @@ pub(super) fn definition(
346348
Definition::Module(it) => label_and_docs(db, it),
347349
Definition::Function(it) => label_and_docs(db, it),
348350
Definition::Adt(it) => label_and_docs(db, it),
349-
Definition::Variant(it) => label_and_docs(db, it),
351+
Definition::Variant(it) => label_value_and_docs(db, it, |&it| {
352+
let hir_db: &dyn HirDatabase = db;
353+
let body = hir_db.const_eval_variant(it.into());
354+
match body {
355+
Ok(x) => Some(format!("{}", x)),
356+
Err(_) => it.value(db).map(|s| format!("{}", s)),
357+
}
358+
}),
350359
Definition::Const(it) => label_value_and_docs(db, it, |it| {
351360
let body = it.eval(db);
352361
match body {

0 commit comments

Comments
 (0)