@@ -42,8 +42,17 @@ pub struct PathSeg(pub DefId, pub usize);
4242pub trait AstConv < ' tcx > {
4343 fn tcx < ' a > ( & ' a self ) -> TyCtxt < ' tcx > ;
4444
45- /// Returns the set of bounds in scope for the type parameter with
46- /// the given id.
45+ /// Returns predicates in scope of the form `X: Foo`, where `X` is
46+ /// a type parameter `X` with the given id `def_id`. This is a
47+ /// subset of the full set of predicates.
48+ ///
49+ /// This is used for one specific purpose: resolving "short-hand"
50+ /// associated type references like `T::Item`. In principle, we
51+ /// would do that by first getting the full set of predicates in
52+ /// scope and then filtering down to find those that apply to `T`,
53+ /// but this can lead to cycle errors. The problem is that we have
54+ /// to do this resolution *in order to create the predicates in
55+ /// the first place*. Hence, we have this "special pass".
4756 fn get_type_parameter_bounds ( & self , span : Span , def_id : DefId )
4857 -> & ' tcx ty:: GenericPredicates < ' tcx > ;
4958
@@ -775,11 +784,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
775784 /// The given trait-ref must actually be a trait.
776785 pub ( super ) fn instantiate_poly_trait_ref_inner ( & self ,
777786 trait_ref : & hir:: TraitRef ,
787+ span : Span ,
778788 self_ty : Ty < ' tcx > ,
779789 bounds : & mut Bounds < ' tcx > ,
780790 speculative : bool ,
781- ) -> ( ty:: PolyTraitRef < ' tcx > , Option < Vec < Span > > )
782- {
791+ ) -> Option < Vec < Span > > {
783792 let trait_def_id = trait_ref. trait_def_id ( ) ;
784793
785794 debug ! ( "instantiate_poly_trait_ref({:?}, def_id={:?})" , trait_ref, trait_def_id) ;
@@ -794,6 +803,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
794803 ) ;
795804 let poly_trait_ref = ty:: Binder :: bind ( ty:: TraitRef :: new ( trait_def_id, substs) ) ;
796805
806+ bounds. trait_bounds . push ( ( poly_trait_ref, span) ) ;
807+
797808 let mut dup_bindings = FxHashMap :: default ( ) ;
798809 for binding in & assoc_bindings {
799810 // Specify type to assert that error was already reported in `Err` case.
@@ -804,14 +815,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
804815 binding,
805816 bounds,
806817 speculative,
807- & mut dup_bindings
818+ & mut dup_bindings,
808819 ) ;
809820 // Okay to ignore `Err` because of `ErrorReported` (see above).
810821 }
811822
812823 debug ! ( "instantiate_poly_trait_ref({:?}, bounds={:?}) -> {:?}" ,
813824 trait_ref, bounds, poly_trait_ref) ;
814- ( poly_trait_ref , potential_assoc_types)
825+ potential_assoc_types
815826 }
816827
817828 /// Given a trait bound like `Debug`, applies that trait bound the given self-type to construct
@@ -836,10 +847,15 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
836847 pub fn instantiate_poly_trait_ref ( & self ,
837848 poly_trait_ref : & hir:: PolyTraitRef ,
838849 self_ty : Ty < ' tcx > ,
839- bounds : & mut Bounds < ' tcx >
840- ) -> ( ty:: PolyTraitRef < ' tcx > , Option < Vec < Span > > )
841- {
842- self . instantiate_poly_trait_ref_inner ( & poly_trait_ref. trait_ref , self_ty, bounds, false )
850+ bounds : & mut Bounds < ' tcx > ,
851+ ) -> Option < Vec < Span > > {
852+ self . instantiate_poly_trait_ref_inner (
853+ & poly_trait_ref. trait_ref ,
854+ poly_trait_ref. span ,
855+ self_ty,
856+ bounds,
857+ false ,
858+ )
843859 }
844860
845861 fn ast_path_to_mono_trait_ref ( & self ,
@@ -983,12 +999,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
983999 }
9841000
9851001 for bound in trait_bounds {
986- let ( poly_trait_ref , _ ) = self . instantiate_poly_trait_ref (
1002+ let _ = self . instantiate_poly_trait_ref (
9871003 bound,
9881004 param_ty,
9891005 bounds,
9901006 ) ;
991- bounds. trait_bounds . push ( ( poly_trait_ref, bound. span ) )
9921007 }
9931008
9941009 bounds. region_bounds . extend ( region_bounds
@@ -1172,11 +1187,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
11721187 // Calling `skip_binder` is okay, because `add_bounds` expects the `param_ty`
11731188 // parameter to have a skipped binder.
11741189 let param_ty = tcx. mk_projection ( assoc_ty. def_id , candidate. skip_binder ( ) . substs ) ;
1175- self . add_bounds (
1176- param_ty,
1177- ast_bounds,
1178- bounds,
1179- ) ;
1190+ self . add_bounds ( param_ty, ast_bounds, bounds) ;
11801191 }
11811192 }
11821193 Ok ( ( ) )
@@ -1216,25 +1227,19 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
12161227 let mut bounds = Bounds :: default ( ) ;
12171228 let mut potential_assoc_types = Vec :: new ( ) ;
12181229 let dummy_self = self . tcx ( ) . types . trait_object_dummy_self ;
1219- // FIXME: we want to avoid collecting into a `Vec` here, but simply cloning the iterator is
1220- // not straightforward due to the borrow checker.
1221- let bound_trait_refs: Vec < _ > = trait_bounds
1222- . iter ( )
1223- . rev ( )
1224- . map ( |trait_bound| {
1225- let ( trait_ref, cur_potential_assoc_types) = self . instantiate_poly_trait_ref (
1226- trait_bound,
1227- dummy_self,
1228- & mut bounds,
1229- ) ;
1230- potential_assoc_types. extend ( cur_potential_assoc_types. into_iter ( ) . flatten ( ) ) ;
1231- ( trait_ref, trait_bound. span )
1232- } )
1233- . collect ( ) ;
1230+ for trait_bound in trait_bounds. iter ( ) . rev ( ) {
1231+ let cur_potential_assoc_types = self . instantiate_poly_trait_ref (
1232+ trait_bound,
1233+ dummy_self,
1234+ & mut bounds,
1235+ ) ;
1236+ potential_assoc_types. extend ( cur_potential_assoc_types. into_iter ( ) . flatten ( ) ) ;
1237+ }
12341238
12351239 // Expand trait aliases recursively and check that only one regular (non-auto) trait
12361240 // is used and no 'maybe' bounds are used.
1237- let expanded_traits = traits:: expand_trait_aliases ( tcx, bound_trait_refs. iter ( ) . cloned ( ) ) ;
1241+ let expanded_traits =
1242+ traits:: expand_trait_aliases ( tcx, bounds. trait_bounds . iter ( ) . cloned ( ) ) ;
12381243 let ( mut auto_traits, regular_traits) : ( Vec < _ > , Vec < _ > ) =
12391244 expanded_traits. partition ( |i| tcx. trait_is_auto ( i. trait_ref ( ) . def_id ( ) ) ) ;
12401245 if regular_traits. len ( ) > 1 {
@@ -1276,7 +1281,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
12761281 // Use a `BTreeSet` to keep output in a more consistent order.
12771282 let mut associated_types = BTreeSet :: default ( ) ;
12781283
1279- let regular_traits_refs = bound_trait_refs
1284+ let regular_traits_refs = bounds . trait_bounds
12801285 . into_iter ( )
12811286 . filter ( |( trait_ref, _) | !tcx. trait_is_auto ( trait_ref. def_id ( ) ) )
12821287 . map ( |( trait_ref, _) | trait_ref) ;
@@ -1491,7 +1496,17 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
14911496 {
14921497 let tcx = self . tcx ( ) ;
14931498
1499+ debug ! (
1500+ "find_bound_for_assoc_item(ty_param_def_id={:?}, assoc_name={:?}, span={:?})" ,
1501+ ty_param_def_id,
1502+ assoc_name,
1503+ span,
1504+ ) ;
1505+
14941506 let predicates = & self . get_type_parameter_bounds ( span, ty_param_def_id) . predicates ;
1507+
1508+ debug ! ( "find_bound_for_assoc_item: predicates={:#?}" , predicates) ;
1509+
14951510 let bounds = predicates. iter ( ) . filter_map ( |( p, _) | p. to_opt_poly_trait_ref ( ) ) ;
14961511
14971512 // Check that there is exactly one way to find an associated type with the
@@ -1515,7 +1530,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
15151530 assoc_name : ast:: Ident ,
15161531 span : Span )
15171532 -> Result < ty:: PolyTraitRef < ' tcx > , ErrorReported >
1518- where I : Iterator < Item = ty:: PolyTraitRef < ' tcx > >
1533+ where I : Iterator < Item = ty:: PolyTraitRef < ' tcx > >
15191534 {
15201535 let bound = match bounds. next ( ) {
15211536 Some ( bound) => bound,
@@ -1524,13 +1539,17 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
15241539 "associated type `{}` not found for `{}`" ,
15251540 assoc_name,
15261541 ty_param_name)
1527- . span_label ( span, format ! ( "associated type `{}` not found" , assoc_name) )
1528- . emit ( ) ;
1542+ . span_label ( span, format ! ( "associated type `{}` not found" , assoc_name) )
1543+ . emit ( ) ;
15291544 return Err ( ErrorReported ) ;
15301545 }
15311546 } ;
15321547
1548+ debug ! ( "one_bound_for_assoc_type: bound = {:?}" , bound) ;
1549+
15331550 if let Some ( bound2) = bounds. next ( ) {
1551+ debug ! ( "one_bound_for_assoc_type: bound2 = {:?}" , bound2) ;
1552+
15341553 let bounds = iter:: once ( bound) . chain ( iter:: once ( bound2) ) . chain ( bounds) ;
15351554 let mut err = struct_span_err ! (
15361555 self . tcx( ) . sess, span, E0221 ,
@@ -1544,7 +1563,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
15441563 item. kind == ty:: AssocKind :: Type &&
15451564 self . tcx ( ) . hygienic_eq ( assoc_name, item. ident , bound. def_id ( ) )
15461565 } )
1547- . and_then ( |item| self . tcx ( ) . hir ( ) . span_if_local ( item. def_id ) ) ;
1566+ . and_then ( |item| self . tcx ( ) . hir ( ) . span_if_local ( item. def_id ) ) ;
15481567
15491568 if let Some ( span) = bound_span {
15501569 err. span_label ( span, format ! ( "ambiguous `{}` from `{}`" ,
0 commit comments