Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-ty/src/next_solver/infer/mod.rs')
-rw-r--r--crates/hir-ty/src/next_solver/infer/mod.rs53
1 files changed, 51 insertions, 2 deletions
diff --git a/crates/hir-ty/src/next_solver/infer/mod.rs b/crates/hir-ty/src/next_solver/infer/mod.rs
index a6352c7899..70d3366675 100644
--- a/crates/hir-ty/src/next_solver/infer/mod.rs
+++ b/crates/hir-ty/src/next_solver/infer/mod.rs
@@ -7,12 +7,11 @@ use std::sync::Arc;
pub use BoundRegionConversionTime::*;
use ena::unify as ut;
-use hir_def::GenericParamId;
+use hir_def::{GenericParamId, TraitId};
use opaque_types::{OpaqueHiddenType, OpaqueTypeStorage};
use region_constraints::{RegionConstraintCollector, RegionConstraintStorage};
use rustc_next_trait_solver::solve::{GoalEvaluation, SolverDelegateEvalExt};
use rustc_pattern_analysis::Captures;
-use rustc_type_ir::solve::{NoSolution, inspect};
use rustc_type_ir::{
ClosureKind, ConstVid, FloatVarValue, FloatVid, GenericArgKind, InferConst, InferTy,
IntVarValue, IntVid, OutlivesPredicate, RegionVid, TermKind, TyVid, TypeFoldable, TypeFolder,
@@ -22,6 +21,10 @@ use rustc_type_ir::{
Const as _, GenericArg as _, GenericArgs as _, IntoKind, SliceLike, Term as _, Ty as _,
},
};
+use rustc_type_ir::{
+ Upcast,
+ solve::{NoSolution, inspect},
+};
use snapshot::undo_log::InferCtxtUndoLogs;
use tracing::{debug, instrument};
use traits::{ObligationCause, PredicateObligations};
@@ -509,6 +512,52 @@ impl<'db> InferCtxt<'db> {
self.evaluate_obligation(obligation).must_apply_modulo_regions()
}
+ /// Check whether a `ty` implements given trait(trait_def_id) without side-effects.
+ ///
+ /// The inputs are:
+ ///
+ /// - the def-id of the trait
+ /// - the type parameters of the trait, including the self-type
+ /// - the parameter environment
+ ///
+ /// Invokes `evaluate_obligation`, so in the event that evaluating
+ /// `Ty: Trait` causes overflow, EvaluatedToAmbigStackDependent will be returned.
+ ///
+ /// `type_implements_trait` is a convenience function for simple cases like
+ ///
+ /// ```ignore (illustrative)
+ /// let copy_trait = infcx.tcx.require_lang_item(LangItem::Copy, span);
+ /// let implements_copy = infcx.type_implements_trait(copy_trait, [ty], param_env)
+ /// .must_apply_modulo_regions();
+ /// ```
+ ///
+ /// In most cases you should instead create an [Obligation] and check whether
+ /// it holds via [`evaluate_obligation`] or one of its helper functions like
+ /// [`predicate_must_hold_modulo_regions`], because it properly handles higher ranked traits
+ /// and it is more convenient and safer when your `params` are inside a [`Binder`].
+ ///
+ /// [Obligation]: traits::Obligation
+ /// [`evaluate_obligation`]: crate::traits::query::evaluate_obligation::InferCtxtExt::evaluate_obligation
+ /// [`predicate_must_hold_modulo_regions`]: crate::traits::query::evaluate_obligation::InferCtxtExt::predicate_must_hold_modulo_regions
+ /// [`Binder`]: ty::Binder
+ #[instrument(level = "debug", skip(self, params), ret)]
+ pub fn type_implements_trait(
+ &self,
+ trait_def_id: TraitId,
+ params: impl IntoIterator<Item: Into<GenericArg<'db>>>,
+ param_env: ParamEnv<'db>,
+ ) -> EvaluationResult {
+ let trait_ref = TraitRef::new(self.interner, trait_def_id.into(), params);
+
+ let obligation = traits::Obligation {
+ cause: traits::ObligationCause::dummy(),
+ param_env,
+ recursion_depth: 0,
+ predicate: trait_ref.upcast(self.interner),
+ };
+ self.evaluate_obligation(&obligation)
+ }
+
/// Evaluate a given predicate, capturing overflow and propagating it back.
fn evaluate_obligation(&self, obligation: &PredicateObligation<'db>) -> EvaluationResult {
self.probe(|snapshot| {