@@ -627,7 +627,8 @@ fn ast_path_to_trait_ref<'a,'tcx>(
627
627
}
628
628
Some ( ref mut v) => {
629
629
for binding in assoc_bindings. iter ( ) {
630
- match ast_type_binding_to_projection_predicate ( this, trait_ref. clone ( ) , binding) {
630
+ match ast_type_binding_to_projection_predicate ( this, trait_ref. clone ( ) ,
631
+ self_ty, binding) {
631
632
Ok ( pp) => { v. push ( pp) ; }
632
633
Err ( ErrorReported ) => { }
633
634
}
@@ -640,10 +641,13 @@ fn ast_path_to_trait_ref<'a,'tcx>(
640
641
641
642
fn ast_type_binding_to_projection_predicate < ' tcx > (
642
643
this : & AstConv < ' tcx > ,
643
- trait_ref : Rc < ty:: TraitRef < ' tcx > > ,
644
+ mut trait_ref : Rc < ty:: TraitRef < ' tcx > > ,
645
+ self_ty : Option < Ty < ' tcx > > ,
644
646
binding : & ConvertedBinding < ' tcx > )
645
647
-> Result < ty:: ProjectionPredicate < ' tcx > , ErrorReported >
646
648
{
649
+ let tcx = this. tcx ( ) ;
650
+
647
651
// Given something like `U : SomeTrait<T=X>`, we want to produce a
648
652
// predicate like `<U as SomeTrait>::T = X`. This is somewhat
649
653
// subtle in the event that `T` is defined in a supertrait of
@@ -671,39 +675,67 @@ fn ast_type_binding_to_projection_predicate<'tcx>(
671
675
} ) ;
672
676
}
673
677
674
- // Otherwise, we have to walk through the supertraits to find those that do.
675
- let mut candidates: Vec < _ > =
676
- traits:: supertraits ( this. tcx ( ) , trait_ref. to_poly_trait_ref ( ) )
678
+ // Otherwise, we have to walk through the supertraits to find
679
+ // those that do. This is complicated by the fact that, for an
680
+ // object type, the `Self` type is not present in the
681
+ // substitutions (after all, it's being constructed right now),
682
+ // but the `supertraits` iterator really wants one. To handle
683
+ // this, we currently insert a dummy type and then remove it
684
+ // later. Yuck.
685
+
686
+ let dummy_self_ty = ty:: mk_infer ( tcx, ty:: FreshTy ( 0 ) ) ;
687
+ if self_ty. is_none ( ) { // if converting for an object type
688
+ let mut dummy_substs = trait_ref. substs . clone ( ) ;
689
+ assert ! ( dummy_substs. self_ty( ) . is_none( ) ) ;
690
+ dummy_substs. types . push ( SelfSpace , dummy_self_ty) ;
691
+ trait_ref = Rc :: new ( ty:: TraitRef :: new ( trait_ref. def_id ,
692
+ tcx. mk_substs ( dummy_substs) ) ) ;
693
+ }
694
+
695
+ let mut candidates: Vec < ty:: PolyTraitRef > =
696
+ traits:: supertraits ( tcx, trait_ref. to_poly_trait_ref ( ) )
677
697
. filter ( |r| trait_defines_associated_type_named ( this, r. def_id ( ) , binding. item_name ) )
678
698
. collect ( ) ;
679
699
700
+ // If converting for an object type, then remove the dummy-ty from `Self` now.
701
+ // Yuckety yuck.
702
+ if self_ty. is_none ( ) {
703
+ for candidate in candidates. iter_mut ( ) {
704
+ let mut dummy_substs = candidate. 0 . substs . clone ( ) ;
705
+ assert ! ( dummy_substs. self_ty( ) == Some ( dummy_self_ty) ) ;
706
+ dummy_substs. types . pop ( SelfSpace ) ;
707
+ * candidate = ty:: Binder ( Rc :: new ( ty:: TraitRef :: new ( candidate. def_id ( ) ,
708
+ tcx. mk_substs ( dummy_substs) ) ) ) ;
709
+ }
710
+ }
711
+
680
712
if candidates. len ( ) > 1 {
681
- this . tcx ( ) . sess . span_err (
713
+ tcx. sess . span_err (
682
714
binding. span ,
683
715
format ! ( "ambiguous associated type: `{}` defined in multiple supertraits `{}`" ,
684
716
token:: get_name( binding. item_name) ,
685
- candidates. user_string( this . tcx( ) ) ) . as_slice ( ) ) ;
717
+ candidates. user_string( tcx) ) . as_slice ( ) ) ;
686
718
return Err ( ErrorReported ) ;
687
719
}
688
720
689
721
let candidate = match candidates. pop ( ) {
690
722
Some ( c) => c,
691
723
None => {
692
- this . tcx ( ) . sess . span_err (
724
+ tcx. sess . span_err (
693
725
binding. span ,
694
726
format ! ( "no associated type `{}` defined in `{}`" ,
695
727
token:: get_name( binding. item_name) ,
696
- trait_ref. user_string( this . tcx( ) ) ) . as_slice ( ) ) ;
728
+ trait_ref. user_string( tcx) ) . as_slice ( ) ) ;
697
729
return Err ( ErrorReported ) ;
698
730
}
699
731
} ;
700
732
701
- if ty:: binds_late_bound_regions ( this . tcx ( ) , & candidate) {
702
- this . tcx ( ) . sess . span_err (
733
+ if ty:: binds_late_bound_regions ( tcx, & candidate) {
734
+ tcx. sess . span_err (
703
735
binding. span ,
704
736
format ! ( "associated type `{}` defined in higher-ranked supertrait `{}`" ,
705
737
token:: get_name( binding. item_name) ,
706
- candidate. user_string( this . tcx( ) ) ) . as_slice ( ) ) ;
738
+ candidate. user_string( tcx) ) . as_slice ( ) ) ;
707
739
return Err ( ErrorReported ) ;
708
740
}
709
741
0 commit comments