Unnamed repository; edit this file 'description' to name the repository.
Auto merge of #14913 - HKalbasi:fix14844, r=HKalbasi
Evaluate `UnevalutedConst` before trait solving cc #14844
bors 2023-05-27
parent 7c81fff · parent cd4bffd · commit 1b5523a
-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 38eae475b5..e33d8f1795 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 1fdeddede0..8f4b807f56 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 d2ca6e5ed7..f40b7db3a5 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 aa40d08479..f60b4607f2 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)
+ }
+}