@@ -326,6 +326,9 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
326
326
let mut user_computed_preds: FxHashSet < _ > =
327
327
user_env. caller_bounds . iter ( ) . cloned ( ) . collect ( ) ;
328
328
329
+
330
+
331
+
329
332
let mut new_env = param_env. clone ( ) ;
330
333
let dummy_cause = ObligationCause :: misc ( DUMMY_SP , ast:: DUMMY_NODE_ID ) ;
331
334
@@ -358,7 +361,8 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
358
361
& Err ( SelectionError :: Unimplemented ) => {
359
362
if self . is_of_param ( pred. skip_binder ( ) . trait_ref . substs ) {
360
363
already_visited. remove ( & pred) ;
361
- user_computed_preds. insert ( ty:: Predicate :: Trait ( pred. clone ( ) ) ) ;
364
+ self . add_user_pred ( & mut user_computed_preds, ty:: Predicate :: Trait ( pred. clone ( ) ) ) ;
365
+ //user_computed_preds.insert(ty::Predicate::Trait(pred.clone()));
362
366
predicates. push_back ( pred) ;
363
367
} else {
364
368
debug ! (
@@ -393,6 +397,62 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
393
397
return Some ( ( new_env, final_user_env) ) ;
394
398
}
395
399
400
+ fn add_user_pred < ' c > ( & self , user_computed_preds : & mut FxHashSet < ty:: Predicate < ' c > > , new_pred : ty:: Predicate < ' c > ) {
401
+ let mut should_add_new = true ;
402
+ user_computed_preds. retain ( |& old_pred| {
403
+ match ( & new_pred, old_pred) {
404
+ ( & ty:: Predicate :: Trait ( new_trait) , ty:: Predicate :: Trait ( old_trait) ) => {
405
+ if new_trait. def_id ( ) == old_trait. def_id ( ) {
406
+ let new_substs = new_trait. skip_binder ( ) . trait_ref . substs ;
407
+ let old_substs = old_trait. skip_binder ( ) . trait_ref . substs ;
408
+ if !new_substs. types ( ) . eq ( old_substs. types ( ) ) {
409
+ // We can't compare lifetimes if the types are different,
410
+ // so skip checking old_pred
411
+ return true
412
+ }
413
+
414
+ for ( new_region, old_region) in new_substs. regions ( ) . zip ( old_substs. regions ( ) ) {
415
+ match ( new_region, old_region) {
416
+ // If both predicates have an 'ReLateBound' (a HRTB) in the
417
+ // same spot, we do nothing
418
+ ( ty:: RegionKind :: ReLateBound ( _, _) , ty:: RegionKind :: ReLateBound ( _, _) ) => { } ,
419
+
420
+ ( ty:: RegionKind :: ReLateBound ( _, _) , _) => {
421
+ // The new predicate has a HRTB in a spot where the old
422
+ // predicate does not (if they both had a HRTB, the previous
423
+ // match arm would have executed).
424
+ //
425
+ // The means we want to remove the older predicate from
426
+ // user_computed_preds, since having both it and the new
427
+ // predicate in a ParamEnv would confuse SelectionContext
428
+ // We're currently in the predicate passed to 'retain',
429
+ // so we return 'false' to remove the old predicate from
430
+ // user_computed_preds
431
+ return false ;
432
+ } ,
433
+ ( _, ty:: RegionKind :: ReLateBound ( _, _) ) => {
434
+ // This is the opposite situation as the previous arm - the
435
+ // old predicate has a HRTB lifetime in a place where the
436
+ // new predicate does not. We want to leave the old
437
+ // predicate in user_computed_preds, and skip adding
438
+ // new_pred to user_computed_params.
439
+ should_add_new = false
440
+ }
441
+ _ => { }
442
+ }
443
+ }
444
+ }
445
+ } ,
446
+ _ => { }
447
+ }
448
+ return true
449
+ } ) ;
450
+
451
+ if should_add_new {
452
+ user_computed_preds. insert ( new_pred) ;
453
+ }
454
+ }
455
+
396
456
pub fn region_name ( & self , region : Region ) -> Option < String > {
397
457
match region {
398
458
& ty:: ReEarlyBound ( r) => Some ( r. name . to_string ( ) ) ,
@@ -555,15 +615,15 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
555
615
let substs = & p. skip_binder ( ) . trait_ref . substs ;
556
616
557
617
if self . is_of_param ( substs) && !only_projections && is_new_pred {
558
- computed_preds . insert ( predicate) ;
618
+ self . add_user_pred ( computed_preds , predicate) ;
559
619
}
560
620
predicates. push_back ( p. clone ( ) ) ;
561
621
}
562
622
& ty:: Predicate :: Projection ( p) => {
563
623
// If the projection isn't all type vars, then
564
624
// we don't want to add it as a bound
565
625
if self . is_of_param ( p. skip_binder ( ) . projection_ty . substs ) && is_new_pred {
566
- computed_preds . insert ( predicate) ;
626
+ self . add_user_pred ( computed_preds , predicate) ;
567
627
} else {
568
628
match poly_project_and_unify_type ( select, & obligation. with ( p. clone ( ) ) ) {
569
629
Err ( e) => {
0 commit comments