13
13
14
14
use rustc:: mir:: visit:: Visitor ;
15
15
use rustc:: mir:: * ;
16
+ use rustc:: ty:: { self , TyCtxt } ;
16
17
17
18
use rustc_data_structures:: indexed_vec:: Idx ;
18
19
use rustc_data_structures:: unify as ut;
@@ -22,11 +23,13 @@ crate struct EscapingLocals {
22
23
}
23
24
24
25
impl EscapingLocals {
25
- crate fn compute ( mir : & Mir < ' _ > ) -> Self {
26
- let mut visitor = GatherAssignedLocalsVisitor :: new ( ) ;
26
+ crate fn compute ( tcx : TyCtxt < ' _ , ' _ , ' tcx > , mir : & Mir < ' tcx > ) -> Self {
27
+ let mut visitor = GatherAssignedLocalsVisitor :: new ( tcx , mir ) ;
27
28
visitor. visit_mir ( mir) ;
28
29
29
- EscapingLocals { unification_table : visitor. unification_table }
30
+ EscapingLocals {
31
+ unification_table : visitor. unification_table ,
32
+ }
30
33
}
31
34
32
35
/// True if `local` is known to escape into static
@@ -40,8 +43,10 @@ impl EscapingLocals {
40
43
41
44
/// The MIR visitor gathering the union-find of the locals used in
42
45
/// assignments.
43
- struct GatherAssignedLocalsVisitor {
46
+ struct GatherAssignedLocalsVisitor < ' cx , ' gcx : ' tcx , ' tcx : ' cx > {
44
47
unification_table : ut:: UnificationTable < ut:: InPlace < AssignedLocal > > ,
48
+ tcx : TyCtxt < ' cx , ' gcx , ' tcx > ,
49
+ mir : & ' cx Mir < ' tcx > ,
45
50
}
46
51
47
52
#[ derive( Copy , Clone , Debug , Hash , PartialEq , Eq ) ]
@@ -71,17 +76,20 @@ impl From<Local> for AssignedLocal {
71
76
}
72
77
}
73
78
74
- impl GatherAssignedLocalsVisitor {
75
- fn new ( ) -> Self {
79
+ impl GatherAssignedLocalsVisitor < ' cx , ' gcx , ' tcx > {
80
+ fn new ( tcx : TyCtxt < ' cx , ' gcx , ' tcx > , mir : & ' cx Mir < ' tcx > ) -> Self {
76
81
Self {
77
82
unification_table : ut:: UnificationTable :: new ( ) ,
83
+ tcx,
84
+ mir,
78
85
}
79
86
}
80
87
81
88
fn union_locals_if_needed ( & mut self , lvalue : Option < Local > , rvalue : Option < Local > ) {
82
89
if let Some ( lvalue) = lvalue {
83
90
if let Some ( rvalue) = rvalue {
84
91
if lvalue != rvalue {
92
+ debug ! ( "EscapingLocals: union {:?} and {:?}" , lvalue, rvalue) ;
85
93
self . unification_table
86
94
. union ( AssignedLocal :: from ( lvalue) , AssignedLocal :: from ( rvalue) ) ;
87
95
}
@@ -115,7 +123,7 @@ fn find_local_in_operand(op: &Operand) -> Option<Local> {
115
123
}
116
124
}
117
125
118
- impl < ' tcx > Visitor < ' tcx > for GatherAssignedLocalsVisitor {
126
+ impl Visitor < ' tcx > for GatherAssignedLocalsVisitor < ' _ , ' _ , ' tcx > {
119
127
fn visit_mir ( & mut self , mir : & Mir < ' tcx > ) {
120
128
// We need as many union-find keys as there are locals
121
129
for _ in 0 ..mir. local_decls . len ( ) {
@@ -139,6 +147,19 @@ impl<'tcx> Visitor<'tcx> for GatherAssignedLocalsVisitor {
139
147
match rvalue {
140
148
Rvalue :: Use ( op) => self . union_locals_if_needed ( local, find_local_in_operand ( op) ) ,
141
149
Rvalue :: Ref ( _, _, place) => {
150
+ // Special case: if you have `X = &*Y` where `Y` is a
151
+ // reference, then the outlives relationships should
152
+ // ensure that all regions in `Y` are constrained by
153
+ // regions in `X`.
154
+ if let Place :: Projection ( proj) = place {
155
+ if let ProjectionElem :: Deref = proj. elem {
156
+ if let ty:: TyRef ( ..) = proj. base . ty ( self . mir , self . tcx ) . to_ty ( self . tcx ) . sty
157
+ {
158
+ self . union_locals_if_needed ( local, find_local_in_place ( & proj. base ) ) ;
159
+ }
160
+ }
161
+ }
162
+
142
163
self . union_locals_if_needed ( local, find_local_in_place ( place) )
143
164
}
144
165
0 commit comments