From 5b7185794faf47c8907a386d60516a4fa2249e4f Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 16 Oct 2018 12:45:44 +0200 Subject: [PATCH] give machine more control over what counts as memory leak --- src/librustc_mir/const_eval.rs | 8 ++++++++ src/librustc_mir/interpret/machine.rs | 7 ++++++- src/librustc_mir/interpret/memory.rs | 21 +++++++++++++-------- src/librustc_mir/interpret/mod.rs | 2 +- 4 files changed, 28 insertions(+), 10 deletions(-) diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs index 497c6a2a80e..fd9af74c5d7 100644 --- a/src/librustc_mir/const_eval.rs +++ b/src/librustc_mir/const_eval.rs @@ -333,6 +333,14 @@ fn get_mut_or( type CompileTimeEvalContext<'a, 'mir, 'tcx> = EvalContext<'a, 'mir, 'tcx, CompileTimeInterpreter<'a, 'mir, 'tcx>>; +impl interpret::MayLeak for ! { + #[inline(always)] + fn may_leak(self) -> bool { + // `self` is uninhabited + self + } +} + impl<'a, 'mir, 'tcx> interpret::Machine<'a, 'mir, 'tcx> for CompileTimeInterpreter<'a, 'mir, 'tcx> { diff --git a/src/librustc_mir/interpret/machine.rs b/src/librustc_mir/interpret/machine.rs index 790a1f6b745..56909938df4 100644 --- a/src/librustc_mir/interpret/machine.rs +++ b/src/librustc_mir/interpret/machine.rs @@ -22,6 +22,11 @@ use super::{EvalContext, PlaceTy, OpTy, MemoryKind}; +/// Whether this kind of memory is allowed to leak +pub trait MayLeak: Copy { + fn may_leak(self) -> bool; +} + /// The functionality needed by memory to manage its allocations pub trait AllocMap { /// Test if the map contains the given key. @@ -63,7 +68,7 @@ fn get_mut_or( /// and some use case dependent behaviour can instead be applied. pub trait Machine<'a, 'mir, 'tcx>: Sized { /// Additional memory kinds a machine wishes to distinguish from the builtin ones - type MemoryKinds: ::std::fmt::Debug + Copy + Eq + 'static; + type MemoryKinds: ::std::fmt::Debug + MayLeak + Eq + 'static; /// Tag tracked alongside every pointer. This is used to implement "Stacked Borrows" /// . diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index d61f3e38569..51dd970e0bb 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -32,7 +32,7 @@ use syntax::ast::Mutability; -use super::{Machine, AllocMap, ScalarMaybeUndef}; +use super::{Machine, AllocMap, MayLeak, ScalarMaybeUndef}; #[derive(Debug, PartialEq, Eq, Copy, Clone, Hash)] pub enum MemoryKind { @@ -44,6 +44,17 @@ pub enum MemoryKind { Machine(T), } +impl MayLeak for MemoryKind { + #[inline] + fn may_leak(self) -> bool { + match self { + MemoryKind::Stack => false, + MemoryKind::Vtable => true, + MemoryKind::Machine(k) => k.may_leak() + } + } +} + // `Memory` has to depend on the `Machine` because some of its operations // (e.g. `get`) call a `Machine` hook. pub struct Memory<'a, 'mir, 'tcx: 'a + 'mir, M: Machine<'a, 'mir, 'tcx>> { @@ -584,13 +595,7 @@ pub fn dump_allocs(&self, mut allocs: Vec) { pub fn leak_report(&self) -> usize { trace!("### LEAK REPORT ###"); let leaks: Vec<_> = self.alloc_map.filter_map_collect(|&id, &(kind, _)| { - // exclude statics and vtables - let exclude = match kind { - MemoryKind::Stack => false, - MemoryKind::Vtable => true, - MemoryKind::Machine(k) => Some(k) == M::STATIC_KIND, - }; - if exclude { None } else { Some(id) } + if kind.may_leak() { None } else { Some(id) } }); let n = leaks.len(); self.dump_allocs(leaks); diff --git a/src/librustc_mir/interpret/mod.rs b/src/librustc_mir/interpret/mod.rs index 39628598ef3..a174b12aaac 100644 --- a/src/librustc_mir/interpret/mod.rs +++ b/src/librustc_mir/interpret/mod.rs @@ -32,7 +32,7 @@ pub use self::memory::{Memory, MemoryKind}; -pub use self::machine::{Machine, AllocMap}; +pub use self::machine::{Machine, AllocMap, MayLeak}; pub use self::operand::{ScalarMaybeUndef, Value, ValTy, Operand, OpTy};