@@ -627,7 +627,8 @@ fn ast_path_to_trait_ref<'a,'tcx>(
627627 }
628628 Some ( ref mut v) => {
629629 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) {
631632 Ok ( pp) => { v. push ( pp) ; }
632633 Err ( ErrorReported ) => { }
633634 }
@@ -640,10 +641,13 @@ fn ast_path_to_trait_ref<'a,'tcx>(
640641
641642fn ast_type_binding_to_projection_predicate < ' tcx > (
642643 this : & AstConv < ' tcx > ,
643- trait_ref : Rc < ty:: TraitRef < ' tcx > > ,
644+ mut trait_ref : Rc < ty:: TraitRef < ' tcx > > ,
645+ self_ty : Option < Ty < ' tcx > > ,
644646 binding : & ConvertedBinding < ' tcx > )
645647 -> Result < ty:: ProjectionPredicate < ' tcx > , ErrorReported >
646648{
649+ let tcx = this. tcx ( ) ;
650+
647651 // Given something like `U : SomeTrait<T=X>`, we want to produce a
648652 // predicate like `<U as SomeTrait>::T = X`. This is somewhat
649653 // subtle in the event that `T` is defined in a supertrait of
@@ -671,39 +675,67 @@ fn ast_type_binding_to_projection_predicate<'tcx>(
671675 } ) ;
672676 }
673677
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 ( ) )
677697 . filter ( |r| trait_defines_associated_type_named ( this, r. def_id ( ) , binding. item_name ) )
678698 . collect ( ) ;
679699
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+
680712 if candidates. len ( ) > 1 {
681- this . tcx ( ) . sess . span_err (
713+ tcx. sess . span_err (
682714 binding. span ,
683715 format ! ( "ambiguous associated type: `{}` defined in multiple supertraits `{}`" ,
684716 token:: get_name( binding. item_name) ,
685- candidates. user_string( this . tcx( ) ) ) . as_slice ( ) ) ;
717+ candidates. user_string( tcx) ) . as_slice ( ) ) ;
686718 return Err ( ErrorReported ) ;
687719 }
688720
689721 let candidate = match candidates. pop ( ) {
690722 Some ( c) => c,
691723 None => {
692- this . tcx ( ) . sess . span_err (
724+ tcx. sess . span_err (
693725 binding. span ,
694726 format ! ( "no associated type `{}` defined in `{}`" ,
695727 token:: get_name( binding. item_name) ,
696- trait_ref. user_string( this . tcx( ) ) ) . as_slice ( ) ) ;
728+ trait_ref. user_string( tcx) ) . as_slice ( ) ) ;
697729 return Err ( ErrorReported ) ;
698730 }
699731 } ;
700732
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 (
703735 binding. span ,
704736 format ! ( "associated type `{}` defined in higher-ranked supertrait `{}`" ,
705737 token:: get_name( binding. item_name) ,
706- candidate. user_string( this . tcx( ) ) ) . as_slice ( ) ) ;
738+ candidate. user_string( tcx) ) . as_slice ( ) ) ;
707739 return Err ( ErrorReported ) ;
708740 }
709741
0 commit comments