1- use rustc_middle :: ty :: TyCtxt ;
1+ use std :: cell :: RefCell ;
22
33use super :: TraitEngine ;
44use super :: { ChalkFulfillmentContext , FulfillmentContext } ;
5+ use crate :: infer:: InferCtxtExt ;
6+ use rustc_hir:: def_id:: DefId ;
7+ use rustc_infer:: infer:: { InferCtxt , InferOk } ;
8+ use rustc_infer:: traits:: {
9+ FulfillmentError , Obligation , ObligationCause , PredicateObligation , TraitEngineExt as _,
10+ } ;
11+ use rustc_middle:: ty:: error:: TypeError ;
12+ use rustc_middle:: ty:: ToPredicate ;
13+ use rustc_middle:: ty:: TypeFoldable ;
14+ use rustc_middle:: ty:: { self , Ty , TyCtxt } ;
515
616pub trait TraitEngineExt < ' tcx > {
717 fn new ( tcx : TyCtxt < ' tcx > ) -> Box < Self > ;
@@ -16,3 +26,87 @@ impl<'tcx> TraitEngineExt<'tcx> for dyn TraitEngine<'tcx> {
1626 }
1727 }
1828}
29+
30+ /// Used if you want to have pleasant experience when dealing
31+ /// with obligations outside of hir or mir typeck.
32+ pub struct ObligationCtxt < ' a , ' tcx > {
33+ pub infcx : & ' a InferCtxt < ' a , ' tcx > ,
34+ engine : RefCell < Box < dyn TraitEngine < ' tcx > > > ,
35+ }
36+
37+ impl < ' a , ' tcx > ObligationCtxt < ' a , ' tcx > {
38+ pub fn new ( infcx : & ' a InferCtxt < ' a , ' tcx > ) -> Self {
39+ Self { infcx, engine : RefCell :: new ( <dyn TraitEngine < ' _ > >:: new ( infcx. tcx ) ) }
40+ }
41+
42+ pub fn register_obligation ( & self , obligation : PredicateObligation < ' tcx > ) {
43+ self . engine . borrow_mut ( ) . register_predicate_obligation ( self . infcx , obligation) ;
44+ }
45+
46+ pub fn register_obligations (
47+ & self ,
48+ obligations : impl IntoIterator < Item = PredicateObligation < ' tcx > > ,
49+ ) {
50+ // Can't use `register_predicate_obligations` because the iterator
51+ // may also use this `ObligationCtxt`.
52+ for obligation in obligations {
53+ self . engine . borrow_mut ( ) . register_predicate_obligation ( self . infcx , obligation)
54+ }
55+ }
56+
57+ pub fn register_infer_ok_obligations < T > ( & self , infer_ok : InferOk < ' tcx , T > ) -> T {
58+ let InferOk { value, obligations } = infer_ok;
59+ self . engine . borrow_mut ( ) . register_predicate_obligations ( self . infcx , obligations) ;
60+ value
61+ }
62+
63+ /// Requires that `ty` must implement the trait with `def_id` in
64+ /// the given environment. This trait must not have any type
65+ /// parameters (except for `Self`).
66+ pub fn register_bound (
67+ & self ,
68+ cause : ObligationCause < ' tcx > ,
69+ param_env : ty:: ParamEnv < ' tcx > ,
70+ ty : Ty < ' tcx > ,
71+ def_id : DefId ,
72+ ) {
73+ let tcx = self . infcx . tcx ;
74+ let trait_ref = ty:: TraitRef { def_id, substs : tcx. mk_substs_trait ( ty, & [ ] ) } ;
75+ self . register_obligation ( Obligation {
76+ cause,
77+ recursion_depth : 0 ,
78+ param_env,
79+ predicate : ty:: Binder :: dummy ( trait_ref) . without_const ( ) . to_predicate ( tcx) ,
80+ } ) ;
81+ }
82+
83+ pub fn normalize < T : TypeFoldable < ' tcx > > (
84+ & self ,
85+ cause : ObligationCause < ' tcx > ,
86+ param_env : ty:: ParamEnv < ' tcx > ,
87+ value : T ,
88+ ) -> T {
89+ let infer_ok = self . infcx . partially_normalize_associated_types_in ( cause, param_env, value) ;
90+ self . register_infer_ok_obligations ( infer_ok)
91+ }
92+
93+ pub fn equate_types (
94+ & self ,
95+ cause : & ObligationCause < ' tcx > ,
96+ param_env : ty:: ParamEnv < ' tcx > ,
97+ expected : Ty < ' tcx > ,
98+ actual : Ty < ' tcx > ,
99+ ) -> Result < ( ) , TypeError < ' tcx > > {
100+ match self . infcx . at ( cause, param_env) . eq ( expected, actual) {
101+ Ok ( InferOk { obligations, value : ( ) } ) => {
102+ self . register_obligations ( obligations) ;
103+ Ok ( ( ) )
104+ }
105+ Err ( e) => Err ( e) ,
106+ }
107+ }
108+
109+ pub fn select_all_or_error ( & self ) -> Vec < FulfillmentError < ' tcx > > {
110+ self . engine . borrow_mut ( ) . select_all_or_error ( self . infcx )
111+ }
112+ }
0 commit comments