about summary refs log tree commit diff
diff options
context:
space:
mode:
authorhkalbasi <hamidrezakalbasi@protonmail.com>2023-03-21 02:20:30 +0330
committerhkalbasi <hamidrezakalbasi@protonmail.com>2023-03-21 02:20:30 +0330
commit8a3ad7c3d592adac72b1fce6bc208cdf7a40c8ad (patch)
tree8f0df3b012a5cd1612f6adf4d2344b63e4e5266b
parent3303a6eff5f759d5bc6f9a2e891bddab0d1f21e7 (diff)
downloadrust-8a3ad7c3d592adac72b1fce6bc208cdf7a40c8ad.tar.gz
rust-8a3ad7c3d592adac72b1fce6bc208cdf7a40c8ad.zip
Support evaluating inherent associated constants with generics
-rw-r--r--crates/hir-ty/src/consteval.rs10
-rw-r--r--crates/hir-ty/src/consteval/tests.rs8
-rw-r--r--crates/hir-ty/src/db.rs2
-rw-r--r--crates/hir-ty/src/infer/expr.rs15
-rw-r--r--crates/hir-ty/src/mir/eval.rs5
-rw-r--r--crates/hir-ty/src/mir/lower.rs11
-rw-r--r--crates/hir/src/lib.rs4
7 files changed, 22 insertions, 33 deletions
diff --git a/crates/hir-ty/src/consteval.rs b/crates/hir-ty/src/consteval.rs
index fcb3445a542..7e69971fee7 100644
--- a/crates/hir-ty/src/consteval.rs
+++ b/crates/hir-ty/src/consteval.rs
@@ -15,7 +15,7 @@ use stdx::never;
 use crate::{
     db::HirDatabase, infer::InferenceContext, layout::layout_of_ty, lower::ParamLoweringMode,
     to_placeholder_idx, utils::Generics, Const, ConstData, ConstScalar, ConstValue, GenericArg,
-    Interner, MemoryMap, Ty, TyBuilder,
+    Interner, MemoryMap, Substitution, Ty, TyBuilder,
 };
 
 use super::mir::{interpret_mir, lower_to_mir, pad16, MirEvalError, MirLowerError};
@@ -169,6 +169,7 @@ pub(crate) fn const_eval_recover(
     _: &dyn HirDatabase,
     _: &[String],
     _: &ConstId,
+    _: &Substitution,
 ) -> Result<Const, ConstEvalError> {
     Err(ConstEvalError::MirLowerError(MirLowerError::Loop))
 }
@@ -184,10 +185,11 @@ pub(crate) fn const_eval_discriminant_recover(
 pub(crate) fn const_eval_query(
     db: &dyn HirDatabase,
     const_id: ConstId,
+    subst: Substitution,
 ) -> Result<Const, ConstEvalError> {
     let def = const_id.into();
     let body = db.mir_body(def)?;
-    let c = interpret_mir(db, &body, false)?;
+    let c = interpret_mir(db, &body, subst, false)?;
     Ok(c)
 }
 
@@ -210,7 +212,7 @@ pub(crate) fn const_eval_discriminant_variant(
         return Ok(value);
     }
     let mir_body = db.mir_body(def)?;
-    let c = interpret_mir(db, &mir_body, false)?;
+    let c = interpret_mir(db, &mir_body, Substitution::empty(Interner), false)?;
     let c = try_const_usize(&c).unwrap() as i128;
     Ok(c)
 }
@@ -234,7 +236,7 @@ pub(crate) fn eval_to_const(
     }
     let infer = ctx.clone().resolve_all();
     if let Ok(mir_body) = lower_to_mir(ctx.db, ctx.owner, &ctx.body, &infer, expr) {
-        if let Ok(result) = interpret_mir(db, &mir_body, true) {
+        if let Ok(result) = interpret_mir(db, &mir_body, Substitution::empty(Interner), true) {
             return result;
         }
     }
diff --git a/crates/hir-ty/src/consteval/tests.rs b/crates/hir-ty/src/consteval/tests.rs
index 47ef26fc586..a0efc7541e3 100644
--- a/crates/hir-ty/src/consteval/tests.rs
+++ b/crates/hir-ty/src/consteval/tests.rs
@@ -1,4 +1,5 @@
 use base_db::fixture::WithFixture;
+use chalk_ir::Substitution;
 use hir_def::db::DefDatabase;
 
 use crate::{
@@ -64,7 +65,7 @@ fn eval_goal(ra_fixture: &str) -> Result<Const, ConstEvalError> {
             _ => None,
         })
         .unwrap();
-    db.const_eval(const_id)
+    db.const_eval(const_id, Substitution::empty(Interner))
 }
 
 #[test]
@@ -1519,8 +1520,7 @@ fn const_generic_subst_fn() {
 
 #[test]
 fn const_generic_subst_assoc_const_impl() {
-    // FIXME: this should evaluate to 5
-    check_fail(
+    check_number(
         r#"
     struct Adder<const N: usize, const M: usize>;
     impl<const N: usize, const M: usize> Adder<N, M> {
@@ -1528,7 +1528,7 @@ fn const_generic_subst_assoc_const_impl() {
     }
     const GOAL: usize = Adder::<2, 3>::VAL;
     "#,
-        ConstEvalError::MirEvalError(MirEvalError::TypeError("missing generic arg")),
+        5,
     );
 }
 
diff --git a/crates/hir-ty/src/db.rs b/crates/hir-ty/src/db.rs
index 8f1af4c2f8e..000944e0b5b 100644
--- a/crates/hir-ty/src/db.rs
+++ b/crates/hir-ty/src/db.rs
@@ -57,7 +57,7 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
 
     #[salsa::invoke(crate::consteval::const_eval_query)]
     #[salsa::cycle(crate::consteval::const_eval_recover)]
-    fn const_eval(&self, def: ConstId) -> Result<Const, ConstEvalError>;
+    fn const_eval(&self, def: ConstId, subst: Substitution) -> Result<Const, ConstEvalError>;
 
     #[salsa::invoke(crate::consteval::const_eval_discriminant_variant)]
     #[salsa::cycle(crate::consteval::const_eval_discriminant_recover)]
diff --git a/crates/hir-ty/src/infer/expr.rs b/crates/hir-ty/src/infer/expr.rs
index d14b3f7140e..d52188bb284 100644
--- a/crates/hir-ty/src/infer/expr.rs
+++ b/crates/hir-ty/src/infer/expr.rs
@@ -612,21 +612,6 @@ impl<'a> InferenceContext<'a> {
                 let inner_ty = self.infer_expr_inner(*expr, &Expectation::none());
                 self.resolve_associated_type(inner_ty, self.resolve_future_future_output())
             }
-            // Expr::Try { expr } => {
-            //     let inner_ty = self.infer_expr_inner(*expr, &Expectation::none());
-            //     if let Some(trait_) = self.resolve_lang_trait(LangItem::Try) {
-            //         if let Some(func) = self.db.trait_data(trait_).method_by_name(&name!(branch)) {
-            //             let subst = TyBuilder::subst_for_def(self.db, trait_, None)
-            //                 .push(inner_ty.clone())
-            //                 .build();
-            //             self.write_method_resolution(tgt_expr, func, subst.clone());
-            //         }
-            //         let try_output = self.resolve_output_on(trait_);
-            //         self.resolve_associated_type(inner_ty, try_output)
-            //     } else {
-            //         self.err_ty()
-            //     }
-            // }
             Expr::Cast { expr, type_ref } => {
                 let cast_ty = self.make_ty(type_ref);
                 // FIXME: propagate the "castable to" expectation
diff --git a/crates/hir-ty/src/mir/eval.rs b/crates/hir-ty/src/mir/eval.rs
index 26bf877cf0b..7b83645faef 100644
--- a/crates/hir-ty/src/mir/eval.rs
+++ b/crates/hir-ty/src/mir/eval.rs
@@ -282,6 +282,7 @@ struct Locals<'a> {
 pub fn interpret_mir(
     db: &dyn HirDatabase,
     body: &MirBody,
+    subst: Substitution,
     // FIXME: This is workaround. Ideally, const generics should have a separate body (issue #7434), but now
     // they share their body with their parent, so in MIR lowering we have locals of the parent body, which
     // might have placeholders. With this argument, we (wrongly) assume that every placeholder type has
@@ -291,11 +292,11 @@ pub fn interpret_mir(
 ) -> Result<Const> {
     let ty = body.locals[return_slot()].ty.clone();
     let mut evaluator = Evaluator::new(db, body, assert_placeholder_ty_is_unused);
-    let bytes = evaluator.interpret_mir_with_no_arg(&body)?;
+    let bytes = evaluator.interpret_mir(&body, None.into_iter(), subst.clone())?;
     let memory_map = evaluator.create_memory_map(
         &bytes,
         &ty,
-        &Locals { ptr: &ArenaMap::new(), body: &body, subst: &Substitution::empty(Interner) },
+        &Locals { ptr: &ArenaMap::new(), body: &body, subst: &subst },
     )?;
     return Ok(intern_const_scalar(ConstScalar::Bytes(bytes, memory_map), ty));
 }
diff --git a/crates/hir-ty/src/mir/lower.rs b/crates/hir-ty/src/mir/lower.rs
index 65e3348b218..1821796be33 100644
--- a/crates/hir-ty/src/mir/lower.rs
+++ b/crates/hir-ty/src/mir/lower.rs
@@ -231,13 +231,13 @@ impl MirLowerCtx<'_> {
                 let pr = match pr {
                     ResolveValueResult::ValueNs(v) => v,
                     ResolveValueResult::Partial(..) => {
-                        if let Some(assoc) = self
+                        if let Some((assoc, subst)) = self
                             .infer
                             .assoc_resolutions_for_expr(expr_id)
                         {
-                            match assoc.0 {
+                            match assoc {
                                 hir_def::AssocItemId::ConstId(c) => {
-                                    self.lower_const(c, current, place, expr_id.into())?;
+                                    self.lower_const(c, current, place, subst, expr_id.into())?;
                                     return Ok(Some(current))
                                 },
                                 hir_def::AssocItemId::FunctionId(_) => {
@@ -274,7 +274,7 @@ impl MirLowerCtx<'_> {
                         Ok(Some(current))
                     }
                     ValueNs::ConstId(const_id) => {
-                        self.lower_const(const_id, current, place, expr_id.into())?;
+                        self.lower_const(const_id, current, place, Substitution::empty(Interner), expr_id.into())?;
                         Ok(Some(current))
                     }
                     ValueNs::EnumVariantId(variant_id) => {
@@ -951,9 +951,10 @@ impl MirLowerCtx<'_> {
         const_id: hir_def::ConstId,
         prev_block: BasicBlockId,
         place: Place,
+        subst: Substitution,
         span: MirSpan,
     ) -> Result<()> {
-        let c = self.db.const_eval(const_id)?;
+        let c = self.db.const_eval(const_id, subst)?;
         self.write_const_to_place(c, prev_block, place, span)
     }
 
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index 35424feec8b..dbf618afa6f 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -1801,7 +1801,7 @@ impl Function {
         let body = db
             .mir_body(self.id.into())
             .map_err(|e| MirEvalError::MirLowerError(self.id.into(), e))?;
-        interpret_mir(db, &body, false)?;
+        interpret_mir(db, &body, Substitution::empty(Interner), false)?;
         Ok(())
     }
 }
@@ -1947,7 +1947,7 @@ impl Const {
     }
 
     pub fn render_eval(self, db: &dyn HirDatabase) -> Result<String, ConstEvalError> {
-        let c = db.const_eval(self.id)?;
+        let c = db.const_eval(self.id, Substitution::empty(Interner))?;
         let r = format!("{}", HexifiedConst(c).display(db));
         // We want to see things like `<utf8-error>` and `<layout-error>` as they are probably bug in our
         // implementation, but there is no need to show things like `<enum-not-supported>` or `<ref-not-supported>` to