1 // Copyright 2017 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.
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.
11 use rustc_data_structures
::indexed_vec
::{Idx, IndexVec}
;
12 use rustc
::ty
::subst
::Substs
;
13 use rustc
::ty
::{self, ClosureSubsts, RegionVid, Ty, TypeFoldable}
;
14 use rustc
::mir
::{BasicBlock, Local, Location, Mir, Statement, StatementKind}
;
15 use rustc
::mir
::visit
::{MutVisitor, TyContext}
;
16 use rustc
::infer
::{InferCtxt, NLLRegionVariableOrigin}
;
18 use super::ToRegionVid
;
19 use super::free_regions
::FreeRegions
;
21 /// Replaces all free regions appearing in the MIR with fresh
22 /// inference variables, returning the number of variables created.
23 pub fn renumber_mir
<'a
, 'gcx
, 'tcx
>(
24 infcx
: &InferCtxt
<'a
, 'gcx
, 'tcx
>,
25 free_regions
: &FreeRegions
<'tcx
>,
28 // Create inference variables for each of the free regions
29 // declared on the function signature.
30 let free_region_inference_vars
= (0..free_regions
.indices
.len())
33 let r
= infcx
.next_nll_region_var(NLLRegionVariableOrigin
::FreeRegion
);
34 assert_eq
!(vid_expected
, r
.to_region_vid());
39 debug
!("renumber_mir()");
40 debug
!("renumber_mir: free_regions={:#?}", free_regions
);
41 debug
!("renumber_mir: mir.arg_count={:?}", mir
.arg_count
);
43 let mut visitor
= NLLVisitor
{
46 free_region_inference_vars
,
47 arg_count
: mir
.arg_count
,
49 visitor
.visit_mir(mir
);
52 struct NLLVisitor
<'a
, 'gcx
: 'a
+ 'tcx
, 'tcx
: 'a
> {
53 infcx
: &'a InferCtxt
<'a
, 'gcx
, 'tcx
>,
54 free_regions
: &'a FreeRegions
<'tcx
>,
55 free_region_inference_vars
: IndexVec
<RegionVid
, ty
::Region
<'tcx
>>,
59 impl<'a
, 'gcx
, 'tcx
> NLLVisitor
<'a
, 'gcx
, 'tcx
> {
60 /// Replaces all regions appearing in `value` with fresh inference
61 /// variables. This is what we do for almost the entire MIR, with
62 /// the exception of the declared types of our arguments.
63 fn renumber_regions
<T
>(&mut self, ty_context
: TyContext
, value
: &T
) -> T
65 T
: TypeFoldable
<'tcx
>,
67 debug
!("renumber_regions(value={:?})", value
);
71 .fold_regions(value
, &mut false, |_region
, _depth
| {
72 let origin
= NLLRegionVariableOrigin
::Inferred(ty_context
);
73 self.infcx
.next_nll_region_var(origin
)
77 /// Renumbers the regions appearing in `value`, but those regions
78 /// are expected to be free regions from the function signature.
79 fn renumber_free_regions
<T
>(&mut self, value
: &T
) -> T
81 T
: TypeFoldable
<'tcx
>,
83 debug
!("renumber_free_regions(value={:?})", value
);
87 .fold_regions(value
, &mut false, |region
, _depth
| {
88 let index
= self.free_regions
.indices
[®ion
];
89 self.free_region_inference_vars
[index
]
93 fn is_argument_or_return_slot(&self, local
: Local
) -> bool
{
94 // The first argument is return slot, next N are arguments.
95 local
.index() <= self.arg_count
99 impl<'a
, 'gcx
, 'tcx
> MutVisitor
<'tcx
> for NLLVisitor
<'a
, 'gcx
, 'tcx
> {
100 fn visit_ty(&mut self, ty
: &mut Ty
<'tcx
>, ty_context
: TyContext
) {
101 let is_arg
= match ty_context
{
102 TyContext
::LocalDecl { local, .. }
=> self.is_argument_or_return_slot(local
),
103 TyContext
::ReturnTy(..) => true,
104 TyContext
::Location(..) => false,
107 "visit_ty(ty={:?}, is_arg={:?}, ty_context={:?})",
115 self.renumber_free_regions(&old_ty
)
117 self.renumber_regions(ty_context
, &old_ty
)
119 debug
!("visit_ty: ty={:?}", ty
);
122 fn visit_substs(&mut self, substs
: &mut &'tcx Substs
<'tcx
>, location
: Location
) {
123 debug
!("visit_substs(substs={:?}, location={:?})", substs
, location
);
125 let ty_context
= TyContext
::Location(location
);
126 *substs
= self.renumber_regions(ty_context
, &{ *substs }
);
128 debug
!("visit_substs: substs={:?}", substs
);
131 fn visit_region(&mut self, region
: &mut ty
::Region
<'tcx
>, location
: Location
) {
132 debug
!("visit_region(region={:?}, location={:?})", region
, location
);
134 let old_region
= *region
;
135 let ty_context
= TyContext
::Location(location
);
136 *region
= self.renumber_regions(ty_context
, &old_region
);
138 debug
!("visit_region: region={:?}", region
);
141 fn visit_closure_substs(&mut self, substs
: &mut ClosureSubsts
<'tcx
>, location
: Location
) {
143 "visit_closure_substs(substs={:?}, location={:?})",
148 let ty_context
= TyContext
::Location(location
);
149 *substs
= self.renumber_regions(ty_context
, substs
);
151 debug
!("visit_closure_substs: substs={:?}", substs
);
157 statement
: &mut Statement
<'tcx
>,
160 if let StatementKind
::EndRegion(_
) = statement
.kind
{
161 statement
.kind
= StatementKind
::Nop
;
163 self.super_statement(block
, statement
, location
);