Skip to content

Commit 2bdaccb

Browse files
committed
Make UnsafetyChecker visitor iterate instead of recurse
1 parent 47f4975 commit 2bdaccb

File tree

1 file changed

+39
-40
lines changed

1 file changed

+39
-40
lines changed

src/librustc_mir/transform/check_unsafety.rs

Lines changed: 39 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)