Skip to content

Commit d97c698

Browse files
authored
Rollup merge of rust-lang#61559 - spastorino:make-visitors-iterate, r=oli-obk
Make visitors iterate r? @oli-obk The second commit is not completely equivalent, unsure if the code is wrong or not. Tests pass though, otherwise we would need to iterate in the opposite direction as it happened in other parts of the code.
2 parents 1853135 + 0cfaa28 commit d97c698

File tree

2 files changed

+87
-77
lines changed

2 files changed

+87
-77
lines changed

src/librustc_codegen_ssa/mir/analyze.rs

+48-37
Original file line numberDiff line numberDiff line change
@@ -154,51 +154,62 @@ impl<'mir, 'a: 'mir, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> Visitor<'tcx>
154154
context: PlaceContext,
155155
location: Location) {
156156
debug!("visit_place(place={:?}, context={:?})", place, context);
157+
let mut context = context;
157158
let cx = self.fx.cx;
158159

159-
if let mir::Place::Projection(ref proj) = *place {
160-
// Allow uses of projections that are ZSTs or from scalar fields.
161-
let is_consume = match context {
162-
PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy) |
163-
PlaceContext::NonMutatingUse(NonMutatingUseContext::Move) => true,
164-
_ => false
165-
};
166-
if is_consume {
167-
let base_ty = proj.base.ty(self.fx.mir, cx.tcx());
168-
let base_ty = self.fx.monomorphize(&base_ty);
169-
170-
// ZSTs don't require any actual memory access.
171-
let elem_ty = base_ty
172-
.projection_ty(cx.tcx(), &proj.elem)
173-
.ty;
174-
let elem_ty = self.fx.monomorphize(&elem_ty);
175-
if cx.layout_of(elem_ty).is_zst() {
176-
return;
177-
}
178-
179-
if let mir::ProjectionElem::Field(..) = proj.elem {
180-
let layout = cx.layout_of(base_ty.ty);
181-
if cx.is_backend_immediate(layout) || cx.is_backend_scalar_pair(layout) {
182-
// Recurse with the same context, instead of `Projection`,
183-
// potentially stopping at non-operand projections,
184-
// which would trigger `not_ssa` on locals.
185-
self.visit_place(&proj.base, context, location);
160+
place.iterate(|place_base, place_projections| {
161+
for proj in place_projections {
162+
// Allow uses of projections that are ZSTs or from scalar fields.
163+
let is_consume = match context {
164+
PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy) |
165+
PlaceContext::NonMutatingUse(NonMutatingUseContext::Move) => true,
166+
_ => false
167+
};
168+
if is_consume {
169+
let base_ty = proj.base.ty(self.fx.mir, cx.tcx());
170+
let base_ty = self.fx.monomorphize(&base_ty);
171+
172+
// ZSTs don't require any actual memory access.
173+
let elem_ty = base_ty
174+
.projection_ty(cx.tcx(), &proj.elem)
175+
.ty;
176+
let elem_ty = self.fx.monomorphize(&elem_ty);
177+
if cx.layout_of(elem_ty).is_zst() {
186178
return;
187179
}
180+
181+
if let mir::ProjectionElem::Field(..) = proj.elem {
182+
let layout = cx.layout_of(base_ty.ty);
183+
if cx.is_backend_immediate(layout) || cx.is_backend_scalar_pair(layout) {
184+
// Recurse with the same context, instead of `Projection`,
185+
// potentially stopping at non-operand projections,
186+
// which would trigger `not_ssa` on locals.
187+
continue;
188+
}
189+
}
188190
}
189-
}
190191

191-
// A deref projection only reads the pointer, never needs the place.
192-
if let mir::ProjectionElem::Deref = proj.elem {
193-
return self.visit_place(
194-
&proj.base,
195-
PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy),
196-
location
197-
);
192+
// A deref projection only reads the pointer, never needs the place.
193+
if let mir::ProjectionElem::Deref = proj.elem {
194+
return self.visit_place(
195+
&proj.base,
196+
PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy),
197+
location
198+
);
199+
}
200+
201+
context = if context.is_mutating_use() {
202+
PlaceContext::MutatingUse(MutatingUseContext::Projection)
203+
} else {
204+
PlaceContext::NonMutatingUse(NonMutatingUseContext::Projection)
205+
};
198206
}
199-
}
200207

201-
self.super_place(place, context, location);
208+
// Default base visit behavior
209+
if let mir::PlaceBase::Local(local) = place_base {
210+
self.visit_local(local, context, location);
211+
}
212+
});
202213
}
203214

204215
fn visit_local(&mut self,

src/librustc_mir/transform/check_unsafety.rs

+39-40
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)