@@ -30,6 +30,7 @@ use rustc_errors::ErrorGuaranteed;
30
30
use rustc_hir as hir;
31
31
use rustc_hir:: def_id:: DefId ;
32
32
use rustc_hir:: lang_items:: LangItem ;
33
+ use rustc_infer:: traits:: TraitEngineExt as _;
33
34
use rustc_middle:: ty:: fold:: TypeFoldable ;
34
35
use rustc_middle:: ty:: subst:: { InternalSubsts , SubstsRef } ;
35
36
use rustc_middle:: ty:: visit:: TypeVisitable ;
@@ -161,22 +162,20 @@ pub fn type_known_to_meet_bound_modulo_regions<'a, 'tcx>(
161
162
// this function's result remains infallible, we must confirm
162
163
// that guess. While imperfect, I believe this is sound.
163
164
164
- // The handling of regions in this area of the code is terrible,
165
- // see issue #29149. We should be able to improve on this with
166
- // NLL.
167
- let mut fulfill_cx = <dyn TraitEngine < ' tcx > >:: new ( infcx. tcx ) ;
168
-
169
165
// We can use a dummy node-id here because we won't pay any mind
170
166
// to region obligations that arise (there shouldn't really be any
171
167
// anyhow).
172
168
let cause = ObligationCause :: misc ( span, hir:: CRATE_HIR_ID ) ;
173
169
174
- fulfill_cx. register_bound ( infcx, param_env, ty, def_id, cause) ;
170
+ // The handling of regions in this area of the code is terrible,
171
+ // see issue #29149. We should be able to improve on this with
172
+ // NLL.
173
+ let errors = fully_solve_bound ( infcx, cause, param_env, ty, def_id) ;
175
174
176
175
// Note: we only assume something is `Copy` if we can
177
176
// *definitively* show that it implements `Copy`. Otherwise,
178
177
// assume it is move; linear is always ok.
179
- match fulfill_cx . select_all_or_error ( infcx ) . as_slice ( ) {
178
+ match & errors [ .. ] {
180
179
[ ] => {
181
180
debug ! (
182
181
"type_known_to_meet_bound_modulo_regions: ty={:?} bound={} success" ,
@@ -222,15 +221,13 @@ fn do_normalize_predicates<'tcx>(
222
221
// them here too, and we will remove this function when
223
222
// we move over to lazy normalization *anyway*.
224
223
tcx. infer_ctxt ( ) . ignoring_regions ( ) . enter ( |infcx| {
225
- let fulfill_cx = FulfillmentContext :: new ( ) ;
226
- let predicates =
227
- match fully_normalize ( & infcx, fulfill_cx, cause, elaborated_env, predicates) {
228
- Ok ( predicates) => predicates,
229
- Err ( errors) => {
230
- let reported = infcx. report_fulfillment_errors ( & errors, None , false ) ;
231
- return Err ( reported) ;
232
- }
233
- } ;
224
+ let predicates = match fully_normalize ( & infcx, cause, elaborated_env, predicates) {
225
+ Ok ( predicates) => predicates,
226
+ Err ( errors) => {
227
+ let reported = infcx. report_fulfillment_errors ( & errors, None , false ) ;
228
+ return Err ( reported) ;
229
+ }
230
+ } ;
234
231
235
232
debug ! ( "do_normalize_predictes: normalized predicates = {:?}" , predicates) ;
236
233
@@ -381,9 +378,9 @@ pub fn normalize_param_env_or_error<'tcx>(
381
378
)
382
379
}
383
380
381
+ /// Normalize a type and process all resulting obligations, returning any errors
384
382
pub fn fully_normalize < ' a , ' tcx , T > (
385
383
infcx : & InferCtxt < ' a , ' tcx > ,
386
- mut fulfill_cx : FulfillmentContext < ' tcx > ,
387
384
cause : ObligationCause < ' tcx > ,
388
385
param_env : ty:: ParamEnv < ' tcx > ,
389
386
value : T ,
@@ -399,8 +396,10 @@ where
399
396
"fully_normalize: normalized_value={:?} obligations={:?}" ,
400
397
normalized_value, obligations
401
398
) ;
399
+
400
+ let mut fulfill_cx = FulfillmentContext :: new ( ) ;
402
401
for obligation in obligations {
403
- fulfill_cx. register_predicate_obligation ( selcx . infcx ( ) , obligation) ;
402
+ fulfill_cx. register_predicate_obligation ( infcx, obligation) ;
404
403
}
405
404
406
405
debug ! ( "fully_normalize: select_all_or_error start" ) ;
@@ -414,6 +413,43 @@ where
414
413
Ok ( resolved_value)
415
414
}
416
415
416
+ /// Process an obligation (and any nested obligations that come from it) to
417
+ /// completion, returning any errors
418
+ pub fn fully_solve_obligation < ' a , ' tcx > (
419
+ infcx : & InferCtxt < ' a , ' tcx > ,
420
+ obligation : PredicateObligation < ' tcx > ,
421
+ ) -> Vec < FulfillmentError < ' tcx > > {
422
+ let mut engine = <dyn TraitEngine < ' tcx > >:: new ( infcx. tcx ) ;
423
+ engine. register_predicate_obligation ( infcx, obligation) ;
424
+ engine. select_all_or_error ( infcx)
425
+ }
426
+
427
+ /// Process a set of obligations (and any nested obligations that come from them)
428
+ /// to completion
429
+ pub fn fully_solve_obligations < ' a , ' tcx > (
430
+ infcx : & InferCtxt < ' a , ' tcx > ,
431
+ obligations : impl IntoIterator < Item = PredicateObligation < ' tcx > > ,
432
+ ) -> Vec < FulfillmentError < ' tcx > > {
433
+ let mut engine = <dyn TraitEngine < ' tcx > >:: new ( infcx. tcx ) ;
434
+ engine. register_predicate_obligations ( infcx, obligations) ;
435
+ engine. select_all_or_error ( infcx)
436
+ }
437
+
438
+ /// Process a bound (and any nested obligations that come from it) to completion.
439
+ /// This is a convenience function for traits that have no generic arguments, such
440
+ /// as auto traits, and builtin traits like Copy or Sized.
441
+ pub fn fully_solve_bound < ' a , ' tcx > (
442
+ infcx : & InferCtxt < ' a , ' tcx > ,
443
+ cause : ObligationCause < ' tcx > ,
444
+ param_env : ty:: ParamEnv < ' tcx > ,
445
+ ty : Ty < ' tcx > ,
446
+ bound : DefId ,
447
+ ) -> Vec < FulfillmentError < ' tcx > > {
448
+ let mut engine = <dyn TraitEngine < ' tcx > >:: new ( infcx. tcx ) ;
449
+ engine. register_bound ( infcx, param_env, ty, bound, cause) ;
450
+ engine. select_all_or_error ( infcx)
451
+ }
452
+
417
453
/// Normalizes the predicates and checks whether they hold in an empty environment. If this
418
454
/// returns true, then either normalize encountered an error or one of the predicates did not
419
455
/// hold. Used when creating vtables to check for unsatisfiable methods.
@@ -428,20 +464,13 @@ pub fn impossible_predicates<'tcx>(
428
464
infcx. set_tainted_by_errors ( ) ;
429
465
430
466
let param_env = ty:: ParamEnv :: reveal_all ( ) ;
431
- let mut selcx = SelectionContext :: new ( & infcx) ;
432
- let mut fulfill_cx = FulfillmentContext :: new ( ) ;
433
- let cause = ObligationCause :: dummy ( ) ;
434
- let Normalized { value : predicates, obligations } =
435
- normalize ( & mut selcx, param_env, cause. clone ( ) , predicates) ;
436
- for obligation in obligations {
437
- fulfill_cx. register_predicate_obligation ( & infcx, obligation) ;
438
- }
467
+ let ocx = ObligationCtxt :: new ( & infcx) ;
468
+ let predicates = ocx. normalize ( ObligationCause :: dummy ( ) , param_env, predicates) ;
439
469
for predicate in predicates {
440
- let obligation = Obligation :: new ( cause . clone ( ) , param_env, predicate) ;
441
- fulfill_cx . register_predicate_obligation ( & infcx , obligation) ;
470
+ let obligation = Obligation :: new ( ObligationCause :: dummy ( ) , param_env, predicate) ;
471
+ ocx . register_obligation ( obligation) ;
442
472
}
443
-
444
- let errors = fulfill_cx. select_all_or_error ( & infcx) ;
473
+ let errors = ocx. select_all_or_error ( ) ;
445
474
446
475
// Clean up after ourselves
447
476
let _ = infcx. inner . borrow_mut ( ) . opaque_type_storage . take_opaque_types ( ) ;
0 commit comments