@@ -42,8 +42,17 @@ pub struct PathSeg(pub DefId, pub usize);
42
42
pub trait AstConv < ' tcx > {
43
43
fn tcx < ' a > ( & ' a self ) -> TyCtxt < ' tcx > ;
44
44
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".
47
56
fn get_type_parameter_bounds ( & self , span : Span , def_id : DefId )
48
57
-> & ' tcx ty:: GenericPredicates < ' tcx > ;
49
58
@@ -775,11 +784,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
775
784
/// The given trait-ref must actually be a trait.
776
785
pub ( super ) fn instantiate_poly_trait_ref_inner ( & self ,
777
786
trait_ref : & hir:: TraitRef ,
787
+ span : Span ,
778
788
self_ty : Ty < ' tcx > ,
779
789
bounds : & mut Bounds < ' tcx > ,
780
790
speculative : bool ,
781
- ) -> ( ty:: PolyTraitRef < ' tcx > , Option < Vec < Span > > )
782
- {
791
+ ) -> Option < Vec < Span > > {
783
792
let trait_def_id = trait_ref. trait_def_id ( ) ;
784
793
785
794
debug ! ( "instantiate_poly_trait_ref({:?}, def_id={:?})" , trait_ref, trait_def_id) ;
@@ -794,6 +803,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
794
803
) ;
795
804
let poly_trait_ref = ty:: Binder :: bind ( ty:: TraitRef :: new ( trait_def_id, substs) ) ;
796
805
806
+ bounds. trait_bounds . push ( ( poly_trait_ref, span) ) ;
807
+
797
808
let mut dup_bindings = FxHashMap :: default ( ) ;
798
809
for binding in & assoc_bindings {
799
810
// Specify type to assert that error was already reported in `Err` case.
@@ -804,14 +815,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
804
815
binding,
805
816
bounds,
806
817
speculative,
807
- & mut dup_bindings
818
+ & mut dup_bindings,
808
819
) ;
809
820
// Okay to ignore `Err` because of `ErrorReported` (see above).
810
821
}
811
822
812
823
debug ! ( "instantiate_poly_trait_ref({:?}, bounds={:?}) -> {:?}" ,
813
824
trait_ref, bounds, poly_trait_ref) ;
814
- ( poly_trait_ref , potential_assoc_types)
825
+ potential_assoc_types
815
826
}
816
827
817
828
/// 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 {
836
847
pub fn instantiate_poly_trait_ref ( & self ,
837
848
poly_trait_ref : & hir:: PolyTraitRef ,
838
849
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
+ )
843
859
}
844
860
845
861
fn ast_path_to_mono_trait_ref ( & self ,
@@ -983,12 +999,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
983
999
}
984
1000
985
1001
for bound in trait_bounds {
986
- let ( poly_trait_ref , _ ) = self . instantiate_poly_trait_ref (
1002
+ let _ = self . instantiate_poly_trait_ref (
987
1003
bound,
988
1004
param_ty,
989
1005
bounds,
990
1006
) ;
991
- bounds. trait_bounds . push ( ( poly_trait_ref, bound. span ) )
992
1007
}
993
1008
994
1009
bounds. region_bounds . extend ( region_bounds
@@ -1172,11 +1187,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
1172
1187
// Calling `skip_binder` is okay, because `add_bounds` expects the `param_ty`
1173
1188
// parameter to have a skipped binder.
1174
1189
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) ;
1180
1191
}
1181
1192
}
1182
1193
Ok ( ( ) )
@@ -1216,25 +1227,19 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
1216
1227
let mut bounds = Bounds :: default ( ) ;
1217
1228
let mut potential_assoc_types = Vec :: new ( ) ;
1218
1229
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
+ }
1234
1238
1235
1239
// Expand trait aliases recursively and check that only one regular (non-auto) trait
1236
1240
// 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 ( ) ) ;
1238
1243
let ( mut auto_traits, regular_traits) : ( Vec < _ > , Vec < _ > ) =
1239
1244
expanded_traits. partition ( |i| tcx. trait_is_auto ( i. trait_ref ( ) . def_id ( ) ) ) ;
1240
1245
if regular_traits. len ( ) > 1 {
@@ -1276,7 +1281,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
1276
1281
// Use a `BTreeSet` to keep output in a more consistent order.
1277
1282
let mut associated_types = BTreeSet :: default ( ) ;
1278
1283
1279
- let regular_traits_refs = bound_trait_refs
1284
+ let regular_traits_refs = bounds . trait_bounds
1280
1285
. into_iter ( )
1281
1286
. filter ( |( trait_ref, _) | !tcx. trait_is_auto ( trait_ref. def_id ( ) ) )
1282
1287
. map ( |( trait_ref, _) | trait_ref) ;
@@ -1491,7 +1496,17 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
1491
1496
{
1492
1497
let tcx = self . tcx ( ) ;
1493
1498
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
+
1494
1506
let predicates = & self . get_type_parameter_bounds ( span, ty_param_def_id) . predicates ;
1507
+
1508
+ debug ! ( "find_bound_for_assoc_item: predicates={:#?}" , predicates) ;
1509
+
1495
1510
let bounds = predicates. iter ( ) . filter_map ( |( p, _) | p. to_opt_poly_trait_ref ( ) ) ;
1496
1511
1497
1512
// 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 {
1515
1530
assoc_name : ast:: Ident ,
1516
1531
span : Span )
1517
1532
-> Result < ty:: PolyTraitRef < ' tcx > , ErrorReported >
1518
- where I : Iterator < Item = ty:: PolyTraitRef < ' tcx > >
1533
+ where I : Iterator < Item = ty:: PolyTraitRef < ' tcx > >
1519
1534
{
1520
1535
let bound = match bounds. next ( ) {
1521
1536
Some ( bound) => bound,
@@ -1524,13 +1539,17 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
1524
1539
"associated type `{}` not found for `{}`" ,
1525
1540
assoc_name,
1526
1541
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 ( ) ;
1529
1544
return Err ( ErrorReported ) ;
1530
1545
}
1531
1546
} ;
1532
1547
1548
+ debug ! ( "one_bound_for_assoc_type: bound = {:?}" , bound) ;
1549
+
1533
1550
if let Some ( bound2) = bounds. next ( ) {
1551
+ debug ! ( "one_bound_for_assoc_type: bound2 = {:?}" , bound2) ;
1552
+
1534
1553
let bounds = iter:: once ( bound) . chain ( iter:: once ( bound2) ) . chain ( bounds) ;
1535
1554
let mut err = struct_span_err ! (
1536
1555
self . tcx( ) . sess, span, E0221 ,
@@ -1544,7 +1563,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
1544
1563
item. kind == ty:: AssocKind :: Type &&
1545
1564
self . tcx ( ) . hygienic_eq ( assoc_name, item. ident , bound. def_id ( ) )
1546
1565
} )
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 ) ) ;
1548
1567
1549
1568
if let Some ( span) = bound_span {
1550
1569
err. span_label ( span, format ! ( "ambiguous `{}` from `{}`" ,
0 commit comments