@@ -86,6 +86,7 @@ There are some shortcomings in this design:
86
86
*/
87
87
88
88
use astconv:: { self , AstConv , ty_of_arg, ast_ty_to_ty, ast_region_to_region} ;
89
+ use middle:: def;
89
90
use middle:: lang_items:: SizedTraitLangItem ;
90
91
use middle:: region;
91
92
use middle:: resolve_lifetime;
@@ -1199,8 +1200,23 @@ fn convert_typed_item<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
1199
1200
predicates. clone ( ) ) ;
1200
1201
assert ! ( prev_predicates. is_none( ) ) ;
1201
1202
1202
- return ( scheme, predicates) ;
1203
+ // Debugging aid.
1204
+ if ty:: has_attr ( tcx, local_def ( it. id ) , "rustc_object_lifetime_default" ) {
1205
+ let object_lifetime_default_reprs: String =
1206
+ scheme. generics . types . iter ( )
1207
+ . map ( |t| match t. object_lifetime_default {
1208
+ Some ( ty:: ObjectLifetimeDefault :: Specific ( r) ) =>
1209
+ r. user_string ( tcx) ,
1210
+ d =>
1211
+ d. repr ( ccx. tcx ( ) ) ,
1212
+ } )
1213
+ . collect :: < Vec < String > > ( )
1214
+ . connect ( "," ) ;
1215
+
1216
+ tcx. sess . span_err ( it. span , & object_lifetime_default_reprs) ;
1217
+ }
1203
1218
1219
+ return ( scheme, predicates) ;
1204
1220
}
1205
1221
1206
1222
fn type_scheme_of_foreign_item < ' a , ' tcx > (
@@ -1269,6 +1285,7 @@ fn ty_generics_for_type_or_impl<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
1269
1285
subst:: TypeSpace ,
1270
1286
& generics. lifetimes [ ] ,
1271
1287
& generics. ty_params [ ] ,
1288
+ & generics. where_clause ,
1272
1289
ty:: Generics :: empty ( ) )
1273
1290
}
1274
1291
@@ -1298,6 +1315,7 @@ fn ty_generics_for_trait<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
1298
1315
subst:: TypeSpace ,
1299
1316
& ast_generics. lifetimes [ ] ,
1300
1317
& ast_generics. ty_params [ ] ,
1318
+ & ast_generics. where_clause ,
1301
1319
ty:: Generics :: empty ( ) ) ;
1302
1320
1303
1321
// Add in the self type parameter.
@@ -1321,7 +1339,8 @@ fn ty_generics_for_trait<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
1321
1339
trait_bounds : vec ! ( ty:: Binder ( self_trait_ref. clone( ) ) ) ,
1322
1340
projection_bounds : vec ! ( ) ,
1323
1341
} ,
1324
- default : None
1342
+ default : None ,
1343
+ object_lifetime_default : None ,
1325
1344
} ;
1326
1345
1327
1346
ccx. tcx . ty_param_defs . borrow_mut ( ) . insert ( param_id, def. clone ( ) ) ;
@@ -1341,6 +1360,7 @@ fn ty_generics_for_fn_or_method<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
1341
1360
subst:: FnSpace ,
1342
1361
& early_lifetimes[ ] ,
1343
1362
& generics. ty_params [ ] ,
1363
+ & generics. where_clause ,
1344
1364
base_generics)
1345
1365
}
1346
1366
@@ -1487,6 +1507,7 @@ fn ty_generics<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
1487
1507
space : subst:: ParamSpace ,
1488
1508
lifetime_defs : & [ ast:: LifetimeDef ] ,
1489
1509
types : & [ ast:: TyParam ] ,
1510
+ where_clause : & ast:: WhereClause ,
1490
1511
base_generics : ty:: Generics < ' tcx > )
1491
1512
-> ty:: Generics < ' tcx >
1492
1513
{
@@ -1511,7 +1532,7 @@ fn ty_generics<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
1511
1532
1512
1533
// Now create the real type parameters.
1513
1534
for ( i, param) in types. iter ( ) . enumerate ( ) {
1514
- let def = get_or_create_type_parameter_def ( ccx, space, param, i as u32 ) ;
1535
+ let def = get_or_create_type_parameter_def ( ccx, space, param, i as u32 , where_clause ) ;
1515
1536
debug ! ( "ty_generics: def for type param: {:?}, {:?}" , def, space) ;
1516
1537
result. types . push ( space, def) ;
1517
1538
}
@@ -1522,7 +1543,8 @@ fn ty_generics<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
1522
1543
fn get_or_create_type_parameter_def < ' a , ' tcx > ( ccx : & CollectCtxt < ' a , ' tcx > ,
1523
1544
space : subst:: ParamSpace ,
1524
1545
param : & ast:: TyParam ,
1525
- index : u32 )
1546
+ index : u32 ,
1547
+ where_clause : & ast:: WhereClause )
1526
1548
-> ty:: TypeParameterDef < ' tcx >
1527
1549
{
1528
1550
let tcx = ccx. tcx ;
@@ -1558,20 +1580,117 @@ fn get_or_create_type_parameter_def<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
1558
1580
}
1559
1581
} ;
1560
1582
1583
+ let object_lifetime_default =
1584
+ compute_object_lifetime_default ( ccx, space, index, & param. bounds , where_clause) ;
1585
+
1561
1586
let def = ty:: TypeParameterDef {
1562
1587
space : space,
1563
1588
index : index,
1564
1589
name : param. ident . name ,
1565
1590
def_id : local_def ( param. id ) ,
1566
1591
bounds : bounds,
1567
- default : default
1592
+ default : default,
1593
+ object_lifetime_default : object_lifetime_default,
1568
1594
} ;
1569
1595
1570
1596
tcx. ty_param_defs . borrow_mut ( ) . insert ( param. id , def. clone ( ) ) ;
1571
1597
1572
1598
def
1573
1599
}
1574
1600
1601
+ /// Scan the bounds and where-clauses on a parameter to extract bounds
1602
+ /// of the form `T:'a` so as to determine the `ObjectLifetimeDefault`.
1603
+ /// This runs as part of computing the minimal type scheme, so we
1604
+ /// intentionally avoid just asking astconv to convert all the where
1605
+ /// clauses into a `ty::Predicate`. This is because that could induce
1606
+ /// artificial cycles.
1607
+ fn compute_object_lifetime_default < ' a , ' tcx > ( ccx : & CollectCtxt < ' a , ' tcx > ,
1608
+ space : subst:: ParamSpace ,
1609
+ index : u32 ,
1610
+ param_bounds : & [ ast:: TyParamBound ] ,
1611
+ where_clause : & ast:: WhereClause )
1612
+ -> Option < ty:: ObjectLifetimeDefault >
1613
+ {
1614
+ let inline_bounds = from_bounds ( ccx, param_bounds) ;
1615
+ let where_bounds = from_predicates ( ccx, space, index, & where_clause. predicates ) ;
1616
+ let all_bounds: HashSet < _ > = inline_bounds. into_iter ( )
1617
+ . chain ( where_bounds. into_iter ( ) )
1618
+ . collect ( ) ;
1619
+ return if all_bounds. len ( ) > 1 {
1620
+ Some ( ty:: ObjectLifetimeDefault :: Ambiguous )
1621
+ } else {
1622
+ all_bounds. into_iter ( )
1623
+ . next ( )
1624
+ . map ( ty:: ObjectLifetimeDefault :: Specific )
1625
+ } ;
1626
+
1627
+ fn from_bounds < ' a , ' tcx > ( ccx : & CollectCtxt < ' a , ' tcx > ,
1628
+ bounds : & [ ast:: TyParamBound ] )
1629
+ -> Vec < ty:: Region >
1630
+ {
1631
+ bounds. iter ( )
1632
+ . filter_map ( |bound| {
1633
+ match * bound {
1634
+ ast:: TraitTyParamBound ( ..) =>
1635
+ None ,
1636
+ ast:: RegionTyParamBound ( ref lifetime) =>
1637
+ Some ( astconv:: ast_region_to_region ( ccx. tcx ( ) , lifetime) ) ,
1638
+ }
1639
+ } )
1640
+ . collect ( )
1641
+ }
1642
+
1643
+ fn from_predicates < ' a , ' tcx > ( ccx : & CollectCtxt < ' a , ' tcx > ,
1644
+ space : subst:: ParamSpace ,
1645
+ index : u32 ,
1646
+ predicates : & [ ast:: WherePredicate ] )
1647
+ -> Vec < ty:: Region >
1648
+ {
1649
+ predicates. iter ( )
1650
+ . flat_map ( |predicate| {
1651
+ match * predicate {
1652
+ ast:: WherePredicate :: BoundPredicate ( ref data) => {
1653
+ if data. bound_lifetimes . len ( ) == 0 &&
1654
+ is_param ( ccx, & data. bounded_ty , space, index)
1655
+ {
1656
+ from_bounds ( ccx, & data. bounds ) . into_iter ( )
1657
+ } else {
1658
+ Vec :: new ( ) . into_iter ( )
1659
+ }
1660
+ }
1661
+ ast:: WherePredicate :: RegionPredicate ( ..) |
1662
+ ast:: WherePredicate :: EqPredicate ( ..) => {
1663
+ Vec :: new ( ) . into_iter ( )
1664
+ }
1665
+ }
1666
+ } )
1667
+ . collect ( )
1668
+ }
1669
+
1670
+ fn is_param ( ccx : & CollectCtxt ,
1671
+ ast_ty : & ast:: Ty ,
1672
+ space : subst:: ParamSpace ,
1673
+ index : u32 )
1674
+ -> bool
1675
+ {
1676
+ match ast_ty. node {
1677
+ ast:: TyPath ( _, id) => {
1678
+ match ccx. tcx . def_map . borrow ( ) [ id] {
1679
+ def:: DefTyParam ( s, i, _, _) => {
1680
+ space == s && index == i
1681
+ }
1682
+ _ => {
1683
+ false
1684
+ }
1685
+ }
1686
+ }
1687
+ _ => {
1688
+ false
1689
+ }
1690
+ }
1691
+ }
1692
+ }
1693
+
1575
1694
enum SizedByDefault { Yes , No }
1576
1695
1577
1696
/// Translate the AST's notion of ty param bounds (which are an enum consisting of a newtyped Ty or
0 commit comments