@@ -86,8 +86,6 @@ pub struct FulfillmentContext<'tcx> {
86
86
// obligations (otherwise, it's easy to fail to walk to a
87
87
// particular node-id).
88
88
region_obligations : NodeMap < Vec < RegionObligation < ' tcx > > > ,
89
-
90
- pub errors_will_be_reported : bool ,
91
89
}
92
90
93
91
#[ derive( Clone ) ]
@@ -105,28 +103,11 @@ pub struct PendingPredicateObligation<'tcx> {
105
103
106
104
impl < ' tcx > FulfillmentContext < ' tcx > {
107
105
/// Creates a new fulfillment context.
108
- ///
109
- /// `errors_will_be_reported` indicates whether ALL errors that
110
- /// are generated by this fulfillment context will be reported to
111
- /// the end user. This is used to inform caching, because it
112
- /// allows us to conclude that traits that resolve successfully
113
- /// will in fact always resolve successfully (in particular, it
114
- /// guarantees that if some dependent obligation encounters a
115
- /// problem, compilation will be aborted). If you're not sure of
116
- /// the right value here, pass `false`, as that is the more
117
- /// conservative option.
118
- ///
119
- /// FIXME -- a better option would be to hold back on modifying
120
- /// the global cache until we know that all dependent obligations
121
- /// are also satisfied. In that case, we could actually remove
122
- /// this boolean flag, and we'd also avoid the problem of squelching
123
- /// duplicate errors that occur across fns.
124
- pub fn new ( errors_will_be_reported : bool ) -> FulfillmentContext < ' tcx > {
106
+ pub fn new ( ) -> FulfillmentContext < ' tcx > {
125
107
FulfillmentContext {
126
108
duplicate_set : FulfilledPredicates :: new ( ) ,
127
109
predicates : ObligationForest :: new ( ) ,
128
110
region_obligations : NodeMap ( ) ,
129
- errors_will_be_reported : errors_will_be_reported,
130
111
}
131
112
}
132
113
@@ -250,23 +231,27 @@ impl<'tcx> FulfillmentContext<'tcx> {
250
231
tcx : & ty:: ctxt < ' tcx > ,
251
232
predicate : & ty:: Predicate < ' tcx > )
252
233
-> bool {
253
- // This is a kind of dirty hack to allow us to avoid "rederiving"
254
- // things that we have already proven in other methods.
255
- //
256
- // The idea is that any predicate that doesn't involve type
257
- // parameters and which only involves the 'static region (and
258
- // no other regions) is universally solvable, since impls are global.
259
- //
260
- // This is particularly important since even if we have a
261
- // cache hit in the selection context, we still wind up
262
- // evaluating the 'nested obligations'. This cache lets us
263
- // skip those.
264
-
265
- if self . errors_will_be_reported && predicate. is_global ( ) {
266
- tcx. fulfilled_predicates . borrow_mut ( ) . is_duplicate_or_add ( predicate)
267
- } else {
268
- self . duplicate_set . is_duplicate_or_add ( predicate)
234
+ // For "global" predicates -- that is, predicates that don't
235
+ // involve type parameters, inference variables, or regions
236
+ // other than 'static -- we can check the cache in the tcx,
237
+ // which allows us to leverage work from other threads. Note
238
+ // that we don't add anything to this cache yet (unlike the
239
+ // local cache). This is because the tcx cache maintains the
240
+ // invariant that it only contains things that have been
241
+ // proven, and we have not yet proven that `predicate` holds.
242
+ if predicate. is_global ( ) && tcx. fulfilled_predicates . borrow ( ) . is_duplicate ( predicate) {
243
+ return true ;
269
244
}
245
+
246
+ // If `predicate` is not global, or not present in the tcx
247
+ // cache, we can still check for it in our local cache and add
248
+ // it if not present. Note that if we find this predicate in
249
+ // the local cache we can stop immediately, without reporting
250
+ // any errors, even though we don't know yet if it is
251
+ // true. This is because, while we don't yet know if the
252
+ // predicate holds, we know that this same fulfillment context
253
+ // already is in the process of finding out.
254
+ self . duplicate_set . is_duplicate_or_add ( predicate)
270
255
}
271
256
272
257
/// Attempts to select obligations using `selcx`. If `only_new_obligations` is true, then it
@@ -294,6 +279,12 @@ impl<'tcx> FulfillmentContext<'tcx> {
294
279
295
280
debug ! ( "select_where_possible: outcome={:?}" , outcome) ;
296
281
282
+ // these are obligations that were proven to be true.
283
+ for pending_obligation in outcome. successful {
284
+ let predicate = & pending_obligation. obligation . predicate ;
285
+ if predicate. is_global ( ) {
286
+ selcx. tcx ( ) . fulfilled_predicates . borrow_mut ( )
287
+ . is_duplicate_or_add ( predicate) ;
297
288
}
298
289
}
299
290
0 commit comments