@@ -326,6 +326,9 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
326326 let mut user_computed_preds: FxHashSet < _ > =
327327 user_env. caller_bounds . iter ( ) . cloned ( ) . collect ( ) ;
328328
329+
330+
331+
329332 let mut new_env = param_env. clone ( ) ;
330333 let dummy_cause = ObligationCause :: misc ( DUMMY_SP , ast:: DUMMY_NODE_ID ) ;
331334
@@ -358,7 +361,8 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
358361 & Err ( SelectionError :: Unimplemented ) => {
359362 if self . is_of_param ( pred. skip_binder ( ) . trait_ref . substs ) {
360363 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()));
362366 predicates. push_back ( pred) ;
363367 } else {
364368 debug ! (
@@ -393,6 +397,62 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
393397 return Some ( ( new_env, final_user_env) ) ;
394398 }
395399
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+
396456 pub fn region_name ( & self , region : Region ) -> Option < String > {
397457 match region {
398458 & ty:: ReEarlyBound ( r) => Some ( r. name . to_string ( ) ) ,
@@ -555,15 +615,15 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
555615 let substs = & p. skip_binder ( ) . trait_ref . substs ;
556616
557617 if self . is_of_param ( substs) && !only_projections && is_new_pred {
558- computed_preds . insert ( predicate) ;
618+ self . add_user_pred ( computed_preds , predicate) ;
559619 }
560620 predicates. push_back ( p. clone ( ) ) ;
561621 }
562622 & ty:: Predicate :: Projection ( p) => {
563623 // If the projection isn't all type vars, then
564624 // we don't want to add it as a bound
565625 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) ;
567627 } else {
568628 match poly_project_and_unify_type ( select, & obligation. with ( p. clone ( ) ) ) {
569629 Err ( e) => {
0 commit comments