@@ -53,7 +53,8 @@ use middle::def;
53
53
use middle:: resolve_lifetime as rl;
54
54
use middle:: subst:: { FnSpace , TypeSpace , SelfSpace , Subst , Substs } ;
55
55
use middle:: subst:: { VecPerParamSpace } ;
56
- use middle:: ty:: { self , RegionEscape , Ty } ;
56
+ use middle:: traits;
57
+ use middle:: ty:: { self , RegionEscape , ToPolyTraitRef , Ty } ;
57
58
use rscope:: { self , UnelidableRscope , RegionScope , SpecificRscope ,
58
59
ShiftedRscope , BindingRscope } ;
59
60
use TypeAndSubsts ;
@@ -637,7 +638,7 @@ fn ast_path_to_trait_ref<'a,'tcx>(
637
638
trait_ref
638
639
}
639
640
640
- pub fn ast_type_binding_to_projection_predicate < ' tcx > (
641
+ fn ast_type_binding_to_projection_predicate < ' tcx > (
641
642
this : & AstConv < ' tcx > ,
642
643
trait_ref : Rc < ty:: TraitRef < ' tcx > > ,
643
644
binding : & ConvertedBinding < ' tcx > )
@@ -659,20 +660,56 @@ pub fn ast_type_binding_to_projection_predicate<'tcx>(
659
660
//
660
661
// We want to produce `<B as SuperTrait<int>>::T == foo`.
661
662
662
- // FIXME(#19541): supertrait upcasting not actually impl'd :)
663
+ // Simple case: X is defined in the current trait.
664
+ if trait_defines_associated_type_named ( this, trait_ref. def_id , binding. item_name ) {
665
+ return Ok ( ty:: ProjectionPredicate {
666
+ projection_ty : ty:: ProjectionTy {
667
+ trait_ref : trait_ref,
668
+ item_name : binding. item_name ,
669
+ } ,
670
+ ty : binding. ty ,
671
+ } ) ;
672
+ }
673
+
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 ( ) )
677
+ . filter ( |r| trait_defines_associated_type_named ( this, r. def_id ( ) , binding. item_name ) )
678
+ . collect ( ) ;
679
+
680
+ if candidates. len ( ) > 1 {
681
+ this. tcx ( ) . sess . span_err (
682
+ binding. span ,
683
+ format ! ( "ambiguous associated type: `{}` defined in multiple supertraits `{}`" ,
684
+ token:: get_name( binding. item_name) ,
685
+ candidates. user_string( this. tcx( ) ) ) . as_slice ( ) ) ;
686
+ return Err ( ErrorReported ) ;
687
+ }
688
+
689
+ let candidate = match candidates. pop ( ) {
690
+ Some ( c) => c,
691
+ None => {
692
+ this. tcx ( ) . sess . span_err (
693
+ binding. span ,
694
+ format ! ( "no associated type `{}` defined in `{}`" ,
695
+ token:: get_name( binding. item_name) ,
696
+ trait_ref. user_string( this. tcx( ) ) ) . as_slice ( ) ) ;
697
+ return Err ( ErrorReported ) ;
698
+ }
699
+ } ;
663
700
664
- if ! trait_defines_associated_type_named ( this, trait_ref . def_id , binding . item_name ) {
701
+ if ty :: binds_late_bound_regions ( this. tcx ( ) , & candidate ) {
665
702
this. tcx ( ) . sess . span_err (
666
703
binding. span ,
667
- format ! ( "no associated type `{}` defined in `{}`" ,
704
+ format ! ( "associated type `{}` defined in higher-ranked supertrait `{}`" ,
668
705
token:: get_name( binding. item_name) ,
669
- trait_ref . user_string( this. tcx( ) ) ) . as_slice ( ) ) ;
706
+ candidate . user_string( this. tcx( ) ) ) . as_slice ( ) ) ;
670
707
return Err ( ErrorReported ) ;
671
708
}
672
709
673
710
Ok ( ty:: ProjectionPredicate {
674
711
projection_ty : ty:: ProjectionTy {
675
- trait_ref : trait_ref ,
712
+ trait_ref : candidate . 0 ,
676
713
item_name : binding. item_name ,
677
714
} ,
678
715
ty : binding. ty ,
@@ -899,20 +936,17 @@ fn associated_path_def_to_ty<'tcx>(this: &AstConv<'tcx>,
899
936
{
900
937
let tcx = this. tcx ( ) ;
901
938
let ty_param_def_id = provenance. def_id ( ) ;
939
+
902
940
let mut suitable_bounds: Vec < _ > ;
903
941
let ty_param_name: ast:: Name ;
904
942
{ // contain scope of refcell:
905
943
let ty_param_defs = tcx. ty_param_defs . borrow ( ) ;
906
944
let ty_param_def = & ty_param_defs[ ty_param_def_id. node ] ;
907
945
ty_param_name = ty_param_def. name ;
908
946
909
- // FIXME(#19541): we should consider associated types in
910
- // super-traits. Probably by elaborating the bounds.
911
-
947
+ // FIXME(#20300) -- search where clauses, not bounds
912
948
suitable_bounds =
913
- ty_param_def. bounds . trait_bounds // FIXME(#20300) -- search where clauses, not bounds
914
- . iter ( )
915
- . cloned ( )
949
+ traits:: transitive_bounds ( tcx, ty_param_def. bounds . trait_bounds . as_slice ( ) )
916
950
. filter ( |b| trait_defines_associated_type_named ( this, b. def_id ( ) , assoc_name) )
917
951
. collect ( ) ;
918
952
}
0 commit comments