@@ -95,6 +95,7 @@ use middle::ty::{self, ClosureTyper, ReScope, Ty, MethodCall};
95
95
use middle:: infer:: { self , GenericKind } ;
96
96
use middle:: pat_util;
97
97
98
+ use std:: collections:: HashSet ;
98
99
use std:: mem;
99
100
use syntax:: { ast, ast_util} ;
100
101
use syntax:: codemap:: Span ;
@@ -1397,115 +1398,133 @@ pub fn type_must_outlive<'a, 'tcx>(rcx: &mut Rcx<'a, 'tcx>,
1397
1398
ty : Ty < ' tcx > ,
1398
1399
region : ty:: Region )
1399
1400
{
1400
- debug ! ( "type_must_outlive(ty={:?}, region={:?})" ,
1401
+ type_must_outlive_inner ( rcx, origin, ty, region, & mut HashSet :: new ( ) ) ;
1402
+
1403
+ fn type_must_outlive_inner < ' a , ' tcx > ( rcx : & mut Rcx < ' a , ' tcx > ,
1404
+ origin : infer:: SubregionOrigin < ' tcx > ,
1405
+ ty : Ty < ' tcx > ,
1406
+ region : ty:: Region ,
1407
+ visited : & mut HashSet < ( Ty < ' tcx > , ty:: Region , Span ) > ) {
1408
+ debug ! ( "type_must_outlive(ty={:?}, region={:?})" ,
1401
1409
ty,
1402
1410
region) ;
1403
1411
1404
- let implications = implicator:: implications ( rcx. fcx . infcx ( ) , rcx. fcx , rcx. body_id ,
1405
- ty, region, origin. span ( ) ) ;
1406
- for implication in implications {
1407
- debug ! ( "implication: {:?}" , implication) ;
1408
- match implication {
1409
- implicator:: Implication :: RegionSubRegion ( None , r_a, r_b) => {
1410
- rcx. fcx . mk_subr ( origin. clone ( ) , r_a, r_b) ;
1411
- }
1412
- implicator:: Implication :: RegionSubRegion ( Some ( ty) , r_a, r_b) => {
1413
- let o1 = infer:: ReferenceOutlivesReferent ( ty, origin. span ( ) ) ;
1414
- rcx. fcx . mk_subr ( o1, r_a, r_b) ;
1415
- }
1416
- implicator:: Implication :: RegionSubGeneric ( None , r_a, ref generic_b) => {
1417
- generic_must_outlive ( rcx, origin. clone ( ) , r_a, generic_b) ;
1418
- }
1419
- implicator:: Implication :: RegionSubGeneric ( Some ( ty) , r_a, ref generic_b) => {
1420
- let o1 = infer:: ReferenceOutlivesReferent ( ty, origin. span ( ) ) ;
1421
- generic_must_outlive ( rcx, o1, r_a, generic_b) ;
1422
- }
1423
- implicator:: Implication :: RegionSubClosure ( _, r_a, def_id, substs) => {
1424
- closure_must_outlive ( rcx, origin. clone ( ) , r_a, def_id, substs) ;
1425
- }
1426
- implicator:: Implication :: Predicate ( def_id, predicate) => {
1427
- let cause = traits:: ObligationCause :: new ( origin. span ( ) ,
1428
- rcx. body_id ,
1429
- traits:: ItemObligation ( def_id) ) ;
1430
- let obligation = traits:: Obligation :: new ( cause, predicate) ;
1431
- rcx. fcx . register_predicate ( obligation) ;
1412
+ let implications = implicator:: implications ( rcx. fcx . infcx ( ) , rcx. fcx , rcx. body_id ,
1413
+ ty, region, origin. span ( ) ) ;
1414
+
1415
+ let candidate = ( ty, region, origin. span ( ) ) ;
1416
+ if visited. contains ( & candidate) {
1417
+ span_err ! ( rcx. tcx( ) . sess, origin. span( ) , E0399 ,
1418
+ "recursive overflow detected while checking type lifetime rules for {}" , ty) ;
1419
+ return ;
1420
+ }
1421
+ visited. insert ( candidate) ;
1422
+
1423
+ for implication in implications {
1424
+ debug ! ( "implication: {:?}" , implication) ;
1425
+ match implication {
1426
+ implicator:: Implication :: RegionSubRegion ( None , r_a, r_b) => {
1427
+ rcx. fcx . mk_subr ( origin. clone ( ) , r_a, r_b) ;
1428
+ }
1429
+ implicator:: Implication :: RegionSubRegion ( Some ( ty) , r_a, r_b) => {
1430
+ let o1 = infer:: ReferenceOutlivesReferent ( ty, origin. span ( ) ) ;
1431
+ rcx. fcx . mk_subr ( o1, r_a, r_b) ;
1432
+ }
1433
+ implicator:: Implication :: RegionSubGeneric ( None , r_a, ref generic_b) => {
1434
+ generic_must_outlive_inner ( rcx, origin. clone ( ) , r_a, generic_b) ;
1435
+ }
1436
+ implicator:: Implication :: RegionSubGeneric ( Some ( ty) , r_a, ref generic_b) => {
1437
+ let o1 = infer:: ReferenceOutlivesReferent ( ty, origin. span ( ) ) ;
1438
+ generic_must_outlive_inner ( rcx, o1, r_a, generic_b) ;
1439
+ }
1440
+ implicator:: Implication :: RegionSubClosure ( _, r_a, def_id, substs) => {
1441
+ closure_must_outlive_inner ( rcx, origin. clone ( ) , r_a, def_id, substs, visited) ;
1442
+ }
1443
+ implicator:: Implication :: Predicate ( def_id, predicate) => {
1444
+ let cause = traits:: ObligationCause :: new ( origin. span ( ) ,
1445
+ rcx. body_id ,
1446
+ traits:: ItemObligation ( def_id) ) ;
1447
+ let obligation = traits:: Obligation :: new ( cause, predicate) ;
1448
+ rcx. fcx . register_predicate ( obligation) ;
1449
+ }
1432
1450
}
1433
1451
}
1434
1452
}
1435
- }
1436
1453
1437
- fn closure_must_outlive < ' a , ' tcx > ( rcx : & mut Rcx < ' a , ' tcx > ,
1454
+ fn closure_must_outlive_inner < ' a , ' tcx > ( rcx : & mut Rcx < ' a , ' tcx > ,
1438
1455
origin : infer:: SubregionOrigin < ' tcx > ,
1439
1456
region : ty:: Region ,
1440
1457
def_id : ast:: DefId ,
1441
- substs : & ' tcx Substs < ' tcx > ) {
1442
- debug ! ( "closure_must_outlive(region={:?}, def_id={:?}, substs={:?})" ,
1458
+ substs : & ' tcx Substs < ' tcx > ,
1459
+ visited : & mut HashSet < ( Ty < ' tcx > , ty:: Region , Span ) > ) {
1460
+ debug ! ( "closure_must_outlive(region={:?}, def_id={:?}, substs={:?})" ,
1443
1461
region, def_id, substs) ;
1444
1462
1445
- let upvars = rcx. fcx . closure_upvars ( def_id, substs) . unwrap ( ) ;
1446
- for upvar in upvars {
1447
- let var_id = upvar. def . def_id ( ) . local_id ( ) ;
1448
- type_must_outlive (
1449
- rcx, infer:: FreeVariable ( origin. span ( ) , var_id) ,
1450
- upvar. ty , region) ;
1463
+ let upvars = rcx. fcx . closure_upvars ( def_id, substs) . unwrap ( ) ;
1464
+ for upvar in upvars {
1465
+ let var_id = upvar. def . def_id ( ) . local_id ( ) ;
1466
+ type_must_outlive_inner (
1467
+ rcx, infer:: FreeVariable ( origin. span ( ) , var_id) ,
1468
+ upvar. ty , region, & mut visited. clone ( ) ) ;
1469
+ }
1451
1470
}
1452
- }
1453
1471
1454
- fn generic_must_outlive < ' a , ' tcx > ( rcx : & Rcx < ' a , ' tcx > ,
1472
+ fn generic_must_outlive_inner < ' a , ' tcx > ( rcx : & mut Rcx < ' a , ' tcx > ,
1455
1473
origin : infer:: SubregionOrigin < ' tcx > ,
1456
1474
region : ty:: Region ,
1457
1475
generic : & GenericKind < ' tcx > ) {
1458
- let param_env = & rcx. fcx . inh . param_env ;
1476
+ let param_env = & rcx. fcx . inh . param_env ;
1459
1477
1460
- debug ! ( "param_must_outlive(region={:?}, generic={:?})" ,
1478
+ debug ! ( "param_must_outlive(region={:?}, generic={:?})" ,
1461
1479
region,
1462
1480
generic) ;
1463
1481
1464
- // To start, collect bounds from user:
1465
- let mut param_bounds =
1466
- ty:: required_region_bounds ( rcx. tcx ( ) ,
1467
- generic. to_ty ( rcx. tcx ( ) ) ,
1468
- param_env. caller_bounds . clone ( ) ) ;
1469
-
1470
- // In the case of a projection T::Foo, we may be able to extract bounds from the trait def:
1471
- match * generic {
1472
- GenericKind :: Param ( ..) => { }
1473
- GenericKind :: Projection ( ref projection_ty) => {
1474
- param_bounds. push_all (
1475
- & projection_bounds ( rcx, origin. span ( ) , projection_ty) ) ;
1482
+ // To start, collect bounds from user:
1483
+ let mut param_bounds =
1484
+ ty:: required_region_bounds ( rcx. tcx ( ) ,
1485
+ generic. to_ty ( rcx. tcx ( ) ) ,
1486
+ param_env. caller_bounds . clone ( ) ) ;
1487
+
1488
+ // In the case of a projection T::Foo, we may be able to extract bounds from the trait def:
1489
+ match * generic {
1490
+ GenericKind :: Param ( ..) => { }
1491
+ GenericKind :: Projection ( ref projection_ty) => {
1492
+ param_bounds. push_all (
1493
+ & projection_bounds ( rcx, origin. span ( ) , projection_ty) ) ;
1494
+ }
1476
1495
}
1477
- }
1478
1496
1479
- // Add in the default bound of fn body that applies to all in
1480
- // scope type parameters:
1481
- param_bounds. push ( param_env. implicit_region_bound ) ;
1497
+ // Add in the default bound of fn body that applies to all in
1498
+ // scope type parameters:
1499
+ param_bounds. push ( param_env. implicit_region_bound ) ;
1482
1500
1483
- // Finally, collect regions we scraped from the well-formedness
1484
- // constraints in the fn signature. To do that, we walk the list
1485
- // of known relations from the fn ctxt.
1486
- //
1487
- // This is crucial because otherwise code like this fails:
1488
- //
1489
- // fn foo<'a, A>(x: &'a A) { x.bar() }
1490
- //
1491
- // The problem is that the type of `x` is `&'a A`. To be
1492
- // well-formed, then, A must be lower-generic by `'a`, but we
1493
- // don't know that this holds from first principles.
1494
- for & ( ref r, ref p) in & rcx. region_bound_pairs {
1495
- debug ! ( "generic={:?} p={:?}" ,
1501
+ // Finally, collect regions we scraped from the well-formedness
1502
+ // constraints in the fn signature. To do that, we walk the list
1503
+ // of known relations from the fn ctxt.
1504
+ //
1505
+ // This is crucial because otherwise code like this fails:
1506
+ //
1507
+ // fn foo<'a, A>(x: &'a A) { x.bar() }
1508
+ //
1509
+ // The problem is that the type of `x` is `&'a A`. To be
1510
+ // well-formed, then, A must be lower-generic by `'a`, but we
1511
+ // don't know that this holds from first principles.
1512
+ for & ( ref r, ref p) in & rcx. region_bound_pairs {
1513
+ debug ! ( "generic={:?} p={:?}" ,
1496
1514
generic,
1497
1515
p) ;
1498
- if generic == p {
1499
- param_bounds. push ( * r) ;
1516
+ if generic == p {
1517
+ param_bounds. push ( * r) ;
1518
+ }
1500
1519
}
1501
- }
1502
1520
1503
- // Inform region inference that this generic must be properly
1504
- // bounded.
1505
- rcx. fcx . infcx ( ) . verify_generic_bound ( origin,
1506
- generic. clone ( ) ,
1507
- region,
1508
- param_bounds) ;
1521
+ // Inform region inference that this generic must be properly
1522
+ // bounded.
1523
+ rcx. fcx . infcx ( ) . verify_generic_bound ( origin,
1524
+ generic. clone ( ) ,
1525
+ region,
1526
+ param_bounds) ;
1527
+ }
1509
1528
}
1510
1529
1511
1530
fn projection_bounds < ' a , ' tcx > ( rcx : & Rcx < ' a , ' tcx > ,
0 commit comments