@@ -334,7 +334,12 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
334
334
continue ;
335
335
}
336
336
337
- let result = select. select ( & Obligation :: new ( dummy_cause. clone ( ) , new_env, pred) ) ;
337
+ // Call infcx.resolve_type_vars_if_possible to see if we can
338
+ // get rid of any inference variables.
339
+ let obligation = infcx. resolve_type_vars_if_possible (
340
+ & Obligation :: new ( dummy_cause. clone ( ) , new_env, pred)
341
+ ) ;
342
+ let result = select. select ( & obligation) ;
338
343
339
344
match & result {
340
345
& Ok ( Some ( ref vtable) ) => {
@@ -369,7 +374,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
369
374
}
370
375
& Ok ( None ) => { }
371
376
& Err ( SelectionError :: Unimplemented ) => {
372
- if self . is_of_param ( pred. skip_binder ( ) . trait_ref . substs ) {
377
+ if self . is_param_no_infer ( pred. skip_binder ( ) . trait_ref . substs ) {
373
378
already_visited. remove ( & pred) ;
374
379
self . add_user_pred (
375
380
& mut user_computed_preds,
@@ -631,18 +636,28 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
631
636
finished_map
632
637
}
633
638
634
- pub fn is_of_param ( & self , substs : & Substs < ' _ > ) -> bool {
635
- if substs. is_noop ( ) {
636
- return false ;
637
- }
639
+ fn is_param_no_infer ( & self , substs : & Substs < ' _ > ) -> bool {
640
+ return self . is_of_param ( substs. type_at ( 0 ) ) &&
641
+ !substs . types ( ) . any ( |t| t . has_infer_types ( ) ) ;
642
+ }
638
643
639
- return match substs. type_at ( 0 ) . sty {
644
+ pub fn is_of_param ( & self , ty : Ty < ' _ > ) -> bool {
645
+ return match ty. sty {
640
646
ty:: Param ( _) => true ,
641
- ty:: Projection ( p) => self . is_of_param ( p. substs ) ,
647
+ ty:: Projection ( p) => self . is_of_param ( p. self_ty ( ) ) ,
642
648
_ => false ,
643
649
} ;
644
650
}
645
651
652
+ fn is_self_referential_projection ( & self , p : ty:: PolyProjectionPredicate < ' _ > ) -> bool {
653
+ match p. ty ( ) . skip_binder ( ) . sty {
654
+ ty:: Projection ( proj) if proj == p. skip_binder ( ) . projection_ty => {
655
+ true
656
+ } ,
657
+ _ => false
658
+ }
659
+ }
660
+
646
661
pub fn evaluate_nested_obligations <
647
662
' b ,
648
663
' c ,
@@ -661,28 +676,77 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
661
676
) -> bool {
662
677
let dummy_cause = ObligationCause :: misc ( DUMMY_SP , ast:: DUMMY_NODE_ID ) ;
663
678
664
- for ( obligation, predicate) in nested
665
- . filter ( |o| o. recursion_depth == 1 )
679
+ for ( obligation, mut predicate) in nested
666
680
. map ( |o| ( o. clone ( ) , o. predicate . clone ( ) ) )
667
681
{
668
682
let is_new_pred =
669
683
fresh_preds. insert ( self . clean_pred ( select. infcx ( ) , predicate. clone ( ) ) ) ;
670
684
685
+ // Resolve any inference variables that we can, to help selection succeed
686
+ predicate = select. infcx ( ) . resolve_type_vars_if_possible ( & predicate) ;
687
+
688
+ // We only add a predicate as a user-displayable bound if
689
+ // it involves a generic parameter, and doesn't contain
690
+ // any inference variables.
691
+ //
692
+ // Displaying a bound involving a concrete type (instead of a generic
693
+ // parameter) would be pointless, since it's always true
694
+ // (e.g. u8: Copy)
695
+ // Displaying an inference variable is impossible, since they're
696
+ // an internal compiler detail without a defined visual representation
697
+ //
698
+ // We check this by calling is_of_param on the relevant types
699
+ // from the various possible predicates
671
700
match & predicate {
672
701
& ty:: Predicate :: Trait ( ref p) => {
673
- let substs = & p. skip_binder ( ) . trait_ref . substs ;
702
+ if self . is_param_no_infer ( p. skip_binder ( ) . trait_ref . substs )
703
+ && !only_projections
704
+ && is_new_pred {
674
705
675
- if self . is_of_param ( substs) && !only_projections && is_new_pred {
676
706
self . add_user_pred ( computed_preds, predicate) ;
677
707
}
678
708
predicates. push_back ( p. clone ( ) ) ;
679
709
}
680
710
& ty:: Predicate :: Projection ( p) => {
681
- // If the projection isn't all type vars, then
682
- // we don't want to add it as a bound
683
- if self . is_of_param ( p. skip_binder ( ) . projection_ty . substs ) && is_new_pred {
684
- self . add_user_pred ( computed_preds, predicate) ;
685
- } else {
711
+ debug ! ( "evaluate_nested_obligations: examining projection predicate {:?}" ,
712
+ predicate) ;
713
+
714
+ // As described above, we only want to display
715
+ // bounds which include a generic parameter but don't include
716
+ // an inference variable.
717
+ // Additionally, we check if we've seen this predicate before,
718
+ // to avoid rendering duplicate bounds to the user.
719
+ if self . is_param_no_infer ( p. skip_binder ( ) . projection_ty . substs )
720
+ && !p. ty ( ) . skip_binder ( ) . is_ty_infer ( )
721
+ && is_new_pred {
722
+ debug ! ( "evaluate_nested_obligations: adding projection predicate\
723
+ to computed_preds: {:?}", predicate) ;
724
+
725
+ // Under unusual circumstances, we can end up with a self-refeential
726
+ // projection predicate. For example:
727
+ // <T as MyType>::Value == <T as MyType>::Value
728
+ // Not only is displaying this to the user pointless,
729
+ // having it in the ParamEnv will cause an issue if we try to call
730
+ // poly_project_and_unify_type on the predicate, since this kind of
731
+ // predicate will normally never end up in a ParamEnv.
732
+ //
733
+ // For these reasons, we ignore these weird predicates,
734
+ // ensuring that we're able to properly synthesize an auto trait impl
735
+ if self . is_self_referential_projection ( p) {
736
+ debug ! ( "evaluate_nested_obligations: encountered a projection
737
+ predicate equating a type with itself! Skipping" ) ;
738
+
739
+ } else {
740
+ self . add_user_pred ( computed_preds, predicate) ;
741
+ }
742
+ }
743
+
744
+ // We can only call poly_project_and_unify_type when our predicate's
745
+ // Ty contains an inference variable - otherwise, there won't be anything to
746
+ // unify
747
+ if p. ty ( ) . skip_binder ( ) . has_infer_types ( ) {
748
+ debug ! ( "Projecting and unifying projection predicate {:?}" ,
749
+ predicate) ;
686
750
match poly_project_and_unify_type ( select, & obligation. with ( p. clone ( ) ) ) {
687
751
Err ( e) => {
688
752
debug ! (
0 commit comments