about summary refs log tree commit diff
diff options
context:
space:
mode:
authorhkalbasi <hamidrezakalbasi@protonmail.com>2023-05-27 00:28:11 +0330
committerhkalbasi <hamidrezakalbasi@protonmail.com>2023-05-27 00:28:11 +0330
commitcd4bffdd69c33e3987307ef06db3096385fbeec9 (patch)
tree14806505a75ff019b599a62bfd88f151558de85d
parent08f0c299548dde3fd4421e10d2d27ec33e9b644e (diff)
downloadrust-cd4bffdd69c33e3987307ef06db3096385fbeec9.tar.gz
rust-cd4bffdd69c33e3987307ef06db3096385fbeec9.zip
Evaluate `UnevalutedConst` before trait solving
-rw-r--r--crates/hir-ty/src/infer/unify.rs14
-rw-r--r--crates/hir-ty/src/tests/regression.rs23
-rw-r--r--crates/hir-ty/src/traits.rs14
-rw-r--r--crates/hir-ty/src/utils.rs43
4 files changed, 80 insertions, 14 deletions
diff --git a/crates/hir-ty/src/infer/unify.rs b/crates/hir-ty/src/infer/unify.rs
index 38eae475b55..e33d8f1795e 100644
--- a/crates/hir-ty/src/infer/unify.rs
+++ b/crates/hir-ty/src/infer/unify.rs
@@ -15,11 +15,11 @@ use triomphe::Arc;
 
 use super::{InferOk, InferResult, InferenceContext, TypeError};
 use crate::{
-    db::HirDatabase, fold_tys_and_consts, static_lifetime, to_chalk_trait_id, traits::FnTrait,
-    AliasEq, AliasTy, BoundVar, Canonical, Const, ConstValue, DebruijnIndex, GenericArg,
-    GenericArgData, Goal, Guidance, InEnvironment, InferenceVar, Interner, Lifetime, ParamKind,
-    ProjectionTy, ProjectionTyExt, Scalar, Solution, Substitution, TraitEnvironment, Ty, TyBuilder,
-    TyExt, TyKind, VariableKind,
+    consteval::unknown_const, db::HirDatabase, fold_tys_and_consts, static_lifetime,
+    to_chalk_trait_id, traits::FnTrait, AliasEq, AliasTy, BoundVar, Canonical, Const, ConstValue,
+    DebruijnIndex, GenericArg, GenericArgData, Goal, Guidance, InEnvironment, InferenceVar,
+    Interner, Lifetime, ParamKind, ProjectionTy, ProjectionTyExt, Scalar, Solution, Substitution,
+    TraitEnvironment, Ty, TyBuilder, TyExt, TyKind, VariableKind,
 };
 
 impl<'a> InferenceContext<'a> {
@@ -256,10 +256,10 @@ impl<'a> InferenceTable<'a> {
                                 {
                                     eval
                                 } else {
-                                    c
+                                    unknown_const(c.data(Interner).ty.clone())
                                 }
                             } else {
-                                c
+                                unknown_const(c.data(Interner).ty.clone())
                             }
                         }
                         _ => c,
diff --git a/crates/hir-ty/src/tests/regression.rs b/crates/hir-ty/src/tests/regression.rs
index 1fdeddede09..8f4b807f560 100644
--- a/crates/hir-ty/src/tests/regression.rs
+++ b/crates/hir-ty/src/tests/regression.rs
@@ -1912,3 +1912,26 @@ fn main() {
         "#,
     );
 }
+
+#[test]
+fn regression_14844_2() {
+    check_no_mismatches(
+        r#"
+//- minicore: fn
+pub const ONE: usize = 1;
+
+pub type MyInner = Inner<ONE>;
+
+pub struct Inner<const P: usize>();
+
+impl Inner<1> {
+    fn map<F>(&self, func: F) -> bool
+    where
+        F: Fn(&MyInner) -> bool,
+    {
+        func(self)
+    }
+}
+        "#,
+    );
+}
diff --git a/crates/hir-ty/src/traits.rs b/crates/hir-ty/src/traits.rs
index d2ca6e5ed7c..f40b7db3a55 100644
--- a/crates/hir-ty/src/traits.rs
+++ b/crates/hir-ty/src/traits.rs
@@ -2,7 +2,7 @@
 
 use std::env::var;
 
-use chalk_ir::GoalData;
+use chalk_ir::{fold::TypeFoldable, DebruijnIndex, GoalData};
 use chalk_recursive::Cache;
 use chalk_solve::{logging_db::LoggingRustIrDatabase, rust_ir, Solver};
 
@@ -16,9 +16,9 @@ use stdx::panic_context;
 use triomphe::Arc;
 
 use crate::{
-    db::HirDatabase, infer::unify::InferenceTable, AliasEq, AliasTy, Canonical, DomainGoal, Goal,
-    Guidance, InEnvironment, Interner, ProjectionTy, ProjectionTyExt, Solution, TraitRefExt, Ty,
-    TyKind, WhereClause,
+    db::HirDatabase, infer::unify::InferenceTable, utils::UnevaluatedConstEvaluatorFolder, AliasEq,
+    AliasTy, Canonical, DomainGoal, Goal, Guidance, InEnvironment, Interner, ProjectionTy,
+    ProjectionTyExt, Solution, TraitRefExt, Ty, TyKind, WhereClause,
 };
 
 /// This controls how much 'time' we give the Chalk solver before giving up.
@@ -106,6 +106,12 @@ pub(crate) fn trait_solve_query(
         }
     }
 
+    // Chalk see `UnevaluatedConst` as a unique concrete value, but we see it as an alias for another const. So
+    // we should get rid of it when talking to chalk.
+    let goal = goal
+        .try_fold_with(&mut UnevaluatedConstEvaluatorFolder { db }, DebruijnIndex::INNERMOST)
+        .unwrap();
+
     // We currently don't deal with universes (I think / hope they're not yet
     // relevant for our use cases?)
     let u_canonical = chalk_ir::UCanonical { canonical: goal, universes: 1 };
diff --git a/crates/hir-ty/src/utils.rs b/crates/hir-ty/src/utils.rs
index aa40d084795..f60b4607f22 100644
--- a/crates/hir-ty/src/utils.rs
+++ b/crates/hir-ty/src/utils.rs
@@ -4,7 +4,11 @@
 use std::iter;
 
 use base_db::CrateId;
-use chalk_ir::{cast::Cast, fold::Shift, BoundVar, DebruijnIndex, Mutability};
+use chalk_ir::{
+    cast::Cast,
+    fold::{FallibleTypeFolder, Shift},
+    BoundVar, DebruijnIndex, Mutability,
+};
 use either::Either;
 use hir_def::{
     db::DefDatabase,
@@ -26,8 +30,8 @@ use smallvec::{smallvec, SmallVec};
 use stdx::never;
 
 use crate::{
-    db::HirDatabase, ChalkTraitId, GenericArg, Interner, Substitution, TraitRef, TraitRefExt, Ty,
-    TyExt, WhereClause,
+    consteval::unknown_const, db::HirDatabase, ChalkTraitId, Const, ConstScalar, GenericArg,
+    Interner, Substitution, TraitRef, TraitRefExt, Ty, TyExt, WhereClause,
 };
 
 pub(crate) fn fn_traits(
@@ -403,3 +407,36 @@ pub(crate) fn pattern_matching_dereference_count(
     }
     r
 }
+
+pub(crate) struct UnevaluatedConstEvaluatorFolder<'a> {
+    pub(crate) db: &'a dyn HirDatabase,
+}
+
+impl FallibleTypeFolder<Interner> for UnevaluatedConstEvaluatorFolder<'_> {
+    type Error = ();
+
+    fn as_dyn(&mut self) -> &mut dyn FallibleTypeFolder<Interner, Error = ()> {
+        self
+    }
+
+    fn interner(&self) -> Interner {
+        Interner
+    }
+
+    fn try_fold_const(
+        &mut self,
+        constant: Const,
+        _outer_binder: DebruijnIndex,
+    ) -> Result<Const, Self::Error> {
+        if let chalk_ir::ConstValue::Concrete(c) = &constant.data(Interner).value {
+            if let ConstScalar::UnevaluatedConst(id, subst) = &c.interned {
+                if let Ok(eval) = self.db.const_eval(*id, subst.clone()) {
+                    return Ok(eval);
+                } else {
+                    return Ok(unknown_const(constant.data(Interner).ty.clone()));
+                }
+            }
+        }
+        Ok(constant)
+    }
+}