Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-ty/src/next_solver/infer/traits.rs')
-rw-r--r--crates/hir-ty/src/next_solver/infer/traits.rs96
1 files changed, 48 insertions, 48 deletions
diff --git a/crates/hir-ty/src/next_solver/infer/traits.rs b/crates/hir-ty/src/next_solver/infer/traits.rs
index 68aa12d7bb..4f000c24cc 100644
--- a/crates/hir-ty/src/next_solver/infer/traits.rs
+++ b/crates/hir-ty/src/next_solver/infer/traits.rs
@@ -7,16 +7,15 @@ use std::{
hash::{Hash, Hasher},
};
+use hir_def::TraitId;
+use macros::{TypeFoldable, TypeVisitable};
+use rustc_type_ir::Upcast;
use rustc_type_ir::elaborate::Elaboratable;
-use rustc_type_ir::{
- PredicatePolarity, Upcast,
- solve::{Certainty, NoSolution},
-};
-use rustc_type_ir::{TypeFoldable, TypeVisitable};
+use tracing::debug;
use crate::next_solver::{
- Binder, Clause, DbInterner, Goal, ParamEnv, PolyTraitPredicate, Predicate, SolverDefId, Span,
- TraitPredicate, Ty,
+ Clause, DbInterner, Goal, ParamEnv, PolyTraitPredicate, Predicate, Span, TraitPredicate,
+ TraitRef, Ty,
};
use super::InferCtxt;
@@ -63,8 +62,10 @@ impl ObligationCause {
/// either identifying an `impl` (e.g., `impl Eq for i32`) that
/// satisfies the obligation, or else finding a bound that is in
/// scope. The eventual result is usually a `Selection` (defined below).
-#[derive(Clone, Debug)]
+#[derive(Clone, Debug, TypeVisitable, TypeFoldable)]
pub struct Obligation<'db, T> {
+ #[type_foldable(identity)]
+ #[type_visitable(ignore)]
/// The reason we have to prove this thing.
pub cause: ObligationCause,
@@ -101,9 +102,9 @@ impl<'db> Elaboratable<DbInterner<'db>> for PredicateObligation<'db> {
fn child_with_derived_cause(
&self,
clause: Clause<'db>,
- span: Span,
- parent_trait_pred: PolyTraitPredicate<'db>,
- index: usize,
+ _span: Span,
+ _parent_trait_pred: PolyTraitPredicate<'db>,
+ _index: usize,
) -> Self {
let cause = ObligationCause::new();
Obligation {
@@ -115,39 +116,6 @@ impl<'db> Elaboratable<DbInterner<'db>> for PredicateObligation<'db> {
}
}
-impl<'db, T: TypeVisitable<DbInterner<'db>>> TypeVisitable<DbInterner<'db>> for Obligation<'db, T> {
- fn visit_with<V: rustc_type_ir::TypeVisitor<DbInterner<'db>>>(
- &self,
- visitor: &mut V,
- ) -> V::Result {
- rustc_ast_ir::try_visit!(self.param_env.visit_with(visitor));
- self.predicate.visit_with(visitor)
- }
-}
-
-impl<'db, T: TypeFoldable<DbInterner<'db>>> TypeFoldable<DbInterner<'db>> for Obligation<'db, T> {
- fn try_fold_with<F: rustc_type_ir::FallibleTypeFolder<DbInterner<'db>>>(
- self,
- folder: &mut F,
- ) -> Result<Self, F::Error> {
- Ok(Obligation {
- cause: self.cause.clone(),
- param_env: self.param_env.try_fold_with(folder)?,
- predicate: self.predicate.try_fold_with(folder)?,
- recursion_depth: self.recursion_depth,
- })
- }
-
- fn fold_with<F: rustc_type_ir::TypeFolder<DbInterner<'db>>>(self, folder: &mut F) -> Self {
- Obligation {
- cause: self.cause.clone(),
- param_env: self.param_env.fold_with(folder),
- predicate: self.predicate.fold_with(folder),
- recursion_depth: self.recursion_depth,
- }
- }
-}
-
impl<'db, T: Copy> Obligation<'db, T> {
pub fn as_goal(&self) -> Goal<'db, T> {
Goal { param_env: self.param_env, predicate: self.predicate }
@@ -181,16 +149,16 @@ impl<'db, P> From<Obligation<'db, P>> for Goal<'db, P> {
}
}
-pub type PredicateObligation<'db> = Obligation<'db, Predicate<'db>>;
-pub type TraitObligation<'db> = Obligation<'db, TraitPredicate<'db>>;
+pub(crate) type PredicateObligation<'db> = Obligation<'db, Predicate<'db>>;
+pub(crate) type TraitObligation<'db> = Obligation<'db, TraitPredicate<'db>>;
-pub type PredicateObligations<'db> = Vec<PredicateObligation<'db>>;
+pub(crate) type PredicateObligations<'db> = Vec<PredicateObligation<'db>>;
impl<'db> PredicateObligation<'db> {
/// Flips the polarity of the inner predicate.
///
/// Given `T: Trait` predicate it returns `T: !Trait` and given `T: !Trait` returns `T: Trait`.
- pub fn flip_polarity(&self, tcx: DbInterner<'db>) -> Option<PredicateObligation<'db>> {
+ pub fn flip_polarity(&self, _interner: DbInterner<'db>) -> Option<PredicateObligation<'db>> {
Some(PredicateObligation {
cause: self.cause.clone(),
param_env: self.param_env,
@@ -237,3 +205,35 @@ impl<'db, O> Obligation<'db, O> {
Obligation::with_depth(tcx, self.cause.clone(), self.recursion_depth, self.param_env, value)
}
}
+
+/// Determines whether the type `ty` is known to meet `bound` and
+/// returns true if so. Returns false if `ty` either does not meet
+/// `bound` or is not known to meet bound (note that this is
+/// conservative towards *no impl*, which is the opposite of the
+/// `evaluate` methods).
+pub(crate) fn type_known_to_meet_bound_modulo_regions<'tcx>(
+ infcx: &InferCtxt<'tcx>,
+ param_env: ParamEnv<'tcx>,
+ ty: Ty<'tcx>,
+ def_id: TraitId,
+) -> bool {
+ let trait_ref = TraitRef::new(infcx.interner, def_id.into(), [ty]);
+ pred_known_to_hold_modulo_regions(infcx, param_env, trait_ref)
+}
+
+/// FIXME(@lcnr): this function doesn't seem right and shouldn't exist?
+///
+/// Ping me on zulip if you want to use this method and need help with finding
+/// an appropriate replacement.
+fn pred_known_to_hold_modulo_regions<'db>(
+ infcx: &InferCtxt<'db>,
+ param_env: ParamEnv<'db>,
+ pred: impl Upcast<DbInterner<'db>, Predicate<'db>>,
+) -> bool {
+ let obligation = Obligation::new(infcx.interner, ObligationCause::dummy(), param_env, pred);
+
+ let result = infcx.evaluate_obligation(&obligation);
+ debug!(?result);
+
+ result.must_apply_modulo_regions()
+}