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 @@ impl interpret::AllocMap for FxHashMap { 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 rustc::ty::{self, layout::TyLayout, query::TyCtxtAt}; 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 @@ pub trait AllocMap { /// 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 rustc_data_structures::fx::{FxHashSet, FxHashMap}; 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 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { 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::place::{Place, PlaceTy, MemPlace, MPlaceTy}; 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};