@@ -1405,18 +1405,39 @@ impl<'tcx> RegionInferenceContext<'tcx> {
1405
1405
}
1406
1406
1407
1407
/// Walks the graph of constraints (where `'a: 'b` is considered
1408
- /// an edge `'a -> 'b`) to find all paths from `from_region` to
1409
- /// `to_region`. The paths are accumulated into the vector
1410
- /// `results`. The paths are stored as a series of
1411
- /// `ConstraintIndex` values -- in other words, a list of *edges*.
1408
+ /// an edge `'a -> 'b`) to find a path from `from_region` to
1409
+ /// `to_region`.
1412
1410
///
1413
1411
/// Returns: a series of constraints as well as the region `R`
1414
1412
/// that passed the target test.
1415
1413
#[ instrument( skip( self , target_test) , ret) ]
1416
- pub ( crate ) fn find_constraint_paths_between_regions (
1414
+ pub ( crate ) fn find_constraint_path_between_regions (
1417
1415
& self ,
1418
1416
from_region : RegionVid ,
1419
1417
target_test : impl Fn ( RegionVid ) -> bool ,
1418
+ ) -> Option < ( Vec < OutlivesConstraint < ' tcx > > , RegionVid ) > {
1419
+ self . find_constraint_path_between_regions_inner ( true , from_region, & target_test) . or_else (
1420
+ || self . find_constraint_path_between_regions_inner ( false , from_region, & target_test) ,
1421
+ )
1422
+ }
1423
+
1424
+ /// The constraints we get from equating the hidden type of each use of an opaque
1425
+ /// with its final concrete type may end up getting preferred over other, potentially
1426
+ /// longer constraint paths.
1427
+ ///
1428
+ /// Given that we compute the final concrete type by relying on this existing constraint
1429
+ /// path, this can easily end up hiding the actual reason for why we require these regions
1430
+ /// to be equal.
1431
+ ///
1432
+ /// To handle this, we first look at the path while ignoring these constraints and then
1433
+ /// retry while considering them. This is not perfect, as the `from_region` may have already
1434
+ /// been partially related to its argument region, so while we rely on a member constraint
1435
+ /// to get a complete path, the most relevant step of that path already existed before then.
1436
+ fn find_constraint_path_between_regions_inner (
1437
+ & self ,
1438
+ ignore_opaque_type_constraints : bool ,
1439
+ from_region : RegionVid ,
1440
+ target_test : impl Fn ( RegionVid ) -> bool ,
1420
1441
) -> Option < ( Vec < OutlivesConstraint < ' tcx > > , RegionVid ) > {
1421
1442
let mut context = IndexVec :: from_elem ( Trace :: NotVisited , & self . definitions ) ;
1422
1443
context[ from_region] = Trace :: StartRegion ;
@@ -1431,7 +1452,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
1431
1452
1432
1453
while let Some ( r) = deque. pop_front ( ) {
1433
1454
debug ! (
1434
- "find_constraint_paths_between_regions : from_region={:?} r={:?} value={}" ,
1455
+ "find_constraint_path_between_regions : from_region={:?} r={:?} value={}" ,
1435
1456
from_region,
1436
1457
r,
1437
1458
self . region_value_str( r) ,
@@ -1503,9 +1524,16 @@ impl<'tcx> RegionInferenceContext<'tcx> {
1503
1524
let edges = self . constraint_graph . outgoing_edges_from_graph ( r, & self . constraints ) ;
1504
1525
// This loop can be hot.
1505
1526
for constraint in edges {
1506
- if matches ! ( constraint. category, ConstraintCategory :: IllegalUniverse ) {
1507
- debug ! ( "Ignoring illegal universe constraint: {constraint:?}" ) ;
1508
- continue ;
1527
+ match constraint. category {
1528
+ ConstraintCategory :: IllegalUniverse => {
1529
+ debug ! ( "Ignoring illegal universe constraint: {constraint:?}" ) ;
1530
+ continue ;
1531
+ }
1532
+ ConstraintCategory :: OpaqueType if ignore_opaque_type_constraints => {
1533
+ debug ! ( "Ignoring member constraint: {constraint:?}" ) ;
1534
+ continue ;
1535
+ }
1536
+ _ => { }
1509
1537
}
1510
1538
debug_assert_eq ! ( constraint. sup, r) ;
1511
1539
handle_trace ( constraint. sub , Trace :: FromGraph ( constraint) ) ;
@@ -1521,7 +1549,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
1521
1549
pub ( crate ) fn find_sub_region_live_at ( & self , fr1 : RegionVid , location : Location ) -> RegionVid {
1522
1550
trace ! ( scc = ?self . constraint_sccs. scc( fr1) ) ;
1523
1551
trace ! ( universe = ?self . max_nameable_universe( self . constraint_sccs. scc( fr1) ) ) ;
1524
- self . find_constraint_paths_between_regions ( fr1, |r| {
1552
+ self . find_constraint_path_between_regions ( fr1, |r| {
1525
1553
// First look for some `r` such that `fr1: r` and `r` is live at `location`
1526
1554
trace ! ( ?r, liveness_constraints=?self . liveness_constraints. pretty_print_live_points( r) ) ;
1527
1555
self . liveness_constraints . is_live_at ( r, location)
@@ -1531,9 +1559,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
1531
1559
// `fr1: r` and `r` is a placeholder from some universe
1532
1560
// `fr1` cannot name. This would force `fr1` to be
1533
1561
// `'static`.
1534
- self . find_constraint_paths_between_regions ( fr1, |r| {
1535
- self . cannot_name_placeholder ( fr1, r)
1536
- } )
1562
+ self . find_constraint_path_between_regions ( fr1, |r| self . cannot_name_placeholder ( fr1, r) )
1537
1563
} )
1538
1564
. or_else ( || {
1539
1565
// If we fail to find THAT, it may be that `fr1` is a
@@ -1546,9 +1572,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
1546
1572
// must be able to name the universe of R2, because R2 will
1547
1573
// be at least `'empty(Universe(R2))`, and `R1` must be at
1548
1574
// larger than that.
1549
- self . find_constraint_paths_between_regions ( fr1, |r| {
1550
- self . cannot_name_placeholder ( r, fr1)
1551
- } )
1575
+ self . find_constraint_path_between_regions ( fr1, |r| self . cannot_name_placeholder ( r, fr1) )
1552
1576
} )
1553
1577
. map ( |( _path, r) | r)
1554
1578
. unwrap ( )
@@ -1604,9 +1628,9 @@ impl<'tcx> RegionInferenceContext<'tcx> {
1604
1628
) -> ( BlameConstraint < ' tcx > , Vec < OutlivesConstraint < ' tcx > > ) {
1605
1629
// Find all paths
1606
1630
let ( path, target_region) = self
1607
- . find_constraint_paths_between_regions ( from_region, target_test)
1631
+ . find_constraint_path_between_regions ( from_region, target_test)
1608
1632
. or_else ( || {
1609
- self . find_constraint_paths_between_regions ( from_region, |r| {
1633
+ self . find_constraint_path_between_regions ( from_region, |r| {
1610
1634
self . cannot_name_placeholder ( from_region, r)
1611
1635
} )
1612
1636
} )
0 commit comments