about summary refs log tree commit diff
diff options
context:
space:
mode:
authorSantiago Pastorino <spastorino@gmail.com>2023-06-22 17:40:59 -0300
committerSantiago Pastorino <spastorino@gmail.com>2023-06-29 14:04:26 -0300
commit373293c3ca0a86dfd00df298be75a87ed414f99c (patch)
tree1990534daf8c94bcedef80a221b29320d541bdff
parente69c7306e2be08939d95f14229e3f96566fb206c (diff)
downloadrust-373293c3ca0a86dfd00df298be75a87ed414f99c.tar.gz
rust-373293c3ca0a86dfd00df298be75a87ed414f99c.zip
Extract compute_bidirectional_outlives_predicates fn
-rw-r--r--compiler/rustc_hir_analysis/src/collect/predicates_of.rs84
1 files changed, 51 insertions, 33 deletions
diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
index d9b2aacab9d..0fa4c786e66 100644
--- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
@@ -2,7 +2,7 @@ use crate::astconv::{AstConv, OnlySelfBounds, PredicateFilter};
 use crate::bounds::Bounds;
 use crate::collect::ItemCtxt;
 use crate::constrained_generic_params as cgp;
-use hir::{HirId, Node};
+use hir::{HirId, Lifetime, Node};
 use rustc_data_structures::fx::FxIndexSet;
 use rustc_hir as hir;
 use rustc_hir::def::DefKind;
@@ -10,9 +10,9 @@ use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::intravisit::{self, Visitor};
 use rustc_middle::ty::subst::InternalSubsts;
 use rustc_middle::ty::{self, Ty, TyCtxt};
-use rustc_middle::ty::{GenericPredicates, ToPredicate};
+use rustc_middle::ty::{GenericPredicates, Generics, ToPredicate};
 use rustc_span::symbol::{sym, Ident};
-use rustc_span::{Span, DUMMY_SP};
+use rustc_span::{Span, Symbol, DUMMY_SP};
 
 /// Returns a list of all type predicates (explicit and implicit) for the definition with
 /// ID `def_id`. This includes all predicates returned by `predicates_defined_on`, plus
@@ -289,38 +289,16 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
             bug!("unexpected {opaque_ty_node:?}")
         };
         debug!(?lifetimes);
-        for (arg, duplicate) in std::iter::zip(lifetimes, ast_generics.params) {
-            let hir::GenericArg::Lifetime(arg) = arg else { bug!() };
-            let orig_region = icx.astconv().ast_region_to_region(&arg, None);
-            if !matches!(orig_region.kind(), ty::ReEarlyBound(..)) {
-                // Only early-bound regions can point to the original generic parameter.
-                continue;
-            }
-
-            let hir::GenericParamKind::Lifetime { .. } = duplicate.kind else { continue };
-            let dup_def = duplicate.def_id.to_def_id();
 
-            let Some(dup_index) = generics.param_def_id_to_index(tcx, dup_def) else { bug!() };
+        let lifetime_mapping = std::iter::zip(lifetimes, ast_generics.params)
+            .map(|(arg, dup)| {
+                let hir::GenericArg::Lifetime(arg) = arg else { bug!() };
+                (**arg, dup)
+            })
+            .filter(|(_, dup)| matches!(dup.kind, hir::GenericParamKind::Lifetime { .. }))
+            .map(|(lifetime, dup)| (lifetime, (dup.def_id, dup.name.ident().name, dup.span)));
 
-            let dup_region = ty::Region::new_early_bound(
-                tcx,
-                ty::EarlyBoundRegion {
-                    def_id: dup_def,
-                    index: dup_index,
-                    name: duplicate.name.ident().name,
-                },
-            );
-            predicates.push((
-                ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(orig_region, dup_region))
-                    .to_predicate(icx.tcx),
-                duplicate.span,
-            ));
-            predicates.push((
-                ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(dup_region, orig_region))
-                    .to_predicate(icx.tcx),
-                duplicate.span,
-            ));
-        }
+        bidirectional_lifetime_predicates(tcx, def_id, lifetime_mapping, generics, &mut predicates);
         debug!(?predicates);
     }
 
@@ -330,6 +308,46 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
     }
 }
 
+/// Opaques have duplicated lifetimes and we need to compute bidirectional outlives predicates to
+/// enforce that these lifetimes stay in sync.
+fn compute_bidirectional_outlives_predicates<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    item_def_id: LocalDefId,
+    lifetime_mapping: impl Iterator<Item = (Lifetime, (LocalDefId, Symbol, Span))>,
+    generics: &Generics,
+    predicates: &mut Vec<(ty::Clause<'tcx>, Span)>,
+) {
+    let icx = ItemCtxt::new(tcx, item_def_id);
+
+    for (arg, (dup_def, name, span)) in lifetime_mapping {
+        let orig_region = icx.astconv().ast_region_to_region(&arg, None);
+        if !matches!(orig_region.kind(), ty::ReEarlyBound(..)) {
+            // There is no late-bound lifetime to actually match up here, since the lifetime doesn't
+            // show up in the opaque's parent's substs.
+            continue;
+        }
+
+        let Some(dup_index) = generics.param_def_id_to_index(icx.tcx, dup_def.to_def_id()) else { bug!() };
+
+        let dup_region = ty::Region::new_early_bound(
+            tcx,
+            ty::EarlyBoundRegion { def_id: dup_def.to_def_id(), index: dup_index, name },
+        );
+
+        predicates.push((
+            ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(orig_region, dup_region))
+                .to_predicate(tcx),
+            span,
+        ));
+
+        predicates.push((
+            ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(dup_region, orig_region))
+                .to_predicate(tcx),
+            span,
+        ));
+    }
+}
+
 fn const_evaluatable_predicates_of(
     tcx: TyCtxt<'_>,
     def_id: LocalDefId,