@@ -199,11 +199,39 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
199199 fn visit_place ( & mut self ,
200200 place : & Place < ' tcx > ,
201201 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 {
207235 if context. is_borrow ( ) {
208236 if util:: is_disaligned ( self . tcx , self . mir , self . param_env , place) {
209237 let source_info = self . source_info ;
@@ -220,7 +248,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
220248 } ] , & [ ] ) ;
221249 }
222250 }
223- let is_borrow_of_interior_mut = context. is_borrow ( ) && !base
251+ let is_borrow_of_interior_mut = context. is_borrow ( ) && !proj . base
224252 . ty ( self . mir , self . tcx )
225253 . ty
226254 . is_freeze ( self . tcx , self . param_env , self . source_info . span ) ;
@@ -236,15 +264,15 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
236264 ) ;
237265 }
238266 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 {
240268 if self . mir . local_decls [ local] . internal {
241269 // Internal locals are used in the `move_val_init` desugaring.
242270 // We want to check unsafety against the source info of the
243271 // desugaring, rather than the source info of the RHS.
244272 self . source_info = self . mir . local_decls [ local] . source_info ;
245273 }
246274 }
247- let base_ty = base. ty ( self . mir , self . tcx ) . ty ;
275+ let base_ty = proj . base . ty ( self . mir , self . tcx ) . ty ;
248276 match base_ty. sty {
249277 ty:: RawPtr ( ..) => {
250278 self . require_unsafe ( "dereference of raw pointer" ,
@@ -260,8 +288,8 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
260288 MutatingUseContext :: AsmOutput
261289 )
262290 {
263- let elem_ty = match elem {
264- & ProjectionElem :: Field ( _, ty) => ty,
291+ let elem_ty = match proj . elem {
292+ ProjectionElem :: Field ( _, ty) => ty,
265293 _ => span_bug ! (
266294 self . source_info. span,
267295 "non-field projection {:?} from union?" ,
@@ -292,36 +320,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
292320 }
293321 self . source_info = old_source_info;
294322 }
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+ } ) ;
325324 }
326325}
327326
0 commit comments