diff --git a/crates/hir-ty/src/infer/unify.rs b/crates/hir-ty/src/infer/unify.rs index 38eae475b556f..e33d8f1795e2e 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 1fdeddede096c..8f4b807f560b4 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; + +pub struct Inner(); + +impl Inner<1> { + fn map(&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 d2ca6e5ed7c8f..f40b7db3a5512 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 aa40d084795a0..f60b4607f224c 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 for UnevaluatedConstEvaluatorFolder<'_> { + type Error = (); + + fn as_dyn(&mut self) -> &mut dyn FallibleTypeFolder { + self + } + + fn interner(&self) -> Interner { + Interner + } + + fn try_fold_const( + &mut self, + constant: Const, + _outer_binder: DebruijnIndex, + ) -> Result { + 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) + } +}