@@ -21,6 +21,7 @@ use middle::const_val::{ConstEvalErr, ErrKind};
2121use super :: CodeAmbiguity ;
2222use super :: CodeProjectionError ;
2323use super :: CodeSelectionError ;
24+ use super :: engine:: TraitEngine ;
2425use super :: { FulfillmentError , FulfillmentErrorCode } ;
2526use super :: { ObligationCause , PredicateObligation , Obligation } ;
2627use super :: project;
@@ -85,19 +86,72 @@ impl<'a, 'gcx, 'tcx> FulfillmentContext<'tcx> {
8586 }
8687 }
8788
89+ pub fn register_predicate_obligations < I > ( & mut self ,
90+ infcx : & InferCtxt < ' a , ' gcx , ' tcx > ,
91+ obligations : I )
92+ where I : IntoIterator < Item = PredicateObligation < ' tcx > >
93+ {
94+ for obligation in obligations {
95+ self . register_predicate_obligation ( infcx, obligation) ;
96+ }
97+ }
98+
99+ /// Attempts to select obligations using `selcx`. If `only_new_obligations` is true, then it
100+ /// only attempts to select obligations that haven't been seen before.
101+ fn select ( & mut self , selcx : & mut SelectionContext < ' a , ' gcx , ' tcx > )
102+ -> Result < ( ) , Vec < FulfillmentError < ' tcx > > > {
103+ debug ! ( "select(obligation-forest-size={})" , self . predicates. len( ) ) ;
104+
105+ let mut errors = Vec :: new ( ) ;
106+
107+ loop {
108+ debug ! ( "select: starting another iteration" ) ;
109+
110+ // Process pending obligations.
111+ let outcome = self . predicates . process_obligations ( & mut FulfillProcessor {
112+ selcx,
113+ register_region_obligations : self . register_region_obligations
114+ } ) ;
115+ debug ! ( "select: outcome={:?}" , outcome) ;
116+
117+ // FIXME: if we kept the original cache key, we could mark projection
118+ // obligations as complete for the projection cache here.
119+
120+ errors. extend (
121+ outcome. errors . into_iter ( )
122+ . map ( |e| to_fulfillment_error ( e) ) ) ;
123+
124+ // If nothing new was added, no need to keep looping.
125+ if outcome. stalled {
126+ break ;
127+ }
128+ }
129+
130+ debug ! ( "select({} predicates remaining, {} errors) done" ,
131+ self . predicates. len( ) , errors. len( ) ) ;
132+
133+ if errors. is_empty ( ) {
134+ Ok ( ( ) )
135+ } else {
136+ Err ( errors)
137+ }
138+ }
139+ }
140+
141+ impl < ' tcx > TraitEngine < ' tcx > for FulfillmentContext < ' tcx > {
88142 /// "Normalize" a projection type `<SomeType as SomeTrait>::X` by
89143 /// creating a fresh type variable `$0` as well as a projection
90144 /// predicate `<SomeType as SomeTrait>::X == $0`. When the
91145 /// inference engine runs, it will attempt to find an impl of
92146 /// `SomeTrait` or a where clause that lets us unify `$0` with
93147 /// something concrete. If this fails, we'll unify `$0` with
94148 /// `projection_ty` again.
95- pub fn normalize_projection_type ( & mut self ,
96- infcx : & InferCtxt < ' a , ' gcx , ' tcx > ,
97- param_env : ty:: ParamEnv < ' tcx > ,
98- projection_ty : ty:: ProjectionTy < ' tcx > ,
99- cause : ObligationCause < ' tcx > )
100- -> Ty < ' tcx >
149+ fn normalize_projection_type < ' a , ' gcx > ( & mut self ,
150+ infcx : & InferCtxt < ' a , ' gcx , ' tcx > ,
151+ param_env : ty:: ParamEnv < ' tcx > ,
152+ projection_ty : ty:: ProjectionTy < ' tcx > ,
153+ cause : ObligationCause < ' tcx > )
154+ -> Ty < ' tcx >
101155 {
102156 debug ! ( "normalize_projection_type(projection_ty={:?})" ,
103157 projection_ty) ;
@@ -125,12 +179,12 @@ impl<'a, 'gcx, 'tcx> FulfillmentContext<'tcx> {
125179 /// Requires that `ty` must implement the trait with `def_id` in
126180 /// the given environment. This trait must not have any type
127181 /// parameters (except for `Self`).
128- pub fn register_bound ( & mut self ,
129- infcx : & InferCtxt < ' a , ' gcx , ' tcx > ,
130- param_env : ty:: ParamEnv < ' tcx > ,
131- ty : Ty < ' tcx > ,
132- def_id : DefId ,
133- cause : ObligationCause < ' tcx > )
182+ fn register_bound < ' a , ' gcx > ( & mut self ,
183+ infcx : & InferCtxt < ' a , ' gcx , ' tcx > ,
184+ param_env : ty:: ParamEnv < ' tcx > ,
185+ ty : Ty < ' tcx > ,
186+ def_id : DefId ,
187+ cause : ObligationCause < ' tcx > )
134188 {
135189 let trait_ref = ty:: TraitRef {
136190 def_id,
@@ -144,9 +198,9 @@ impl<'a, 'gcx, 'tcx> FulfillmentContext<'tcx> {
144198 } ) ;
145199 }
146200
147- pub fn register_predicate_obligation ( & mut self ,
148- infcx : & InferCtxt < ' a , ' gcx , ' tcx > ,
149- obligation : PredicateObligation < ' tcx > )
201+ fn register_predicate_obligation < ' a , ' gcx > ( & mut self ,
202+ infcx : & InferCtxt < ' a , ' gcx , ' tcx > ,
203+ obligation : PredicateObligation < ' tcx > )
150204 {
151205 // this helps to reduce duplicate errors, as well as making
152206 // debug output much nicer to read and so on.
@@ -162,19 +216,9 @@ impl<'a, 'gcx, 'tcx> FulfillmentContext<'tcx> {
162216 } ) ;
163217 }
164218
165- pub fn register_predicate_obligations < I > ( & mut self ,
166- infcx : & InferCtxt < ' a , ' gcx , ' tcx > ,
167- obligations : I )
168- where I : IntoIterator < Item = PredicateObligation < ' tcx > >
169- {
170- for obligation in obligations {
171- self . register_predicate_obligation ( infcx, obligation) ;
172- }
173- }
174-
175- pub fn select_all_or_error ( & mut self ,
176- infcx : & InferCtxt < ' a , ' gcx , ' tcx > )
177- -> Result < ( ) , Vec < FulfillmentError < ' tcx > > >
219+ fn select_all_or_error < ' a , ' gcx > ( & mut self ,
220+ infcx : & InferCtxt < ' a , ' gcx , ' tcx > )
221+ -> Result < ( ) , Vec < FulfillmentError < ' tcx > > >
178222 {
179223 self . select_where_possible ( infcx) ?;
180224
@@ -190,58 +234,17 @@ impl<'a, 'gcx, 'tcx> FulfillmentContext<'tcx> {
190234 }
191235 }
192236
193- pub fn select_where_possible ( & mut self ,
194- infcx : & InferCtxt < ' a , ' gcx , ' tcx > )
195- -> Result < ( ) , Vec < FulfillmentError < ' tcx > > >
237+ fn select_where_possible < ' a , ' gcx > ( & mut self ,
238+ infcx : & InferCtxt < ' a , ' gcx , ' tcx > )
239+ -> Result < ( ) , Vec < FulfillmentError < ' tcx > > >
196240 {
197241 let mut selcx = SelectionContext :: new ( infcx) ;
198242 self . select ( & mut selcx)
199243 }
200244
201- pub fn pending_obligations ( & self ) -> Vec < PendingPredicateObligation < ' tcx > > {
245+ fn pending_obligations ( & self ) -> Vec < PendingPredicateObligation < ' tcx > > {
202246 self . predicates . pending_obligations ( )
203247 }
204-
205- /// Attempts to select obligations using `selcx`. If `only_new_obligations` is true, then it
206- /// only attempts to select obligations that haven't been seen before.
207- fn select ( & mut self , selcx : & mut SelectionContext < ' a , ' gcx , ' tcx > )
208- -> Result < ( ) , Vec < FulfillmentError < ' tcx > > > {
209- debug ! ( "select(obligation-forest-size={})" , self . predicates. len( ) ) ;
210-
211- let mut errors = Vec :: new ( ) ;
212-
213- loop {
214- debug ! ( "select: starting another iteration" ) ;
215-
216- // Process pending obligations.
217- let outcome = self . predicates . process_obligations ( & mut FulfillProcessor {
218- selcx,
219- register_region_obligations : self . register_region_obligations
220- } ) ;
221- debug ! ( "select: outcome={:?}" , outcome) ;
222-
223- // FIXME: if we kept the original cache key, we could mark projection
224- // obligations as complete for the projection cache here.
225-
226- errors. extend (
227- outcome. errors . into_iter ( )
228- . map ( |e| to_fulfillment_error ( e) ) ) ;
229-
230- // If nothing new was added, no need to keep looping.
231- if outcome. stalled {
232- break ;
233- }
234- }
235-
236- debug ! ( "select({} predicates remaining, {} errors) done" ,
237- self . predicates. len( ) , errors. len( ) ) ;
238-
239- if errors. is_empty ( ) {
240- Ok ( ( ) )
241- } else {
242- Err ( errors)
243- }
244- }
245248}
246249
247250struct FulfillProcessor < ' a , ' b : ' a , ' gcx : ' tcx , ' tcx : ' b > {
0 commit comments