10
10
11
11
use rustc:: mir:: { self , Location , Mir } ;
12
12
use rustc:: mir:: visit:: Visitor ;
13
- use rustc:: ty:: { Region , TyCtxt } ;
13
+ use rustc:: ty:: { self , Region , TyCtxt } ;
14
14
use rustc:: ty:: RegionKind ;
15
15
use rustc:: ty:: RegionKind :: ReScope ;
16
16
use rustc:: util:: nodemap:: { FxHashMap , FxHashSet } ;
@@ -71,10 +71,14 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> {
71
71
mir : & ' a Mir < ' tcx > ,
72
72
nonlexical_regioncx : Option < & ' a RegionInferenceContext < ' tcx > > )
73
73
-> Self {
74
- let mut visitor = GatherBorrows { idx_vec : IndexVec :: new ( ) ,
75
- location_map : FxHashMap ( ) ,
76
- region_map : FxHashMap ( ) ,
77
- region_span_map : FxHashMap ( ) } ;
74
+ let mut visitor = GatherBorrows {
75
+ tcx,
76
+ mir,
77
+ idx_vec : IndexVec :: new ( ) ,
78
+ location_map : FxHashMap ( ) ,
79
+ region_map : FxHashMap ( ) ,
80
+ region_span_map : FxHashMap ( )
81
+ } ;
78
82
visitor. visit_mir ( mir) ;
79
83
return Borrows { tcx : tcx,
80
84
mir : mir,
@@ -84,17 +88,22 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> {
84
88
region_span_map : visitor. region_span_map ,
85
89
nonlexical_regioncx } ;
86
90
87
- struct GatherBorrows < ' tcx > {
91
+ struct GatherBorrows < ' a , ' gcx : ' tcx , ' tcx : ' a > {
92
+ tcx : TyCtxt < ' a , ' gcx , ' tcx > ,
93
+ mir : & ' a Mir < ' tcx > ,
88
94
idx_vec : IndexVec < BorrowIndex , BorrowData < ' tcx > > ,
89
95
location_map : FxHashMap < Location , BorrowIndex > ,
90
96
region_map : FxHashMap < Region < ' tcx > , FxHashSet < BorrowIndex > > ,
91
97
region_span_map : FxHashMap < RegionKind , Span > ,
92
98
}
93
- impl < ' tcx > Visitor < ' tcx > for GatherBorrows < ' tcx > {
99
+
100
+ impl < ' a , ' gcx , ' tcx > Visitor < ' tcx > for GatherBorrows < ' a , ' gcx , ' tcx > {
94
101
fn visit_rvalue ( & mut self ,
95
102
rvalue : & mir:: Rvalue < ' tcx > ,
96
103
location : mir:: Location ) {
97
104
if let mir:: Rvalue :: Ref ( region, kind, ref lvalue) = * rvalue {
105
+ if is_unsafe_lvalue ( self . tcx , self . mir , lvalue) { return ; }
106
+
98
107
let borrow = BorrowData {
99
108
location : location, kind : kind, region : region, lvalue : lvalue. clone ( ) ,
100
109
} ;
@@ -197,7 +206,8 @@ impl<'a, 'gcx, 'tcx> BitDenotation for Borrows<'a, 'gcx, 'tcx> {
197
206
}
198
207
199
208
mir:: StatementKind :: Assign ( _, ref rhs) => {
200
- if let mir:: Rvalue :: Ref ( region, _, _) = * rhs {
209
+ if let mir:: Rvalue :: Ref ( region, _, ref lvalue) = * rhs {
210
+ if is_unsafe_lvalue ( self . tcx , self . mir , lvalue) { return ; }
201
211
let index = self . location_map . get ( & location) . unwrap_or_else ( || {
202
212
panic ! ( "could not find BorrowIndex for location {:?}" , location) ;
203
213
} ) ;
@@ -248,3 +258,35 @@ impl<'a, 'gcx, 'tcx> DataflowOperator for Borrows<'a, 'gcx, 'tcx> {
248
258
false // bottom = no Rvalue::Refs are active by default
249
259
}
250
260
}
261
+
262
+ fn is_unsafe_lvalue < ' a , ' gcx : ' tcx , ' tcx : ' a > (
263
+ tcx : TyCtxt < ' a , ' gcx , ' tcx > ,
264
+ mir : & ' a Mir < ' tcx > ,
265
+ lvalue : & mir:: Lvalue < ' tcx >
266
+ ) -> bool {
267
+ use self :: mir:: Lvalue :: * ;
268
+ use self :: mir:: ProjectionElem ;
269
+
270
+ match * lvalue {
271
+ Local ( _) => false ,
272
+ Static ( ref static_) => tcx. is_static_mut ( static_. def_id ) ,
273
+ Projection ( ref proj) => {
274
+ match proj. elem {
275
+ ProjectionElem :: Field ( ..) |
276
+ ProjectionElem :: Downcast ( ..) |
277
+ ProjectionElem :: Subslice { .. } |
278
+ ProjectionElem :: ConstantIndex { .. } |
279
+ ProjectionElem :: Index ( _) => {
280
+ is_unsafe_lvalue ( tcx, mir, & proj. base )
281
+ }
282
+ ProjectionElem :: Deref => {
283
+ let ty = proj. base . ty ( mir, tcx) . to_ty ( tcx) ;
284
+ match ty. sty {
285
+ ty:: TyRawPtr ( ..) => true ,
286
+ _ => is_unsafe_lvalue ( tcx, mir, & proj. base ) ,
287
+ }
288
+ }
289
+ }
290
+ }
291
+ }
292
+ }
0 commit comments