Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion generate/src/pgraph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -781,7 +781,9 @@ impl PlaceGraph {
let Some(target) = self.pointee(r) else {
return false;
};
self.is_place_init(target)
// Note that since typed copies produce retags, this must also check
// if the reference is valid to retag.
self.is_place_init(target) && self.can_read_through(r, target)
}

/// Whether all refs contained in a place are all valid
Expand Down
24 changes: 24 additions & 0 deletions generate/src/place_select.rs
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,15 @@ impl PlaceSelector {
.chain(pt.return_dest_stack()) // Don't touch anything that overlaps with any RET in the stack
.chain(pt.moved_in_args_stack()) // Don't touch anything that overlaps with moved in args in the stack
.collect();
// The explicit exclusions are the places this operation writes (e.g. the
// assignment destination). A read operand must not contain a reference
// pointing into one of these, since it may be moved at any time and thus
// still require validity.
let dest_indices: Vec<PlaceIndex> = self
.exclusions
.iter()
.map(|place| place.to_place_index(pt).expect("excluded place exists"))
.collect();
let moved: Vec<PlaceIndex> = self
.moved
.iter()
Expand Down Expand Up @@ -233,6 +242,16 @@ impl PlaceSelector {
return false;
}

// Don't read an operand that holds a reference pointing into a place
// this operation writes; the write would invalidate that reference.
if self.usage != PlaceUsage::LHS
&& dest_indices
.iter()
.any(|excl| pt.contains_ref_to(index, *excl))
{
return false;
}

// Has the right size
if self.size.is_some() && BasicMemory::ty_size(pt.ty(index), &self.tcx) != self.size {
return false;
Expand Down Expand Up @@ -265,6 +284,11 @@ impl PlaceSelector {
if moved.iter().any(|excl| pt.overlap(index, excl)) {
return false;
}
// Passing a self-referential argument by value will not work, because the retagging
// will protect the argument while we are moving it.
if pt.contains_ref_to(index, index) {
return false;
}
// If this contains a ref, then it cannot point to an already-picked moved arg
for m in &moved {
if pt.contains_ref_to(index, *m) {
Expand Down