about summary refs log tree commit diff
path: root/compiler/rustc_infer/src
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_infer/src')
-rw-r--r--compiler/rustc_infer/src/infer/outlives/components.rs266
-rw-r--r--compiler/rustc_infer/src/infer/outlives/mod.rs1
-rw-r--r--compiler/rustc_infer/src/infer/outlives/obligations.rs4
-rw-r--r--compiler/rustc_infer/src/infer/outlives/verify.rs6
-rw-r--r--compiler/rustc_infer/src/traits/util.rs2
5 files changed, 6 insertions, 273 deletions
diff --git a/compiler/rustc_infer/src/infer/outlives/components.rs b/compiler/rustc_infer/src/infer/outlives/components.rs
deleted file mode 100644
index 6bab3ad6ba3..00000000000
--- a/compiler/rustc_infer/src/infer/outlives/components.rs
+++ /dev/null
@@ -1,266 +0,0 @@
-// The outlines relation `T: 'a` or `'a: 'b`. This code frequently
-// refers to rules defined in RFC 1214 (`OutlivesFooBar`), so see that
-// RFC for reference.
-
-use rustc_data_structures::sso::SsoHashSet;
-use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
-use rustc_middle::ty::{GenericArg, GenericArgKind};
-use smallvec::{smallvec, SmallVec};
-
-#[derive(Debug)]
-pub enum Component<'tcx> {
-    Region(ty::Region<'tcx>),
-    Param(ty::ParamTy),
-    Placeholder(ty::PlaceholderType),
-    UnresolvedInferenceVariable(ty::InferTy),
-
-    // Projections like `T::Foo` are tricky because a constraint like
-    // `T::Foo: 'a` can be satisfied in so many ways. There may be a
-    // where-clause that says `T::Foo: 'a`, or the defining trait may
-    // include a bound like `type Foo: 'static`, or -- in the most
-    // conservative way -- we can prove that `T: 'a` (more generally,
-    // that all components in the projection outlive `'a`). This code
-    // is not in a position to judge which is the best technique, so
-    // we just product the projection as a component and leave it to
-    // the consumer to decide (but see `EscapingProjection` below).
-    Alias(ty::AliasTy<'tcx>),
-
-    // In the case where a projection has escaping regions -- meaning
-    // regions bound within the type itself -- we always use
-    // the most conservative rule, which requires that all components
-    // outlive the bound. So for example if we had a type like this:
-    //
-    //     for<'a> Trait1<  <T as Trait2<'a,'b>>::Foo  >
-    //                      ~~~~~~~~~~~~~~~~~~~~~~~~~
-    //
-    // then the inner projection (underlined) has an escaping region
-    // `'a`. We consider that outer trait `'c` to meet a bound if `'b`
-    // outlives `'b: 'c`, and we don't consider whether the trait
-    // declares that `Foo: 'static` etc. Therefore, we just return the
-    // free components of such a projection (in this case, `'b`).
-    //
-    // However, in the future, we may want to get smarter, and
-    // actually return a "higher-ranked projection" here. Therefore,
-    // we mark that these components are part of an escaping
-    // projection, so that implied bounds code can avoid relying on
-    // them. This gives us room to improve the regionck reasoning in
-    // the future without breaking backwards compat.
-    EscapingAlias(Vec<Component<'tcx>>),
-}
-
-/// Push onto `out` all the things that must outlive `'a` for the condition
-/// `ty0: 'a` to hold. Note that `ty0` must be a **fully resolved type**.
-pub fn push_outlives_components<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    ty0: Ty<'tcx>,
-    out: &mut SmallVec<[Component<'tcx>; 4]>,
-) {
-    let mut visited = SsoHashSet::new();
-    compute_components(tcx, ty0, out, &mut visited);
-    debug!("components({:?}) = {:?}", ty0, out);
-}
-
-fn compute_components<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    ty: Ty<'tcx>,
-    out: &mut SmallVec<[Component<'tcx>; 4]>,
-    visited: &mut SsoHashSet<GenericArg<'tcx>>,
-) {
-    // Descend through the types, looking for the various "base"
-    // components and collecting them into `out`. This is not written
-    // with `collect()` because of the need to sometimes skip subtrees
-    // in the `subtys` iterator (e.g., when encountering a
-    // projection).
-    match *ty.kind() {
-            ty::FnDef(_, args) => {
-                // HACK(eddyb) ignore lifetimes found shallowly in `args`.
-                // This is inconsistent with `ty::Adt` (including all args)
-                // and with `ty::Closure` (ignoring all args other than
-                // upvars, of which a `ty::FnDef` doesn't have any), but
-                // consistent with previous (accidental) behavior.
-                // See https://github.com/rust-lang/rust/issues/70917
-                // for further background and discussion.
-                for child in args {
-                    match child.unpack() {
-                        GenericArgKind::Type(ty) => {
-                            compute_components(tcx, ty, out, visited);
-                        }
-                        GenericArgKind::Lifetime(_) => {}
-                        GenericArgKind::Const(_) => {
-                            compute_components_recursive(tcx, child, out, visited);
-                        }
-                    }
-                }
-            }
-
-            ty::Pat(element, _) |
-            ty::Array(element, _) => {
-                // Don't look into the len const as it doesn't affect regions
-                compute_components(tcx, element, out, visited);
-            }
-
-            ty::Closure(_, args) => {
-                let tupled_ty = args.as_closure().tupled_upvars_ty();
-                compute_components(tcx, tupled_ty, out, visited);
-            }
-
-            ty::CoroutineClosure(_, args) => {
-                let tupled_ty = args.as_coroutine_closure().tupled_upvars_ty();
-                compute_components(tcx, tupled_ty, out, visited);
-            }
-
-            ty::Coroutine(_, args) => {
-                // Same as the closure case
-                let tupled_ty = args.as_coroutine().tupled_upvars_ty();
-                compute_components(tcx, tupled_ty, out, visited);
-
-                // We ignore regions in the coroutine interior as we don't
-                // want these to affect region inference
-            }
-
-            // All regions are bound inside a witness
-            ty::CoroutineWitness(..) => (),
-
-            // OutlivesTypeParameterEnv -- the actual checking that `X:'a`
-            // is implied by the environment is done in regionck.
-            ty::Param(p) => {
-                out.push(Component::Param(p));
-            }
-
-            ty::Placeholder(p) => {
-                out.push(Component::Placeholder(p));
-            }
-
-            // For projections, we prefer to generate an obligation like
-            // `<P0 as Trait<P1...Pn>>::Foo: 'a`, because this gives the
-            // regionck more ways to prove that it holds. However,
-            // regionck is not (at least currently) prepared to deal with
-            // higher-ranked regions that may appear in the
-            // trait-ref. Therefore, if we see any higher-ranked regions,
-            // we simply fallback to the most restrictive rule, which
-            // requires that `Pi: 'a` for all `i`.
-            ty::Alias(_, alias_ty) => {
-                if !alias_ty.has_escaping_bound_vars() {
-                    // best case: no escaping regions, so push the
-                    // projection and skip the subtree (thus generating no
-                    // constraints for Pi). This defers the choice between
-                    // the rules OutlivesProjectionEnv,
-                    // OutlivesProjectionTraitDef, and
-                    // OutlivesProjectionComponents to regionck.
-                    out.push(Component::Alias(alias_ty));
-                } else {
-                    // fallback case: hard code
-                    // OutlivesProjectionComponents. Continue walking
-                    // through and constrain Pi.
-                    let mut subcomponents = smallvec![];
-                    let mut subvisited = SsoHashSet::new();
-                    compute_alias_components_recursive(tcx, ty, &mut subcomponents, &mut subvisited);
-                    out.push(Component::EscapingAlias(subcomponents.into_iter().collect()));
-                }
-            }
-
-            // We assume that inference variables are fully resolved.
-            // So, if we encounter an inference variable, just record
-            // the unresolved variable as a component.
-            ty::Infer(infer_ty) => {
-                out.push(Component::UnresolvedInferenceVariable(infer_ty));
-            }
-
-            // Most types do not introduce any region binders, nor
-            // involve any other subtle cases, and so the WF relation
-            // simply constraints any regions referenced directly by
-            // the type and then visits the types that are lexically
-            // contained within. (The comments refer to relevant rules
-            // from RFC1214.)
-            ty::Bool |            // OutlivesScalar
-            ty::Char |            // OutlivesScalar
-            ty::Int(..) |         // OutlivesScalar
-            ty::Uint(..) |        // OutlivesScalar
-            ty::Float(..) |       // OutlivesScalar
-            ty::Never |           // ...
-            ty::Adt(..) |         // OutlivesNominalType
-            ty::Foreign(..) |     // OutlivesNominalType
-            ty::Str |             // OutlivesScalar (ish)
-            ty::Slice(..) |       // ...
-            ty::RawPtr(..) |      // ...
-            ty::Ref(..) |         // OutlivesReference
-            ty::Tuple(..) |       // ...
-            ty::FnPtr(_) |        // OutlivesFunction (*)
-            ty::Dynamic(..) |     // OutlivesObject, OutlivesFragment (*)
-            ty::Bound(..) |
-            ty::Error(_) => {
-                // (*) Function pointers and trait objects are both binders.
-                // In the RFC, this means we would add the bound regions to
-                // the "bound regions list". In our representation, no such
-                // list is maintained explicitly, because bound regions
-                // themselves can be readily identified.
-                compute_components_recursive(tcx, ty.into(), out, visited);
-            }
-        }
-}
-
-/// Collect [Component]s for *all* the args of `parent`.
-///
-/// This should not be used to get the components of `parent` itself.
-/// Use [push_outlives_components] instead.
-pub(super) fn compute_alias_components_recursive<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    alias_ty: Ty<'tcx>,
-    out: &mut SmallVec<[Component<'tcx>; 4]>,
-    visited: &mut SsoHashSet<GenericArg<'tcx>>,
-) {
-    let ty::Alias(kind, alias_ty) = alias_ty.kind() else {
-        unreachable!("can only call `compute_alias_components_recursive` on an alias type")
-    };
-    let opt_variances = if *kind == ty::Opaque { tcx.variances_of(alias_ty.def_id) } else { &[] };
-    for (index, child) in alias_ty.args.iter().enumerate() {
-        if opt_variances.get(index) == Some(&ty::Bivariant) {
-            continue;
-        }
-        if !visited.insert(child) {
-            continue;
-        }
-        match child.unpack() {
-            GenericArgKind::Type(ty) => {
-                compute_components(tcx, ty, out, visited);
-            }
-            GenericArgKind::Lifetime(lt) => {
-                // Ignore higher ranked regions.
-                if !lt.is_bound() {
-                    out.push(Component::Region(lt));
-                }
-            }
-            GenericArgKind::Const(_) => {
-                compute_components_recursive(tcx, child, out, visited);
-            }
-        }
-    }
-}
-
-/// Collect [Component]s for *all* the args of `parent`.
-///
-/// This should not be used to get the components of `parent` itself.
-/// Use [push_outlives_components] instead.
-fn compute_components_recursive<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    parent: GenericArg<'tcx>,
-    out: &mut SmallVec<[Component<'tcx>; 4]>,
-    visited: &mut SsoHashSet<GenericArg<'tcx>>,
-) {
-    for child in parent.walk_shallow(visited) {
-        match child.unpack() {
-            GenericArgKind::Type(ty) => {
-                compute_components(tcx, ty, out, visited);
-            }
-            GenericArgKind::Lifetime(lt) => {
-                // Ignore higher ranked regions.
-                if !lt.is_bound() {
-                    out.push(Component::Region(lt));
-                }
-            }
-            GenericArgKind::Const(_) => {
-                compute_components_recursive(tcx, child, out, visited);
-            }
-        }
-    }
-}
diff --git a/compiler/rustc_infer/src/infer/outlives/mod.rs b/compiler/rustc_infer/src/infer/outlives/mod.rs
index 48d006e7fbc..89ff4604560 100644
--- a/compiler/rustc_infer/src/infer/outlives/mod.rs
+++ b/compiler/rustc_infer/src/infer/outlives/mod.rs
@@ -8,7 +8,6 @@ use crate::infer::lexical_region_resolve;
 use rustc_middle::traits::query::{NoSolution, OutlivesBound};
 use rustc_middle::ty;
 
-pub mod components;
 pub mod env;
 pub mod for_liveness;
 pub mod obligations;
diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs
index 32c790523b6..9bb5f775e4a 100644
--- a/compiler/rustc_infer/src/infer/outlives/obligations.rs
+++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs
@@ -59,7 +59,6 @@
 //! might later infer `?U` to something like `&'b u32`, which would
 //! imply that `'b: 'a`.
 
-use crate::infer::outlives::components::{push_outlives_components, Component};
 use crate::infer::outlives::env::RegionBoundPairs;
 use crate::infer::outlives::verify::VerifyBoundCx;
 use crate::infer::resolve::OpportunisticRegionResolver;
@@ -75,6 +74,7 @@ use rustc_middle::ty::{
 };
 use rustc_middle::ty::{GenericArgKind, PolyTypeOutlivesPredicate};
 use rustc_span::DUMMY_SP;
+use rustc_type_ir::outlives::{push_outlives_components, Component};
 use smallvec::smallvec;
 
 use super::env::OutlivesEnvironment;
@@ -291,7 +291,7 @@ where
     fn components_must_outlive(
         &mut self,
         origin: infer::SubregionOrigin<'tcx>,
-        components: &[Component<'tcx>],
+        components: &[Component<TyCtxt<'tcx>>],
         region: ty::Region<'tcx>,
         category: ConstraintCategory<'tcx>,
     ) {
diff --git a/compiler/rustc_infer/src/infer/outlives/verify.rs b/compiler/rustc_infer/src/infer/outlives/verify.rs
index 7e977b9b954..ad102dfcc1f 100644
--- a/compiler/rustc_infer/src/infer/outlives/verify.rs
+++ b/compiler/rustc_infer/src/infer/outlives/verify.rs
@@ -1,10 +1,10 @@
-use crate::infer::outlives::components::{compute_alias_components_recursive, Component};
 use crate::infer::outlives::env::RegionBoundPairs;
 use crate::infer::region_constraints::VerifyIfEq;
 use crate::infer::{GenericKind, VerifyBound};
 use rustc_data_structures::sso::SsoHashSet;
 use rustc_middle::ty::GenericArg;
 use rustc_middle::ty::{self, OutlivesPredicate, Ty, TyCtxt};
+use rustc_type_ir::outlives::{compute_alias_components_recursive, Component};
 
 use smallvec::smallvec;
 
@@ -139,7 +139,7 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
 
     fn bound_from_components(
         &self,
-        components: &[Component<'tcx>],
+        components: &[Component<TyCtxt<'tcx>>],
         visited: &mut SsoHashSet<GenericArg<'tcx>>,
     ) -> VerifyBound<'tcx> {
         let mut bounds = components
@@ -158,7 +158,7 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
 
     fn bound_from_single_component(
         &self,
-        component: &Component<'tcx>,
+        component: &Component<TyCtxt<'tcx>>,
         visited: &mut SsoHashSet<GenericArg<'tcx>>,
     ) -> VerifyBound<'tcx> {
         match *component {
diff --git a/compiler/rustc_infer/src/traits/util.rs b/compiler/rustc_infer/src/traits/util.rs
index 18d36c3a5df..b269bfcbfeb 100644
--- a/compiler/rustc_infer/src/traits/util.rs
+++ b/compiler/rustc_infer/src/traits/util.rs
@@ -1,12 +1,12 @@
 use smallvec::smallvec;
 
-use crate::infer::outlives::components::{push_outlives_components, Component};
 use crate::traits::{self, Obligation, ObligationCauseCode, PredicateObligation};
 use rustc_data_structures::fx::FxHashSet;
 use rustc_middle::ty::ToPolyTraitRef;
 use rustc_middle::ty::{self, Ty, TyCtxt, Upcast};
 use rustc_span::symbol::Ident;
 use rustc_span::Span;
+use rustc_type_ir::outlives::{push_outlives_components, Component};
 
 pub fn anonymize_predicate<'tcx>(
     tcx: TyCtxt<'tcx>,