rustc_middle/ty/
erase_regions.rs

1use tracing::debug;
2
3use crate::query::Providers;
4use crate::ty::{
5    self, Ty, TyCtxt, TypeFlags, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt,
6};
7
8pub(super) fn provide(providers: &mut Providers) {
9    *providers = Providers { erase_regions_ty, ..*providers };
10}
11
12fn erase_regions_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
13    // N.B., use `super_fold_with` here. If we used `fold_with`, it
14    // could invoke the `erase_regions_ty` query recursively.
15    ty.super_fold_with(&mut RegionEraserVisitor { tcx })
16}
17
18impl<'tcx> TyCtxt<'tcx> {
19    /// Returns an equivalent value with all free regions removed (note
20    /// that late-bound regions remain, because they are important for
21    /// subtyping, but they are anonymized and normalized as well)..
22    pub fn erase_regions<T>(self, value: T) -> T
23    where
24        T: TypeFoldable<TyCtxt<'tcx>>,
25    {
26        // If there's nothing to erase or anonymize, avoid performing the query at all
27        if !value.has_type_flags(TypeFlags::HAS_BINDER_VARS | TypeFlags::HAS_FREE_REGIONS) {
28            return value;
29        }
30        debug!("erase_regions({:?})", value);
31        let value1 = value.fold_with(&mut RegionEraserVisitor { tcx: self });
32        debug!("erase_regions = {:?}", value1);
33        value1
34    }
35}
36
37struct RegionEraserVisitor<'tcx> {
38    tcx: TyCtxt<'tcx>,
39}
40
41impl<'tcx> TypeFolder<TyCtxt<'tcx>> for RegionEraserVisitor<'tcx> {
42    fn cx(&self) -> TyCtxt<'tcx> {
43        self.tcx
44    }
45
46    fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
47        if !ty.has_type_flags(TypeFlags::HAS_BINDER_VARS | TypeFlags::HAS_FREE_REGIONS) {
48            ty
49        } else if ty.has_infer() {
50            ty.super_fold_with(self)
51        } else {
52            self.tcx.erase_regions_ty(ty)
53        }
54    }
55
56    fn fold_binder<T>(&mut self, t: ty::Binder<'tcx, T>) -> ty::Binder<'tcx, T>
57    where
58        T: TypeFoldable<TyCtxt<'tcx>>,
59    {
60        let u = self.tcx.anonymize_bound_vars(t);
61        u.super_fold_with(self)
62    }
63
64    fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
65        // We must not erase bound regions. `for<'a> fn(&'a ())` and
66        // `fn(&'free ())` are different types: they may implement different
67        // traits and have a different `TypeId`.
68        match r.kind() {
69            ty::ReBound(..) => r,
70            _ => self.tcx.lifetimes.re_erased,
71        }
72    }
73
74    fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
75        if ct.has_type_flags(TypeFlags::HAS_BINDER_VARS | TypeFlags::HAS_FREE_REGIONS) {
76            ct.super_fold_with(self)
77        } else {
78            ct
79        }
80    }
81
82    fn fold_predicate(&mut self, p: ty::Predicate<'tcx>) -> ty::Predicate<'tcx> {
83        if p.has_type_flags(TypeFlags::HAS_BINDER_VARS | TypeFlags::HAS_FREE_REGIONS) {
84            p.super_fold_with(self)
85        } else {
86            p
87        }
88    }
89}