@@ -86,6 +86,7 @@ There are some shortcomings in this design:
8686*/
8787
8888use astconv:: { self , AstConv , ty_of_arg, ast_ty_to_ty, ast_region_to_region} ;
89+ use middle:: def;
8990use middle:: lang_items:: SizedTraitLangItem ;
9091use middle:: region;
9192use middle:: resolve_lifetime;
@@ -1199,8 +1200,23 @@ fn convert_typed_item<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
11991200 predicates. clone ( ) ) ;
12001201 assert ! ( prev_predicates. is_none( ) ) ;
12011202
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+ }
12031218
1219+ return ( scheme, predicates) ;
12041220}
12051221
12061222fn type_scheme_of_foreign_item < ' a , ' tcx > (
@@ -1269,6 +1285,7 @@ fn ty_generics_for_type_or_impl<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
12691285 subst:: TypeSpace ,
12701286 & generics. lifetimes [ ] ,
12711287 & generics. ty_params [ ] ,
1288+ & generics. where_clause ,
12721289 ty:: Generics :: empty ( ) )
12731290}
12741291
@@ -1298,6 +1315,7 @@ fn ty_generics_for_trait<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
12981315 subst:: TypeSpace ,
12991316 & ast_generics. lifetimes [ ] ,
13001317 & ast_generics. ty_params [ ] ,
1318+ & ast_generics. where_clause ,
13011319 ty:: Generics :: empty ( ) ) ;
13021320
13031321 // Add in the self type parameter.
@@ -1321,7 +1339,8 @@ fn ty_generics_for_trait<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
13211339 trait_bounds : vec ! ( ty:: Binder ( self_trait_ref. clone( ) ) ) ,
13221340 projection_bounds : vec ! ( ) ,
13231341 } ,
1324- default : None
1342+ default : None ,
1343+ object_lifetime_default : None ,
13251344 } ;
13261345
13271346 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>,
13411360 subst:: FnSpace ,
13421361 & early_lifetimes[ ] ,
13431362 & generics. ty_params [ ] ,
1363+ & generics. where_clause ,
13441364 base_generics)
13451365}
13461366
@@ -1487,6 +1507,7 @@ fn ty_generics<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
14871507 space : subst:: ParamSpace ,
14881508 lifetime_defs : & [ ast:: LifetimeDef ] ,
14891509 types : & [ ast:: TyParam ] ,
1510+ where_clause : & ast:: WhereClause ,
14901511 base_generics : ty:: Generics < ' tcx > )
14911512 -> ty:: Generics < ' tcx >
14921513{
@@ -1511,7 +1532,7 @@ fn ty_generics<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
15111532
15121533 // Now create the real type parameters.
15131534 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 ) ;
15151536 debug ! ( "ty_generics: def for type param: {:?}, {:?}" , def, space) ;
15161537 result. types . push ( space, def) ;
15171538 }
@@ -1522,7 +1543,8 @@ fn ty_generics<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
15221543fn get_or_create_type_parameter_def < ' a , ' tcx > ( ccx : & CollectCtxt < ' a , ' tcx > ,
15231544 space : subst:: ParamSpace ,
15241545 param : & ast:: TyParam ,
1525- index : u32 )
1546+ index : u32 ,
1547+ where_clause : & ast:: WhereClause )
15261548 -> ty:: TypeParameterDef < ' tcx >
15271549{
15281550 let tcx = ccx. tcx ;
@@ -1558,20 +1580,117 @@ fn get_or_create_type_parameter_def<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
15581580 }
15591581 } ;
15601582
1583+ let object_lifetime_default =
1584+ compute_object_lifetime_default ( ccx, space, index, & param. bounds , where_clause) ;
1585+
15611586 let def = ty:: TypeParameterDef {
15621587 space : space,
15631588 index : index,
15641589 name : param. ident . name ,
15651590 def_id : local_def ( param. id ) ,
15661591 bounds : bounds,
1567- default : default
1592+ default : default,
1593+ object_lifetime_default : object_lifetime_default,
15681594 } ;
15691595
15701596 tcx. ty_param_defs . borrow_mut ( ) . insert ( param. id , def. clone ( ) ) ;
15711597
15721598 def
15731599}
15741600
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+
15751694enum SizedByDefault { Yes , No }
15761695
15771696/// Translate the AST's notion of ty param bounds (which are an enum consisting of a newtyped Ty or
0 commit comments