@@ -199,11 +199,39 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
199
199
fn visit_place ( & mut self ,
200
200
place : & Place < ' tcx > ,
201
201
context : PlaceContext ,
202
- location : Location ) {
203
- match place {
204
- & Place :: Projection ( box Projection {
205
- ref base, ref elem
206
- } ) => {
202
+ _location : Location ) {
203
+ place. iterate ( |place_base, place_projections| {
204
+ match place_base {
205
+ PlaceBase :: Local ( ..) => {
206
+ // Locals are safe.
207
+ }
208
+ PlaceBase :: Static ( box Static { kind : StaticKind :: Promoted ( _) , .. } ) => {
209
+ bug ! ( "unsafety checking should happen before promotion" )
210
+ }
211
+ PlaceBase :: Static ( box Static { kind : StaticKind :: Static ( def_id) , .. } ) => {
212
+ if self . tcx . is_mutable_static ( * def_id) {
213
+ self . require_unsafe ( "use of mutable static" ,
214
+ "mutable statics can be mutated by multiple threads: aliasing \
215
+ violations or data races will cause undefined behavior",
216
+ UnsafetyViolationKind :: General ) ;
217
+ } else if self . tcx . is_foreign_item ( * def_id) {
218
+ let source_info = self . source_info ;
219
+ let lint_root =
220
+ self . source_scope_local_data [ source_info. scope ] . lint_root ;
221
+ self . register_violations ( & [ UnsafetyViolation {
222
+ source_info,
223
+ description : InternedString :: intern ( "use of extern static" ) ,
224
+ details : InternedString :: intern (
225
+ "extern statics are not controlled by the Rust type system: \
226
+ invalid data, aliasing violations or data races will cause \
227
+ undefined behavior") ,
228
+ kind : UnsafetyViolationKind :: ExternStatic ( lint_root)
229
+ } ] , & [ ] ) ;
230
+ }
231
+ }
232
+ }
233
+
234
+ for proj in place_projections {
207
235
if context. is_borrow ( ) {
208
236
if util:: is_disaligned ( self . tcx , self . mir , self . param_env , place) {
209
237
let source_info = self . source_info ;
@@ -220,7 +248,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
220
248
} ] , & [ ] ) ;
221
249
}
222
250
}
223
- let is_borrow_of_interior_mut = context. is_borrow ( ) && !base
251
+ let is_borrow_of_interior_mut = context. is_borrow ( ) && !proj . base
224
252
. ty ( self . mir , self . tcx )
225
253
. ty
226
254
. is_freeze ( self . tcx , self . param_env , self . source_info . span ) ;
@@ -236,15 +264,15 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
236
264
) ;
237
265
}
238
266
let old_source_info = self . source_info ;
239
- if let & Place :: Base ( PlaceBase :: Local ( local) ) = base {
267
+ if let Place :: Base ( PlaceBase :: Local ( local) ) = proj . base {
240
268
if self . mir . local_decls [ local] . internal {
241
269
// Internal locals are used in the `move_val_init` desugaring.
242
270
// We want to check unsafety against the source info of the
243
271
// desugaring, rather than the source info of the RHS.
244
272
self . source_info = self . mir . local_decls [ local] . source_info ;
245
273
}
246
274
}
247
- let base_ty = base. ty ( self . mir , self . tcx ) . ty ;
275
+ let base_ty = proj . base . ty ( self . mir , self . tcx ) . ty ;
248
276
match base_ty. sty {
249
277
ty:: RawPtr ( ..) => {
250
278
self . require_unsafe ( "dereference of raw pointer" ,
@@ -260,8 +288,8 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
260
288
MutatingUseContext :: AsmOutput
261
289
)
262
290
{
263
- let elem_ty = match elem {
264
- & ProjectionElem :: Field ( _, ty) => ty,
291
+ let elem_ty = match proj . elem {
292
+ ProjectionElem :: Field ( _, ty) => ty,
265
293
_ => span_bug ! (
266
294
self . source_info. span,
267
295
"non-field projection {:?} from union?" ,
@@ -292,36 +320,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
292
320
}
293
321
self . source_info = old_source_info;
294
322
}
295
- & Place :: Base ( PlaceBase :: Local ( ..) ) => {
296
- // locals are safe
297
- }
298
- & Place :: Base ( PlaceBase :: Static ( box Static { kind : StaticKind :: Promoted ( _) , .. } ) ) => {
299
- bug ! ( "unsafety checking should happen before promotion" )
300
- }
301
- & Place :: Base (
302
- PlaceBase :: Static ( box Static { kind : StaticKind :: Static ( def_id) , .. } )
303
- ) => {
304
- if self . tcx . is_mutable_static ( def_id) {
305
- self . require_unsafe ( "use of mutable static" ,
306
- "mutable statics can be mutated by multiple threads: aliasing violations \
307
- or data races will cause undefined behavior",
308
- UnsafetyViolationKind :: General ) ;
309
- } else if self . tcx . is_foreign_item ( def_id) {
310
- let source_info = self . source_info ;
311
- let lint_root =
312
- self . source_scope_local_data [ source_info. scope ] . lint_root ;
313
- self . register_violations ( & [ UnsafetyViolation {
314
- source_info,
315
- description : InternedString :: intern ( "use of extern static" ) ,
316
- details : InternedString :: intern (
317
- "extern statics are not controlled by the Rust type system: invalid \
318
- data, aliasing violations or data races will cause undefined behavior") ,
319
- kind : UnsafetyViolationKind :: ExternStatic ( lint_root)
320
- } ] , & [ ] ) ;
321
- }
322
- }
323
- } ;
324
- self . super_place ( place, context, location) ;
323
+ } ) ;
325
324
}
326
325
}
327
326
0 commit comments