@@ -43,6 +43,7 @@ use rustc_const_math::ConstInt;
43
43
use std:: collections:: BTreeMap ;
44
44
45
45
use syntax:: { abi, ast} ;
46
+ use syntax:: ptr:: P ;
46
47
use syntax:: codemap:: Spanned ;
47
48
use syntax:: symbol:: { Symbol , keywords} ;
48
49
use syntax_pos:: { Span , DUMMY_SP } ;
@@ -873,22 +874,32 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
873
874
let mut allow_defaults = false ;
874
875
875
876
let no_generics = hir:: Generics :: empty ( ) ;
876
- let ast_generics = match node {
877
- NodeTraitItem ( item) => & item. generics ,
877
+ let ( ast_generics, opt_inputs) = match node {
878
+ NodeTraitItem ( item) => {
879
+ match item. node {
880
+ TraitItemKind :: Method ( ref sig, _) => ( & item. generics , Some ( & sig. decl . inputs ) ) ,
881
+ _ => ( & item. generics , None )
882
+ }
883
+ }
878
884
879
- NodeImplItem ( item) => & item. generics ,
885
+ NodeImplItem ( item) => {
886
+ match item. node {
887
+ ImplItemKind :: Method ( ref sig, _) => ( & item. generics , Some ( & sig. decl . inputs ) ) ,
888
+ _ => ( & item. generics , None )
889
+ }
890
+ }
880
891
881
892
NodeItem ( item) => {
882
893
match item. node {
883
- ItemFn ( .., ref generics, _) |
884
- ItemImpl ( _, _, _, ref generics, ..) => generics,
894
+ ItemFn ( ref decl , .., ref generics, _) => ( generics , Some ( & decl . inputs ) ) ,
895
+ ItemImpl ( _, _, _, ref generics, ..) => ( generics, None ) ,
885
896
886
897
ItemTy ( _, ref generics) |
887
898
ItemEnum ( _, ref generics) |
888
899
ItemStruct ( _, ref generics) |
889
900
ItemUnion ( _, ref generics) => {
890
901
allow_defaults = true ;
891
- generics
902
+ ( generics, None )
892
903
}
893
904
894
905
ItemTrait ( _, _, ref generics, ..) => {
@@ -909,22 +920,22 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
909
920
} ) ;
910
921
911
922
allow_defaults = true ;
912
- generics
923
+ ( generics, None )
913
924
}
914
925
915
- _ => & no_generics
926
+ _ => ( & no_generics, None )
916
927
}
917
928
}
918
929
919
930
NodeForeignItem ( item) => {
920
931
match item. node {
921
- ForeignItemStatic ( ..) => & no_generics,
922
- ForeignItemFn ( _ , _, ref generics) => generics,
923
- ForeignItemType => & no_generics,
932
+ ForeignItemStatic ( ..) => ( & no_generics, None ) ,
933
+ ForeignItemFn ( ref decl , _, ref generics) => ( generics, Some ( & decl . inputs ) ) ,
934
+ ForeignItemType => ( & no_generics, None )
924
935
}
925
936
}
926
937
927
- _ => & no_generics
938
+ _ => ( & no_generics, None )
928
939
} ;
929
940
930
941
let has_self = opt_self. is_some ( ) ;
@@ -981,7 +992,24 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
981
992
synthetic : p. synthetic ,
982
993
}
983
994
} ) ;
984
- let mut types: Vec < _ > = opt_self. into_iter ( ) . chain ( types) . collect ( ) ;
995
+
996
+ let fn_ins = opt_inputs. map ( |tys| & tys[ ..] ) ;
997
+ let univ_impl_trait_info = extract_universal_impl_trait_info ( tcx, fn_ins) ;
998
+ let other_type_start = type_start + ast_generics. ty_params . len ( ) as u32 ;
999
+ let mut types: Vec < _ > = opt_self. into_iter ( )
1000
+ . chain ( types)
1001
+ . chain ( univ_impl_trait_info. iter ( ) . enumerate ( ) . map ( |( i, info) | {
1002
+ ty:: TypeParameterDef {
1003
+ index : other_type_start + i as u32 ,
1004
+ name : keywords:: Invalid . name ( ) /* FIXME(chrisvittal) maybe make not Invalid */ ,
1005
+ def_id : info. def_id ,
1006
+ has_default : false ,
1007
+ object_lifetime_default : rl:: Set1 :: Empty ,
1008
+ pure_wrt_drop : false ,
1009
+ synthetic : Some ( SyntheticTyParamKind :: ImplTrait ) ,
1010
+ }
1011
+ } ) )
1012
+ . collect ( ) ;
985
1013
986
1014
// provide junk type parameter defs - the only place that
987
1015
// cares about anything but the length is instantiation,
@@ -1337,39 +1365,50 @@ fn explicit_predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
1337
1365
1338
1366
let icx = ItemCtxt :: new ( tcx, def_id) ;
1339
1367
let no_generics = hir:: Generics :: empty ( ) ;
1340
- let ast_generics = match node {
1341
- NodeTraitItem ( item) => & item. generics ,
1368
+ let ( ast_generics, opt_inputs) = match node {
1369
+ NodeTraitItem ( item) => {
1370
+ match item. node {
1371
+ TraitItemKind :: Method ( ref sig, _) => ( & item. generics , Some ( & sig. decl . inputs ) ) ,
1372
+ _ => ( & item. generics , None )
1373
+ }
1374
+ }
1342
1375
1343
- NodeImplItem ( item) => & item. generics ,
1376
+ NodeImplItem ( item) => {
1377
+ match item. node {
1378
+ ImplItemKind :: Method ( ref sig, _) => ( & item. generics , Some ( & sig. decl . inputs ) ) ,
1379
+ _ => ( & item. generics , None )
1380
+ }
1381
+ }
1344
1382
1345
1383
NodeItem ( item) => {
1346
1384
match item. node {
1347
- ItemFn ( .., ref generics, _) |
1385
+ ItemFn ( ref decl, .., ref generics, _) => ( generics, Some ( & decl. inputs ) ) ,
1386
+
1348
1387
ItemImpl ( _, _, _, ref generics, ..) |
1349
1388
ItemTy ( _, ref generics) |
1350
1389
ItemEnum ( _, ref generics) |
1351
1390
ItemStruct ( _, ref generics) |
1352
1391
ItemUnion ( _, ref generics) => {
1353
- generics
1392
+ ( generics, None )
1354
1393
}
1355
1394
1356
1395
ItemTrait ( _, _, ref generics, .., ref items) => {
1357
1396
is_trait = Some ( ( ty:: TraitRef {
1358
1397
def_id,
1359
1398
substs : Substs :: identity_for_item ( tcx, def_id)
1360
1399
} , items) ) ;
1361
- generics
1400
+ ( generics, None )
1362
1401
}
1363
1402
1364
- _ => & no_generics
1403
+ _ => ( & no_generics, None )
1365
1404
}
1366
1405
}
1367
1406
1368
1407
NodeForeignItem ( item) => {
1369
1408
match item. node {
1370
- ForeignItemStatic ( ..) => & no_generics,
1371
- ForeignItemFn ( _ , _, ref generics) => generics,
1372
- ForeignItemType => & no_generics,
1409
+ ForeignItemStatic ( ..) => ( & no_generics, None ) ,
1410
+ ForeignItemFn ( ref decl , _, ref generics) => ( generics, Some ( & decl . inputs ) ) ,
1411
+ ForeignItemType => ( & no_generics, None ) ,
1373
1412
}
1374
1413
}
1375
1414
@@ -1387,7 +1426,7 @@ fn explicit_predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
1387
1426
} ;
1388
1427
}
1389
1428
1390
- _ => & no_generics
1429
+ _ => ( & no_generics, None )
1391
1430
} ;
1392
1431
1393
1432
let generics = tcx. generics_of ( def_id) ;
@@ -1518,6 +1557,19 @@ fn explicit_predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
1518
1557
} ) )
1519
1558
}
1520
1559
1560
+ // Add predicates from impl Trait arguments
1561
+ let fn_ins = opt_inputs. map ( |tys| & tys[ ..] ) ;
1562
+ let univ_impl_trait_info = extract_universal_impl_trait_info ( tcx, fn_ins) ;
1563
+ for info in univ_impl_trait_info. iter ( ) {
1564
+ let name = keywords:: Invalid . name ( ) ;
1565
+ let param_ty = ty:: ParamTy :: new ( index, name) . to_ty ( tcx) ;
1566
+ index += 1 ;
1567
+ let bounds = compute_bounds ( & icx, param_ty, info. bounds ,
1568
+ SizedByDefault :: Yes ,
1569
+ info. span ) ;
1570
+ predicates. extend ( bounds. predicates ( tcx, param_ty) ) ;
1571
+ }
1572
+
1521
1573
// Subtle: before we store the predicates into the tcx, we
1522
1574
// sort them so that predicates like `T: Foo<Item=U>` come
1523
1575
// before uses of `U`. This avoids false ambiguity errors
@@ -1678,3 +1730,48 @@ fn is_auto_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
1678
1730
_ => bug ! ( "is_auto_impl applied to non-local def-id {:?}" , def_id)
1679
1731
}
1680
1732
}
1733
+
1734
+ struct ImplTraitUniversalInfo < ' hir > {
1735
+ def_id : DefId ,
1736
+ span : Span ,
1737
+ bounds : & ' hir [ hir:: TyParamBound ] ,
1738
+ }
1739
+
1740
+ /// Take some possible list of arguments and return the DefIds of the ImplTraitUniversal
1741
+ /// arguments
1742
+ fn extract_universal_impl_trait_info < ' a , ' tcx > ( tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
1743
+ opt_inputs : Option < & ' tcx [ P < hir:: Ty > ] > )
1744
+ -> Vec < ImplTraitUniversalInfo < ' tcx > >
1745
+ {
1746
+ // A visitor for simply collecting Universally quantified impl Trait arguments
1747
+ struct ImplTraitUniversalVisitor < ' tcx > {
1748
+ items : Vec < & ' tcx hir:: Ty >
1749
+ }
1750
+
1751
+ impl < ' tcx > Visitor < ' tcx > for ImplTraitUniversalVisitor < ' tcx > {
1752
+ fn nested_visit_map < ' this > ( & ' this mut self ) -> NestedVisitorMap < ' this , ' tcx > {
1753
+ NestedVisitorMap :: None
1754
+ }
1755
+
1756
+ fn visit_ty ( & mut self , ty : & ' tcx hir:: Ty ) {
1757
+ if let hir:: TyImplTraitUniversal ( ..) = ty. node {
1758
+ self . items . push ( ty) ;
1759
+ }
1760
+ intravisit:: walk_ty ( self , ty) ;
1761
+ }
1762
+ }
1763
+
1764
+ let mut visitor = ImplTraitUniversalVisitor { items : Vec :: new ( ) } ;
1765
+ opt_inputs. map ( |inputs| for t in inputs. iter ( ) {
1766
+ visitor. visit_ty ( t) ;
1767
+ } ) ;
1768
+ visitor. items . into_iter ( ) . map ( |ty| if let hir:: TyImplTraitUniversal ( _, ref bounds) = ty. node {
1769
+ ImplTraitUniversalInfo {
1770
+ def_id : tcx. hir . local_def_id ( ty. id ) ,
1771
+ span : ty. span ,
1772
+ bounds : bounds
1773
+ }
1774
+ } else {
1775
+ span_bug ! ( ty. span, "this type should be a universally quantified impl trait. this is a bug" )
1776
+ } ) . collect ( )
1777
+ }
0 commit comments