Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-ty/src/traits.rs')
-rw-r--r--crates/hir-ty/src/traits.rs64
1 files changed, 60 insertions, 4 deletions
diff --git a/crates/hir-ty/src/traits.rs b/crates/hir-ty/src/traits.rs
index 16ad54a2f2..cd125f3af8 100644
--- a/crates/hir-ty/src/traits.rs
+++ b/crates/hir-ty/src/traits.rs
@@ -12,7 +12,7 @@ use intern::sym;
use rustc_next_trait_solver::solve::{HasChanged, SolverDelegateEvalExt};
use rustc_type_ir::{
InferCtxtLike, TypingMode,
- inherent::{SliceLike, Span as _, Ty as _},
+ inherent::{IntoKind, SliceLike, Span as _, Ty as _},
solve::Certainty,
};
use span::Edition;
@@ -28,6 +28,7 @@ use crate::{
DbInterner, GenericArg, ParamEnv, Predicate, SolverContext, Span,
infer::{DbInternerInferExt, InferCtxt, traits::ObligationCause},
mapping::{ChalkToNextSolver, NextSolverToChalk, convert_canonical_args_for_result},
+ obligation_ctxt::ObligationCtxt,
util::mini_canonicalize,
},
utils::UnevaluatedConstEvaluatorFolder,
@@ -43,7 +44,7 @@ pub struct TraitEnvironment<'db> {
pub krate: Crate,
pub block: Option<BlockId>,
// FIXME make this a BTreeMap
- traits_from_clauses: Box<[(Ty, TraitId)]>,
+ traits_from_clauses: Box<[(crate::next_solver::Ty<'db>, TraitId)]>,
pub env: ParamEnv<'db>,
}
@@ -60,7 +61,7 @@ impl<'db> TraitEnvironment<'db> {
pub fn new(
krate: Crate,
block: Option<BlockId>,
- traits_from_clauses: Box<[(Ty, TraitId)]>,
+ traits_from_clauses: Box<[(crate::next_solver::Ty<'db>, TraitId)]>,
env: ParamEnv<'db>,
) -> Arc<Self> {
Arc::new(TraitEnvironment { krate, block, traits_from_clauses, env })
@@ -71,13 +72,28 @@ impl<'db> TraitEnvironment<'db> {
Arc::make_mut(this).block = Some(block);
}
- pub fn traits_in_scope_from_clauses(&self, ty: Ty) -> impl Iterator<Item = TraitId> + '_ {
+ pub fn traits_in_scope_from_clauses(
+ &self,
+ ty: crate::next_solver::Ty<'db>,
+ ) -> impl Iterator<Item = TraitId> + '_ {
self.traits_from_clauses
.iter()
.filter_map(move |(self_ty, trait_id)| (*self_ty == ty).then_some(*trait_id))
}
}
+/// This should be used in `hir` only.
+pub fn structurally_normalize_ty<'db>(
+ infcx: &InferCtxt<'db>,
+ ty: crate::next_solver::Ty<'db>,
+ env: Arc<TraitEnvironment<'db>>,
+) -> crate::next_solver::Ty<'db> {
+ let crate::next_solver::TyKind::Alias(..) = ty.kind() else { return ty };
+ let mut ocx = ObligationCtxt::new(infcx);
+ let ty = ocx.structurally_normalize_ty(&ObligationCause::dummy(), env.env, ty).unwrap_or(ty);
+ ty.replace_infer_with_error(infcx.interner)
+}
+
pub(crate) fn normalize_projection_query<'db>(
db: &'db dyn HirDatabase,
projection: ProjectionTy,
@@ -440,3 +456,43 @@ impl FnTrait {
self.lang_item().resolve_trait(db, krate)
}
}
+
+/// This should not be used in `hir-ty`, only in `hir`.
+pub fn implements_trait_unique<'db>(
+ ty: crate::next_solver::Ty<'db>,
+ db: &'db dyn HirDatabase,
+ env: Arc<TraitEnvironment<'db>>,
+ trait_: TraitId,
+) -> bool {
+ implements_trait_unique_impl(db, env, trait_, &mut |infcx| {
+ infcx.fill_rest_fresh_args(trait_.into(), [ty.into()])
+ })
+}
+
+/// This should not be used in `hir-ty`, only in `hir`.
+pub fn implements_trait_unique_with_args<'db>(
+ db: &'db dyn HirDatabase,
+ env: Arc<TraitEnvironment<'db>>,
+ trait_: TraitId,
+ args: crate::next_solver::GenericArgs<'db>,
+) -> bool {
+ implements_trait_unique_impl(db, env, trait_, &mut |_| args)
+}
+
+fn implements_trait_unique_impl<'db>(
+ db: &'db dyn HirDatabase,
+ env: Arc<TraitEnvironment<'db>>,
+ trait_: TraitId,
+ create_args: &mut dyn FnMut(&InferCtxt<'db>) -> crate::next_solver::GenericArgs<'db>,
+) -> bool {
+ let interner = DbInterner::new_with(db, Some(env.krate), env.block);
+ // FIXME(next-solver): I believe this should be `PostAnalysis`.
+ let infcx = interner.infer_ctxt().build(TypingMode::non_body_analysis());
+
+ let args = create_args(&infcx);
+ let trait_ref = rustc_type_ir::TraitRef::new_from_args(interner, trait_.into(), args);
+ let goal = crate::next_solver::Goal::new(interner, env.env, trait_ref);
+
+ let result = crate::traits::next_trait_solve_in_ctxt(&infcx, goal);
+ matches!(result, Ok((_, Certainty::Yes)))
+}