1
- use rustc_middle :: ty :: TyCtxt ;
1
+ use std :: cell :: RefCell ;
2
2
3
3
use super :: TraitEngine ;
4
4
use 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 } ;
5
15
6
16
pub trait TraitEngineExt < ' tcx > {
7
17
fn new ( tcx : TyCtxt < ' tcx > ) -> Box < Self > ;
@@ -16,3 +26,87 @@ impl<'tcx> TraitEngineExt<'tcx> for dyn TraitEngine<'tcx> {
16
26
}
17
27
}
18
28
}
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