1313
1414use rustc:: mir:: visit:: Visitor ;
1515use rustc:: mir:: * ;
16+ use rustc:: ty:: { self , TyCtxt } ;
1617
1718use rustc_data_structures:: indexed_vec:: Idx ;
1819use rustc_data_structures:: unify as ut;
@@ -22,11 +23,13 @@ crate struct EscapingLocals {
2223}
2324
2425impl 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 ) ;
2728 visitor. visit_mir ( mir) ;
2829
29- EscapingLocals { unification_table : visitor. unification_table }
30+ EscapingLocals {
31+ unification_table : visitor. unification_table ,
32+ }
3033 }
3134
3235 /// True if `local` is known to escape into static
@@ -40,8 +43,10 @@ impl EscapingLocals {
4043
4144/// The MIR visitor gathering the union-find of the locals used in
4245/// assignments.
43- struct GatherAssignedLocalsVisitor {
46+ struct GatherAssignedLocalsVisitor < ' cx , ' gcx : ' tcx , ' tcx : ' cx > {
4447 unification_table : ut:: UnificationTable < ut:: InPlace < AssignedLocal > > ,
48+ tcx : TyCtxt < ' cx , ' gcx , ' tcx > ,
49+ mir : & ' cx Mir < ' tcx > ,
4550}
4651
4752#[ derive( Copy , Clone , Debug , Hash , PartialEq , Eq ) ]
@@ -71,17 +76,20 @@ impl From<Local> for AssignedLocal {
7176 }
7277}
7378
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 {
7681 Self {
7782 unification_table : ut:: UnificationTable :: new ( ) ,
83+ tcx,
84+ mir,
7885 }
7986 }
8087
8188 fn union_locals_if_needed ( & mut self , lvalue : Option < Local > , rvalue : Option < Local > ) {
8289 if let Some ( lvalue) = lvalue {
8390 if let Some ( rvalue) = rvalue {
8491 if lvalue != rvalue {
92+ debug ! ( "EscapingLocals: union {:?} and {:?}" , lvalue, rvalue) ;
8593 self . unification_table
8694 . union ( AssignedLocal :: from ( lvalue) , AssignedLocal :: from ( rvalue) ) ;
8795 }
@@ -115,7 +123,7 @@ fn find_local_in_operand(op: &Operand) -> Option<Local> {
115123 }
116124}
117125
118- impl < ' tcx > Visitor < ' tcx > for GatherAssignedLocalsVisitor {
126+ impl Visitor < ' tcx > for GatherAssignedLocalsVisitor < ' _ , ' _ , ' tcx > {
119127 fn visit_mir ( & mut self , mir : & Mir < ' tcx > ) {
120128 // We need as many union-find keys as there are locals
121129 for _ in 0 ..mir. local_decls . len ( ) {
@@ -139,6 +147,19 @@ impl<'tcx> Visitor<'tcx> for GatherAssignedLocalsVisitor {
139147 match rvalue {
140148 Rvalue :: Use ( op) => self . union_locals_if_needed ( local, find_local_in_operand ( op) ) ,
141149 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+
142163 self . union_locals_if_needed ( local, find_local_in_place ( place) )
143164 }
144165
0 commit comments