miri: avoid cloning AllocExtra · rust-lang/rust@bc4366b (original) (raw)
`@@ -993,11 +993,14 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
`
993
993
` bytes
`
994
994
`}
`
995
995
``
996
``
`` -
/// Find leaked allocations. Allocations reachable from static_roots
or a Global
allocation
``
997
``
`` -
/// are not considered leaked, as well as leaks whose kind's may_leak()
returns true.
``
998
``
`-
pub fn find_leaked_allocations(
`
999
``
`-
&self,
`
1000
``
`-
static_roots: &[AllocId],
`
``
996
`+
/// Find leaked allocations, remove them from memory and return them. Allocations reachable from
`
``
997
`` +
/// static_roots
or a Global
allocation are not considered leaked, as well as leaks whose
``
``
998
`` +
/// kind's may_leak()
returns true.
``
``
999
`+
///
`
``
1000
`+
/// This is highly destructive, no more execution can happen after this!
`
``
1001
`+
pub fn take_leaked_allocations(
`
``
1002
`+
&mut self,
`
``
1003
`+
static_roots: impl FnOnce(&Self) -> &[AllocId],
`
1001
1004
`) -> Vec<(AllocId, MemoryKind<M::MemoryKind>, Allocation<M::Provenance, M::AllocExtra, M::Bytes>)>
`
1002
1005
`{
`
1003
1006
`` // Collect the set of allocations that are reachable from Global
allocations.
``
`@@ -1008,7 +1011,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
`
1008
1011
`self.memory.alloc_map.filter_map_collect(move |&id, &(kind, _)| {
`
1009
1012
`if Some(kind) == global_kind { Some(id) } else { None }
`
1010
1013
`});
`
1011
``
`-
todo.extend(static_roots);
`
``
1014
`+
todo.extend(static_roots(self));
`
1012
1015
`while let Some(id) = todo.pop() {
`
1013
1016
`if reachable.insert(id) {
`
1014
1017
`` // This is a new allocation, add the allocation it points to todo
.
``
`@@ -1023,13 +1026,15 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
`
1023
1026
`};
`
1024
1027
``
1025
1028
`` // All allocations that are not reachable
and not may_leak
are considered leaking.
``
1026
``
`-
self.memory.alloc_map.filter_map_collect(|id, (kind, alloc)| {
`
1027
``
`-
if kind.may_leak() || reachable.contains(id) {
`
1028
``
`-
None
`
1029
``
`-
} else {
`
1030
``
`-
Some((*id, *kind, alloc.clone()))
`
1031
``
`-
}
`
1032
``
`-
})
`
``
1029
`+
let leaked: Vec<_> = self.memory.alloc_map.filter_map_collect(|&id, &(kind, _)| {
`
``
1030
`+
if kind.may_leak() || reachable.contains(&id) { None } else { Some(id) }
`
``
1031
`+
});
`
``
1032
`+
let mut result = Vec::new();
`
``
1033
`+
for &id in leaked.iter() {
`
``
1034
`+
let (kind, alloc) = self.memory.alloc_map.remove(&id).unwrap();
`
``
1035
`+
result.push((id, kind, alloc));
`
``
1036
`+
}
`
``
1037
`+
result
`
1033
1038
`}
`
1034
1039
``
1035
1040
`/// Runs the closure in "validation" mode, which means the machine's memory read hooks will be
`