1
1
use std:: marker:: PhantomData ;
2
- use std:: mem;
3
2
use std:: ops:: ControlFlow ;
4
3
5
4
use rustc_data_structures:: thinvec:: ExtractIf ;
@@ -75,6 +74,13 @@ impl<'tcx> ObligationStorage<'tcx> {
75
74
self . pending . push ( ( obligation, stalled_on) ) ;
76
75
}
77
76
77
+ fn register_overflowed (
78
+ & mut self ,
79
+ overflowed : impl IntoIterator < Item = PredicateObligation < ' tcx > > ,
80
+ ) {
81
+ self . overflowed . extend ( overflowed) ;
82
+ }
83
+
78
84
fn has_pending_obligations ( & self ) -> bool {
79
85
!self . pending . is_empty ( ) || !self . overflowed . is_empty ( )
80
86
}
@@ -88,35 +94,10 @@ impl<'tcx> ObligationStorage<'tcx> {
88
94
89
95
fn drain_pending (
90
96
& mut self ,
91
- cond : impl Fn ( & PredicateObligation < ' tcx > ) -> bool ,
92
- ) -> PendingObligations < ' tcx > {
93
- let ( unstalled, pending) =
94
- mem:: take ( & mut self . pending ) . into_iter ( ) . partition ( |( o, _) | cond ( o) ) ;
95
- self . pending = pending;
96
- unstalled
97
- }
98
-
99
- fn on_fulfillment_overflow ( & mut self , infcx : & InferCtxt < ' tcx > ) {
100
- infcx. probe ( |_| {
101
- // IMPORTANT: we must not use solve any inference variables in the obligations
102
- // as this is all happening inside of a probe. We use a probe to make sure
103
- // we get all obligations involved in the overflow. We pretty much check: if
104
- // we were to do another step of `select_where_possible`, which goals would
105
- // change.
106
- // FIXME: <https://github.com/Gankra/thin-vec/pull/66> is merged, this can be removed.
107
- self . overflowed . extend (
108
- ExtractIf :: new ( & mut self . pending , |( o, stalled_on) | {
109
- let goal = o. as_goal ( ) ;
110
- let result = <& SolverDelegate < ' tcx > >:: from ( infcx) . evaluate_root_goal (
111
- goal,
112
- o. cause . span ,
113
- stalled_on. take ( ) ,
114
- ) ;
115
- matches ! ( result, Ok ( GoalEvaluation { has_changed: HasChanged :: Yes , .. } ) )
116
- } )
117
- . map ( |( o, _) | o) ,
118
- ) ;
119
- } )
97
+ cond : impl Fn ( & PredicateObligation < ' tcx > , Option < & GoalStalledOn < TyCtxt < ' tcx > > > ) -> bool ,
98
+ ) -> impl Iterator < Item = ( PredicateObligation < ' tcx > , Option < GoalStalledOn < TyCtxt < ' tcx > > > ) >
99
+ {
100
+ ExtractIf :: new ( & mut self . pending , move |( o, stalled) | cond ( o, stalled. as_ref ( ) ) )
120
101
}
121
102
}
122
103
@@ -133,21 +114,6 @@ impl<'tcx, E: 'tcx> FulfillmentCtxt<'tcx, E> {
133
114
_errors : PhantomData ,
134
115
}
135
116
}
136
-
137
- fn inspect_evaluated_obligation (
138
- & self ,
139
- infcx : & InferCtxt < ' tcx > ,
140
- obligation : & PredicateObligation < ' tcx > ,
141
- result : & Result < GoalEvaluation < TyCtxt < ' tcx > > , NoSolution > ,
142
- ) {
143
- if let Some ( inspector) = infcx. obligation_inspector . get ( ) {
144
- let result = match result {
145
- Ok ( GoalEvaluation { certainty, .. } ) => Ok ( * certainty) ,
146
- Err ( NoSolution ) => Err ( NoSolution ) ,
147
- } ;
148
- ( inspector) ( infcx, & obligation, result) ;
149
- }
150
- }
151
117
}
152
118
153
119
impl < ' tcx , E > TraitEngine < ' tcx , E > for FulfillmentCtxt < ' tcx , E >
@@ -181,32 +147,42 @@ where
181
147
182
148
fn select_where_possible ( & mut self , infcx : & InferCtxt < ' tcx > ) -> Vec < E > {
183
149
assert_eq ! ( self . usable_in_snapshot, infcx. num_open_snapshots( ) ) ;
150
+ let delegate = <& SolverDelegate < ' tcx > >:: from ( infcx) ;
184
151
let mut errors = Vec :: new ( ) ;
185
152
loop {
186
153
let mut any_changed = false ;
187
- for ( mut obligation, stalled_on) in self . obligations . drain_pending ( |_| true ) {
154
+ let mut overflowed = vec ! [ ] ;
155
+ let mut pending = vec ! [ ] ;
156
+
157
+ for ( mut obligation, stalled_on) in self . obligations . drain_pending ( |_, stalled_on| {
158
+ stalled_on. is_none_or ( |s| !delegate. is_still_stalled ( s) )
159
+ } ) {
188
160
if !infcx. tcx . recursion_limit ( ) . value_within_limit ( obligation. recursion_depth ) {
189
- self . obligations . on_fulfillment_overflow ( infcx) ;
190
- // Only return true errors that we have accumulated while processing.
191
- return errors;
161
+ overflowed. push ( obligation) ;
162
+ continue ;
192
163
}
193
164
194
165
let goal = obligation. as_goal ( ) ;
195
- let delegate = <& SolverDelegate < ' tcx > >:: from ( infcx) ;
196
166
if let Some ( certainty) =
197
167
delegate. compute_goal_fast_path ( goal, obligation. cause . span )
198
168
{
199
169
match certainty {
200
170
Certainty :: Yes => { }
201
- Certainty :: Maybe ( _) => {
202
- self . obligations . register ( obligation, None ) ;
203
- }
171
+ Certainty :: Maybe ( _) => pending. push ( ( obligation, None ) ) ,
204
172
}
205
173
continue ;
206
174
}
207
175
208
176
let result = delegate. evaluate_root_goal ( goal, obligation. cause . span , stalled_on) ;
209
- self . inspect_evaluated_obligation ( infcx, & obligation, & result) ;
177
+
178
+ if let Some ( inspector) = infcx. obligation_inspector . get ( ) {
179
+ let result = match result {
180
+ Ok ( GoalEvaluation { certainty, .. } ) => Ok ( certainty) ,
181
+ Err ( NoSolution ) => Err ( NoSolution ) ,
182
+ } ;
183
+ ( inspector) ( infcx, & obligation, result) ;
184
+ }
185
+
210
186
let GoalEvaluation { certainty, has_changed, stalled_on } = match result {
211
187
Ok ( result) => result,
212
188
Err ( NoSolution ) => {
@@ -231,10 +207,19 @@ where
231
207
232
208
match certainty {
233
209
Certainty :: Yes => { }
234
- Certainty :: Maybe ( _) => self . obligations . register ( obligation, stalled_on) ,
210
+ Certainty :: Maybe ( _) => pending . push ( ( obligation, stalled_on) ) ,
235
211
}
236
212
}
237
213
214
+ if !overflowed. is_empty ( ) {
215
+ self . obligations . register_overflowed ( overflowed) ;
216
+ return errors;
217
+ }
218
+
219
+ for ( obligation, stalled_on) in pending {
220
+ self . obligations . register ( obligation, stalled_on) ;
221
+ }
222
+
238
223
if !any_changed {
239
224
break ;
240
225
}
@@ -270,7 +255,7 @@ where
270
255
}
271
256
272
257
self . obligations
273
- . drain_pending ( |obl| {
258
+ . drain_pending ( |obl, _ | {
274
259
infcx. probe ( |_| {
275
260
infcx
276
261
. visit_proof_tree (
0 commit comments