-
Notifications
You must be signed in to change notification settings - Fork 13.3k
Make visitors iterate #61559
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Make visitors iterate #61559
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -199,11 +199,39 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> { | |
fn visit_place(&mut self, | ||
place: &Place<'tcx>, | ||
context: PlaceContext, | ||
location: Location) { | ||
match place { | ||
&Place::Projection(box Projection { | ||
ref base, ref elem | ||
}) => { | ||
_location: Location) { | ||
place.iterate(|place_base, place_projections| { | ||
match place_base { | ||
PlaceBase::Local(..) => { | ||
// Locals are safe. | ||
} | ||
PlaceBase::Static(box Static { kind: StaticKind::Promoted(_), .. }) => { | ||
bug!("unsafety checking should happen before promotion") | ||
} | ||
PlaceBase::Static(box Static { kind: StaticKind::Static(def_id), .. }) => { | ||
if self.tcx.is_mutable_static(*def_id) { | ||
self.require_unsafe("use of mutable static", | ||
"mutable statics can be mutated by multiple threads: aliasing \ | ||
violations or data races will cause undefined behavior", | ||
UnsafetyViolationKind::General); | ||
} else if self.tcx.is_foreign_item(*def_id) { | ||
let source_info = self.source_info; | ||
let lint_root = | ||
self.source_scope_local_data[source_info.scope].lint_root; | ||
self.register_violations(&[UnsafetyViolation { | ||
source_info, | ||
description: InternedString::intern("use of extern static"), | ||
details: InternedString::intern( | ||
"extern statics are not controlled by the Rust type system: \ | ||
invalid data, aliasing violations or data races will cause \ | ||
undefined behavior"), | ||
kind: UnsafetyViolationKind::ExternStatic(lint_root) | ||
}], &[]); | ||
} | ||
} | ||
} | ||
|
||
for proj in place_projections { | ||
if context.is_borrow() { | ||
if util::is_disaligned(self.tcx, self.mir, self.param_env, place) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This change looks very suspicious. Previously, There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah no, we actually only care about the outermost place as that's what the reference is created for. But then it seems unnecessary to have this in the loop. |
||
let source_info = self.source_info; | ||
|
@@ -220,7 +248,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> { | |
}], &[]); | ||
} | ||
} | ||
let is_borrow_of_interior_mut = context.is_borrow() && !base | ||
let is_borrow_of_interior_mut = context.is_borrow() && !proj.base | ||
.ty(self.mir, self.tcx) | ||
.ty | ||
.is_freeze(self.tcx, self.param_env, self.source_info.span); | ||
|
@@ -236,15 +264,15 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> { | |
); | ||
} | ||
let old_source_info = self.source_info; | ||
if let &Place::Base(PlaceBase::Local(local)) = base { | ||
if let Place::Base(PlaceBase::Local(local)) = proj.base { | ||
if self.mir.local_decls[local].internal { | ||
// Internal locals are used in the `move_val_init` desugaring. | ||
// We want to check unsafety against the source info of the | ||
// desugaring, rather than the source info of the RHS. | ||
self.source_info = self.mir.local_decls[local].source_info; | ||
} | ||
} | ||
let base_ty = base.ty(self.mir, self.tcx).ty; | ||
let base_ty = proj.base.ty(self.mir, self.tcx).ty; | ||
match base_ty.sty { | ||
ty::RawPtr(..) => { | ||
self.require_unsafe("dereference of raw pointer", | ||
|
@@ -260,8 +288,8 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> { | |
MutatingUseContext::AsmOutput | ||
) | ||
{ | ||
let elem_ty = match elem { | ||
&ProjectionElem::Field(_, ty) => ty, | ||
let elem_ty = match proj.elem { | ||
ProjectionElem::Field(_, ty) => ty, | ||
_ => span_bug!( | ||
self.source_info.span, | ||
"non-field projection {:?} from union?", | ||
|
@@ -292,36 +320,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> { | |
} | ||
self.source_info = old_source_info; | ||
} | ||
&Place::Base(PlaceBase::Local(..)) => { | ||
// locals are safe | ||
} | ||
&Place::Base(PlaceBase::Static(box Static { kind: StaticKind::Promoted(_), .. })) => { | ||
bug!("unsafety checking should happen before promotion") | ||
} | ||
&Place::Base( | ||
PlaceBase::Static(box Static { kind: StaticKind::Static(def_id), .. }) | ||
) => { | ||
if self.tcx.is_mutable_static(def_id) { | ||
self.require_unsafe("use of mutable static", | ||
"mutable statics can be mutated by multiple threads: aliasing violations \ | ||
or data races will cause undefined behavior", | ||
UnsafetyViolationKind::General); | ||
} else if self.tcx.is_foreign_item(def_id) { | ||
let source_info = self.source_info; | ||
let lint_root = | ||
self.source_scope_local_data[source_info.scope].lint_root; | ||
self.register_violations(&[UnsafetyViolation { | ||
source_info, | ||
description: InternedString::intern("use of extern static"), | ||
details: InternedString::intern( | ||
"extern statics are not controlled by the Rust type system: invalid \ | ||
data, aliasing violations or data races will cause undefined behavior"), | ||
kind: UnsafetyViolationKind::ExternStatic(lint_root) | ||
}], &[]); | ||
} | ||
} | ||
}; | ||
self.super_place(place, context, location); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. you can keep the base checking after the projection checking. It's not very important, all that can happen is that the order of evaluation changes. Since the order is not important, put the base checking back here, so the diff is smaller. |
||
}); | ||
} | ||
} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doing this suggests to me that you want a
.fold
method onplace
such that you can provide an initial state...There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, may be nice to fix that. Maybe we can leave this for a different PR?. It's pre-existing logic that exists in the default Visitor implementation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, file an issue about it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't need an explicit
fold
method.place_projections
is an iterator, so we can just callfold
on it.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fold
does not work ok because there's a return and a continue there and we would be trying to do that inside a closure :/