]> git.proxmox.com Git - rustc.git/blob - src/librustc_mir/transform/erase_regions.rs
New upstream version 1.28.0~beta.14+dfsg1
[rustc.git] / src / librustc_mir / transform / erase_regions.rs
1 // Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 //! This pass erases all early-bound regions from the types occurring in the MIR.
12 //! We want to do this once just before codegen, so codegen does not have to take
13 //! care erasing regions all over the place.
14 //! NOTE: We do NOT erase regions of statements that are relevant for
15 //! "types-as-contracts"-validation, namely, AcquireValid, ReleaseValid, and EndRegion.
16
17 use rustc::ty::subst::Substs;
18 use rustc::ty::{self, Ty, TyCtxt};
19 use rustc::mir::*;
20 use rustc::mir::visit::{MutVisitor, TyContext};
21 use transform::{MirPass, MirSource};
22
23 struct EraseRegionsVisitor<'a, 'tcx: 'a> {
24 tcx: TyCtxt<'a, 'tcx, 'tcx>,
25 in_validation_statement: bool,
26 }
27
28 impl<'a, 'tcx> EraseRegionsVisitor<'a, 'tcx> {
29 pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Self {
30 EraseRegionsVisitor {
31 tcx,
32 in_validation_statement: false,
33 }
34 }
35 }
36
37 impl<'a, 'tcx> MutVisitor<'tcx> for EraseRegionsVisitor<'a, 'tcx> {
38 fn visit_ty(&mut self, ty: &mut Ty<'tcx>, _: TyContext) {
39 if !self.in_validation_statement {
40 *ty = self.tcx.erase_regions(ty);
41 }
42 self.super_ty(ty);
43 }
44
45 fn visit_region(&mut self, region: &mut ty::Region<'tcx>, _: Location) {
46 *region = self.tcx.types.re_erased;
47 }
48
49 fn visit_const(&mut self, constant: &mut &'tcx ty::Const<'tcx>, _: Location) {
50 *constant = self.tcx.erase_regions(constant);
51 }
52
53 fn visit_substs(&mut self, substs: &mut &'tcx Substs<'tcx>, _: Location) {
54 *substs = self.tcx.erase_regions(substs);
55 }
56
57 fn visit_statement(&mut self,
58 block: BasicBlock,
59 statement: &mut Statement<'tcx>,
60 location: Location) {
61 // Do NOT delete EndRegion if validation statements are emitted.
62 // Validation needs EndRegion.
63 if self.tcx.sess.opts.debugging_opts.mir_emit_validate == 0 {
64 if let StatementKind::EndRegion(_) = statement.kind {
65 statement.kind = StatementKind::Nop;
66 }
67 }
68
69 self.in_validation_statement = match statement.kind {
70 StatementKind::Validate(..) => true,
71 _ => false,
72 };
73 self.super_statement(block, statement, location);
74 self.in_validation_statement = false;
75 }
76 }
77
78 pub struct EraseRegions;
79
80 impl MirPass for EraseRegions {
81 fn run_pass<'a, 'tcx>(&self,
82 tcx: TyCtxt<'a, 'tcx, 'tcx>,
83 _: MirSource,
84 mir: &mut Mir<'tcx>) {
85 EraseRegionsVisitor::new(tcx).visit_mir(mir);
86 }
87 }