Rework the logic for PointerFinder::visit_place

This makes the implementation of our PointerFinder a bit more
straightforward.
This commit is contained in:
Bastian Kersting
2025-03-17 15:37:17 +00:00
parent a3e7c699bc
commit 7082fa27a7

View File

@@ -182,35 +182,29 @@ impl<'a, 'tcx> Visitor<'tcx> for PointerFinder<'a, 'tcx> {
return;
}
// Since Deref projections must come first and only once, the pointer for an indirect place
// is the Local that the Place is based on.
// Get the place and type we visit.
let pointer = Place::from(place.local);
let pointer_ty = self.local_decls[place.local].ty;
let pointer_ty = pointer.ty(self.local_decls, self.tcx).ty;
// We only want to check places based on raw pointers
if !pointer_ty.is_raw_ptr() {
let &ty::RawPtr(mut pointee_ty, _) = pointer_ty.kind() else {
trace!("Indirect, but not based on an raw ptr, not checking {:?}", place);
return;
};
// If we see a borrow of a field projection, we want to pass the field type to the
// check and not the pointee type.
if matches!(self.field_projection_mode, BorrowedFieldProjectionMode::FollowProjections)
&& matches!(
context,
PlaceContext::NonMutatingUse(NonMutatingUseContext::SharedBorrow)
| PlaceContext::MutatingUse(MutatingUseContext::Borrow)
)
{
// Naturally, the field type is type of the initial place we look at.
pointee_ty = place.ty(self.local_decls, self.tcx).ty;
}
// If we see a borrow of a field projection, we want to pass the field Ty to the
// check and not the pointee Ty.
let pointee_ty = match self.field_projection_mode {
BorrowedFieldProjectionMode::FollowProjections
if matches!(
context,
PlaceContext::NonMutatingUse(NonMutatingUseContext::SharedBorrow)
| PlaceContext::MutatingUse(MutatingUseContext::Borrow)
) =>
{
if let Some(PlaceElem::Field(_, ty)) = place.projection.last() {
*ty
} else {
pointer_ty.builtin_deref(true).expect("no builtin_deref for an raw pointer")
}
}
_ => pointer_ty.builtin_deref(true).expect("no builtin_deref for an raw pointer"),
};
// Ideally we'd support this in the future, but for now we are limited to sized types.
if !pointee_ty.is_sized(self.tcx, self.typing_env) {
trace!("Raw pointer, but pointee is not known to be sized: {:?}", pointer_ty);
@@ -222,6 +216,7 @@ impl<'a, 'tcx> Visitor<'tcx> for PointerFinder<'a, 'tcx> {
ty::Array(ty, _) => *ty,
_ => pointee_ty,
};
// Check if we excluded this pointee type from the check.
if self.excluded_pointees.contains(&element_ty) {
trace!("Skipping pointer for type: {:?}", pointee_ty);
return;