summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_middle/src/ty/erase_regions.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_middle/src/ty/erase_regions.rs')
-rw-r--r--compiler/rustc_middle/src/ty/erase_regions.rs74
1 files changed, 74 insertions, 0 deletions
diff --git a/compiler/rustc_middle/src/ty/erase_regions.rs b/compiler/rustc_middle/src/ty/erase_regions.rs
new file mode 100644
index 000000000..3226950e7
--- /dev/null
+++ b/compiler/rustc_middle/src/ty/erase_regions.rs
@@ -0,0 +1,74 @@
+use crate::mir;
+use crate::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
+use crate::ty::visit::TypeVisitable;
+use crate::ty::{self, Ty, TyCtxt, TypeFlags};
+
+pub(super) fn provide(providers: &mut ty::query::Providers) {
+ *providers = ty::query::Providers { erase_regions_ty, ..*providers };
+}
+
+fn erase_regions_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
+ // N.B., use `super_fold_with` here. If we used `fold_with`, it
+ // could invoke the `erase_regions_ty` query recursively.
+ ty.super_fold_with(&mut RegionEraserVisitor { tcx })
+}
+
+impl<'tcx> TyCtxt<'tcx> {
+ /// Returns an equivalent value with all free regions removed (note
+ /// that late-bound regions remain, because they are important for
+ /// subtyping, but they are anonymized and normalized as well)..
+ pub fn erase_regions<T>(self, value: T) -> T
+ where
+ T: TypeFoldable<'tcx>,
+ {
+ // If there's nothing to erase avoid performing the query at all
+ if !value.has_type_flags(TypeFlags::HAS_RE_LATE_BOUND | TypeFlags::HAS_FREE_REGIONS) {
+ return value;
+ }
+ debug!("erase_regions({:?})", value);
+ let value1 = value.fold_with(&mut RegionEraserVisitor { tcx: self });
+ debug!("erase_regions = {:?}", value1);
+ value1
+ }
+}
+
+struct RegionEraserVisitor<'tcx> {
+ tcx: TyCtxt<'tcx>,
+}
+
+impl<'tcx> TypeFolder<'tcx> for RegionEraserVisitor<'tcx> {
+ fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
+ self.tcx
+ }
+
+ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
+ if ty.needs_infer() { ty.super_fold_with(self) } else { self.tcx.erase_regions_ty(ty) }
+ }
+
+ fn fold_binder<T>(&mut self, t: ty::Binder<'tcx, T>) -> ty::Binder<'tcx, T>
+ where
+ T: TypeFoldable<'tcx>,
+ {
+ let u = self.tcx.anonymize_bound_vars(t);
+ u.super_fold_with(self)
+ }
+
+ fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
+ // because late-bound regions affect subtyping, we can't
+ // erase the bound/free distinction, but we can replace
+ // all free regions with 'erased.
+ //
+ // Note that we *CAN* replace early-bound regions -- the
+ // type system never "sees" those, they get substituted
+ // away. In codegen, they will always be erased to 'erased
+ // whenever a substitution occurs.
+ match *r {
+ ty::ReLateBound(..) => r,
+ _ => self.tcx.lifetimes.re_erased,
+ }
+ }
+
+ fn fold_mir_const(&mut self, c: mir::ConstantKind<'tcx>) -> mir::ConstantKind<'tcx> {
+ c.super_fold_with(self)
+ }
+}