Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit 8a3ad7c

Browse files
committed
Support evaluating inherent associated constants with generics
1 parent 3303a6e commit 8a3ad7c

File tree

7 files changed

+22
-33
lines changed

7 files changed

+22
-33
lines changed

crates/hir-ty/src/consteval.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use stdx::never;
1515
use crate::{
1616
db::HirDatabase, infer::InferenceContext, layout::layout_of_ty, lower::ParamLoweringMode,
1717
to_placeholder_idx, utils::Generics, Const, ConstData, ConstScalar, ConstValue, GenericArg,
18-
Interner, MemoryMap, Ty, TyBuilder,
18+
Interner, MemoryMap, Substitution, Ty, TyBuilder,
1919
};
2020

2121
use super::mir::{interpret_mir, lower_to_mir, pad16, MirEvalError, MirLowerError};
@@ -169,6 +169,7 @@ pub(crate) fn const_eval_recover(
169169
_: &dyn HirDatabase,
170170
_: &[String],
171171
_: &ConstId,
172+
_: &Substitution,
172173
) -> Result<Const, ConstEvalError> {
173174
Err(ConstEvalError::MirLowerError(MirLowerError::Loop))
174175
}
@@ -184,10 +185,11 @@ pub(crate) fn const_eval_discriminant_recover(
184185
pub(crate) fn const_eval_query(
185186
db: &dyn HirDatabase,
186187
const_id: ConstId,
188+
subst: Substitution,
187189
) -> Result<Const, ConstEvalError> {
188190
let def = const_id.into();
189191
let body = db.mir_body(def)?;
190-
let c = interpret_mir(db, &body, false)?;
192+
let c = interpret_mir(db, &body, subst, false)?;
191193
Ok(c)
192194
}
193195

@@ -210,7 +212,7 @@ pub(crate) fn const_eval_discriminant_variant(
210212
return Ok(value);
211213
}
212214
let mir_body = db.mir_body(def)?;
213-
let c = interpret_mir(db, &mir_body, false)?;
215+
let c = interpret_mir(db, &mir_body, Substitution::empty(Interner), false)?;
214216
let c = try_const_usize(&c).unwrap() as i128;
215217
Ok(c)
216218
}
@@ -234,7 +236,7 @@ pub(crate) fn eval_to_const(
234236
}
235237
let infer = ctx.clone().resolve_all();
236238
if let Ok(mir_body) = lower_to_mir(ctx.db, ctx.owner, &ctx.body, &infer, expr) {
237-
if let Ok(result) = interpret_mir(db, &mir_body, true) {
239+
if let Ok(result) = interpret_mir(db, &mir_body, Substitution::empty(Interner), true) {
238240
return result;
239241
}
240242
}

crates/hir-ty/src/consteval/tests.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use base_db::fixture::WithFixture;
2+
use chalk_ir::Substitution;
23
use hir_def::db::DefDatabase;
34

45
use crate::{
@@ -64,7 +65,7 @@ fn eval_goal(ra_fixture: &str) -> Result<Const, ConstEvalError> {
6465
_ => None,
6566
})
6667
.unwrap();
67-
db.const_eval(const_id)
68+
db.const_eval(const_id, Substitution::empty(Interner))
6869
}
6970

7071
#[test]
@@ -1519,16 +1520,15 @@ fn const_generic_subst_fn() {
15191520

15201521
#[test]
15211522
fn const_generic_subst_assoc_const_impl() {
1522-
// FIXME: this should evaluate to 5
1523-
check_fail(
1523+
check_number(
15241524
r#"
15251525
struct Adder<const N: usize, const M: usize>;
15261526
impl<const N: usize, const M: usize> Adder<N, M> {
15271527
const VAL: usize = N + M;
15281528
}
15291529
const GOAL: usize = Adder::<2, 3>::VAL;
15301530
"#,
1531-
ConstEvalError::MirEvalError(MirEvalError::TypeError("missing generic arg")),
1531+
5,
15321532
);
15331533
}
15341534

crates/hir-ty/src/db.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
5757

5858
#[salsa::invoke(crate::consteval::const_eval_query)]
5959
#[salsa::cycle(crate::consteval::const_eval_recover)]
60-
fn const_eval(&self, def: ConstId) -> Result<Const, ConstEvalError>;
60+
fn const_eval(&self, def: ConstId, subst: Substitution) -> Result<Const, ConstEvalError>;
6161

6262
#[salsa::invoke(crate::consteval::const_eval_discriminant_variant)]
6363
#[salsa::cycle(crate::consteval::const_eval_discriminant_recover)]

crates/hir-ty/src/infer/expr.rs

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -612,21 +612,6 @@ impl<'a> InferenceContext<'a> {
612612
let inner_ty = self.infer_expr_inner(*expr, &Expectation::none());
613613
self.resolve_associated_type(inner_ty, self.resolve_future_future_output())
614614
}
615-
// Expr::Try { expr } => {
616-
// let inner_ty = self.infer_expr_inner(*expr, &Expectation::none());
617-
// if let Some(trait_) = self.resolve_lang_trait(LangItem::Try) {
618-
// if let Some(func) = self.db.trait_data(trait_).method_by_name(&name!(branch)) {
619-
// let subst = TyBuilder::subst_for_def(self.db, trait_, None)
620-
// .push(inner_ty.clone())
621-
// .build();
622-
// self.write_method_resolution(tgt_expr, func, subst.clone());
623-
// }
624-
// let try_output = self.resolve_output_on(trait_);
625-
// self.resolve_associated_type(inner_ty, try_output)
626-
// } else {
627-
// self.err_ty()
628-
// }
629-
// }
630615
Expr::Cast { expr, type_ref } => {
631616
let cast_ty = self.make_ty(type_ref);
632617
// FIXME: propagate the "castable to" expectation

crates/hir-ty/src/mir/eval.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,7 @@ struct Locals<'a> {
282282
pub fn interpret_mir(
283283
db: &dyn HirDatabase,
284284
body: &MirBody,
285+
subst: Substitution,
285286
// FIXME: This is workaround. Ideally, const generics should have a separate body (issue #7434), but now
286287
// they share their body with their parent, so in MIR lowering we have locals of the parent body, which
287288
// might have placeholders. With this argument, we (wrongly) assume that every placeholder type has
@@ -291,11 +292,11 @@ pub fn interpret_mir(
291292
) -> Result<Const> {
292293
let ty = body.locals[return_slot()].ty.clone();
293294
let mut evaluator = Evaluator::new(db, body, assert_placeholder_ty_is_unused);
294-
let bytes = evaluator.interpret_mir_with_no_arg(&body)?;
295+
let bytes = evaluator.interpret_mir(&body, None.into_iter(), subst.clone())?;
295296
let memory_map = evaluator.create_memory_map(
296297
&bytes,
297298
&ty,
298-
&Locals { ptr: &ArenaMap::new(), body: &body, subst: &Substitution::empty(Interner) },
299+
&Locals { ptr: &ArenaMap::new(), body: &body, subst: &subst },
299300
)?;
300301
return Ok(intern_const_scalar(ConstScalar::Bytes(bytes, memory_map), ty));
301302
}

crates/hir-ty/src/mir/lower.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -231,13 +231,13 @@ impl MirLowerCtx<'_> {
231231
let pr = match pr {
232232
ResolveValueResult::ValueNs(v) => v,
233233
ResolveValueResult::Partial(..) => {
234-
if let Some(assoc) = self
234+
if let Some((assoc, subst)) = self
235235
.infer
236236
.assoc_resolutions_for_expr(expr_id)
237237
{
238-
match assoc.0 {
238+
match assoc {
239239
hir_def::AssocItemId::ConstId(c) => {
240-
self.lower_const(c, current, place, expr_id.into())?;
240+
self.lower_const(c, current, place, subst, expr_id.into())?;
241241
return Ok(Some(current))
242242
},
243243
hir_def::AssocItemId::FunctionId(_) => {
@@ -274,7 +274,7 @@ impl MirLowerCtx<'_> {
274274
Ok(Some(current))
275275
}
276276
ValueNs::ConstId(const_id) => {
277-
self.lower_const(const_id, current, place, expr_id.into())?;
277+
self.lower_const(const_id, current, place, Substitution::empty(Interner), expr_id.into())?;
278278
Ok(Some(current))
279279
}
280280
ValueNs::EnumVariantId(variant_id) => {
@@ -951,9 +951,10 @@ impl MirLowerCtx<'_> {
951951
const_id: hir_def::ConstId,
952952
prev_block: BasicBlockId,
953953
place: Place,
954+
subst: Substitution,
954955
span: MirSpan,
955956
) -> Result<()> {
956-
let c = self.db.const_eval(const_id)?;
957+
let c = self.db.const_eval(const_id, subst)?;
957958
self.write_const_to_place(c, prev_block, place, span)
958959
}
959960

crates/hir/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1801,7 +1801,7 @@ impl Function {
18011801
let body = db
18021802
.mir_body(self.id.into())
18031803
.map_err(|e| MirEvalError::MirLowerError(self.id.into(), e))?;
1804-
interpret_mir(db, &body, false)?;
1804+
interpret_mir(db, &body, Substitution::empty(Interner), false)?;
18051805
Ok(())
18061806
}
18071807
}
@@ -1947,7 +1947,7 @@ impl Const {
19471947
}
19481948

19491949
pub fn render_eval(self, db: &dyn HirDatabase) -> Result<String, ConstEvalError> {
1950-
let c = db.const_eval(self.id)?;
1950+
let c = db.const_eval(self.id, Substitution::empty(Interner))?;
19511951
let r = format!("{}", HexifiedConst(c).display(db));
19521952
// We want to see things like `<utf8-error>` and `<layout-error>` as they are probably bug in our
19531953
// implementation, but there is no need to show things like `<enum-not-supported>` or `<ref-not-supported>` to

0 commit comments

Comments
 (0)